1*4882a593Smuzhiyun<?xml version="1.0" encoding="ISO-8859-1"?> 2*4882a593Smuzhiyun<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN" 3*4882a593Smuzhiyun "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [ 4*4882a593Smuzhiyun <!ENTITY % xorg-defs SYSTEM "defs.ent"> %xorg-defs; 5*4882a593Smuzhiyun <!ENTITY % defs SYSTEM "/xserver/doc/xml/xserver.ent"> %defs; 6*4882a593Smuzhiyun]> 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun<article> 9*4882a593Smuzhiyun <articleinfo> 10*4882a593Smuzhiyun <title>Definition of the Porting Layer for the X v11 Sample Server</title> 11*4882a593Smuzhiyun <titleabbrev>X Porting Layer</titleabbrev> 12*4882a593Smuzhiyun <author> 13*4882a593Smuzhiyun <firstname>Susan</firstname><surname>Angebranndt</surname> 14*4882a593Smuzhiyun <affiliation><orgname>Digital Equipment Corporation</orgname></affiliation> 15*4882a593Smuzhiyun </author> 16*4882a593Smuzhiyun <author> 17*4882a593Smuzhiyun <firstname>Raymond</firstname><surname>Drewry</surname> 18*4882a593Smuzhiyun <affiliation><orgname>Digital Equipment Corporation</orgname></affiliation> 19*4882a593Smuzhiyun </author> 20*4882a593Smuzhiyun <author> 21*4882a593Smuzhiyun <firstname>Philip</firstname><surname>Karlton</surname> 22*4882a593Smuzhiyun <affiliation><orgname>Digital Equipment Corporation</orgname></affiliation> 23*4882a593Smuzhiyun </author> 24*4882a593Smuzhiyun <author> 25*4882a593Smuzhiyun <firstname>Todd</firstname><surname>Newman</surname> 26*4882a593Smuzhiyun <affiliation><orgname>Digital Equipment Corporation</orgname></affiliation> 27*4882a593Smuzhiyun </author> 28*4882a593Smuzhiyun <author> 29*4882a593Smuzhiyun <firstname>Bob</firstname><surname>Scheifler</surname> 30*4882a593Smuzhiyun <affiliation><orgname>Massachusetts Institute of Technology</orgname></affiliation> 31*4882a593Smuzhiyun </author> 32*4882a593Smuzhiyun <author> 33*4882a593Smuzhiyun <firstname>Keith</firstname><surname>Packard</surname> 34*4882a593Smuzhiyun <affiliation><orgname>MIT X Consortium</orgname></affiliation> 35*4882a593Smuzhiyun </author> 36*4882a593Smuzhiyun <author> 37*4882a593Smuzhiyun <firstname>David</firstname><othername>P.</othername><surname>Wiggins</surname> 38*4882a593Smuzhiyun <affiliation><orgname>X Consortium</orgname></affiliation> 39*4882a593Smuzhiyun </author> 40*4882a593Smuzhiyun <author> 41*4882a593Smuzhiyun <firstname>Jim</firstname><surname>Gettys</surname> 42*4882a593Smuzhiyun <affiliation><orgname>X.org Foundation and Hewlett Packard</orgname></affiliation> 43*4882a593Smuzhiyun </author> 44*4882a593Smuzhiyun <publisher><publishername>The X.Org Foundation</publishername></publisher> 45*4882a593Smuzhiyun <releaseinfo>X Version 11, Release &fullrelvers;</releaseinfo> 46*4882a593Smuzhiyun <releaseinfo>X Server Version &xserver.version;</releaseinfo> 47*4882a593Smuzhiyun <copyright><year>1994</year><holder>X Consortium, Inc.</holder></copyright> 48*4882a593Smuzhiyun <copyright><year>2004</year><holder>X.org Foundation, Inc.</holder></copyright> 49*4882a593Smuzhiyun <legalnotice> 50*4882a593Smuzhiyun <para>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:</para> 51*4882a593Smuzhiyun <para>The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.</para> 52*4882a593Smuzhiyun <para>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.</para> 53*4882a593Smuzhiyun <para>LK201 and DEC are trademarks of Digital Equipment Corporation. Macintosh and Apple are trademarks of Apple Computer, Inc. PostScript is a trademark of Adobe Systems, Inc. Ethernet is a trademark of Xerox Corporation. X Window System is a trademark of the X.org Foundation, Inc. Cray is a trademark of Cray Research, Inc.</para> 54*4882a593Smuzhiyun </legalnotice> 55*4882a593Smuzhiyun <pubdate>&xserver.reldate;</pubdate> 56*4882a593Smuzhiyun <revhistory> 57*4882a593Smuzhiyun <revision> 58*4882a593Smuzhiyun <revnumber>1.0</revnumber> 59*4882a593Smuzhiyun <date>27 Oct 2004</date> 60*4882a593Smuzhiyun <authorinitials>sa</authorinitials> 61*4882a593Smuzhiyun <revremark>Initial Version</revremark> 62*4882a593Smuzhiyun </revision> 63*4882a593Smuzhiyun <revision> 64*4882a593Smuzhiyun <revnumber>1.1</revnumber> 65*4882a593Smuzhiyun <date>27 Oct 2004</date> 66*4882a593Smuzhiyun <authorinitials>bs</authorinitials> 67*4882a593Smuzhiyun <revremark>Minor Revisions</revremark> 68*4882a593Smuzhiyun </revision> 69*4882a593Smuzhiyun <revision> 70*4882a593Smuzhiyun <revnumber>2.0</revnumber> 71*4882a593Smuzhiyun <date>27 Oct 2004</date> 72*4882a593Smuzhiyun <authorinitials>kp</authorinitials> 73*4882a593Smuzhiyun <revremark>Revised for Release 4 and 5</revremark> 74*4882a593Smuzhiyun </revision> 75*4882a593Smuzhiyun <revision> 76*4882a593Smuzhiyun <revnumber>3.0</revnumber> 77*4882a593Smuzhiyun <date>27 Oct 2004</date> 78*4882a593Smuzhiyun <authorinitials>dpw</authorinitials> 79*4882a593Smuzhiyun <revremark>Revised for Release 6</revremark> 80*4882a593Smuzhiyun </revision> 81*4882a593Smuzhiyun <revision> 82*4882a593Smuzhiyun <revnumber>3.1</revnumber> 83*4882a593Smuzhiyun <date>27 Oct 2004</date> 84*4882a593Smuzhiyun <authorinitials>jg</authorinitials> 85*4882a593Smuzhiyun <revremark>Revised for Release 6.8.2</revremark> 86*4882a593Smuzhiyun </revision> 87*4882a593Smuzhiyun <revision> 88*4882a593Smuzhiyun <revnumber>3.2</revnumber> 89*4882a593Smuzhiyun <date>17 Dec 2006</date> 90*4882a593Smuzhiyun <authorinitials>efw</authorinitials> 91*4882a593Smuzhiyun <revremark>DocBook conversion</revremark> 92*4882a593Smuzhiyun </revision> 93*4882a593Smuzhiyun <revision> 94*4882a593Smuzhiyun <revnumber>3.3</revnumber> 95*4882a593Smuzhiyun <date>17 Feb 2008</date> 96*4882a593Smuzhiyun <authorinitials>aj</authorinitials> 97*4882a593Smuzhiyun <revremark>Revised for backing store changes</revremark> 98*4882a593Smuzhiyun </revision> 99*4882a593Smuzhiyun <revision> 100*4882a593Smuzhiyun <revnumber>3.4</revnumber> 101*4882a593Smuzhiyun <date>31 Mar 2008</date> 102*4882a593Smuzhiyun <authorinitials>efw</authorinitials> 103*4882a593Smuzhiyun <revremark>Revised for devPrivates changes</revremark> 104*4882a593Smuzhiyun </revision> 105*4882a593Smuzhiyun <revision> 106*4882a593Smuzhiyun <revnumber>3.5</revnumber> 107*4882a593Smuzhiyun <date>July 2010</date> 108*4882a593Smuzhiyun <authorinitials>ac</authorinitials> 109*4882a593Smuzhiyun <revremark>Revised for Xorg 1.9 devPrivates changes 110*4882a593Smuzhiyun and 1.8 CreateNewResourceType changes</revremark> 111*4882a593Smuzhiyun </revision> 112*4882a593Smuzhiyun <revision> 113*4882a593Smuzhiyun <revnumber>3.6</revnumber> 114*4882a593Smuzhiyun <date>July 2012</date> 115*4882a593Smuzhiyun <authorinitials>kp</authorinitials> 116*4882a593Smuzhiyun <revremark>Revised for X server 1.13 screen-specific devPrivates changes</revremark> 117*4882a593Smuzhiyun </revision> 118*4882a593Smuzhiyun </revhistory> 119*4882a593Smuzhiyun <abstract> 120*4882a593Smuzhiyun <para>The following document explains the structure of the X Window System display server and the interfaces among the larger pieces. It is intended as a reference for programmers who are implementing an X Display Server on their workstation hardware. It is included with the X Window System source tape, along with the document "Strategies for Porting the X v11 Sample Server." The order in which you should read these documents is: 121*4882a593Smuzhiyun <orderedlist> 122*4882a593Smuzhiyun <listitem><para>Read the first section of the "Strategies for Porting" document (Overview of Porting Process).</para></listitem> 123*4882a593Smuzhiyun <listitem><para>Skim over this document (the Definition document).</para></listitem> 124*4882a593Smuzhiyun <listitem><para>Skim over the remainder of the Strategies document.</para></listitem> 125*4882a593Smuzhiyun <listitem><para>Start planning and working, referring to the Strategies and Definition documents.</para></listitem> 126*4882a593Smuzhiyun </orderedlist> 127*4882a593Smuzhiyun You may also want to look at the following documents: 128*4882a593Smuzhiyun <itemizedlist> 129*4882a593Smuzhiyun <listitem><para>"The X Window System" for an overview of X.</para></listitem> 130*4882a593Smuzhiyun <listitem><para>"Xlib - C Language X Interface" for a view of what the client programmer sees.</para></listitem> 131*4882a593Smuzhiyun <listitem><para>"X Window System Protocol" for a terse description of the byte stream protocol between the client and server.</para></listitem> 132*4882a593Smuzhiyun </itemizedlist> 133*4882a593Smuzhiyun </para> 134*4882a593Smuzhiyun <para>To understand this document and the accompanying source code, you should know the C language. You should be familiar with 2D graphics and windowing concepts such as clipping, bitmaps, fonts, etc. You should have a general knowledge of the X Window System. To implement the server code on your hardware, you need to know a lot about your hardware, its graphic display device(s), and (possibly) its networking and multitasking facilities. This document depends a lot on the source code, so you should have a listing of the code handy.</para> 135*4882a593Smuzhiyun <para>Some source in the distribution is directly compilable on your machine. Some of it will require modification. Other parts may have to be completely written from scratch. The distribution also includes source for a sample implementation of a display server which runs on a very wide variety of color and monochrome displays on Linux and *BSD which you will find useful for implementing any type of X server.</para> 136*4882a593Smuzhiyun <para>Note to the 2008 edition: at this time this document must be considered incomplete, though improved over the 2004 edition. In particular, the new Render extension is still lacking good documentation, and has become vital to high performance X implementations. Modern applications and desktop environments are now much more sensitive to good implementation of the Render extension than in most operations of the old X graphics model. The shadow frame buffer implementation is also very useful in many circumstances, and also needs documentation. We hope to rectify these shortcomings in our documentation in the future. Help would be greatly appreciated.</para> 137*4882a593Smuzhiyun </abstract> 138*4882a593Smuzhiyun </articleinfo> 139*4882a593Smuzhiyun 140*4882a593Smuzhiyun<!-- Original authorship information: 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun.OF 'Porting Layer Definition'- % -'October 27, 2004' 143*4882a593SmuzhiyunDefinition of the Porting Layer 144*4882a593Smuzhiyunfor the X v11 Sample Server 145*4882a593SmuzhiyunSusan Angebranndt 146*4882a593SmuzhiyunRaymond Drewry 147*4882a593SmuzhiyunPhilip Karlton 148*4882a593SmuzhiyunTodd Newman 149*4882a593SmuzhiyunDigital Equipment Corporation 150*4882a593Smuzhiyun 151*4882a593Smuzhiyunminor revisions by 152*4882a593SmuzhiyunBob Scheifler 153*4882a593SmuzhiyunMassachusetts Institute of Technology 154*4882a593Smuzhiyun 155*4882a593SmuzhiyunRevised for Release 4 and Release 5 by 156*4882a593SmuzhiyunKeith Packard 157*4882a593SmuzhiyunMIT X Consortium 158*4882a593Smuzhiyun 159*4882a593SmuzhiyunRevised for Release 6 by 160*4882a593SmuzhiyunDavid P. Wiggins 161*4882a593SmuzhiyunX Consortium 162*4882a593Smuzhiyun 163*4882a593SmuzhiyunMinor Revisions for Release 6.8.2 by 164*4882a593SmuzhiyunJim Gettys 165*4882a593SmuzhiyunX.org Foundation and Hewlett Packard 166*4882a593Smuzhiyun--> 167*4882a593Smuzhiyun 168*4882a593Smuzhiyun<section> 169*4882a593Smuzhiyun <title>The X Window System</title> 170*4882a593Smuzhiyun<para> 171*4882a593SmuzhiyunThe X Window System, or simply "X," is a 172*4882a593Smuzhiyunwindowing system that provides high-performance, high-level, 173*4882a593Smuzhiyundevice-independent graphics. 174*4882a593Smuzhiyun</para> 175*4882a593Smuzhiyun<para> 176*4882a593SmuzhiyunX is a windowing system designed for bitmapped graphic displays. 177*4882a593SmuzhiyunThe display can have a 178*4882a593Smuzhiyunsimple, monochrome display or it can have a color display with up to 32 bits 179*4882a593Smuzhiyunper pixel with a special graphics processor doing the work. (In this 180*4882a593Smuzhiyundocument, monochrome means a black and white display with one bit per pixel. 181*4882a593SmuzhiyunEven though the usual meaning of monochrome is more general, this special 182*4882a593Smuzhiyuncase is so common that we decided to reserve the word for this purpose.) 183*4882a593SmuzhiyunIn practice, monochrome displays are now almost unheard of, with 4 bit 184*4882a593Smuzhiyungray scale displays being the low end. 185*4882a593Smuzhiyun</para> 186*4882a593Smuzhiyun<para> 187*4882a593SmuzhiyunX is designed for a networking environment where 188*4882a593Smuzhiyunusers can run applications on machines other than their own workstations. 189*4882a593SmuzhiyunSometimes, the connection is over an Ethernet network with a protocol such as TCP/IP; 190*4882a593Smuzhiyunbut, any "reliable" byte stream is allowable. 191*4882a593SmuzhiyunA high-bandwidth byte stream is preferable; RS-232 at 192*4882a593Smuzhiyun9600 baud would be slow without compression techniques. 193*4882a593Smuzhiyun</para> 194*4882a593Smuzhiyun<para> 195*4882a593SmuzhiyunX by itself allows great freedom of design. 196*4882a593SmuzhiyunFor instance, it does not include any user interface standard. 197*4882a593SmuzhiyunIts intent is to "provide mechanism, not policy." 198*4882a593SmuzhiyunBy making it general, it can be the foundation for a wide 199*4882a593Smuzhiyunvariety of interactive software. 200*4882a593Smuzhiyun</para> 201*4882a593Smuzhiyun<para> 202*4882a593SmuzhiyunFor a more detailed overview, see the document "The X Window System." 203*4882a593SmuzhiyunFor details on the byte stream protocol, see "X Window System protocol." 204*4882a593Smuzhiyun</para> 205*4882a593Smuzhiyun</section> 206*4882a593Smuzhiyun<section> 207*4882a593Smuzhiyun<title>Overview of the Server</title> 208*4882a593Smuzhiyun<para> 209*4882a593SmuzhiyunThe display server 210*4882a593Smuzhiyunmanages windows and simple graphics requests 211*4882a593Smuzhiyunfor the user on behalf of different client applications. 212*4882a593SmuzhiyunThe client applications can be running on any machine on the network. 213*4882a593SmuzhiyunThe server mainly does three things: 214*4882a593Smuzhiyun<itemizedlist> 215*4882a593Smuzhiyun <listitem><para>Responds to protocol requests from existing clients (mostly graphic and text drawing commands)</para></listitem> 216*4882a593Smuzhiyun <listitem><para>Sends device input (keystrokes and mouse actions) and other events to existing clients</para></listitem> 217*4882a593Smuzhiyun <listitem><para>Maintains client connections</para></listitem> 218*4882a593Smuzhiyun</itemizedlist> 219*4882a593Smuzhiyun</para> 220*4882a593Smuzhiyun<para> 221*4882a593SmuzhiyunThe server code is organized into four major pieces: 222*4882a593Smuzhiyun<itemizedlist> 223*4882a593Smuzhiyun <listitem><para>Device Independent (DIX) layer - code shared among all implementations</para></listitem> 224*4882a593Smuzhiyun <listitem><para>Operating System (OS) layer - code that is different for each operating system but is shared among all graphic devices for this operating system</para></listitem> 225*4882a593Smuzhiyun <listitem><para>Device Dependent (DDX) layer - code that is (potentially) different for each combination of operating system and graphic device</para></listitem> 226*4882a593Smuzhiyun <listitem><para>Extension Interface - a standard way to add features to the X server</para></listitem> 227*4882a593Smuzhiyun</itemizedlist> 228*4882a593Smuzhiyun</para> 229*4882a593Smuzhiyun<para> 230*4882a593SmuzhiyunThe "porting layer" consists of the OS and DDX layers; these are 231*4882a593Smuzhiyunactually parallel and neither one is on top of the other. 232*4882a593SmuzhiyunThe DIX layer is intended to be portable 233*4882a593Smuzhiyunwithout change to target systems and is not 234*4882a593Smuzhiyundetailed here, although several routines 235*4882a593Smuzhiyunin DIX that are called by DDX are 236*4882a593Smuzhiyundocumented. 237*4882a593SmuzhiyunExtensions incorporate new functionality into the server; and require 238*4882a593Smuzhiyunadditional functionality over a simple DDX. 239*4882a593Smuzhiyun</para> 240*4882a593Smuzhiyun<para> 241*4882a593SmuzhiyunThe following sections outline the functions of the layers. 242*4882a593SmuzhiyunSection 3 briefly tells what you need to know about the DIX layer. 243*4882a593SmuzhiyunThe OS layer is explained in Section 4. 244*4882a593SmuzhiyunSection 5 gives the theory of operation and procedural interface for the 245*4882a593SmuzhiyunDDX layer. 246*4882a593SmuzhiyunSection 6 describes the functions which exist for the extension writer. 247*4882a593Smuzhiyun</para> 248*4882a593Smuzhiyun</section> 249*4882a593Smuzhiyun 250*4882a593Smuzhiyun<section> 251*4882a593Smuzhiyun <title>DIX Layer</title> 252*4882a593Smuzhiyun<para> 253*4882a593SmuzhiyunThe DIX layer is the machine and device independent part of X. 254*4882a593SmuzhiyunThe source should be common to all operating systems and devices. 255*4882a593SmuzhiyunThe port process should not include changes to this part, therefore internal interfaces to DIX 256*4882a593Smuzhiyunmodules are not discussed, except for public interfaces to the DDX and the OS layers. 257*4882a593SmuzhiyunThe functions described in this section are available for extension writers to use. 258*4882a593Smuzhiyun</para> 259*4882a593Smuzhiyun<para> 260*4882a593SmuzhiyunIn the process of getting your server to work, if 261*4882a593Smuzhiyunyou think that DIX must be modified for purposes other than bug fixes, 262*4882a593Smuzhiyunyou may be doing something wrong. 263*4882a593SmuzhiyunKeep looking for a more compatible solution. 264*4882a593SmuzhiyunWhen the next release of the X server code is available, 265*4882a593Smuzhiyunyou should be able to just drop in the new DIX code and compile it. 266*4882a593SmuzhiyunIf you change DIX, 267*4882a593Smuzhiyunyou will have to remember what changes you made and will have 268*4882a593Smuzhiyunto change the new sources before you can update to the new version. 269*4882a593Smuzhiyun</para> 270*4882a593Smuzhiyun<para> 271*4882a593SmuzhiyunThe heart of the DIX code is a loop called the dispatch loop. 272*4882a593SmuzhiyunEach time the processor goes around the loop, it sends off accumulated input events 273*4882a593Smuzhiyunfrom the input devices to the clients, and it processes requests from the clients. 274*4882a593SmuzhiyunThis loop is the most organized way for the server to 275*4882a593Smuzhiyunprocess the asynchronous requests that 276*4882a593Smuzhiyunit needs to process. 277*4882a593SmuzhiyunMost of these operations are performed by OS and DDX routines that you must supply. 278*4882a593Smuzhiyun</para> 279*4882a593Smuzhiyun<section> 280*4882a593Smuzhiyun <title>Server Resource System</title> 281*4882a593Smuzhiyun<para> 282*4882a593SmuzhiyunX resources are C structs inside the server. 283*4882a593SmuzhiyunClient applications create and manipulate these objects 284*4882a593Smuzhiyunaccording to the rules of the X byte stream protocol. 285*4882a593SmuzhiyunClient applications refer to resources with resource IDs, 286*4882a593Smuzhiyunwhich are 32-bit integers that are sent over the network. 287*4882a593SmuzhiyunWithin the server, of course, they are just C structs, and we refer to them 288*4882a593Smuzhiyunby pointers. 289*4882a593Smuzhiyun</para> 290*4882a593Smuzhiyun<section> 291*4882a593Smuzhiyun <title>Pre-Defined Resource Types</title> 292*4882a593Smuzhiyun<para> 293*4882a593SmuzhiyunThe DDX layer has several kinds of resources: 294*4882a593Smuzhiyun<itemizedlist> 295*4882a593Smuzhiyun<listitem><para>Window</para></listitem> 296*4882a593Smuzhiyun<listitem><para>Pixmap</para></listitem> 297*4882a593Smuzhiyun<listitem><para>Screen</para></listitem> 298*4882a593Smuzhiyun<listitem><para>Device</para></listitem> 299*4882a593Smuzhiyun<listitem><para>Colormap</para></listitem> 300*4882a593Smuzhiyun<listitem><para>Font</para></listitem> 301*4882a593Smuzhiyun<listitem><para>Cursor</para></listitem> 302*4882a593Smuzhiyun<listitem><para>Graphics Contexts</para></listitem> 303*4882a593Smuzhiyun</itemizedlist> 304*4882a593Smuzhiyun</para> 305*4882a593Smuzhiyun<para> 306*4882a593SmuzhiyunThe type names of the more 307*4882a593Smuzhiyunimportant server 308*4882a593Smuzhiyunstructs usually end in "Rec," such as "DeviceRec;" 309*4882a593Smuzhiyunthe pointer types usually end in "Ptr," such as "DevicePtr." 310*4882a593Smuzhiyun</para> 311*4882a593Smuzhiyun<para> 312*4882a593SmuzhiyunThe structs and 313*4882a593Smuzhiyunimportant defined constants are declared 314*4882a593Smuzhiyunin .h files that have names that suggest the name of the object. 315*4882a593SmuzhiyunFor instance, there are two .h files for windows, 316*4882a593Smuzhiyunwindow.h and windowstr.h. 317*4882a593Smuzhiyunwindow.h defines only what needs to be defined in order to use windows 318*4882a593Smuzhiyunwithout peeking inside of them; 319*4882a593Smuzhiyunwindowstr.h defines the structs with all of their components in great detail 320*4882a593Smuzhiyunfor those who need it. 321*4882a593Smuzhiyun</para> 322*4882a593Smuzhiyun<para> 323*4882a593SmuzhiyunThree kinds of fields are in these structs: 324*4882a593Smuzhiyun<itemizedlist> 325*4882a593Smuzhiyun<listitem><para>Attribute fields - struct fields that contain values like normal structs</para></listitem> 326*4882a593Smuzhiyun<listitem><para>Pointers to procedures, or structures of procedures, that operate on the object</para></listitem> 327*4882a593Smuzhiyun<listitem><para>A single private field or a devPrivates list (see <xref linkend="wrappers_and_privates"/>) 328*4882a593Smuzhiyunused by your DDX code to store private data.</para></listitem> 329*4882a593Smuzhiyun</itemizedlist> 330*4882a593Smuzhiyun</para> 331*4882a593Smuzhiyun<para> 332*4882a593SmuzhiyunDIX calls through 333*4882a593Smuzhiyunthe struct's procedure pointers to do its tasks. 334*4882a593SmuzhiyunThese procedures are set either directly or indirectly by DDX procedures. 335*4882a593SmuzhiyunMost of 336*4882a593Smuzhiyunthe procedures described in the remainder of this 337*4882a593Smuzhiyundocument are accessed through one of these structs. 338*4882a593SmuzhiyunFor example, the procedure to create a pixmap 339*4882a593Smuzhiyunis attached to a ScreenRec and might be called by using the expression 340*4882a593Smuzhiyun</para> 341*4882a593Smuzhiyun<para> 342*4882a593Smuzhiyun<blockquote> 343*4882a593Smuzhiyun<programlisting>(* pScreen->CreatePixmap)(pScreen, width, height, depth).</programlisting> 344*4882a593Smuzhiyun</blockquote> 345*4882a593Smuzhiyun</para> 346*4882a593Smuzhiyun<para> 347*4882a593SmuzhiyunAll procedure pointers must be set to some routine unless noted otherwise; 348*4882a593Smuzhiyuna null pointer will have unfortunate consequences. 349*4882a593Smuzhiyun</para> 350*4882a593Smuzhiyun<para> 351*4882a593SmuzhiyunProcedure routines will be indicated in the documentation by this convention: 352*4882a593Smuzhiyun<blockquote> 353*4882a593Smuzhiyun<programlisting>void pScreen->MyScreenRoutine(arg, arg, ...)</programlisting> 354*4882a593Smuzhiyun</blockquote> 355*4882a593Smuzhiyunas opposed to a free routine, not in a data structure: 356*4882a593Smuzhiyun<blockquote> 357*4882a593Smuzhiyun<programlisting>void MyFreeRoutine(arg, arg, ...)</programlisting> 358*4882a593Smuzhiyun</blockquote> 359*4882a593Smuzhiyun</para> 360*4882a593Smuzhiyun<para> 361*4882a593SmuzhiyunThe attribute fields are mostly set by DIX; DDX should not modify them 362*4882a593Smuzhiyununless noted otherwise. 363*4882a593Smuzhiyun</para> 364*4882a593Smuzhiyun</section> 365*4882a593Smuzhiyun<section> 366*4882a593Smuzhiyun <title>Creating Resources and Resource Types</title> 367*4882a593Smuzhiyun<para> 368*4882a593SmuzhiyunThese functions should also be called from your extensionInitProc to 369*4882a593Smuzhiyunallocate all of the various resource classes and types required for 370*4882a593Smuzhiyunthe extension. Each time the server resets, these types must be reallocated 371*4882a593Smuzhiyunas the old allocations will have been discarded. 372*4882a593SmuzhiyunResource types are integer values starting at 1. Get 373*4882a593Smuzhiyuna resource type by calling 374*4882a593Smuzhiyun<blockquote><programlisting> 375*4882a593Smuzhiyun 376*4882a593Smuzhiyun RESTYPE CreateNewResourceType(deleteFunc, char *name) 377*4882a593Smuzhiyun 378*4882a593Smuzhiyun</programlisting></blockquote> 379*4882a593SmuzhiyundeleteFunc will be called to destroy all resources with this 380*4882a593Smuzhiyuntype. name will be used to identify this type of resource 381*4882a593Smuzhiyunto clients using the X-Resource extension, to security 382*4882a593Smuzhiyunextensions such as SELinux, and to tracing frameworks such as DTrace. 383*4882a593Smuzhiyun[The name argument was added in xorg-server 1.8.] 384*4882a593Smuzhiyun</para> 385*4882a593Smuzhiyun<para> 386*4882a593SmuzhiyunResource classes are masks starting at 1 << 31 which can 387*4882a593Smuzhiyunbe or'ed with any resource type to provide attributes for the 388*4882a593Smuzhiyuntype. To allocate a new class bit, call 389*4882a593Smuzhiyun<blockquote><programlisting> 390*4882a593Smuzhiyun 391*4882a593Smuzhiyun RESTYPE CreateNewResourceClass() 392*4882a593Smuzhiyun 393*4882a593Smuzhiyun</programlisting></blockquote> 394*4882a593Smuzhiyun</para> 395*4882a593Smuzhiyun<para> 396*4882a593SmuzhiyunThere are two ways of looking up resources, by type or 397*4882a593Smuzhiyunby class. Classes are non-exclusive subsets of the space of 398*4882a593Smuzhiyunall resources, so you can lookup the union of multiple classes. 399*4882a593Smuzhiyun(RC_ANY is the union of all classes).</para> 400*4882a593Smuzhiyun<para> 401*4882a593SmuzhiyunNote that the appropriate class bits must be or'ed into the value returned 402*4882a593Smuzhiyunby CreateNewResourceType when calling resource lookup functions.</para> 403*4882a593Smuzhiyun<para> 404*4882a593SmuzhiyunIf you need to create a ``private'' resource ID for internal use, you 405*4882a593Smuzhiyuncan call FakeClientID. 406*4882a593Smuzhiyun<blockquote><programlisting> 407*4882a593Smuzhiyun 408*4882a593Smuzhiyun XID FakeClientID(client) 409*4882a593Smuzhiyun int client; 410*4882a593Smuzhiyun 411*4882a593Smuzhiyun</programlisting></blockquote> 412*4882a593SmuzhiyunThis allocates from ID space reserved for the server.</para> 413*4882a593Smuzhiyun<para> 414*4882a593SmuzhiyunTo associate a resource value with an ID, use AddResource. 415*4882a593Smuzhiyun<blockquote><programlisting> 416*4882a593Smuzhiyun 417*4882a593Smuzhiyun Bool AddResource(id, type, value) 418*4882a593Smuzhiyun XID id; 419*4882a593Smuzhiyun RESTYPE type; 420*4882a593Smuzhiyun pointer value; 421*4882a593Smuzhiyun 422*4882a593Smuzhiyun</programlisting></blockquote> 423*4882a593SmuzhiyunThe type should be the full type of the resource, including any class 424*4882a593Smuzhiyunbits. If AddResource fails to allocate memory to store the resource, 425*4882a593Smuzhiyunit will call the deleteFunc for the type, and then return False.</para> 426*4882a593Smuzhiyun<para> 427*4882a593SmuzhiyunTo free a resource, use one of the following. 428*4882a593Smuzhiyun<blockquote><programlisting> 429*4882a593Smuzhiyun 430*4882a593Smuzhiyun void FreeResource(id, skipDeleteFuncType) 431*4882a593Smuzhiyun XID id; 432*4882a593Smuzhiyun RESTYPE skipDeleteFuncType; 433*4882a593Smuzhiyun 434*4882a593Smuzhiyun void FreeResourceByType(id, type, skipFree) 435*4882a593Smuzhiyun XID id; 436*4882a593Smuzhiyun RESTYPE type; 437*4882a593Smuzhiyun Bool skipFree; 438*4882a593Smuzhiyun 439*4882a593Smuzhiyun</programlisting></blockquote> 440*4882a593SmuzhiyunFreeResource frees all resources matching the given id, regardless of 441*4882a593Smuzhiyuntype; the type's deleteFunc will be called on each matching resource, 442*4882a593Smuzhiyunexcept that skipDeleteFuncType can be set to a single type for which 443*4882a593Smuzhiyunthe deleteFunc should not be called (otherwise pass RT_NONE). 444*4882a593SmuzhiyunFreeResourceByType frees a specific resource matching a given id 445*4882a593Smuzhiyunand type; if skipFree is true, then the deleteFunc is not called. 446*4882a593Smuzhiyun</para> 447*4882a593Smuzhiyun</section> 448*4882a593Smuzhiyun<section> 449*4882a593Smuzhiyun <title>Looking Up Resources</title> 450*4882a593Smuzhiyun<para> 451*4882a593SmuzhiyunTo look up a resource, use one of the following. 452*4882a593Smuzhiyun<blockquote><programlisting> 453*4882a593Smuzhiyun 454*4882a593Smuzhiyun int dixLookupResourceByType( 455*4882a593Smuzhiyun pointer *result, 456*4882a593Smuzhiyun XID id, 457*4882a593Smuzhiyun RESTYPE rtype, 458*4882a593Smuzhiyun ClientPtr client, 459*4882a593Smuzhiyun Mask access_mode); 460*4882a593Smuzhiyun 461*4882a593Smuzhiyun int dixLookupResourceByClass( 462*4882a593Smuzhiyun pointer *result, 463*4882a593Smuzhiyun XID id, 464*4882a593Smuzhiyun RESTYPE rclass, 465*4882a593Smuzhiyun ClientPtr client, 466*4882a593Smuzhiyun Mask access_mode); 467*4882a593Smuzhiyun 468*4882a593Smuzhiyun</programlisting></blockquote> 469*4882a593SmuzhiyundixLookupResourceByType finds a resource with the given id and exact type. 470*4882a593SmuzhiyundixLookupResourceByClass finds a resource with the given id whose type is 471*4882a593Smuzhiyunincluded in any one of the specified classes. 472*4882a593SmuzhiyunThe client and access_mode must be provided to allow security extensions to 473*4882a593Smuzhiyuncheck if the client has the right privileges for the requested access. 474*4882a593SmuzhiyunThe bitmask values defined in the dixaccess.h header are or'ed together 475*4882a593Smuzhiyunto define the requested access_mode. 476*4882a593Smuzhiyun</para> 477*4882a593Smuzhiyun</section> 478*4882a593Smuzhiyun</section> 479*4882a593Smuzhiyun<section> 480*4882a593Smuzhiyun <title>Callback Manager</title> 481*4882a593Smuzhiyun<para> 482*4882a593SmuzhiyunTo satisfy a growing number of requests for the introduction of ad hoc 483*4882a593Smuzhiyunnotification style hooks in the server, a generic callback manager was 484*4882a593Smuzhiyunintroduced in R6. A callback list object can be introduced for each 485*4882a593Smuzhiyunnew hook that is desired, and other modules in the server can register 486*4882a593Smuzhiyuninterest in the new callback list. The following functions support 487*4882a593Smuzhiyunthese operations.</para> 488*4882a593Smuzhiyun<para> 489*4882a593SmuzhiyunBefore getting bogged down in the interface details, an typical usage 490*4882a593Smuzhiyunexample should establish the framework. Let's look at the 491*4882a593SmuzhiyunClientStateCallback in dix/dispatch.c. The purpose of this particular 492*4882a593Smuzhiyuncallback is to notify interested parties when a client's state 493*4882a593Smuzhiyun(initial, running, gone) changes. The callback is "created" in this 494*4882a593Smuzhiyuncase by simply declaring a variable: 495*4882a593Smuzhiyun<blockquote><programlisting> 496*4882a593Smuzhiyun CallbackListPtr ClientStateCallback; 497*4882a593Smuzhiyun</programlisting></blockquote> 498*4882a593Smuzhiyun</para> 499*4882a593Smuzhiyun<para> 500*4882a593SmuzhiyunWhenever the client's state changes, the following code appears, which notifies 501*4882a593Smuzhiyunall interested parties of the change: 502*4882a593Smuzhiyun<blockquote><programlisting> 503*4882a593Smuzhiyun if (ClientStateCallback) CallCallbacks(&ClientStateCallback, (pointer)client); 504*4882a593Smuzhiyun</programlisting></blockquote> 505*4882a593Smuzhiyun</para> 506*4882a593Smuzhiyun<para> 507*4882a593SmuzhiyunInterested parties subscribe to the ClientStateCallback list by saying: 508*4882a593Smuzhiyun<blockquote><programlisting> 509*4882a593Smuzhiyun AddCallback(&ClientStateCallback, func, data); 510*4882a593Smuzhiyun</programlisting></blockquote> 511*4882a593Smuzhiyun</para> 512*4882a593Smuzhiyun<para> 513*4882a593SmuzhiyunWhen CallCallbacks is invoked on the list, func will be called thusly: 514*4882a593Smuzhiyun<blockquote><programlisting> 515*4882a593Smuzhiyun (*func)(&ClientStateCallback, data, client) 516*4882a593Smuzhiyun</programlisting></blockquote> 517*4882a593Smuzhiyun</para> 518*4882a593Smuzhiyun<para> 519*4882a593SmuzhiyunNow for the details. 520*4882a593Smuzhiyun<blockquote><programlisting> 521*4882a593Smuzhiyun 522*4882a593Smuzhiyun Bool AddCallback(pcbl, callback, subscriber_data) 523*4882a593Smuzhiyun CallbackListPtr *pcbl; 524*4882a593Smuzhiyun CallbackProcPtr callback; 525*4882a593Smuzhiyun pointer subscriber_data; 526*4882a593Smuzhiyun 527*4882a593Smuzhiyun</programlisting></blockquote> 528*4882a593SmuzhiyunAdds the (callback, subscriber_data) pair to the given callback list. Creates the callback 529*4882a593Smuzhiyunlist if it doesn't exist. Returns TRUE if successful.</para> 530*4882a593Smuzhiyun<para> 531*4882a593Smuzhiyun<blockquote><programlisting> 532*4882a593Smuzhiyun 533*4882a593Smuzhiyun Bool DeleteCallback(pcbl, callback, subscriber_data) 534*4882a593Smuzhiyun CallbackListPtr *pcbl; 535*4882a593Smuzhiyun CallbackProcPtr callback; 536*4882a593Smuzhiyun pointer subscriber_data; 537*4882a593Smuzhiyun 538*4882a593Smuzhiyun</programlisting></blockquote> 539*4882a593SmuzhiyunRemoves the (callback, data) pair to the given callback list if present. 540*4882a593SmuzhiyunReturns TRUE if (callback, data) was found.</para> 541*4882a593Smuzhiyun<para> 542*4882a593Smuzhiyun<blockquote><programlisting> 543*4882a593Smuzhiyun 544*4882a593Smuzhiyun void CallCallbacks(pcbl, call_data) 545*4882a593Smuzhiyun CallbackListPtr *pcbl; 546*4882a593Smuzhiyun pointer call_data; 547*4882a593Smuzhiyun 548*4882a593Smuzhiyun</programlisting></blockquote> 549*4882a593SmuzhiyunFor each callback currently registered on the given callback list, call 550*4882a593Smuzhiyunit as follows: 551*4882a593Smuzhiyun<blockquote><programlisting> 552*4882a593Smuzhiyun 553*4882a593Smuzhiyun (*callback)(pcbl, subscriber_data, call_data); 554*4882a593Smuzhiyun</programlisting></blockquote> 555*4882a593Smuzhiyun</para> 556*4882a593Smuzhiyun<para> 557*4882a593Smuzhiyun<blockquote><programlisting> 558*4882a593Smuzhiyun void DeleteCallbackList(pcbl) 559*4882a593Smuzhiyun CallbackListPtr *pcbl; 560*4882a593Smuzhiyun 561*4882a593Smuzhiyun</programlisting></blockquote> 562*4882a593SmuzhiyunDestroys the given callback list.</para> 563*4882a593Smuzhiyun</section> 564*4882a593Smuzhiyun<section> 565*4882a593Smuzhiyun <title>Extension Interfaces</title> 566*4882a593Smuzhiyun<para> 567*4882a593SmuzhiyunThis function should be called from your extensionInitProc which 568*4882a593Smuzhiyunshould be called by InitExtensions. 569*4882a593Smuzhiyun<blockquote><programlisting> 570*4882a593Smuzhiyun 571*4882a593Smuzhiyun ExtensionEntry *AddExtension(name, NumEvents,NumErrors, 572*4882a593Smuzhiyun MainProc, SwappedMainProc, CloseDownProc, MinorOpcodeProc) 573*4882a593Smuzhiyun 574*4882a593Smuzhiyun const char *name; /*Null terminate string; case matters*/ 575*4882a593Smuzhiyun int NumEvents; 576*4882a593Smuzhiyun int NumErrors; 577*4882a593Smuzhiyun int (* MainProc)(ClientPtr);/*Called if client matches server order*/ 578*4882a593Smuzhiyun int (* SwappedMainProc)(ClientPtr);/*Called if client differs from server*/ 579*4882a593Smuzhiyun void (* CloseDownProc)(ExtensionEntry *); 580*4882a593Smuzhiyun unsigned short (*MinorOpcodeProc)(ClientPtr); 581*4882a593Smuzhiyun 582*4882a593Smuzhiyun</programlisting></blockquote> 583*4882a593Smuzhiyunname is the name used by clients to refer to the extension. NumEvents is the 584*4882a593Smuzhiyunnumber of event types used by the extension, NumErrors is the number of 585*4882a593Smuzhiyunerror codes needed by the extension. MainProc is called whenever a client 586*4882a593Smuzhiyunaccesses the major opcode assigned to the extension. SwappedMainProc is 587*4882a593Smuzhiyunidentical, except the client using the extension has reversed byte-sex. 588*4882a593SmuzhiyunCloseDownProc is called at server reset time to deallocate any private 589*4882a593Smuzhiyunstorage used by the extension. MinorOpcodeProc is used by DIX to place the 590*4882a593Smuzhiyunappropriate value into errors. The DIX routine StandardMinorOpcode can be 591*4882a593Smuzhiyunused here which takes the minor opcode from the normal place in the request 592*4882a593Smuzhiyun(i.e. just after the major opcode).</para> 593*4882a593Smuzhiyun</section> 594*4882a593Smuzhiyun<section> 595*4882a593Smuzhiyun <title>Macros and Other Helpers</title> 596*4882a593Smuzhiyun<para> 597*4882a593SmuzhiyunThere are a number of macros in Xserver/include/dix.h which 598*4882a593Smuzhiyunare useful to the extension writer. Ones of particular interest 599*4882a593Smuzhiyunare: REQUEST, REQUEST_SIZE_MATCH, REQUEST_AT_LEAST_SIZE, 600*4882a593SmuzhiyunREQUEST_FIXED_SIZE, LEGAL_NEW_RESOURCE, and 601*4882a593SmuzhiyunVALIDATE_DRAWABLE_AND_GC. Useful byte swapping macros can be found 602*4882a593Smuzhiyunin Xserver/include/dix.h: WriteReplyToClient and WriteSwappedDataToClient; and 603*4882a593Smuzhiyunin Xserver/include/misc.h: bswap_64, bswap_32, bswap_16, LengthRestB, LengthRestS, 604*4882a593SmuzhiyunLengthRestL, SwapRestS, SwapRestL, swapl, swaps, cpswapl, and cpswaps.</para> 605*4882a593Smuzhiyun</section> 606*4882a593Smuzhiyun</section> 607*4882a593Smuzhiyun 608*4882a593Smuzhiyun<section> 609*4882a593Smuzhiyun <title>OS Layer</title> 610*4882a593Smuzhiyun<para> 611*4882a593SmuzhiyunThis part of the source consists of a few routines that you have to rewrite 612*4882a593Smuzhiyunfor each operating system. 613*4882a593SmuzhiyunThese OS functions maintain the client connections and schedule work 614*4882a593Smuzhiyunto be done for clients. 615*4882a593SmuzhiyunThey also provide an interface to font files, 616*4882a593Smuzhiyunfont name to file name translation, and 617*4882a593Smuzhiyunlow level memory management. 618*4882a593Smuzhiyun<blockquote> 619*4882a593Smuzhiyun<programlisting>void OsInit()</programlisting> 620*4882a593Smuzhiyun</blockquote> 621*4882a593SmuzhiyunOsInit initializes your OS code, performing whatever tasks need to be done. 622*4882a593SmuzhiyunFrequently there is not much to be done. 623*4882a593SmuzhiyunThe sample server implementation is in Xserver/os/osinit.c. 624*4882a593Smuzhiyun</para> 625*4882a593Smuzhiyun<section> 626*4882a593Smuzhiyun <title>Scheduling and Request Delivery</title> 627*4882a593Smuzhiyun<para> 628*4882a593SmuzhiyunThe main dispatch loop in DIX creates the illusion of multitasking between 629*4882a593Smuzhiyundifferent windows, while the server is itself but a single process. 630*4882a593SmuzhiyunThe dispatch loop breaks up the work for each client into small digestible parts. 631*4882a593SmuzhiyunSome parts are requests from a client, such as individual graphic commands. 632*4882a593SmuzhiyunSome parts are events delivered to the client, such as keystrokes from the user. 633*4882a593SmuzhiyunThe processing of events and requests for different 634*4882a593Smuzhiyunclients can be interleaved with one another so true multitasking 635*4882a593Smuzhiyunis not needed in the server. 636*4882a593Smuzhiyun</para> 637*4882a593Smuzhiyun<para> 638*4882a593SmuzhiyunYou must supply some of the pieces for proper scheduling between clients. 639*4882a593Smuzhiyun<blockquote> 640*4882a593Smuzhiyun<programlisting> 641*4882a593Smuzhiyun int WaitForSomething(pClientReady) 642*4882a593Smuzhiyun int *pClientReady; 643*4882a593Smuzhiyun</programlisting> 644*4882a593Smuzhiyun</blockquote> 645*4882a593Smuzhiyun</para> 646*4882a593Smuzhiyun<para> 647*4882a593SmuzhiyunWaitForSomething is the scheduler procedure you must write that will 648*4882a593Smuzhiyunsuspend your server process until something needs to be done. 649*4882a593SmuzhiyunThis call should 650*4882a593Smuzhiyunmake the server suspend until one or more of the following occurs: 651*4882a593Smuzhiyun<itemizedlist> 652*4882a593Smuzhiyun<listitem><para>There is an input event from the user or hardware (see SetInputCheck())</para></listitem> 653*4882a593Smuzhiyun<listitem><para>There are requests waiting from known clients, in which case you should return a count of clients stored in pClientReady</para></listitem> 654*4882a593Smuzhiyun<listitem><para>A new client tries to connect, in which case you should create the client and then continue waiting</para></listitem> 655*4882a593Smuzhiyun</itemizedlist> 656*4882a593Smuzhiyun</para> 657*4882a593Smuzhiyun<para> 658*4882a593SmuzhiyunBefore WaitForSomething() computes the masks to pass to select, poll or 659*4882a593Smuzhiyunsimilar operating system interface, it needs to 660*4882a593Smuzhiyunsee if there is anything to do on the work queue; if so, it must call a DIX 661*4882a593Smuzhiyunroutine called ProcessWorkQueue. 662*4882a593Smuzhiyun<blockquote> 663*4882a593Smuzhiyun<programlisting> 664*4882a593Smuzhiyun extern WorkQueuePtr workQueue; 665*4882a593Smuzhiyun 666*4882a593Smuzhiyun if (workQueue) 667*4882a593Smuzhiyun ProcessWorkQueue (); 668*4882a593Smuzhiyun</programlisting> 669*4882a593Smuzhiyun</blockquote> 670*4882a593Smuzhiyun</para> 671*4882a593Smuzhiyun<para> 672*4882a593SmuzhiyunIf WaitForSomething() decides it is about to do something that might block 673*4882a593Smuzhiyun(in the sample server, before it calls select() or poll) it must call a DIX 674*4882a593Smuzhiyunroutine called BlockHandler(). 675*4882a593Smuzhiyun<blockquote> 676*4882a593Smuzhiyun<programlisting> 677*4882a593Smuzhiyun void BlockHandler(void *pTimeout) 678*4882a593Smuzhiyun</programlisting> 679*4882a593Smuzhiyun</blockquote> 680*4882a593SmuzhiyunThe types of the arguments are for agreement between the OS and DDX 681*4882a593Smuzhiyunimplementations, but the pTimeout is a pointer to the information 682*4882a593Smuzhiyundetermining how long the block is allowed to last. 683*4882a593Smuzhiyun</para> 684*4882a593Smuzhiyun<para> 685*4882a593SmuzhiyunIn the sample server, pTimeout is a pointer. 686*4882a593Smuzhiyun</para> 687*4882a593Smuzhiyun<para> 688*4882a593SmuzhiyunThe DIX BlockHandler() iterates through the Screens, for each one calling 689*4882a593Smuzhiyunits BlockHandler. A BlockHandler is declared thus: 690*4882a593Smuzhiyun<blockquote> 691*4882a593Smuzhiyun<programlisting> 692*4882a593Smuzhiyun void xxxBlockHandler(ScreenPtr pScreen, void *pTimeout) 693*4882a593Smuzhiyun</programlisting> 694*4882a593Smuzhiyun</blockquote> 695*4882a593SmuzhiyunThe arguments are a pointer to the Screen, and the arguments to the 696*4882a593SmuzhiyunDIX BlockHandler(). 697*4882a593Smuzhiyun</para> 698*4882a593Smuzhiyun<para> 699*4882a593SmuzhiyunImmediately after WaitForSomething returns from the 700*4882a593Smuzhiyunblock, even if it didn't actually block, it must call the DIX routine 701*4882a593SmuzhiyunWakeupHandler(). 702*4882a593Smuzhiyun<blockquote> 703*4882a593Smuzhiyun<programlisting> 704*4882a593Smuzhiyun void WakeupHandler(int result) 705*4882a593Smuzhiyun</programlisting> 706*4882a593Smuzhiyun</blockquote> 707*4882a593SmuzhiyunOnce again, the types are not specified by DIX. The result is the 708*4882a593Smuzhiyunsuccess indicator for the thing that (may have) blocked. 709*4882a593SmuzhiyunIn the sample server, result is the result from select() (or equivalent 710*4882a593Smuzhiyunoperating system function). 711*4882a593Smuzhiyun</para> 712*4882a593Smuzhiyun<para> 713*4882a593SmuzhiyunThe DIX WakeupHandler() calls each Screen's 714*4882a593SmuzhiyunWakeupHandler. A WakeupHandler is declared thus: 715*4882a593Smuzhiyun<blockquote> 716*4882a593Smuzhiyun<programlisting> 717*4882a593Smuzhiyun void xxxWakeupHandler(ScreenPtr pScreen, int result) 718*4882a593Smuzhiyun</programlisting> 719*4882a593Smuzhiyun</blockquote> 720*4882a593SmuzhiyunThe arguments are the Screen, of the Screen, and the arguments to 721*4882a593Smuzhiyunthe DIX WakeupHandler(). 722*4882a593Smuzhiyun</para> 723*4882a593Smuzhiyun<para> 724*4882a593SmuzhiyunIn addition to the per-screen BlockHandlers, any module may register 725*4882a593Smuzhiyunblock and wakeup handlers (only together) using: 726*4882a593Smuzhiyun<blockquote> 727*4882a593Smuzhiyun<programlisting> 728*4882a593Smuzhiyun Bool RegisterBlockAndWakeupHandlers (blockHandler, wakeupHandler, blockData) 729*4882a593Smuzhiyun ServerBlockHandlerProcPtr blockHandler; 730*4882a593Smuzhiyun ServerWakeupHandlerProcPtr wakeupHandler; 731*4882a593Smuzhiyun pointer blockData; 732*4882a593Smuzhiyun</programlisting> 733*4882a593Smuzhiyun</blockquote> 734*4882a593SmuzhiyunA FALSE return code indicates that the registration failed for lack of 735*4882a593Smuzhiyunmemory. To remove a registered Block handler at other than server reset time 736*4882a593Smuzhiyun(when they are all removed automatically), use: 737*4882a593Smuzhiyun<blockquote> 738*4882a593Smuzhiyun<programlisting> 739*4882a593Smuzhiyun RemoveBlockAndWakeupHandlers (blockHandler, wakeupHandler, blockData) 740*4882a593Smuzhiyun ServerBlockHandlerProcPtr blockHandler; 741*4882a593Smuzhiyun ServerWakeupHandlerProcPtr wakeupHandler; 742*4882a593Smuzhiyun pointer blockData; 743*4882a593Smuzhiyun</programlisting> 744*4882a593Smuzhiyun</blockquote> 745*4882a593SmuzhiyunAll three arguments must match the values passed to 746*4882a593SmuzhiyunRegisterBlockAndWakeupHandlers. 747*4882a593Smuzhiyun</para> 748*4882a593Smuzhiyun<para> 749*4882a593SmuzhiyunThese registered block handlers are called before the per-screen handlers: 750*4882a593Smuzhiyun<blockquote> 751*4882a593Smuzhiyun<programlisting> 752*4882a593Smuzhiyun void (*ServerBlockHandler) (void *blockData, void *pTimeout) 753*4882a593Smuzhiyun</programlisting> 754*4882a593Smuzhiyun</blockquote> 755*4882a593Smuzhiyun</para> 756*4882a593Smuzhiyun<para> 757*4882a593SmuzhiyunSometimes block handlers need to adjust the time referenced by pTimeout, 758*4882a593Smuzhiyunwhich on UNIX family systems is generally represented by a struct timeval 759*4882a593Smuzhiyunconsisting of seconds and microseconds in 32 bit values. 760*4882a593SmuzhiyunAs a convenience to reduce error prone struct timeval computations which 761*4882a593Smuzhiyunrequire modulus arithmetic and correct overflow behavior in the face of 762*4882a593Smuzhiyunmillisecond wrapping through 32 bits, 763*4882a593Smuzhiyun<blockquote><programlisting> 764*4882a593Smuzhiyun 765*4882a593Smuzhiyun void AdjustWaitForDelay(void *pTimeout, unsigned long newdelay) 766*4882a593Smuzhiyun 767*4882a593Smuzhiyun</programlisting></blockquote> 768*4882a593Smuzhiyunhas been provided. 769*4882a593Smuzhiyun</para> 770*4882a593Smuzhiyun<para> 771*4882a593SmuzhiyunAny wakeup handlers registered with RegisterBlockAndWakeupHandlers will 772*4882a593Smuzhiyunbe called after the Screen handlers: 773*4882a593Smuzhiyun<blockquote><programlisting> 774*4882a593Smuzhiyun 775*4882a593Smuzhiyun void (*ServerWakeupHandler) (void *blockData, int result) 776*4882a593Smuzhiyun</programlisting></blockquote> 777*4882a593Smuzhiyun</para> 778*4882a593Smuzhiyun<para> 779*4882a593SmuzhiyunThe WaitForSomething on the sample server also has a built 780*4882a593Smuzhiyunin screen saver that darkens the screen if no input happens for a period of time. 781*4882a593SmuzhiyunThe sample server implementation is in Xserver/os/WaitFor.c. 782*4882a593Smuzhiyun</para> 783*4882a593Smuzhiyun<para> 784*4882a593SmuzhiyunNote that WaitForSomething() may be called when you already have several 785*4882a593Smuzhiyunoutstanding things (events, requests, or new clients) queued up. 786*4882a593SmuzhiyunFor instance, your server may have just done a large graphics request, 787*4882a593Smuzhiyunand it may have been a long time since WaitForSomething() was last called. 788*4882a593SmuzhiyunIf many clients have lots of requests queued up, DIX will only service 789*4882a593Smuzhiyunsome of them for a given client 790*4882a593Smuzhiyunbefore going on to the next client (see isItTimeToYield, below). 791*4882a593SmuzhiyunTherefore, WaitForSomething() will have to report that these same clients 792*4882a593Smuzhiyunstill have requests queued up the next time around. 793*4882a593Smuzhiyun</para> 794*4882a593Smuzhiyun<para> 795*4882a593SmuzhiyunAn implementation should return information on as 796*4882a593Smuzhiyunmany outstanding things as it can. 797*4882a593SmuzhiyunFor instance, if your implementation always checks for client data first and does not 798*4882a593Smuzhiyunreport any input events until there is no client data left, 799*4882a593Smuzhiyunyour mouse and keyboard might get locked out by an application that constantly 800*4882a593Smuzhiyunbarrages the server with graphics drawing requests. 801*4882a593SmuzhiyunTherefore, as a general rule, input devices should always have priority over graphics 802*4882a593Smuzhiyundevices. 803*4882a593Smuzhiyun</para> 804*4882a593Smuzhiyun<para> 805*4882a593SmuzhiyunA list of indexes (client->index) for clients with data ready to be read or 806*4882a593Smuzhiyunprocessed should be returned in pClientReady, and the count of indexes 807*4882a593Smuzhiyunreturned as the result value of the call. 808*4882a593SmuzhiyunThese are not clients that have full requests ready, but any clients who have 809*4882a593Smuzhiyunany data ready to be read or processed. 810*4882a593SmuzhiyunThe DIX dispatcher 811*4882a593Smuzhiyunwill process requests from each client in turn by calling 812*4882a593SmuzhiyunReadRequestFromClient(), below. 813*4882a593Smuzhiyun</para> 814*4882a593Smuzhiyun<para> 815*4882a593SmuzhiyunWaitForSomething() must create new clients as they are requested (by 816*4882a593Smuzhiyunwhatever mechanism at the transport level). A new client is created 817*4882a593Smuzhiyunby calling the DIX routine: 818*4882a593Smuzhiyun<blockquote><programlisting> 819*4882a593Smuzhiyun 820*4882a593Smuzhiyun ClientPtr NextAvailableClient(ospriv) 821*4882a593Smuzhiyun pointer ospriv; 822*4882a593Smuzhiyun</programlisting></blockquote> 823*4882a593SmuzhiyunThis routine returns NULL if a new client cannot be allocated (e.g. maximum 824*4882a593Smuzhiyunnumber of clients reached). The ospriv argument will be stored into the OS 825*4882a593Smuzhiyunprivate field (pClient->osPrivate), to store OS private information about the 826*4882a593Smuzhiyunclient. In the sample server, the osPrivate field contains the 827*4882a593Smuzhiyunnumber of the socket for this client. See also "New Client Connections." 828*4882a593SmuzhiyunNextAvailableClient() will call InsertFakeRequest(), so you must be 829*4882a593Smuzhiyunprepared for this. 830*4882a593Smuzhiyun</para> 831*4882a593Smuzhiyun<para> 832*4882a593SmuzhiyunIf there are outstanding input events, 833*4882a593Smuzhiyunyou should make sure that the two SetInputCheck() locations are unequal. 834*4882a593SmuzhiyunThe DIX dispatcher will call your implementation of ProcessInputEvents() 835*4882a593Smuzhiyununtil the SetInputCheck() locations are equal. 836*4882a593Smuzhiyun</para> 837*4882a593Smuzhiyun<para> 838*4882a593SmuzhiyunThe sample server contains an implementation of WaitForSomething(). 839*4882a593SmuzhiyunThe 840*4882a593Smuzhiyunfollowing two routines indicate to WaitForSomething() what devices should 841*4882a593Smuzhiyunbe waited for. fd is an OS dependent type; in the sample server 842*4882a593Smuzhiyunit is an open file descriptor. 843*4882a593Smuzhiyun<blockquote><programlisting> 844*4882a593Smuzhiyun 845*4882a593Smuzhiyun int AddEnabledDevice(fd) 846*4882a593Smuzhiyun int fd; 847*4882a593Smuzhiyun 848*4882a593Smuzhiyun int RemoveEnabledDevice(fd) 849*4882a593Smuzhiyun int fd; 850*4882a593Smuzhiyun</programlisting></blockquote> 851*4882a593SmuzhiyunThese two routines are 852*4882a593Smuzhiyunusually called by DDX from the initialize cases of the 853*4882a593SmuzhiyunInput Procedures that are stored in the DeviceRec (the 854*4882a593Smuzhiyunroutine passed to AddInputDevice()). 855*4882a593SmuzhiyunThe sample server implementation of AddEnabledDevice 856*4882a593Smuzhiyunand RemoveEnabledDevice are in Xserver/os/connection.c. 857*4882a593Smuzhiyun</para> 858*4882a593Smuzhiyun<section> 859*4882a593Smuzhiyun <title>Timer Facilities</title> 860*4882a593Smuzhiyun<para> 861*4882a593SmuzhiyunSimilarly, the X server or an extension may need to wait for some timeout. 862*4882a593SmuzhiyunEarly X releases implemented this functionality using block and wakeup handlers, 863*4882a593Smuzhiyunbut this has been rewritten to use a general timer facilty, and the 864*4882a593Smuzhiyuninternal screen saver facilities reimplemented to use Timers. 865*4882a593SmuzhiyunThese functions are TimerInit, TimerForce, TimerSet, TimerCheck, TimerCancel, 866*4882a593Smuzhiyunand TimerFree, as defined in Xserver/include/os.h. A callback function will be called 867*4882a593Smuzhiyunwhen the timer fires, along with the current time, and a user provided argument. 868*4882a593Smuzhiyun<blockquote><programlisting> 869*4882a593Smuzhiyun typedef struct _OsTimerRec *OsTimerPtr; 870*4882a593Smuzhiyun 871*4882a593Smuzhiyun typedef CARD32 (*OsTimerCallback)( 872*4882a593Smuzhiyun OsTimerPtr /* timer */, 873*4882a593Smuzhiyun CARD32 /* time */, 874*4882a593Smuzhiyun pointer /* arg */); 875*4882a593Smuzhiyun 876*4882a593Smuzhiyun OsTimerPtr TimerSet( OsTimerPtr /* timer */, 877*4882a593Smuzhiyun int /* flags */, 878*4882a593Smuzhiyun CARD32 /* millis */, 879*4882a593Smuzhiyun OsTimerCallback /* func */, 880*4882a593Smuzhiyun pointer /* arg */); 881*4882a593Smuzhiyun 882*4882a593Smuzhiyun</programlisting></blockquote> 883*4882a593Smuzhiyun</para> 884*4882a593Smuzhiyun<para> 885*4882a593SmuzhiyunTimerSet returns a pointer to a timer structure and sets a timer to the specified time 886*4882a593Smuzhiyunwith the specified argument. The flags can be TimerAbsolute and TimerForceOld. 887*4882a593SmuzhiyunThe TimerSetOld flag controls whether if the timer is reset and the timer is pending, the 888*4882a593Smuzhiyunwhether the callback function will get called. 889*4882a593SmuzhiyunThe TimerAbsolute flag sets the callback time to an absolute time in the future rather 890*4882a593Smuzhiyunthan a time relative to when TimerSet is called. 891*4882a593SmuzhiyunTimerFree should be called to free the memory allocated 892*4882a593Smuzhiyunfor the timer entry. 893*4882a593Smuzhiyun<blockquote><programlisting> 894*4882a593Smuzhiyun void TimerInit(void) 895*4882a593Smuzhiyun 896*4882a593Smuzhiyun Bool TimerForce(OsTimerPtr /* pTimer */) 897*4882a593Smuzhiyun 898*4882a593Smuzhiyun void TimerCheck(void); 899*4882a593Smuzhiyun 900*4882a593Smuzhiyun void TimerCancel(OsTimerPtr /* pTimer */) 901*4882a593Smuzhiyun 902*4882a593Smuzhiyun void TimerFree(OsTimerPtr /* pTimer */) 903*4882a593Smuzhiyun</programlisting></blockquote> 904*4882a593Smuzhiyun</para> 905*4882a593Smuzhiyun<para> 906*4882a593SmuzhiyunTimerInit frees any existing timer entries. TimerForce forces a call to the timer's 907*4882a593Smuzhiyuncallback function and returns true if the timer entry existed, else it returns false and 908*4882a593Smuzhiyundoes not call the callback function. TimerCancel will cancel the specified timer. 909*4882a593SmuzhiyunTimerFree calls TimerCancel and frees the specified timer. 910*4882a593SmuzhiyunCalling TimerCheck will force the server to see if any timer callbacks should be called. 911*4882a593Smuzhiyun</para> 912*4882a593Smuzhiyun</section> 913*4882a593Smuzhiyun</section> 914*4882a593Smuzhiyun<section> 915*4882a593Smuzhiyun <title>New Client Connections</title> 916*4882a593Smuzhiyun<para> 917*4882a593SmuzhiyunThe process whereby a new client-server connection starts up is 918*4882a593Smuzhiyunvery dependent upon what your byte stream mechanism. 919*4882a593SmuzhiyunThis section describes byte stream initiation using examples from the TCP/IP 920*4882a593Smuzhiyunimplementation on the sample server. 921*4882a593Smuzhiyun</para> 922*4882a593Smuzhiyun<para> 923*4882a593SmuzhiyunThe first thing that happens is a client initiates a connection with the server. 924*4882a593SmuzhiyunHow a client knows to do this depends upon your network facilities and the 925*4882a593SmuzhiyunXlib implementation. 926*4882a593SmuzhiyunIn a typical scenario, a user named Fred 927*4882a593Smuzhiyunon his X workstation is logged onto a Cray 928*4882a593Smuzhiyunsupercomputer running a command shell in an X window. Fred can type shell 929*4882a593Smuzhiyuncommands and have the Cray respond as though the X server were a dumb terminal. 930*4882a593SmuzhiyunFred types in a command to run an X client application that was linked with Xlib. 931*4882a593SmuzhiyunXlib looks at the shell environment variable DISPLAY, which has the 932*4882a593Smuzhiyunvalue "fredsbittube:0.0." 933*4882a593SmuzhiyunThe host name of Fred's workstation is "fredsbittube," and the 0s are 934*4882a593Smuzhiyunfor multiple screens and multiple X server processes. 935*4882a593Smuzhiyun(Precisely what 936*4882a593Smuzhiyunhappens on your system depends upon how X and Xlib are implemented.) 937*4882a593Smuzhiyun</para> 938*4882a593Smuzhiyun<para> 939*4882a593SmuzhiyunThe client application calls a TCP routine on the 940*4882a593SmuzhiyunCray to open a TCP connection for X 941*4882a593Smuzhiyunto communicate with the network node "fredsbittube." 942*4882a593SmuzhiyunThe TCP software on the Cray does this by looking up the TCP 943*4882a593Smuzhiyunaddress of "fredsbittube" and sending an open request to TCP port 6000 944*4882a593Smuzhiyunon fredsbittube. 945*4882a593Smuzhiyun</para> 946*4882a593Smuzhiyun<para> 947*4882a593SmuzhiyunAll X servers on TCP listen for new clients on port 6000 by default; 948*4882a593Smuzhiyunthis is known as a "well-known port" in IP terminology. 949*4882a593Smuzhiyun</para> 950*4882a593Smuzhiyun<para> 951*4882a593SmuzhiyunThe server receives this request from its port 6000 952*4882a593Smuzhiyunand checks where it came from to see if it is on the server's list 953*4882a593Smuzhiyunof "trustworthy" hosts to talk to. 954*4882a593SmuzhiyunThen, it opens another port for communications with the client. 955*4882a593SmuzhiyunThis is the byte stream that all X communications will go over. 956*4882a593Smuzhiyun</para> 957*4882a593Smuzhiyun<para> 958*4882a593SmuzhiyunActually, it is a bit more complicated than that. 959*4882a593SmuzhiyunEach X server process running on the host machine is called a "display." 960*4882a593SmuzhiyunEach display can have more than one screen that it manages. 961*4882a593Smuzhiyun"corporatehydra:3.2" represents screen 2 on display 3 on 962*4882a593Smuzhiyunthe multi-screened network node corporatehydra. 963*4882a593SmuzhiyunThe open request would be sent on well-known port number 6003. 964*4882a593Smuzhiyun</para> 965*4882a593Smuzhiyun<para> 966*4882a593SmuzhiyunOnce the byte stream is set up, what goes on does not depend very much 967*4882a593Smuzhiyunupon whether or not it is TCP. 968*4882a593SmuzhiyunThe client sends an xConnClientPrefix struct (see Xproto.h) that has the 969*4882a593Smuzhiyunversion numbers for the version of Xlib it is running, some byte-ordering information, 970*4882a593Smuzhiyunand two character strings used for authorization. 971*4882a593SmuzhiyunIf the server does not like the authorization strings 972*4882a593Smuzhiyunor the version numbers do not match within the rules, 973*4882a593Smuzhiyunor if anything else is wrong, it sends a failure 974*4882a593Smuzhiyunresponse with a reason string. 975*4882a593Smuzhiyun</para> 976*4882a593Smuzhiyun<para> 977*4882a593SmuzhiyunIf the information never comes, or comes much too slowly, the connection 978*4882a593Smuzhiyunshould be broken off. You must implement the connection timeout. The 979*4882a593Smuzhiyunsample server implements this by keeping a timestamp for each still-connecting 980*4882a593Smuzhiyunclient and, each time just before it attempts to accept new connections, it 981*4882a593Smuzhiyuncloses any connection that are too old. 982*4882a593SmuzhiyunThe connection timeout can be set from the command line. 983*4882a593Smuzhiyun</para> 984*4882a593Smuzhiyun<para> 985*4882a593SmuzhiyunYou must implement whatever authorization schemes you want to support. 986*4882a593SmuzhiyunThe sample server on the distribution tape supports a simple authorization 987*4882a593Smuzhiyunscheme. The only interface seen by DIX is: 988*4882a593Smuzhiyun<blockquote><programlisting> 989*4882a593Smuzhiyun 990*4882a593Smuzhiyun char * 991*4882a593Smuzhiyun ClientAuthorized(client, proto_n, auth_proto, string_n, auth_string) 992*4882a593Smuzhiyun ClientPtr client; 993*4882a593Smuzhiyun unsigned int proto_n; 994*4882a593Smuzhiyun char *auth_proto; 995*4882a593Smuzhiyun unsigned int string_n; 996*4882a593Smuzhiyun char *auth_string; 997*4882a593Smuzhiyun</programlisting></blockquote> 998*4882a593SmuzhiyunDIX will only call this once per client, once it has read the full initial 999*4882a593Smuzhiyunconnection data from the client. If the connection should be 1000*4882a593Smuzhiyunaccepted ClientAuthorized() should return NULL, and otherwise should 1001*4882a593Smuzhiyunreturn an error message string. 1002*4882a593Smuzhiyun</para> 1003*4882a593Smuzhiyun<para> 1004*4882a593SmuzhiyunAccepting new connections happens internally to WaitForSomething(). 1005*4882a593SmuzhiyunWaitForSomething() must call the DIX routine NextAvailableClient() 1006*4882a593Smuzhiyunto create a client object. 1007*4882a593SmuzhiyunProcessing of the initial connection data will be handled by DIX. 1008*4882a593SmuzhiyunYour OS layer must be able to map from a client 1009*4882a593Smuzhiyunto whatever information your OS code needs to communicate 1010*4882a593Smuzhiyunon the given byte stream to the client. 1011*4882a593SmuzhiyunDIX uses this ClientPtr to refer to 1012*4882a593Smuzhiyunthe client from now on. The sample server uses the osPrivate field in 1013*4882a593Smuzhiyunthe ClientPtr to store the file descriptor for the socket, the 1014*4882a593Smuzhiyuninput and output buffers, and authorization information. 1015*4882a593Smuzhiyun</para> 1016*4882a593Smuzhiyun<para> 1017*4882a593SmuzhiyunTo initialize the methods you choose to allow clients to connect to 1018*4882a593Smuzhiyunyour server, main() calls the routine 1019*4882a593Smuzhiyun<blockquote><programlisting> 1020*4882a593Smuzhiyun 1021*4882a593Smuzhiyun void CreateWellKnownSockets() 1022*4882a593Smuzhiyun</programlisting></blockquote> 1023*4882a593SmuzhiyunThis routine is called only once, and not called when the server 1024*4882a593Smuzhiyunis reset. To recreate any sockets during server resets, the following 1025*4882a593Smuzhiyunroutine is called from the main loop: 1026*4882a593Smuzhiyun<blockquote><programlisting> 1027*4882a593Smuzhiyun 1028*4882a593Smuzhiyun void ResetWellKnownSockets() 1029*4882a593Smuzhiyun</programlisting></blockquote> 1030*4882a593SmuzhiyunSample implementations of both of these routines are found in 1031*4882a593SmuzhiyunXserver/os/connection.c. 1032*4882a593Smuzhiyun</para> 1033*4882a593Smuzhiyun<para> 1034*4882a593SmuzhiyunFor more details, see the section called "Connection Setup" in the X protocol specification. 1035*4882a593Smuzhiyun</para> 1036*4882a593Smuzhiyun</section> 1037*4882a593Smuzhiyun<section> 1038*4882a593Smuzhiyun <title>Reading Data from Clients</title> 1039*4882a593Smuzhiyun<para> 1040*4882a593SmuzhiyunRequests from the client are read in as a byte stream by the OS layer. 1041*4882a593SmuzhiyunThey may be in the form of several blocks of bytes delivered in sequence; requests may 1042*4882a593Smuzhiyunbe broken up over block boundaries or there may be many requests per block. 1043*4882a593SmuzhiyunEach request carries with it length information. 1044*4882a593SmuzhiyunIt is the responsibility of the following routine to break it up into request blocks. 1045*4882a593Smuzhiyun<blockquote><programlisting> 1046*4882a593Smuzhiyun 1047*4882a593Smuzhiyun int ReadRequestFromClient(who) 1048*4882a593Smuzhiyun ClientPtr who; 1049*4882a593Smuzhiyun</programlisting></blockquote> 1050*4882a593Smuzhiyun</para> 1051*4882a593Smuzhiyun<para> 1052*4882a593SmuzhiyunYou must write 1053*4882a593Smuzhiyunthe routine ReadRequestFromClient() to get one request from the byte stream 1054*4882a593Smuzhiyunbelonging to client "who." 1055*4882a593SmuzhiyunYou must swap the third and fourth bytes (the second 16-bit word) according to the 1056*4882a593Smuzhiyunbyte-swap rules of 1057*4882a593Smuzhiyunthe protocol to determine the length of the 1058*4882a593Smuzhiyunrequest. 1059*4882a593SmuzhiyunThis length is measured in 32-bit words, not in bytes. Therefore, the 1060*4882a593Smuzhiyuntheoretical maximum request is 256K. 1061*4882a593Smuzhiyun(However, the maximum length allowed is dependent upon the server's input 1062*4882a593Smuzhiyunbuffer. This size is sent to the client upon connection. The maximum 1063*4882a593Smuzhiyunsize is the constant MAX_REQUEST_SIZE in Xserver/include/os.h) 1064*4882a593SmuzhiyunThe rest of the request you return is 1065*4882a593Smuzhiyunassumed NOT to be correctly swapped for internal 1066*4882a593Smuzhiyunuse, because that is the responsibility of DIX. 1067*4882a593Smuzhiyun</para> 1068*4882a593Smuzhiyun<para> 1069*4882a593SmuzhiyunThe 'who' argument is the ClientPtr returned from WaitForSomething. 1070*4882a593SmuzhiyunThe return value indicating status should be set to the (positive) byte count if the read is successful, 1071*4882a593Smuzhiyun0 if the read was blocked, or a negative error code if an error happened. 1072*4882a593Smuzhiyun</para> 1073*4882a593Smuzhiyun<para> 1074*4882a593SmuzhiyunYou must then store a pointer to 1075*4882a593Smuzhiyunthe bytes of the request in the client request buffer field; 1076*4882a593Smuzhiyunwho->requestBuffer. This can simply be a pointer into your buffer; 1077*4882a593SmuzhiyunDIX may modify it in place but will not otherwise cause damage. 1078*4882a593SmuzhiyunOf course, the request must be contiguous; you must 1079*4882a593Smuzhiyunshuffle it around in your buffers if not. 1080*4882a593Smuzhiyun</para> 1081*4882a593Smuzhiyun<para> 1082*4882a593SmuzhiyunThe sample server implementation is in Xserver/os/io.c. 1083*4882a593Smuzhiyun</para> 1084*4882a593Smuzhiyun<section><title>Inserting Data for Clients</title> 1085*4882a593Smuzhiyun<para> 1086*4882a593SmuzhiyunDIX can insert data into the client stream, and can cause a "replay" of 1087*4882a593Smuzhiyunthe current request. 1088*4882a593Smuzhiyun<blockquote><programlisting> 1089*4882a593Smuzhiyun 1090*4882a593Smuzhiyun Bool InsertFakeRequest(client, data, count) 1091*4882a593Smuzhiyun ClientPtr client; 1092*4882a593Smuzhiyun char *data; 1093*4882a593Smuzhiyun int count; 1094*4882a593Smuzhiyun 1095*4882a593Smuzhiyun int ResetCurrentRequest(client) 1096*4882a593Smuzhiyun ClientPtr client; 1097*4882a593Smuzhiyun</programlisting></blockquote> 1098*4882a593Smuzhiyun</para> 1099*4882a593Smuzhiyun<para> 1100*4882a593SmuzhiyunInsertFakeRequest() must insert the specified number of bytes of data 1101*4882a593Smuzhiyuninto the head of the input buffer for the client. This may be a 1102*4882a593Smuzhiyuncomplete request, or it might be a partial request. For example, 1103*4882a593SmuzhiyunNextAvailableCient() will insert a partial request in order to read 1104*4882a593Smuzhiyunthe initial connection data sent by the client. The routine returns FALSE 1105*4882a593Smuzhiyunif memory could not be allocated. ResetCurrentRequest() 1106*4882a593Smuzhiyunshould "back up" the input buffer so that the currently executing request 1107*4882a593Smuzhiyunwill be reexecuted. DIX may have altered some values (e.g. the overall 1108*4882a593Smuzhiyunrequest length), so you must recheck to see if you still have a complete 1109*4882a593Smuzhiyunrequest. ResetCurrentRequest() should always cause a yield (isItTimeToYield). 1110*4882a593Smuzhiyun</para> 1111*4882a593Smuzhiyun</section> 1112*4882a593Smuzhiyun</section> 1113*4882a593Smuzhiyun 1114*4882a593Smuzhiyun<section> 1115*4882a593Smuzhiyun <title>Sending Events, Errors And Replies To Clients</title> 1116*4882a593Smuzhiyun<para> 1117*4882a593Smuzhiyun<blockquote><programlisting> 1118*4882a593Smuzhiyun 1119*4882a593Smuzhiyun int WriteToClient(who, n, buf) 1120*4882a593Smuzhiyun ClientPtr who; 1121*4882a593Smuzhiyun int n; 1122*4882a593Smuzhiyun char *buf; 1123*4882a593Smuzhiyun</programlisting></blockquote> 1124*4882a593SmuzhiyunWriteToClient should write n bytes starting at buf to the 1125*4882a593SmuzhiyunClientPtr "who". 1126*4882a593SmuzhiyunIt returns the number of bytes written, but for simplicity, 1127*4882a593Smuzhiyunthe number returned must be either the same value as the number 1128*4882a593Smuzhiyunrequested, or -1, signaling an error. 1129*4882a593SmuzhiyunThe sample server implementation is in Xserver/os/io.c. 1130*4882a593Smuzhiyun</para> 1131*4882a593Smuzhiyun<para> 1132*4882a593Smuzhiyun<blockquote><programlisting> 1133*4882a593Smuzhiyun void SendErrorToClient(client, majorCode, minorCode, resId, errorCode) 1134*4882a593Smuzhiyun ClientPtr client; 1135*4882a593Smuzhiyun unsigned int majorCode; 1136*4882a593Smuzhiyun unsigned int minorCode; 1137*4882a593Smuzhiyun XID resId; 1138*4882a593Smuzhiyun int errorCode; 1139*4882a593Smuzhiyun</programlisting></blockquote> 1140*4882a593SmuzhiyunSendErrorToClient can be used to send errors back to clients, 1141*4882a593Smuzhiyunalthough in most cases your request function should simply return 1142*4882a593Smuzhiyunthe error code, having set client->errorValue to the appropriate 1143*4882a593Smuzhiyunerror value to return to the client, and DIX will call this 1144*4882a593Smuzhiyunfunction with the correct opcodes for you. 1145*4882a593Smuzhiyun</para> 1146*4882a593Smuzhiyun<para> 1147*4882a593Smuzhiyun<blockquote><programlisting> 1148*4882a593Smuzhiyun 1149*4882a593Smuzhiyun void FlushAllOutput() 1150*4882a593Smuzhiyun 1151*4882a593Smuzhiyun void FlushIfCriticalOutputPending() 1152*4882a593Smuzhiyun 1153*4882a593Smuzhiyun void SetCriticalOutputPending() 1154*4882a593Smuzhiyun</programlisting></blockquote> 1155*4882a593SmuzhiyunThese three routines may be implemented to support buffered or delayed 1156*4882a593Smuzhiyunwrites to clients, but at the very least, the stubs must exist. 1157*4882a593SmuzhiyunFlushAllOutput() unconditionally flushes all output to clients; 1158*4882a593SmuzhiyunFlushIfCriticalOutputPending() flushes output only if 1159*4882a593SmuzhiyunSetCriticalOutputPending() has be called since the last time output 1160*4882a593Smuzhiyunwas flushed. 1161*4882a593SmuzhiyunThe sample server implementation is in Xserver/os/io.c and 1162*4882a593Smuzhiyunactually ignores requests to flush output on a per-client basis 1163*4882a593Smuzhiyunif it knows that there 1164*4882a593Smuzhiyunare requests in that client's input queue. 1165*4882a593Smuzhiyun</para> 1166*4882a593Smuzhiyun</section> 1167*4882a593Smuzhiyun<section> 1168*4882a593Smuzhiyun <title>Font Support</title> 1169*4882a593Smuzhiyun<para> 1170*4882a593SmuzhiyunIn the sample server, fonts are encoded in disk files or fetched from the 1171*4882a593Smuzhiyunfont server. The two fonts required by the server, <quote>fixed</quote> 1172*4882a593Smuzhiyunand <quote>cursor</quote> are commonly compiled into the font library. 1173*4882a593SmuzhiyunFor disk fonts, there is one file per font, with a file name like 1174*4882a593Smuzhiyun"fixed.pcf". Font server fonts are read over the network using the 1175*4882a593SmuzhiyunX Font Server Protocol. The disk directories containing disk fonts and 1176*4882a593Smuzhiyunthe names of the font servers are listed together in the current "font path." 1177*4882a593Smuzhiyun</para> 1178*4882a593Smuzhiyun<para> 1179*4882a593SmuzhiyunIn principle, you can put all your fonts in ROM or in RAM in your server. 1180*4882a593SmuzhiyunYou can put them all in one library file on disk. 1181*4882a593SmuzhiyunYou could generate them on the fly from stroke descriptions. By placing the 1182*4882a593Smuzhiyunappropriate code in the Font Library, you will automatically export fonts in 1183*4882a593Smuzhiyunthat format both through the X server and the Font server. 1184*4882a593Smuzhiyun</para> 1185*4882a593Smuzhiyun<para> 1186*4882a593SmuzhiyunThe code for processing fonts in different formats, as well as handling the 1187*4882a593Smuzhiyunmetadata files for them on disk (such as <filename>fonts.dir</filename>) is 1188*4882a593Smuzhiyunlocated in the libXfont library, which is provided as a separately compiled 1189*4882a593Smuzhiyunmodule. These routines are 1190*4882a593Smuzhiyunshared between the X server and the Font server, so instead of this document 1191*4882a593Smuzhiyunspecifying what you must implement, simply refer to the font 1192*4882a593Smuzhiyunlibrary interface specification for the details. All of the interface code to the Font 1193*4882a593Smuzhiyunlibrary is contained in dix/dixfonts.c 1194*4882a593Smuzhiyun</para> 1195*4882a593Smuzhiyun</section> 1196*4882a593Smuzhiyun<section> 1197*4882a593Smuzhiyun <title>Memory Management</title> 1198*4882a593Smuzhiyun<para> 1199*4882a593SmuzhiyunMemory management is based on functions in the C runtime library, malloc(), 1200*4882a593Smuzhiyunrealloc(), and free(), and you should simply call the C library functions 1201*4882a593Smuzhiyundirectly. Consult a C runtime library reference manual for more details. 1202*4882a593Smuzhiyun</para> 1203*4882a593Smuzhiyun<para> 1204*4882a593SmuzhiyunTreat memory allocation carefully in your implementation. Memory 1205*4882a593Smuzhiyunleaks can be very hard to find and are frustrating to a user. An X 1206*4882a593Smuzhiyunserver could be running for days or weeks without being reset, just 1207*4882a593Smuzhiyunlike a regular terminal. If you leak a few dozen k per day, that will 1208*4882a593Smuzhiyunadd up and will cause problems for users that leave their workstations 1209*4882a593Smuzhiyunon. 1210*4882a593Smuzhiyun</para> 1211*4882a593Smuzhiyun</section> 1212*4882a593Smuzhiyun<section> 1213*4882a593Smuzhiyun <title>Client Scheduling</title> 1214*4882a593Smuzhiyun<para> 1215*4882a593SmuzhiyunThe X server 1216*4882a593Smuzhiyunhas the ability to schedule clients much like an operating system would, 1217*4882a593Smuzhiyunsuspending and restarting them without regard for the state of their input 1218*4882a593Smuzhiyunbuffers. This functionality allows the X server to suspend one client and 1219*4882a593Smuzhiyuncontinue processing requests from other clients while waiting for a 1220*4882a593Smuzhiyunlong-term network activity (like loading a font) before continuing with the 1221*4882a593Smuzhiyunfirst client. 1222*4882a593Smuzhiyun<blockquote><programlisting> 1223*4882a593Smuzhiyun Bool isItTimeToYield; 1224*4882a593Smuzhiyun</programlisting></blockquote> 1225*4882a593SmuzhiyunisItTimeToYield is a global variable you can set 1226*4882a593Smuzhiyunif you want to tell 1227*4882a593SmuzhiyunDIX to end the client's "time slice" and start paying attention to the next client. 1228*4882a593SmuzhiyunAfter the current request is finished, DIX will move to the next client. 1229*4882a593Smuzhiyun</para> 1230*4882a593Smuzhiyun<para> 1231*4882a593SmuzhiyunIn the sample 1232*4882a593Smuzhiyunserver, ReadRequestFromClient() sets isItTimeToYield after 1233*4882a593Smuzhiyun10 requests packets in a row are read from the same client. 1234*4882a593Smuzhiyun</para> 1235*4882a593Smuzhiyun<para> 1236*4882a593SmuzhiyunThis scheduling algorithm can have a serious effect upon performance when two 1237*4882a593Smuzhiyunclients are drawing into their windows simultaneously. 1238*4882a593SmuzhiyunIf it allows one client to run until its request 1239*4882a593Smuzhiyunqueue is empty by ignoring isItTimeToYield, the client's queue may 1240*4882a593Smuzhiyunin fact never empty and other clients will be blocked out. 1241*4882a593SmuzhiyunOn the other hand, if it switchs between different clients too quickly, 1242*4882a593Smuzhiyunperformance may suffer due to too much switching between contexts. 1243*4882a593SmuzhiyunFor example, if a graphics processor needs to be set up with drawing modes 1244*4882a593Smuzhiyunbefore drawing, and two different clients are drawing with 1245*4882a593Smuzhiyundifferent modes into two different windows, you may 1246*4882a593Smuzhiyunswitch your graphics processor modes so often that performance is impacted. 1247*4882a593Smuzhiyun</para> 1248*4882a593Smuzhiyun<para> 1249*4882a593SmuzhiyunSee the Strategies document for 1250*4882a593Smuzhiyunheuristics on setting isItTimeToYield. 1251*4882a593Smuzhiyun</para> 1252*4882a593Smuzhiyun<para> 1253*4882a593SmuzhiyunThe following functions provide the ability to suspend request 1254*4882a593Smuzhiyunprocessing on a particular client, resuming it at some later time: 1255*4882a593Smuzhiyun<blockquote><programlisting> 1256*4882a593Smuzhiyun 1257*4882a593Smuzhiyun int IgnoreClient (who) 1258*4882a593Smuzhiyun ClientPtr who; 1259*4882a593Smuzhiyun 1260*4882a593Smuzhiyun int AttendClient (who) 1261*4882a593Smuzhiyun ClientPtr who; 1262*4882a593Smuzhiyun</programlisting></blockquote> 1263*4882a593SmuzhiyunIgnore client is responsible for pretending that the given client doesn't 1264*4882a593Smuzhiyunexist. WaitForSomething should not return this client as ready for reading 1265*4882a593Smuzhiyunand should not return if only this client is ready. AttendClient undoes 1266*4882a593Smuzhiyunwhatever IgnoreClient did, setting it up for input again. 1267*4882a593Smuzhiyun</para> 1268*4882a593Smuzhiyun<para> 1269*4882a593SmuzhiyunThree functions support "process control" for X clients: 1270*4882a593Smuzhiyun<blockquote><programlisting> 1271*4882a593Smuzhiyun 1272*4882a593Smuzhiyun Bool ClientSleep (client, function, closure) 1273*4882a593Smuzhiyun ClientPtr client; 1274*4882a593Smuzhiyun Bool (*function)(); 1275*4882a593Smuzhiyun pointer closure; 1276*4882a593Smuzhiyun 1277*4882a593Smuzhiyun</programlisting></blockquote> 1278*4882a593SmuzhiyunThis suspends the current client (the calling routine is responsible for 1279*4882a593Smuzhiyunmaking its way back to Dispatch()). No more X requests will be processed 1280*4882a593Smuzhiyunfor this client until ClientWakeup is called. 1281*4882a593Smuzhiyun<blockquote><programlisting> 1282*4882a593Smuzhiyun 1283*4882a593Smuzhiyun Bool ClientSignal (client) 1284*4882a593Smuzhiyun ClientPtr client; 1285*4882a593Smuzhiyun 1286*4882a593Smuzhiyun</programlisting></blockquote> 1287*4882a593SmuzhiyunThis function causes a call to the (*function) parameter passed to 1288*4882a593SmuzhiyunClientSleep to be queued on the work queue. This does not automatically 1289*4882a593Smuzhiyun"wakeup" the client, but the function called is free to do so by calling: 1290*4882a593Smuzhiyun<blockquote><programlisting> 1291*4882a593Smuzhiyun 1292*4882a593Smuzhiyun ClientWakeup (client) 1293*4882a593Smuzhiyun ClientPtr client; 1294*4882a593Smuzhiyun 1295*4882a593Smuzhiyun</programlisting></blockquote> 1296*4882a593SmuzhiyunThis re-enables X request processing for the specified client. 1297*4882a593Smuzhiyun</para> 1298*4882a593Smuzhiyun</section> 1299*4882a593Smuzhiyun<section> 1300*4882a593Smuzhiyun <title>Other OS Functions</title> 1301*4882a593Smuzhiyun<para> 1302*4882a593Smuzhiyun<blockquote><programlisting> 1303*4882a593Smuzhiyun void 1304*4882a593Smuzhiyun ErrorF(char *f, ...) 1305*4882a593Smuzhiyun 1306*4882a593Smuzhiyun void 1307*4882a593Smuzhiyun FatalError(char *f, ...) 1308*4882a593Smuzhiyun</programlisting></blockquote> 1309*4882a593SmuzhiyunYou should write these three routines to provide for diagnostic output 1310*4882a593Smuzhiyunfrom the dix and ddx layers, although implementing them to produce no 1311*4882a593Smuzhiyunoutput will not affect the correctness of your server. ErrorF() and 1312*4882a593SmuzhiyunFatalError() take a printf() type of format specification in the first 1313*4882a593Smuzhiyunargument and an implementation-dependent number of arguments following 1314*4882a593Smuzhiyunthat. Normally, the formats passed to ErrorF() and FatalError() 1315*4882a593Smuzhiyunshould be terminated with a newline. 1316*4882a593Smuzhiyun</para> 1317*4882a593Smuzhiyun<para> 1318*4882a593SmuzhiyunAfter printing the message arguments, FatalError() must be implemented 1319*4882a593Smuzhiyunsuch that the server will call AbortDDX() to give the ddx layer 1320*4882a593Smuzhiyuna chance to reset the hardware, and then 1321*4882a593Smuzhiyunterminate the server; it must not return. 1322*4882a593Smuzhiyun</para> 1323*4882a593Smuzhiyun<para> 1324*4882a593SmuzhiyunThe sample server implementation for these routines 1325*4882a593Smuzhiyunis in Xserver/os/log.c along with other routines for logging messages. 1326*4882a593Smuzhiyun</para> 1327*4882a593Smuzhiyun</section> 1328*4882a593Smuzhiyun</section> 1329*4882a593Smuzhiyun 1330*4882a593Smuzhiyun<section> 1331*4882a593Smuzhiyun <title>DDX Layer</title> 1332*4882a593Smuzhiyun<para> 1333*4882a593SmuzhiyunThis section describes the 1334*4882a593Smuzhiyuninterface between DIX and DDX. 1335*4882a593SmuzhiyunWhile there may be an OS-dependent driver interface between DDX 1336*4882a593Smuzhiyunand the physical device, that interface is left to the DDX 1337*4882a593Smuzhiyunimplementor and is not specified here. 1338*4882a593Smuzhiyun</para> 1339*4882a593Smuzhiyun<para> 1340*4882a593SmuzhiyunThe DDX layer does most of its work through procedures that are 1341*4882a593Smuzhiyunpointed to by different structs. 1342*4882a593SmuzhiyunAs previously described, the behavior of these resources is largely determined by 1343*4882a593Smuzhiyunthese procedure pointers. 1344*4882a593SmuzhiyunMost of these routines are for graphic display on the screen or support functions thereof. 1345*4882a593SmuzhiyunThe rest are for user input from input devices. 1346*4882a593Smuzhiyun</para> 1347*4882a593Smuzhiyun<section> 1348*4882a593Smuzhiyun <title>Input</title> 1349*4882a593Smuzhiyun<para> 1350*4882a593SmuzhiyunIn this document "input" refers to input from the user, 1351*4882a593Smuzhiyunsuch as mouse, keyboard, and 1352*4882a593Smuzhiyunbar code readers. 1353*4882a593SmuzhiyunX input devices are of several types: keyboard, pointing device, and 1354*4882a593Smuzhiyunmany others. The core server has support for extension devices as 1355*4882a593Smuzhiyundescribed by the X Input Extension document; the interfaces used by 1356*4882a593Smuzhiyunthat extension are described elsewhere. The core devices are actually 1357*4882a593Smuzhiyunimplemented as two collections of devices, the mouse is a ButtonDevice, 1358*4882a593Smuzhiyuna ValuatorDevice and a PtrFeedbackDevice while the keyboard is a KeyDevice, 1359*4882a593Smuzhiyuna FocusDevice and a KbdFeedbackDevice. Each part implements a portion of 1360*4882a593Smuzhiyunthe functionality of the device. This abstraction is hidden from view for 1361*4882a593Smuzhiyuncore devices by DIX. 1362*4882a593Smuzhiyun</para> 1363*4882a593Smuzhiyun<para> 1364*4882a593SmuzhiyunYou, the DDX programmer, are 1365*4882a593Smuzhiyunresponsible for some of the routines in this section. 1366*4882a593SmuzhiyunOthers are DIX routines that you should call to do the things you need to do in these DDX routines. 1367*4882a593SmuzhiyunPay attention to which is which. 1368*4882a593Smuzhiyun</para> 1369*4882a593Smuzhiyun<section> 1370*4882a593Smuzhiyun <title>Input Device Data Structures</title> 1371*4882a593Smuzhiyun<para> 1372*4882a593SmuzhiyunDIX keeps a global directory of devices in a central data structure 1373*4882a593Smuzhiyuncalled InputInfo. 1374*4882a593SmuzhiyunFor each device there is a device structure called a DeviceRec. 1375*4882a593SmuzhiyunDIX can locate any DeviceRec through InputInfo. 1376*4882a593SmuzhiyunIn addition, it has a special pointer to identify the main pointing device 1377*4882a593Smuzhiyunand a special pointer to identify the main keyboard. 1378*4882a593Smuzhiyun</para> 1379*4882a593Smuzhiyun<para> 1380*4882a593SmuzhiyunThe DeviceRec (Xserver/include/input.h) is a device-independent 1381*4882a593Smuzhiyunstructure that contains the state of an input device. 1382*4882a593SmuzhiyunA DevicePtr is simply a pointer to a DeviceRec. 1383*4882a593Smuzhiyun</para> 1384*4882a593Smuzhiyun<para> 1385*4882a593SmuzhiyunAn xEvent describes an event the server reports to a client. 1386*4882a593SmuzhiyunDefined in Xproto.h, it is a huge struct of union of structs that have fields for 1387*4882a593Smuzhiyunall kinds of events. 1388*4882a593SmuzhiyunAll of the variants overlap, so that the struct is actually very small in memory. 1389*4882a593Smuzhiyun</para> 1390*4882a593Smuzhiyun</section> 1391*4882a593Smuzhiyun<section> 1392*4882a593Smuzhiyun <title>Processing Events</title> 1393*4882a593Smuzhiyun<para> 1394*4882a593SmuzhiyunThe main DDX input interface is the following routine: 1395*4882a593Smuzhiyun<blockquote><programlisting> 1396*4882a593Smuzhiyun 1397*4882a593Smuzhiyun void ProcessInputEvents() 1398*4882a593Smuzhiyun</programlisting></blockquote> 1399*4882a593SmuzhiyunYou must write this routine to deliver input events from the user. 1400*4882a593SmuzhiyunDIX calls it when input is pending (see next section), and possibly 1401*4882a593Smuzhiyuneven when it is not. 1402*4882a593SmuzhiyunYou should write it to get events from each device and deliver 1403*4882a593Smuzhiyunthe events to DIX. 1404*4882a593SmuzhiyunTo deliver the events to DIX, DDX should call the following 1405*4882a593Smuzhiyunroutine: 1406*4882a593Smuzhiyun<blockquote><programlisting> 1407*4882a593Smuzhiyun 1408*4882a593Smuzhiyun void DevicePtr->processInputProc(pEvent, device, count) 1409*4882a593Smuzhiyun xEventPtr events; 1410*4882a593Smuzhiyun DeviceIntPtr device; 1411*4882a593Smuzhiyun int count; 1412*4882a593Smuzhiyun</programlisting></blockquote> 1413*4882a593SmuzhiyunThis is the "input proc" for the device, a DIX procedure. 1414*4882a593SmuzhiyunDIX will fill in this procedure pointer to one of its own routines by 1415*4882a593Smuzhiyunthe time ProcessInputEvents() is called the first time. 1416*4882a593SmuzhiyunCall this input proc routine as many times as needed to 1417*4882a593Smuzhiyundeliver as many events as should be delivered. 1418*4882a593SmuzhiyunDIX will buffer them up and send them out as needed. Count is set 1419*4882a593Smuzhiyunto the number of event records which make up one atomic device event and 1420*4882a593Smuzhiyunis always 1 for the core devices (see the X Input Extension for descriptions 1421*4882a593Smuzhiyunof devices which may use count > 1). 1422*4882a593Smuzhiyun</para> 1423*4882a593Smuzhiyun<para> 1424*4882a593SmuzhiyunFor example, your ProcessInputEvents() routine might check the mouse and the 1425*4882a593Smuzhiyunkeyboard. 1426*4882a593SmuzhiyunIf the keyboard had several keystrokes queued up, it could just call 1427*4882a593Smuzhiyunthe keyboard's processInputProc as many times as needed to flush its internal queue. 1428*4882a593Smuzhiyun</para> 1429*4882a593Smuzhiyun<para> 1430*4882a593Smuzhiyunevent is an xEvent struct you pass to the input proc. 1431*4882a593SmuzhiyunWhen the input proc returns, it is finished with the event rec, and you can fill 1432*4882a593Smuzhiyunin new values and call the input proc again with it. 1433*4882a593Smuzhiyun</para> 1434*4882a593Smuzhiyun<para> 1435*4882a593SmuzhiyunYou should deliver the events in the same order that they were generated. 1436*4882a593Smuzhiyun</para> 1437*4882a593Smuzhiyun<para> 1438*4882a593SmuzhiyunFor keyboard and pointing devices the xEvent variant should be keyButtonPointer. 1439*4882a593SmuzhiyunFill in the following fields in the xEvent record: 1440*4882a593Smuzhiyun<itemizedlist> 1441*4882a593Smuzhiyun 1442*4882a593Smuzhiyun<listitem><para>type - is one of the following: KeyPress, KeyRelease, ButtonPress, 1443*4882a593Smuzhiyun ButtonRelease, or MotionNotify</para></listitem> 1444*4882a593Smuzhiyun<listitem><para>detail - for KeyPress or KeyRelease fields, this should be the 1445*4882a593Smuzhiyun key number (not the ASCII code); otherwise unused</para></listitem> 1446*4882a593Smuzhiyun<listitem><para>time - is the time that the event happened (32-bits, in milliseconds, arbitrary origin)</para></listitem> 1447*4882a593Smuzhiyun<listitem><para>rootX - is the x coordinate of cursor</para></listitem> 1448*4882a593Smuzhiyun<listitem><para>rootY - is the y coordinate of cursor</para></listitem> 1449*4882a593Smuzhiyun 1450*4882a593Smuzhiyun</itemizedlist> 1451*4882a593SmuzhiyunThe rest of the fields are filled in by DIX. 1452*4882a593Smuzhiyun</para> 1453*4882a593Smuzhiyun<para> 1454*4882a593SmuzhiyunThe time stamp is maintained by your code in the DDX layer, and it is your responsibility to 1455*4882a593Smuzhiyunstamp all events correctly. 1456*4882a593Smuzhiyun</para> 1457*4882a593Smuzhiyun<para> 1458*4882a593SmuzhiyunThe x and y coordinates of the pointing device and the time must be filled in for all event types 1459*4882a593Smuzhiyunincluding keyboard events. 1460*4882a593Smuzhiyun</para> 1461*4882a593Smuzhiyun<para> 1462*4882a593SmuzhiyunThe pointing device must report all button press and release events. 1463*4882a593SmuzhiyunIn addition, it should report a MotionNotify event every time it gets called 1464*4882a593Smuzhiyunif the pointing device has moved since the last notify. 1465*4882a593SmuzhiyunIntermediate pointing device moves are stored in a special GetMotionEvents buffer, 1466*4882a593Smuzhiyunbecause most client programs are not interested in them. 1467*4882a593Smuzhiyun</para> 1468*4882a593Smuzhiyun<para> 1469*4882a593SmuzhiyunThere are quite a collection of sample implementations of this routine, 1470*4882a593Smuzhiyunone for each supported device. 1471*4882a593Smuzhiyun</para> 1472*4882a593Smuzhiyun</section> 1473*4882a593Smuzhiyun<section> 1474*4882a593Smuzhiyun<title>Telling DIX When Input is Pending</title> 1475*4882a593Smuzhiyun<para> 1476*4882a593SmuzhiyunIn the server's dispatch loop, DIX checks to see 1477*4882a593Smuzhiyunif there is any device input pending whenever WaitForSomething() returns. 1478*4882a593SmuzhiyunIf the check says that input is pending, DIX calls the 1479*4882a593SmuzhiyunDDX routine ProcessInputEvents(). 1480*4882a593Smuzhiyun</para> 1481*4882a593Smuzhiyun<para> 1482*4882a593SmuzhiyunThis check for pending input must be very quick; a procedure call 1483*4882a593Smuzhiyunis too slow. 1484*4882a593SmuzhiyunThe code that does the check is a hardwired IF 1485*4882a593Smuzhiyunstatement in DIX code that simply compares the values 1486*4882a593Smuzhiyunpointed to by two pointers. 1487*4882a593SmuzhiyunIf the values are different, then it assumes that input is pending and 1488*4882a593SmuzhiyunProcessInputEvents() is called by DIX. 1489*4882a593Smuzhiyun</para> 1490*4882a593Smuzhiyun<para> 1491*4882a593SmuzhiyunYou must pass pointers to DIX to tell it what values to compare. 1492*4882a593SmuzhiyunThe following procedure 1493*4882a593Smuzhiyunis used to set these pointers: 1494*4882a593Smuzhiyun<blockquote><programlisting> 1495*4882a593Smuzhiyun 1496*4882a593Smuzhiyun void SetInputCheck(p1, p2) 1497*4882a593Smuzhiyun long *p1, *p2; 1498*4882a593Smuzhiyun</programlisting></blockquote> 1499*4882a593SmuzhiyunYou should call it sometime during initialization to indicate to DIX the 1500*4882a593Smuzhiyuncorrect locations to check. 1501*4882a593SmuzhiyunYou should 1502*4882a593Smuzhiyunpay special attention to the size of what they actually point to, 1503*4882a593Smuzhiyunbecause the locations are assumed to be longs. 1504*4882a593Smuzhiyun</para> 1505*4882a593Smuzhiyun<para> 1506*4882a593SmuzhiyunThese two pointers are initialized by DIX 1507*4882a593Smuzhiyunto point to arbitrary values that 1508*4882a593Smuzhiyunare different. 1509*4882a593SmuzhiyunIn other words, if you forget to call this routine during initialization, 1510*4882a593Smuzhiyunthe worst thing that will happen is that 1511*4882a593SmuzhiyunProcessInputEvents will be called when 1512*4882a593Smuzhiyunthere are no events to process. 1513*4882a593Smuzhiyun</para> 1514*4882a593Smuzhiyun<para> 1515*4882a593Smuzhiyunp1 and p2 might 1516*4882a593Smuzhiyunpoint at the head and tail of some shared 1517*4882a593Smuzhiyunmemory queue. 1518*4882a593SmuzhiyunAnother use would be to have one point at a constant 0, with the 1519*4882a593Smuzhiyunother pointing at some mask containing 1s 1520*4882a593Smuzhiyunfor each input device that has 1521*4882a593Smuzhiyunsomething pending. 1522*4882a593Smuzhiyun</para> 1523*4882a593Smuzhiyun<para> 1524*4882a593SmuzhiyunThe DDX layer of the sample server calls SetInputCheck() 1525*4882a593Smuzhiyunonce when the 1526*4882a593Smuzhiyunserver's private internal queue is initialized. 1527*4882a593SmuzhiyunIt passes pointers to the queue's head and tail. See Xserver/mi/mieq.c. 1528*4882a593Smuzhiyun</para> 1529*4882a593Smuzhiyun<para> 1530*4882a593Smuzhiyun<blockquote><programlisting> 1531*4882a593Smuzhiyun int TimeSinceLastInputEvent() 1532*4882a593Smuzhiyun</programlisting></blockquote> 1533*4882a593SmuzhiyunDDX must time stamp all hardware input 1534*4882a593Smuzhiyunevents. But DIX sometimes needs to know the 1535*4882a593Smuzhiyuntime and the OS layer needs to know the time since the last hardware 1536*4882a593Smuzhiyuninput event in 1537*4882a593Smuzhiyunorder for the screen saver to work. TimeSinceLastInputEvent() returns 1538*4882a593Smuzhiyunthe this time in milliseconds. 1539*4882a593Smuzhiyun</para> 1540*4882a593Smuzhiyun</section> 1541*4882a593Smuzhiyun<section> 1542*4882a593Smuzhiyun <title>Controlling Input Devices</title> 1543*4882a593Smuzhiyun<para> 1544*4882a593SmuzhiyunYou must write four routines to do various device-specific 1545*4882a593Smuzhiyunthings with the keyboard and pointing device. 1546*4882a593SmuzhiyunThey can have any name you wish because 1547*4882a593Smuzhiyunyou pass the procedure pointers to DIX routines. 1548*4882a593Smuzhiyun</para> 1549*4882a593Smuzhiyun<para> 1550*4882a593Smuzhiyun<blockquote><programlisting> 1551*4882a593Smuzhiyun 1552*4882a593Smuzhiyun int pInternalDevice->valuator->GetMotionProc(pdevice, coords, start, stop, pScreen) 1553*4882a593Smuzhiyun DeviceIntPtr pdevice; 1554*4882a593Smuzhiyun xTimecoord * coords; 1555*4882a593Smuzhiyun unsigned long start; 1556*4882a593Smuzhiyun unsigned long stop; 1557*4882a593Smuzhiyun ScreenPtr pScreen; 1558*4882a593Smuzhiyun</programlisting></blockquote> 1559*4882a593SmuzhiyunYou write this DDX routine to fill in coords with all the motion 1560*4882a593Smuzhiyunevents that have times (32-bit count of milliseconds) between time 1561*4882a593Smuzhiyunstart and time stop. It should return the number of motion events 1562*4882a593Smuzhiyunreturned. If there is no motion events support, this routine should 1563*4882a593Smuzhiyundo nothing and return zero. The maximum number of coords to return is 1564*4882a593Smuzhiyunset in InitPointerDeviceStruct(), below. 1565*4882a593Smuzhiyun</para> 1566*4882a593Smuzhiyun<para> 1567*4882a593SmuzhiyunWhen the user drags the pointing device, the cursor position 1568*4882a593Smuzhiyuntheoretically sweeps through an infinite number of points. Normally, 1569*4882a593Smuzhiyuna client that is concerned with points other than the starting and 1570*4882a593Smuzhiyunending points will receive a pointer-move event only as often as the 1571*4882a593Smuzhiyunserver generates them. (Move events do not queue up; each new one 1572*4882a593Smuzhiyunreplaces the last in the queue.) A server, if desired, can implement 1573*4882a593Smuzhiyuna scheme to save these intermediate events in a motion buffer. A 1574*4882a593Smuzhiyunclient application, like a paint program, may then request that these 1575*4882a593Smuzhiyunevents be delivered to it through the GetMotionProc routine. 1576*4882a593Smuzhiyun</para> 1577*4882a593Smuzhiyun<para> 1578*4882a593Smuzhiyun<blockquote><programlisting> 1579*4882a593Smuzhiyun 1580*4882a593Smuzhiyun void pInternalDevice->bell->BellProc(percent, pDevice, ctrl, unknown) 1581*4882a593Smuzhiyun int percent; 1582*4882a593Smuzhiyun DeviceIntPtr pDevice; 1583*4882a593Smuzhiyun pointer ctrl; 1584*4882a593Smuzhiyun int class; 1585*4882a593Smuzhiyun</programlisting></blockquote> 1586*4882a593SmuzhiyunYou need to write this routine to ring the bell on the keyboard. 1587*4882a593Smuzhiyunloud is a number from 0 to 100, with 100 being the loudest. 1588*4882a593SmuzhiyunClass is either BellFeedbackClass or KbdFeedbackClass (from XI.h). 1589*4882a593Smuzhiyun</para> 1590*4882a593Smuzhiyun<para> 1591*4882a593Smuzhiyun<blockquote><programlisting> 1592*4882a593Smuzhiyun 1593*4882a593Smuzhiyun void pInternalDevice->somedevice->CtrlProc(device, ctrl) 1594*4882a593Smuzhiyun DevicePtr device; 1595*4882a593Smuzhiyun SomethingCtrl *ctrl; 1596*4882a593Smuzhiyun 1597*4882a593Smuzhiyun</programlisting></blockquote> 1598*4882a593SmuzhiyunYou write two versions of this procedure, one for the keyboard and one for the pointing device. 1599*4882a593SmuzhiyunDIX calls it to inform DDX when a client has requested changes in the current 1600*4882a593Smuzhiyunsettings for the particular device. 1601*4882a593SmuzhiyunFor a keyboard, this might be the repeat threshold and rate. 1602*4882a593SmuzhiyunFor a pointing device, this might be a scaling factor (coarse or fine) for position reporting. 1603*4882a593SmuzhiyunSee input.h for the ctrl structures. 1604*4882a593Smuzhiyun</para> 1605*4882a593Smuzhiyun</section> 1606*4882a593Smuzhiyun<section> 1607*4882a593Smuzhiyun <title>Input Initialization</title> 1608*4882a593Smuzhiyun<para> 1609*4882a593SmuzhiyunInput initialization is a bit complicated. 1610*4882a593SmuzhiyunIt all starts with InitInput(), a routine that you write to call 1611*4882a593SmuzhiyunAddInputDevice() twice 1612*4882a593Smuzhiyun(once for pointing device and once for keyboard.) 1613*4882a593Smuzhiyun</para> 1614*4882a593Smuzhiyun<para> 1615*4882a593SmuzhiyunWhen you Add the devices, a routine you supply for each device 1616*4882a593Smuzhiyungets called to initialize them. 1617*4882a593SmuzhiyunYour individual initialize routines must call InitKeyboardDeviceStruct() 1618*4882a593Smuzhiyunor InitPointerDeviceStruct(), depending upon which it is. 1619*4882a593SmuzhiyunIn other words, you indicate twice that the keyboard is the keyboard and 1620*4882a593Smuzhiyunthe pointer is the pointer. 1621*4882a593Smuzhiyun</para> 1622*4882a593Smuzhiyun<para> 1623*4882a593Smuzhiyun<blockquote><programlisting> 1624*4882a593Smuzhiyun 1625*4882a593Smuzhiyun void InitInput(argc, argv) 1626*4882a593Smuzhiyun int argc; 1627*4882a593Smuzhiyun char **argv; 1628*4882a593Smuzhiyun</programlisting></blockquote> 1629*4882a593SmuzhiyunInitInput is a DDX routine you must write to initialize the 1630*4882a593Smuzhiyuninput subsystem in DDX. 1631*4882a593SmuzhiyunIt must call AddInputDevice() for each device that might generate events. 1632*4882a593Smuzhiyun</para> 1633*4882a593Smuzhiyun<para> 1634*4882a593Smuzhiyun<blockquote><programlisting> 1635*4882a593Smuzhiyun 1636*4882a593Smuzhiyun DevicePtr AddInputDevice(deviceProc, autoStart) 1637*4882a593Smuzhiyun DeviceProc deviceProc; 1638*4882a593Smuzhiyun Bool autoStart; 1639*4882a593Smuzhiyun</programlisting></blockquote> 1640*4882a593SmuzhiyunAddInputDevice is a DIX routine you call to create a device object. 1641*4882a593SmuzhiyundeviceProc is a DDX routine that is called by DIX to do various operations. 1642*4882a593SmuzhiyunAutoStart should be TRUE for devices that need to be turned on at 1643*4882a593Smuzhiyuninitialization time with a special call, as opposed to waiting for some 1644*4882a593Smuzhiyunclient application to 1645*4882a593Smuzhiyunturn them on. 1646*4882a593SmuzhiyunThis routine returns NULL if sufficient memory cannot be allocated to 1647*4882a593Smuzhiyuninstall the device. 1648*4882a593Smuzhiyun</para> 1649*4882a593Smuzhiyun<para> 1650*4882a593SmuzhiyunNote also that except for the main keyboard and pointing device, 1651*4882a593Smuzhiyunan extension is needed to provide for a client interface to a device. 1652*4882a593Smuzhiyun</para> 1653*4882a593Smuzhiyun<para> 1654*4882a593SmuzhiyunThe following DIX 1655*4882a593Smuzhiyunprocedures return the specified DevicePtr. They may or may not be useful 1656*4882a593Smuzhiyunto DDX implementors. 1657*4882a593Smuzhiyun</para> 1658*4882a593Smuzhiyun<para> 1659*4882a593Smuzhiyun<blockquote><programlisting> 1660*4882a593Smuzhiyun 1661*4882a593Smuzhiyun DevicePtr LookupKeyboardDevice() 1662*4882a593Smuzhiyun</programlisting></blockquote> 1663*4882a593SmuzhiyunLookupKeyboardDevice returns pointer for current main keyboard device. 1664*4882a593Smuzhiyun</para> 1665*4882a593Smuzhiyun<para> 1666*4882a593Smuzhiyun<blockquote><programlisting> 1667*4882a593Smuzhiyun 1668*4882a593Smuzhiyun DevicePtr LookupPointerDevice() 1669*4882a593Smuzhiyun</programlisting></blockquote> 1670*4882a593SmuzhiyunLookupPointerDevice returns pointer for current main pointing device. 1671*4882a593Smuzhiyun</para> 1672*4882a593Smuzhiyun<para> 1673*4882a593SmuzhiyunA DeviceProc (the kind passed to AddInputDevice()) in the following form: 1674*4882a593Smuzhiyun<blockquote><programlisting> 1675*4882a593Smuzhiyun 1676*4882a593Smuzhiyun Bool pInternalDevice->DeviceProc(device, action); 1677*4882a593Smuzhiyun DeviceIntPtr device; 1678*4882a593Smuzhiyun int action; 1679*4882a593Smuzhiyun</programlisting></blockquote> 1680*4882a593SmuzhiyunYou must write a DeviceProc for each device. 1681*4882a593Smuzhiyundevice points to the device record. 1682*4882a593Smuzhiyunaction tells what action to take; 1683*4882a593Smuzhiyunit will be one of these defined constants (defined in input.h): 1684*4882a593Smuzhiyun<itemizedlist> 1685*4882a593Smuzhiyun<listitem><para> 1686*4882a593SmuzhiyunDEVICE_INIT - 1687*4882a593SmuzhiyunAt DEVICE_INIT time, the device should initialize itself by calling 1688*4882a593SmuzhiyunInitPointerDeviceStruct(), InitKeyboardDeviceStruct(), or a similar 1689*4882a593Smuzhiyunroutine (see below) 1690*4882a593Smuzhiyunand "opening" the device if necessary. 1691*4882a593SmuzhiyunIf you return a non-zero (i.e., != Success) value from the DEVICE_INIT 1692*4882a593Smuzhiyuncall, that device will be considered unavailable. If either the main keyboard 1693*4882a593Smuzhiyunor main pointing device cannot be initialized, the DIX code will refuse 1694*4882a593Smuzhiyunto continue booting up.</para></listitem> 1695*4882a593Smuzhiyun<listitem><para> 1696*4882a593SmuzhiyunDEVICE_ON - If the DeviceProc is called with DEVICE_ON, then it is 1697*4882a593Smuzhiyunallowed to start 1698*4882a593Smuzhiyunputting events into the client stream by calling through the ProcessInputProc 1699*4882a593Smuzhiyunin the device.</para></listitem> 1700*4882a593Smuzhiyun<listitem><para> 1701*4882a593SmuzhiyunDEVICE_OFF - If the DeviceProc is called with DEVICE_OFF, no further 1702*4882a593Smuzhiyunevents from that 1703*4882a593Smuzhiyundevice should be given to the DIX layer. 1704*4882a593SmuzhiyunThe device will appear to be dead to the user.</para></listitem> 1705*4882a593Smuzhiyun<listitem><para> 1706*4882a593SmuzhiyunDEVICE_CLOSE - At DEVICE_CLOSE (terminate or reset) time, the device should 1707*4882a593Smuzhiyunbe totally closed down.</para></listitem> 1708*4882a593Smuzhiyun</itemizedlist> 1709*4882a593Smuzhiyun</para> 1710*4882a593Smuzhiyun<para> 1711*4882a593Smuzhiyun<blockquote><programlisting> 1712*4882a593Smuzhiyun 1713*4882a593Smuzhiyun void InitPointerDeviceStruct(device, map, mapLength, 1714*4882a593Smuzhiyun GetMotionEvents, ControlProc, numMotionEvents) 1715*4882a593Smuzhiyun DevicePtr device; 1716*4882a593Smuzhiyun CARD8 *map; 1717*4882a593Smuzhiyun int mapLength; 1718*4882a593Smuzhiyun ValuatorMotionProcPtr ControlProc; 1719*4882a593Smuzhiyun PtrCtrlProcPtr GetMotionEvents; 1720*4882a593Smuzhiyun int numMotionEvents; 1721*4882a593Smuzhiyun</programlisting></blockquote> 1722*4882a593SmuzhiyunInitPointerDeviceStruct is a DIX routine you call at DEVICE_INIT time to declare 1723*4882a593Smuzhiyunsome operating routines and data structures for a pointing device. 1724*4882a593Smuzhiyunmap and mapLength are as described in the X Window 1725*4882a593SmuzhiyunSystem protocol specification. 1726*4882a593SmuzhiyunControlProc and GetMotionEvents are DDX routines, see above. 1727*4882a593Smuzhiyun</para> 1728*4882a593Smuzhiyun<para> 1729*4882a593SmuzhiyunnumMotionEvents is for the motion-buffer-size for the GetMotionEvents 1730*4882a593Smuzhiyunrequest. 1731*4882a593SmuzhiyunA typical length for a motion buffer would be 100 events. 1732*4882a593SmuzhiyunA server that does not implement this capability should set 1733*4882a593SmuzhiyunnumMotionEvents to zero. 1734*4882a593Smuzhiyun</para> 1735*4882a593Smuzhiyun<para> 1736*4882a593Smuzhiyun<blockquote><programlisting> 1737*4882a593Smuzhiyun 1738*4882a593Smuzhiyun void InitKeyboardDeviceStruct(device, pKeySyms, pModifiers, Bell, ControlProc) 1739*4882a593Smuzhiyun DevicePtr device; 1740*4882a593Smuzhiyun KeySymsPtr pKeySyms; 1741*4882a593Smuzhiyun CARD8 *pModifiers; 1742*4882a593Smuzhiyun BellProcPtr Bell; 1743*4882a593Smuzhiyun KbdCtrlProcPtr ControlProc; 1744*4882a593Smuzhiyun 1745*4882a593Smuzhiyun</programlisting></blockquote> 1746*4882a593SmuzhiyunYou call this DIX routine when a keyboard device is initialized and 1747*4882a593Smuzhiyunits device procedure is called with 1748*4882a593SmuzhiyunDEVICE_INIT. 1749*4882a593SmuzhiyunThe formats of the keysyms and modifier maps are defined in 1750*4882a593SmuzhiyunXserver/include/input.h. 1751*4882a593SmuzhiyunThey describe the layout of keys on the keyboards, and the glyphs 1752*4882a593Smuzhiyunassociated with them. ( See the next section for information on 1753*4882a593Smuzhiyunsetting up the modifier map and the keysym map.) 1754*4882a593SmuzhiyunControlProc and Bell are DDX routines, see above. 1755*4882a593Smuzhiyun</para> 1756*4882a593Smuzhiyun</section> 1757*4882a593Smuzhiyun<section> 1758*4882a593Smuzhiyun <title>Keyboard Mapping and Keycodes</title> 1759*4882a593Smuzhiyun<para> 1760*4882a593SmuzhiyunWhen you send a keyboard event, you send a report that a given key has 1761*4882a593Smuzhiyuneither been pressed or has been released. There must be a keycode for 1762*4882a593Smuzhiyuneach key that identifies the key; the keycode-to-key mapping can be 1763*4882a593Smuzhiyunany mapping you desire, because you specify the mapping in a table you 1764*4882a593Smuzhiyunset up for DIX. However, you are restricted by the protocol 1765*4882a593Smuzhiyunspecification to keycode values in the range 8 to 255 inclusive. 1766*4882a593Smuzhiyun</para> 1767*4882a593Smuzhiyun<para> 1768*4882a593SmuzhiyunThe keycode mapping information that you set up consists of the following: 1769*4882a593Smuzhiyun<itemizedlist> 1770*4882a593Smuzhiyun<listitem><para> 1771*4882a593SmuzhiyunA minimum and maximum keycode number</para></listitem> 1772*4882a593Smuzhiyun<listitem><para> 1773*4882a593SmuzhiyunAn array of sets of keysyms for each key, that is of length 1774*4882a593Smuzhiyunmaxkeycode - minkeycode + 1. 1775*4882a593SmuzhiyunEach element of this array is a list of codes for symbols that are on that key. 1776*4882a593SmuzhiyunThere is no limit to the number of symbols that can be on a key.</para></listitem> 1777*4882a593Smuzhiyun</itemizedlist> 1778*4882a593SmuzhiyunOnce the map is set up, DIX keeps and 1779*4882a593Smuzhiyunmaintains the client's changes to it. 1780*4882a593Smuzhiyun</para> 1781*4882a593Smuzhiyun<para> 1782*4882a593SmuzhiyunThe X protocol defines standard names to indicate the symbol(s) 1783*4882a593Smuzhiyunprinted on each keycap. (See X11/keysym.h) 1784*4882a593Smuzhiyun</para> 1785*4882a593Smuzhiyun<para> 1786*4882a593SmuzhiyunLegal modifier keys must generate both up and down transitions. When 1787*4882a593Smuzhiyuna client tries to change a modifier key (for instance, to make "A" the 1788*4882a593Smuzhiyun"Control" key), DIX calls the following routine, which should return 1789*4882a593SmuzhiyunTRUE if the key can be used as a modifier on the given device: 1790*4882a593Smuzhiyun<blockquote><programlisting> 1791*4882a593Smuzhiyun 1792*4882a593Smuzhiyun Bool LegalModifier(key, pDev) 1793*4882a593Smuzhiyun unsigned int key; 1794*4882a593Smuzhiyun DevicePtr pDev; 1795*4882a593Smuzhiyun</programlisting></blockquote> 1796*4882a593Smuzhiyun</para> 1797*4882a593Smuzhiyun</section> 1798*4882a593Smuzhiyun</section> 1799*4882a593Smuzhiyun<section> 1800*4882a593Smuzhiyun<title>Screens</title> 1801*4882a593Smuzhiyun<para> 1802*4882a593SmuzhiyunDifferent computer graphics 1803*4882a593Smuzhiyundisplays have different capabilities. 1804*4882a593SmuzhiyunSome are simple monochrome 1805*4882a593Smuzhiyunframe buffers that are just lying 1806*4882a593Smuzhiyunthere in memory, waiting to be written into. 1807*4882a593SmuzhiyunOthers are color displays with many bits per pixel using some color lookup table. 1808*4882a593SmuzhiyunStill others have high-speed graphic processors that prefer to do all of the work 1809*4882a593Smuzhiyunthemselves, 1810*4882a593Smuzhiyunincluding maintaining their own high-level, graphic data structures. 1811*4882a593Smuzhiyun</para> 1812*4882a593Smuzhiyun<section> 1813*4882a593Smuzhiyun <title>Screen Hardware Requirements</title> 1814*4882a593Smuzhiyun<para> 1815*4882a593SmuzhiyunThe only requirement on screens is that you be able to both read 1816*4882a593Smuzhiyunand write locations in the frame buffer. 1817*4882a593SmuzhiyunAll screens must have a depth of 32 or less (unless you use 1818*4882a593Smuzhiyunan X extension to allow a greater depth). 1819*4882a593SmuzhiyunAll screens must fit into one of the classes listed in the section 1820*4882a593Smuzhiyunin this document on Visuals and Depths. 1821*4882a593Smuzhiyun</para> 1822*4882a593Smuzhiyun<para> 1823*4882a593SmuzhiyunX uses the pixel as its fundamental unit of distance on the screen. 1824*4882a593SmuzhiyunTherefore, most programs will measure everything in pixels.</para> 1825*4882a593Smuzhiyun<para> 1826*4882a593SmuzhiyunThe sample server assumes square pixels. 1827*4882a593SmuzhiyunSerious WYSIWYG (what you see is what you get) applications for 1828*4882a593Smuzhiyunpublishing and drawing programs will adjust for 1829*4882a593Smuzhiyundifferent screen resolutions automatically. 1830*4882a593SmuzhiyunConsiderable work 1831*4882a593Smuzhiyunis involved in compensating for non-square pixels (a bit in the DDX 1832*4882a593Smuzhiyuncode for the sample server but quite a bit in the client applications).</para> 1833*4882a593Smuzhiyun</section> 1834*4882a593Smuzhiyun<section> 1835*4882a593Smuzhiyun <title>Data Structures</title> 1836*4882a593Smuzhiyun<para> 1837*4882a593SmuzhiyunX supports multiple screens that are connected to the same 1838*4882a593Smuzhiyunserver. Therefore, all the per-screen information is bundled into one data 1839*4882a593Smuzhiyunstructure of attributes and procedures, which is the ScreenRec (see 1840*4882a593SmuzhiyunXserver/include/scrnintstr.h). 1841*4882a593SmuzhiyunThe procedure entry points in a ScreenRec operate on 1842*4882a593Smuzhiyunregions, colormaps, cursors, and fonts, because these resources 1843*4882a593Smuzhiyuncan differ in format from one screen to another.</para> 1844*4882a593Smuzhiyun<para> 1845*4882a593SmuzhiyunWindows are areas on the screen that can be drawn into by graphic 1846*4882a593Smuzhiyunroutines. "Pixmaps" are off-screen graphic areas that can be drawn 1847*4882a593Smuzhiyuninto. They are both considered drawables and are described in the 1848*4882a593Smuzhiyunsection on Drawables. All graphic operations work on drawables, and 1849*4882a593Smuzhiyunoperations are available to copy patches from one drawable to another.</para> 1850*4882a593Smuzhiyun<para> 1851*4882a593SmuzhiyunThe pixel image data in all drawables is in a format that is private 1852*4882a593Smuzhiyunto DDX. In fact, each instance of a drawable is associated with a 1853*4882a593Smuzhiyungiven screen. Presumably, the pixel image data for pixmaps is chosen 1854*4882a593Smuzhiyunto be conveniently understood by the hardware. All screens in a 1855*4882a593Smuzhiyunsingle server must be able to handle all pixmaps depths declared in 1856*4882a593Smuzhiyunthe connection setup information.</para> 1857*4882a593Smuzhiyun<para> 1858*4882a593SmuzhiyunPixmap images are transferred to the server in one of two ways: 1859*4882a593SmuzhiyunXYPixmap or ZPimap. XYPixmaps are a series of bitmaps, one for each 1860*4882a593Smuzhiyunbit plane of the image, using the bitmap padding rules from the 1861*4882a593Smuzhiyunconnection setup. ZPixmaps are a series of bits, nibbles, bytes or 1862*4882a593Smuzhiyunwords, one for each pixel, using the format rules (padding and so on) 1863*4882a593Smuzhiyunfor the appropriate depth.</para> 1864*4882a593Smuzhiyun<para> 1865*4882a593SmuzhiyunAll screens in a given server must agree on a set of pixmap image 1866*4882a593Smuzhiyunformats (PixmapFormat) to support (depth, number of bits per pixel, 1867*4882a593Smuzhiyunetc.).</para> 1868*4882a593Smuzhiyun<para> 1869*4882a593SmuzhiyunThere is no color interpretation of bits in the pixmap. Pixmaps 1870*4882a593Smuzhiyundo not contain pixel values. The interpretation is made only when 1871*4882a593Smuzhiyunthe bits are transferred onto the screen.</para> 1872*4882a593Smuzhiyun<para> 1873*4882a593SmuzhiyunThe screenInfo structure (in scrnintstr.h) is a global data structure 1874*4882a593Smuzhiyunthat has a pointer to an array of ScreenRecs, one for each screen on 1875*4882a593Smuzhiyunthe server. (These constitute the one and only description of each 1876*4882a593Smuzhiyunscreen in the server.) Each screen has an identifying index (0, 1, 2, ...). 1877*4882a593SmuzhiyunIn addition, the screenInfo struct contains global server-wide 1878*4882a593Smuzhiyundetails, such as the bit- and byte- order in all bit images, and the 1879*4882a593Smuzhiyunlist of pixmap image formats that are supported. The X protocol 1880*4882a593Smuzhiyuninsists that these must be the same for all screens on the server.</para> 1881*4882a593Smuzhiyun</section> 1882*4882a593Smuzhiyun<section> 1883*4882a593Smuzhiyun <title>Output Initialization</title> 1884*4882a593Smuzhiyun<para> 1885*4882a593Smuzhiyun<blockquote><programlisting> 1886*4882a593Smuzhiyun 1887*4882a593Smuzhiyun InitOutput(pScreenInfo, argc, argv) 1888*4882a593Smuzhiyun ScreenInfo *pScreenInfo; 1889*4882a593Smuzhiyun int argc; 1890*4882a593Smuzhiyun char **argv; 1891*4882a593Smuzhiyun</programlisting></blockquote> 1892*4882a593SmuzhiyunUpon initialization, your DDX routine InitOutput() is called by DIX. 1893*4882a593SmuzhiyunIt is passed a pointer to screenInfo to initialize. It is also passed 1894*4882a593Smuzhiyunthe argc and argv from main() for your server for the command-line 1895*4882a593Smuzhiyunarguments. These arguments may indicate what or how many screen 1896*4882a593Smuzhiyundevice(s) to use or in what way to use them. For instance, your 1897*4882a593Smuzhiyunserver command line may allow a "-D" flag followed by the name of the 1898*4882a593Smuzhiyunscreen device to use.</para> 1899*4882a593Smuzhiyun<para> 1900*4882a593SmuzhiyunYour InitOutput() routine should initialize each screen you wish to 1901*4882a593Smuzhiyunuse by calling AddScreen(), and then it should initialize the pixmap 1902*4882a593Smuzhiyunformats that you support by storing values directly into the 1903*4882a593SmuzhiyunscreenInfo data structure. You should also set certain 1904*4882a593Smuzhiyunimplementation-dependent numbers and procedures in your screenInfo, 1905*4882a593Smuzhiyunwhich determines the pixmap and scanline padding rules for all screens 1906*4882a593Smuzhiyunin the server.</para> 1907*4882a593Smuzhiyun<para> 1908*4882a593Smuzhiyun<blockquote><programlisting> 1909*4882a593Smuzhiyun 1910*4882a593Smuzhiyun int AddScreen(scrInitProc, argc, argv) 1911*4882a593Smuzhiyun Bool (*scrInitProc)(); 1912*4882a593Smuzhiyun int argc; 1913*4882a593Smuzhiyun char **argv; 1914*4882a593Smuzhiyun</programlisting></blockquote> 1915*4882a593SmuzhiyunYou should call AddScreen(), a DIX procedure, in InitOutput() once for 1916*4882a593Smuzhiyuneach screen to add it to the screenInfo database. The first argument 1917*4882a593Smuzhiyunis an initialization procedure for the screen that you supply. The 1918*4882a593Smuzhiyunsecond and third are the argc and argv from main(). It returns the 1919*4882a593Smuzhiyunscreen number of the screen installed, or -1 if there is either 1920*4882a593Smuzhiyuninsufficient memory to add the screen, or (*scrInitProc) returned 1921*4882a593SmuzhiyunFALSE.</para> 1922*4882a593Smuzhiyun<para> 1923*4882a593SmuzhiyunThe scrInitProc should be of the following form: 1924*4882a593Smuzhiyun<blockquote><programlisting> 1925*4882a593Smuzhiyun 1926*4882a593Smuzhiyun Bool scrInitProc(pScreen, argc, argv) 1927*4882a593Smuzhiyun ScreenPtr pScreen; 1928*4882a593Smuzhiyun int argc; 1929*4882a593Smuzhiyun char **argv; 1930*4882a593Smuzhiyun</programlisting></blockquote> 1931*4882a593SmuzhiyunpScreen is the pointer to the screen's new ScreenRec. argc and argv 1932*4882a593Smuzhiyunare as before. Your screen initialize procedure should return TRUE 1933*4882a593Smuzhiyunupon success or FALSE if the screen cannot be initialized (for 1934*4882a593Smuzhiyun instance, if the screen hardware does not exist on this machine).</para> 1935*4882a593Smuzhiyun<para> 1936*4882a593SmuzhiyunThis procedure must determine what actual device it is supposed to initialize. 1937*4882a593SmuzhiyunIf you have a different procedure for each screen, then it is no problem. 1938*4882a593SmuzhiyunIf you have the same procedure for multiple screens, it may have trouble 1939*4882a593Smuzhiyunfiguring out which screen to initialize each time around, especially if 1940*4882a593SmuzhiyunInitOutput() does not initialize all of the screens. 1941*4882a593SmuzhiyunIt is probably easiest to have one procedure for each screen.</para> 1942*4882a593Smuzhiyun<para> 1943*4882a593SmuzhiyunThe initialization procedure should fill in all the screen procedures 1944*4882a593Smuzhiyunfor that screen (windowing functions, region functions, etc.) and certain 1945*4882a593Smuzhiyunscreen attributes for that screen.</para> 1946*4882a593Smuzhiyun</section> 1947*4882a593Smuzhiyun<section> 1948*4882a593Smuzhiyun <title>Region Routines in the ScreenRec</title> 1949*4882a593Smuzhiyun<para> 1950*4882a593SmuzhiyunA region is a dynamically allocated data structure that describes an 1951*4882a593Smuzhiyunirregularly shaped piece of real estate in XY pixel space. You can 1952*4882a593Smuzhiyunthink of it as a set of pixels on the screen to be operated upon with 1953*4882a593Smuzhiyunset operations such as AND and OR.</para> 1954*4882a593Smuzhiyun<para> 1955*4882a593SmuzhiyunA region is frequently implemented as a list of rectangles or bitmaps 1956*4882a593Smuzhiyunthat enclose the selected pixels. Region operators control the 1957*4882a593Smuzhiyun"clipping policy," or the operations that work on regions. (The 1958*4882a593Smuzhiyunsample server uses YX-banded rectangles. Unless you have something 1959*4882a593Smuzhiyunalready implemented for your graphics system, you should keep that 1960*4882a593Smuzhiyunimplementation.) The procedure pointers to the region operators are 1961*4882a593Smuzhiyunlocated in the ScreenRec data structure. The definition of a region 1962*4882a593Smuzhiyuncan be found in the file Xserver/include/regionstr.h. The region code 1963*4882a593Smuzhiyunis found in Xserver/mi/miregion.c. DDX implementations using other 1964*4882a593Smuzhiyunregion formats will need to supply different versions of the region 1965*4882a593Smuzhiyunoperators.</para> 1966*4882a593Smuzhiyun<para> 1967*4882a593SmuzhiyunSince the list of rectangles is unbounded in size, part of the region 1968*4882a593Smuzhiyundata structure is usually a large, dynamically allocated chunk of 1969*4882a593Smuzhiyunmemory. As your region operators calculate logical combinations of 1970*4882a593Smuzhiyunregions, these blocks may need to be reallocated by your region 1971*4882a593Smuzhiyunsoftware. For instance, in the sample server, a RegionRec has some 1972*4882a593Smuzhiyunheader information and a pointer to a dynamically allocated rectangle 1973*4882a593Smuzhiyunlist. Periodically, the rectangle list needs to be expanded with 1974*4882a593Smuzhiyunrealloc(), whereupon the new pointer is remembered in the RegionRec.</para> 1975*4882a593Smuzhiyun<para> 1976*4882a593SmuzhiyunMost of the region operations come in two forms: a function pointer in 1977*4882a593Smuzhiyunthe Screen structure, and a macro. The server can be compiled so that 1978*4882a593Smuzhiyunthe macros make direct calls to the appropriate functions (instead of 1979*4882a593Smuzhiyunindirecting through a screen function pointer), or it can be compiled 1980*4882a593Smuzhiyunso that the macros are identical to the function pointer forms. 1981*4882a593SmuzhiyunMaking direct calls is faster on many architectures.</para> 1982*4882a593Smuzhiyun<para> 1983*4882a593Smuzhiyun<blockquote><programlisting> 1984*4882a593Smuzhiyun 1985*4882a593Smuzhiyun RegionPtr pScreen->RegionCreate( rect, size) 1986*4882a593Smuzhiyun BoxPtr rect; 1987*4882a593Smuzhiyun int size; 1988*4882a593Smuzhiyun 1989*4882a593Smuzhiyun macro: RegionPtr RegionCreate(rect, size) 1990*4882a593Smuzhiyun 1991*4882a593Smuzhiyun</programlisting></blockquote> 1992*4882a593SmuzhiyunRegionCreate creates a region that describes ONE rectangle. The 1993*4882a593Smuzhiyuncaller can avoid unnecessary reallocation and copying by declaring the 1994*4882a593Smuzhiyunprobable maximum number of rectangles that this region will need to 1995*4882a593Smuzhiyundescribe itself. Your region routines, though, cannot fail just 1996*4882a593Smuzhiyunbecause the region grows beyond this size. The caller of this routine 1997*4882a593Smuzhiyuncan pass almost anything as the size; the value is merely a good guess 1998*4882a593Smuzhiyunas to the maximum size until it is proven wrong by subsequent use. 1999*4882a593SmuzhiyunYour region procedures are then on their own in estimating how big the 2000*4882a593Smuzhiyunregion will get. Your implementation might ignore size, if 2001*4882a593Smuzhiyunapplicable.</para> 2002*4882a593Smuzhiyun<para> 2003*4882a593Smuzhiyun<blockquote><programlisting> 2004*4882a593Smuzhiyun 2005*4882a593Smuzhiyun void pScreen->RegionInit (pRegion, rect, size) 2006*4882a593Smuzhiyun RegionPtr pRegion; 2007*4882a593Smuzhiyun BoxPtr rect; 2008*4882a593Smuzhiyun int size; 2009*4882a593Smuzhiyun 2010*4882a593Smuzhiyun macro: RegionInit(pRegion, rect, size) 2011*4882a593Smuzhiyun 2012*4882a593Smuzhiyun</programlisting></blockquote> 2013*4882a593SmuzhiyunGiven an existing raw region structure (such as an local variable), this 2014*4882a593Smuzhiyunroutine fills in the appropriate fields to make this region as usable as 2015*4882a593Smuzhiyunone returned from RegionCreate. This avoids the additional dynamic memory 2016*4882a593Smuzhiyunallocation overhead for the region structure itself. 2017*4882a593Smuzhiyun</para> 2018*4882a593Smuzhiyun<para> 2019*4882a593Smuzhiyun<blockquote><programlisting> 2020*4882a593Smuzhiyun 2021*4882a593Smuzhiyun Bool pScreen->RegionCopy(dstrgn, srcrgn) 2022*4882a593Smuzhiyun RegionPtr dstrgn, srcrgn; 2023*4882a593Smuzhiyun 2024*4882a593Smuzhiyun macro: Bool RegionCopy(dstrgn, srcrgn) 2025*4882a593Smuzhiyun 2026*4882a593Smuzhiyun</programlisting></blockquote> 2027*4882a593SmuzhiyunRegionCopy copies the description of one region, srcrgn, to another 2028*4882a593Smuzhiyunalready-created region, 2029*4882a593Smuzhiyundstrgn; returning TRUE if the copy succeeded, and FALSE otherwise.</para> 2030*4882a593Smuzhiyun<para> 2031*4882a593Smuzhiyun<blockquote><programlisting> 2032*4882a593Smuzhiyun 2033*4882a593Smuzhiyun void pScreen->RegionDestroy( pRegion) 2034*4882a593Smuzhiyun RegionPtr pRegion; 2035*4882a593Smuzhiyun 2036*4882a593Smuzhiyun macro: RegionDestroy(pRegion) 2037*4882a593Smuzhiyun 2038*4882a593Smuzhiyun</programlisting></blockquote> 2039*4882a593SmuzhiyunRegionDestroy destroys a region and frees all allocated memory.</para> 2040*4882a593Smuzhiyun<para> 2041*4882a593Smuzhiyun<blockquote><programlisting> 2042*4882a593Smuzhiyun 2043*4882a593Smuzhiyun void pScreen->RegionUninit (pRegion) 2044*4882a593Smuzhiyun RegionPtr pRegion; 2045*4882a593Smuzhiyun 2046*4882a593Smuzhiyun macro: RegionUninit(pRegion) 2047*4882a593Smuzhiyun 2048*4882a593Smuzhiyun</programlisting></blockquote> 2049*4882a593SmuzhiyunFrees everything except the region structure itself, useful when the 2050*4882a593Smuzhiyunregion was originally passed to RegionInit instead of received from 2051*4882a593SmuzhiyunRegionCreate. When this call returns, pRegion must not be reused until 2052*4882a593Smuzhiyunit has been RegionInit'ed again.</para> 2053*4882a593Smuzhiyun<para> 2054*4882a593Smuzhiyun<blockquote><programlisting> 2055*4882a593Smuzhiyun 2056*4882a593Smuzhiyun Bool pScreen->Intersect(newReg, reg1, reg2) 2057*4882a593Smuzhiyun RegionPtr newReg, reg1, reg2; 2058*4882a593Smuzhiyun 2059*4882a593Smuzhiyun macro: Bool RegionIntersect(newReg, reg1, reg2) 2060*4882a593Smuzhiyun 2061*4882a593Smuzhiyun Bool pScreen->Union(newReg, reg1, reg2) 2062*4882a593Smuzhiyun RegionPtr newReg, reg1, reg2; 2063*4882a593Smuzhiyun 2064*4882a593Smuzhiyun macro: Bool RegionUnion(newReg, reg1, reg2) 2065*4882a593Smuzhiyun 2066*4882a593Smuzhiyun Bool pScreen->Subtract(newReg, regMinuend, regSubtrahend) 2067*4882a593Smuzhiyun RegionPtr newReg, regMinuend, regSubtrahend; 2068*4882a593Smuzhiyun 2069*4882a593Smuzhiyun macro: Bool RegionUnion(newReg, regMinuend, regSubtrahend) 2070*4882a593Smuzhiyun 2071*4882a593Smuzhiyun Bool pScreen->Inverse(newReg, pReg, pBox) 2072*4882a593Smuzhiyun RegionPtr newReg, pReg; 2073*4882a593Smuzhiyun BoxPtr pBox; 2074*4882a593Smuzhiyun 2075*4882a593Smuzhiyun macro: Bool RegionInverse(newReg, pReg, pBox) 2076*4882a593Smuzhiyun 2077*4882a593Smuzhiyun</programlisting></blockquote> 2078*4882a593SmuzhiyunThe above four calls all do basic logical operations on regions. They 2079*4882a593Smuzhiyunset the new region (which already exists) to describe the logical 2080*4882a593Smuzhiyunintersection, union, set difference, or inverse of the region(s) that 2081*4882a593Smuzhiyunwere passed in. Your routines must be able to handle a situation 2082*4882a593Smuzhiyunwhere the newReg is the same region as one of the other region 2083*4882a593Smuzhiyunarguments.</para> 2084*4882a593Smuzhiyun<para> 2085*4882a593SmuzhiyunThe subtract function removes the Subtrahend from the Minuend and 2086*4882a593Smuzhiyunputs the result in newReg.</para> 2087*4882a593Smuzhiyun<para> 2088*4882a593SmuzhiyunThe inverse function returns a region that is the pBox minus the 2089*4882a593Smuzhiyunregion passed in. (A true "inverse" would make a region that extends 2090*4882a593Smuzhiyunto infinity in all directions but has holes in the middle.) It is 2091*4882a593Smuzhiyunundefined for situations where the region extends beyond the box.</para> 2092*4882a593Smuzhiyun<para> 2093*4882a593SmuzhiyunEach routine must return the value TRUE for success.</para> 2094*4882a593Smuzhiyun<para> 2095*4882a593Smuzhiyun<blockquote><programlisting> 2096*4882a593Smuzhiyun 2097*4882a593Smuzhiyun void pScreen->RegionReset(pRegion, pBox) 2098*4882a593Smuzhiyun RegionPtr pRegion; 2099*4882a593Smuzhiyun BoxPtr pBox; 2100*4882a593Smuzhiyun 2101*4882a593Smuzhiyun macro: RegionReset(pRegion, pBox) 2102*4882a593Smuzhiyun 2103*4882a593Smuzhiyun</programlisting></blockquote> 2104*4882a593SmuzhiyunRegionReset sets the region to describe 2105*4882a593Smuzhiyunone rectangle and reallocates it to a size of one rectangle, if applicable.</para> 2106*4882a593Smuzhiyun<para> 2107*4882a593Smuzhiyun<blockquote><programlisting> 2108*4882a593Smuzhiyun 2109*4882a593Smuzhiyun void pScreen->TranslateRegion(pRegion, x, y) 2110*4882a593Smuzhiyun RegionPtr pRegion; 2111*4882a593Smuzhiyun int x, y; 2112*4882a593Smuzhiyun 2113*4882a593Smuzhiyun macro: RegionTranslate(pRegion, x, y) 2114*4882a593Smuzhiyun 2115*4882a593Smuzhiyun</programlisting></blockquote> 2116*4882a593SmuzhiyunTranslateRegion simply moves a region +x in the x direction and +y in the y 2117*4882a593Smuzhiyundirection.</para> 2118*4882a593Smuzhiyun<para> 2119*4882a593Smuzhiyun<blockquote><programlisting> 2120*4882a593Smuzhiyun 2121*4882a593Smuzhiyun int pScreen->RectIn(pRegion, pBox) 2122*4882a593Smuzhiyun RegionPtr pRegion; 2123*4882a593Smuzhiyun BoxPtr pBox; 2124*4882a593Smuzhiyun 2125*4882a593Smuzhiyun macro: int RegionContainsRect(pRegion, pBox) 2126*4882a593Smuzhiyun 2127*4882a593Smuzhiyun</programlisting></blockquote> 2128*4882a593SmuzhiyunRectIn returns one of the defined constants rgnIN, rgnOUT, or rgnPART, 2129*4882a593Smuzhiyundepending upon whether the box is entirely inside the region, entirely 2130*4882a593Smuzhiyunoutside of the region, or partly in and partly out of the region. 2131*4882a593SmuzhiyunThese constants are defined in Xserver/include/region.h.</para> 2132*4882a593Smuzhiyun<para> 2133*4882a593Smuzhiyun<blockquote><programlisting> 2134*4882a593Smuzhiyun 2135*4882a593Smuzhiyun Bool pScreen->PointInRegion(pRegion, x, y, pBox) 2136*4882a593Smuzhiyun RegionPtr pRegion; 2137*4882a593Smuzhiyun int x, y; 2138*4882a593Smuzhiyun BoxPtr pBox; 2139*4882a593Smuzhiyun 2140*4882a593Smuzhiyun macro: Bool RegionContainsPoint(pRegion, x, y, pBox) 2141*4882a593Smuzhiyun 2142*4882a593Smuzhiyun</programlisting></blockquote> 2143*4882a593SmuzhiyunPointInRegion returns true if the point x, y is in the region. In 2144*4882a593Smuzhiyunaddition, it fills the rectangle pBox with coordinates of a rectangle 2145*4882a593Smuzhiyunthat is entirely inside of pRegion and encloses the point. In the mi 2146*4882a593Smuzhiyunimplementation, it is the largest such rectangle. (Due to the sample 2147*4882a593Smuzhiyunserver implementation, this comes cheaply.)</para> 2148*4882a593Smuzhiyun<para> 2149*4882a593SmuzhiyunThis routine used by DIX when tracking the pointing device and 2150*4882a593Smuzhiyundeciding whether to report mouse events or change the cursor. For 2151*4882a593Smuzhiyuninstance, DIX needs to change the cursor when it moves from one window 2152*4882a593Smuzhiyunto another. Due to overlapping windows, the shape to check may be 2153*4882a593Smuzhiyunirregular. A PointInRegion() call for every pointing device movement 2154*4882a593Smuzhiyunmay be too expensive. The pBox is a kind of wake-up box; DIX need not 2155*4882a593Smuzhiyuncall PointInRegion() again until the cursor wanders outside of the 2156*4882a593Smuzhiyunreturned box.</para> 2157*4882a593Smuzhiyun<para> 2158*4882a593Smuzhiyun<blockquote><programlisting> 2159*4882a593Smuzhiyun 2160*4882a593Smuzhiyun Bool pScreen->RegionNotEmpty(pRegion) 2161*4882a593Smuzhiyun RegionPtr pRegion; 2162*4882a593Smuzhiyun 2163*4882a593Smuzhiyun macro: Bool RegionNotEmpty(pRegion) 2164*4882a593Smuzhiyun 2165*4882a593Smuzhiyun</programlisting></blockquote> 2166*4882a593SmuzhiyunRegionNotEmpty is a boolean function that returns 2167*4882a593Smuzhiyuntrue or false depending upon whether the region encloses any pixels.</para> 2168*4882a593Smuzhiyun<para> 2169*4882a593Smuzhiyun<blockquote><programlisting> 2170*4882a593Smuzhiyun 2171*4882a593Smuzhiyun void pScreen->RegionEmpty(pRegion) 2172*4882a593Smuzhiyun RegionPtr pRegion; 2173*4882a593Smuzhiyun 2174*4882a593Smuzhiyun macro: RegionEmpty(pRegion) 2175*4882a593Smuzhiyun 2176*4882a593Smuzhiyun</programlisting></blockquote> 2177*4882a593SmuzhiyunRegionEmpty sets the region to be empty.</para> 2178*4882a593Smuzhiyun<para> 2179*4882a593Smuzhiyun<blockquote><programlisting> 2180*4882a593Smuzhiyun 2181*4882a593Smuzhiyun BoxPtr pScreen->RegionExtents(pRegion) 2182*4882a593Smuzhiyun RegionPtr pRegion; 2183*4882a593Smuzhiyun 2184*4882a593Smuzhiyun macro: RegionExtents(pRegion) 2185*4882a593Smuzhiyun 2186*4882a593Smuzhiyun</programlisting></blockquote> 2187*4882a593SmuzhiyunRegionExtents returns a rectangle that is the smallest 2188*4882a593Smuzhiyunpossible superset of the entire region. 2189*4882a593SmuzhiyunThe caller will not modify this rectangle, so it can be the one 2190*4882a593Smuzhiyunin your region struct.</para> 2191*4882a593Smuzhiyun<para> 2192*4882a593Smuzhiyun<blockquote><programlisting> 2193*4882a593Smuzhiyun 2194*4882a593Smuzhiyun Bool pScreen->RegionAppend (pDstRgn, pRegion) 2195*4882a593Smuzhiyun RegionPtr pDstRgn; 2196*4882a593Smuzhiyun RegionPtr pRegion; 2197*4882a593Smuzhiyun 2198*4882a593Smuzhiyun macro: Bool RegionAppend(pDstRgn, pRegion) 2199*4882a593Smuzhiyun 2200*4882a593Smuzhiyun Bool pScreen->RegionValidate (pRegion, pOverlap) 2201*4882a593Smuzhiyun RegionPtr pRegion; 2202*4882a593Smuzhiyun Bool *pOverlap; 2203*4882a593Smuzhiyun 2204*4882a593Smuzhiyun macro: Bool RegionValidate(pRegion, pOverlap) 2205*4882a593Smuzhiyun 2206*4882a593Smuzhiyun</programlisting></blockquote> 2207*4882a593SmuzhiyunThese functions provide an optimization for clip list generation and 2208*4882a593Smuzhiyunmust be used in conjunction. The combined effect is to produce the 2209*4882a593Smuzhiyununion of a collection of regions, by using RegionAppend several times, 2210*4882a593Smuzhiyunand finally calling RegionValidate which takes the intermediate 2211*4882a593Smuzhiyunrepresentation (which needn't be a valid region) and produces the 2212*4882a593Smuzhiyundesired union. pOverlap is set to TRUE if any of the original 2213*4882a593Smuzhiyunregions overlap; FALSE otherwise.</para> 2214*4882a593Smuzhiyun<para> 2215*4882a593Smuzhiyun<blockquote><programlisting> 2216*4882a593Smuzhiyun 2217*4882a593Smuzhiyun RegionPtr pScreen->BitmapToRegion (pPixmap) 2218*4882a593Smuzhiyun PixmapPtr pPixmap; 2219*4882a593Smuzhiyun 2220*4882a593Smuzhiyun macro: RegionPtr BitmapToRegion(pScreen, pPixmap) 2221*4882a593Smuzhiyun 2222*4882a593Smuzhiyun</programlisting></blockquote> 2223*4882a593SmuzhiyunGiven a depth-1 pixmap, this routine must create a valid region which 2224*4882a593Smuzhiyunincludes all the areas of the pixmap filled with 1's and excludes the 2225*4882a593Smuzhiyunareas filled with 0's. This routine returns NULL if out of memory.</para> 2226*4882a593Smuzhiyun<para> 2227*4882a593Smuzhiyun<blockquote><programlisting> 2228*4882a593Smuzhiyun 2229*4882a593Smuzhiyun RegionPtr pScreen->RectsToRegion (nrects, pRects, ordering) 2230*4882a593Smuzhiyun int nrects; 2231*4882a593Smuzhiyun xRectangle *pRects; 2232*4882a593Smuzhiyun int ordering; 2233*4882a593Smuzhiyun 2234*4882a593Smuzhiyun macro: RegionPtr RegionFromRects(nrects, pRects, ordering) 2235*4882a593Smuzhiyun 2236*4882a593Smuzhiyun</programlisting></blockquote> 2237*4882a593SmuzhiyunGiven a client-supplied list of rectangles, produces a region which includes 2238*4882a593Smuzhiyunthe union of all the rectangles. Ordering may be used as a hint which 2239*4882a593Smuzhiyundescribes how the rectangles are sorted. As the hint is provided by a 2240*4882a593Smuzhiyunclient, it must not be required to be correct, but the results when it is 2241*4882a593Smuzhiyunnot correct are not defined (core dump is not an option here).</para> 2242*4882a593Smuzhiyun<para> 2243*4882a593Smuzhiyun<blockquote><programlisting> 2244*4882a593Smuzhiyun 2245*4882a593Smuzhiyun void pScreen->SendGraphicsExpose(client,pRegion,drawable,major,minor) 2246*4882a593Smuzhiyun ClientPtr client; 2247*4882a593Smuzhiyun RegionPtr pRegion; 2248*4882a593Smuzhiyun XID drawable; 2249*4882a593Smuzhiyun int major; 2250*4882a593Smuzhiyun int minor; 2251*4882a593Smuzhiyun 2252*4882a593Smuzhiyun</programlisting></blockquote> 2253*4882a593SmuzhiyunSendGraphicsExpose dispatches a list of GraphicsExposure events which 2254*4882a593Smuzhiyunspan the region to the specified client. If the region is empty, or 2255*4882a593Smuzhiyuna NULL pointer, a NoExpose event is sent instead.</para> 2256*4882a593Smuzhiyun</section> 2257*4882a593Smuzhiyun<section> 2258*4882a593Smuzhiyun <title>Cursor Routines for a Screen</title> 2259*4882a593Smuzhiyun<para> 2260*4882a593SmuzhiyunA cursor is the visual form tied to the pointing device. The default 2261*4882a593Smuzhiyuncursor is an "X" shape, but the cursor can have any shape. When a 2262*4882a593Smuzhiyunclient creates a window, it declares what shape the cursor will be 2263*4882a593Smuzhiyunwhen it strays into that window on the screen.</para> 2264*4882a593Smuzhiyun<para> 2265*4882a593SmuzhiyunFor each possible shape the cursor assumes, there is a CursorRec data 2266*4882a593Smuzhiyunstructure. This data structure contains a pointer to a CursorBits 2267*4882a593Smuzhiyundata structure which contains a bitmap for the image of the cursor and 2268*4882a593Smuzhiyuna bitmap for a mask behind the cursor, in addition, the CursorRec data 2269*4882a593Smuzhiyunstructure contains foreground and background colors for the cursor. 2270*4882a593SmuzhiyunThe CursorBits data structure is shared among multiple CursorRec 2271*4882a593Smuzhiyunstructures which use the same font and glyph to describe both source 2272*4882a593Smuzhiyunand mask. The cursor image is applied to the screen by applying the 2273*4882a593Smuzhiyunmask first, clearing 1 bits in its form to the background color, and 2274*4882a593Smuzhiyunthen overwriting on the source image, in the foreground color. (One 2275*4882a593Smuzhiyunbits of the source image that fall on top of zero bits of the mask 2276*4882a593Smuzhiyunimage are undefined.) This way, a cursor can have transparent parts, 2277*4882a593Smuzhiyunand opaque parts in two colors. X allows any cursor size, but some 2278*4882a593Smuzhiyunhardware cursor schemes allow a maximum of N pixels by M pixels. 2279*4882a593SmuzhiyunTherefore, you are allowed to transform the cursor to a smaller size, 2280*4882a593Smuzhiyunbut be sure to include the hot-spot.</para> 2281*4882a593Smuzhiyun<para> 2282*4882a593SmuzhiyunCursorBits in Xserver/include/cursorstr.h is a device-independent 2283*4882a593Smuzhiyunstructure containing a device-independent representation of the bits 2284*4882a593Smuzhiyunfor the source and mask. (This is possible because the bitmap 2285*4882a593Smuzhiyunrepresentation is the same for all screens.)</para> 2286*4882a593Smuzhiyun<para> 2287*4882a593SmuzhiyunWhen a cursor is created, it is "realized" for each screen. At 2288*4882a593Smuzhiyunrealization time, each screen has the chance to convert the bits into 2289*4882a593Smuzhiyunsome other representation that may be more convenient (for instance, 2290*4882a593Smuzhiyunputting the cursor into off-screen memory) and set up its 2291*4882a593Smuzhiyundevice-private area in either the CursorRec data structure or 2292*4882a593SmuzhiyunCursorBits data structure as appropriate to possibly point to whatever 2293*4882a593Smuzhiyundata structures are needed. It is more memory-conservative to share 2294*4882a593Smuzhiyunrealizations by using the CursorBits private field, but this makes the 2295*4882a593Smuzhiyunassumption that the realization is independent of the colors used 2296*4882a593Smuzhiyun(which is typically true). For instance, the following are the device 2297*4882a593Smuzhiyunprivate entries for a particular screen and cursor: 2298*4882a593Smuzhiyun<blockquote><programlisting> 2299*4882a593Smuzhiyun 2300*4882a593Smuzhiyun pCursor->devPriv[pScreen->myNum] 2301*4882a593Smuzhiyun pCursor->bits->devPriv[pScreen->myNum] 2302*4882a593Smuzhiyun 2303*4882a593Smuzhiyun</programlisting></blockquote> 2304*4882a593SmuzhiyunThis is done because the change from one cursor shape to another must 2305*4882a593Smuzhiyunbe fast and responsive; the cursor image should be able to flutter as 2306*4882a593Smuzhiyunfast as the user moves it across the screen.</para> 2307*4882a593Smuzhiyun<para> 2308*4882a593SmuzhiyunYou must implement the following routines for your hardware: 2309*4882a593Smuzhiyun<blockquote><programlisting> 2310*4882a593Smuzhiyun 2311*4882a593Smuzhiyun Bool pScreen->RealizeCursor( pScr, pCurs) 2312*4882a593Smuzhiyun ScreenPtr pScr; 2313*4882a593Smuzhiyun CursorPtr pCurs; 2314*4882a593Smuzhiyun 2315*4882a593Smuzhiyun Bool pScreen->UnrealizeCursor( pScr, pCurs) 2316*4882a593Smuzhiyun ScreenPtr pScr; 2317*4882a593Smuzhiyun CursorPtr pCurs; 2318*4882a593Smuzhiyun 2319*4882a593Smuzhiyun</programlisting></blockquote> 2320*4882a593Smuzhiyun</para> 2321*4882a593Smuzhiyun<para> 2322*4882a593SmuzhiyunRealizeCursor and UnrealizeCursor should realize (allocate and 2323*4882a593Smuzhiyuncalculate all data needed) and unrealize (free the dynamically 2324*4882a593Smuzhiyunallocated data) a given cursor when DIX needs them. They are called 2325*4882a593Smuzhiyunwhenever a device-independent cursor is created or destroyed. The 2326*4882a593Smuzhiyunsource and mask bits pointed to by fields in pCurs are undefined for 2327*4882a593Smuzhiyunbits beyond the right edge of the cursor. This is so because the bits 2328*4882a593Smuzhiyunare in Bitmap format, which may have pad bits on the right edge. You 2329*4882a593Smuzhiyunshould inhibit UnrealizeCursor() if the cursor is currently in use; 2330*4882a593Smuzhiyunthis happens when the system is reset.</para> 2331*4882a593Smuzhiyun<para> 2332*4882a593Smuzhiyun<blockquote><programlisting> 2333*4882a593Smuzhiyun 2334*4882a593Smuzhiyun Bool pScreen->DisplayCursor( pScr, pCurs) 2335*4882a593Smuzhiyun ScreenPtr pScr; 2336*4882a593Smuzhiyun CursorPtr pCurs; 2337*4882a593Smuzhiyun 2338*4882a593Smuzhiyun</programlisting></blockquote> 2339*4882a593SmuzhiyunDisplayCursor should change the cursor on the given screen to the one 2340*4882a593Smuzhiyunpassed in. It is called by DIX when the user moves the pointing 2341*4882a593Smuzhiyundevice into a different window with a different cursor. The hotspot 2342*4882a593Smuzhiyunin the cursor should be aligned with the current cursor position.</para> 2343*4882a593Smuzhiyun<para> 2344*4882a593Smuzhiyun<blockquote><programlisting> 2345*4882a593Smuzhiyun 2346*4882a593Smuzhiyun void pScreen->RecolorCursor( pScr, pCurs, displayed) 2347*4882a593Smuzhiyun ScreenPtr pScr; 2348*4882a593Smuzhiyun CursorPtr pCurs; 2349*4882a593Smuzhiyun Bool displayed; 2350*4882a593Smuzhiyun</programlisting></blockquote> 2351*4882a593SmuzhiyunRecolorCursor notifies DDX that the colors in pCurs have changed and 2352*4882a593Smuzhiyunindicates whether this is the cursor currently being displayed. If it 2353*4882a593Smuzhiyunis, the cursor hardware state may have to be updated. Whether 2354*4882a593Smuzhiyundisplayed or not, state created at RealizeCursor time may have to be 2355*4882a593Smuzhiyunupdated. A generic version, miRecolorCursor, may be used that 2356*4882a593Smuzhiyundoes an unrealize, a realize, and possibly a display (in micursor.c); 2357*4882a593Smuzhiyunhowever this constrains UnrealizeCursor and RealizeCursor to always return 2358*4882a593SmuzhiyunTRUE as no error indication is returned here.</para> 2359*4882a593Smuzhiyun<para> 2360*4882a593Smuzhiyun<blockquote><programlisting> 2361*4882a593Smuzhiyun 2362*4882a593Smuzhiyun void pScreen->ConstrainCursor( pScr, pBox) 2363*4882a593Smuzhiyun ScreenPtr pScr; 2364*4882a593Smuzhiyun BoxPtr pBox; 2365*4882a593Smuzhiyun 2366*4882a593Smuzhiyun</programlisting></blockquote> 2367*4882a593SmuzhiyunConstrainCursor should cause the cursor to restrict its motion to the 2368*4882a593Smuzhiyunrectangle pBox. DIX code is capable of enforcing this constraint by 2369*4882a593Smuzhiyunforcefully moving the cursor if it strays out of the rectangle, but 2370*4882a593SmuzhiyunConstrainCursor offers a way to send a hint to the driver or hardware 2371*4882a593Smuzhiyunif such support is available. This can prevent the cursor from 2372*4882a593Smuzhiyunwandering out of the box, then jumping back, as DIX forces it back.</para> 2373*4882a593Smuzhiyun<para> 2374*4882a593Smuzhiyun<blockquote><programlisting> 2375*4882a593Smuzhiyun 2376*4882a593Smuzhiyun void pScreen->PointerNonInterestBox( pScr, pBox) 2377*4882a593Smuzhiyun ScreenPtr pScr; 2378*4882a593Smuzhiyun BoxPtr pBox; 2379*4882a593Smuzhiyun 2380*4882a593Smuzhiyun</programlisting></blockquote> 2381*4882a593SmuzhiyunPointerNonInterestBox is DIX's way of telling the pointing device code 2382*4882a593Smuzhiyunnot to report motion events while the cursor is inside a given 2383*4882a593Smuzhiyunrectangle on the given screen. It is optional and, if not 2384*4882a593Smuzhiyunimplemented, it should do nothing. This routine is called only when 2385*4882a593Smuzhiyunthe client has declared that it is not interested in motion events in 2386*4882a593Smuzhiyuna given window. The rectangle you get may be a subset of that window. 2387*4882a593SmuzhiyunIt saves DIX code the time required to discard uninteresting mouse 2388*4882a593Smuzhiyunmotion events. This is only a hint, which may speed performance. 2389*4882a593SmuzhiyunNothing in DIX currently calls PointerNonInterestBox.</para> 2390*4882a593Smuzhiyun<para> 2391*4882a593Smuzhiyun<blockquote><programlisting> 2392*4882a593Smuzhiyun 2393*4882a593Smuzhiyun void pScreen->CursorLimits( pScr, pCurs, pHotBox, pTopLeftBox) 2394*4882a593Smuzhiyun ScreenPtr pScr; 2395*4882a593Smuzhiyun CursorPtr pCurs; 2396*4882a593Smuzhiyun BoxPtr pHotBox; 2397*4882a593Smuzhiyun BoxPtr pTopLeftBox; /* return value */ 2398*4882a593Smuzhiyun 2399*4882a593Smuzhiyun</programlisting></blockquote> 2400*4882a593SmuzhiyunCursorLimits should calculate the box that the cursor hot spot is 2401*4882a593Smuzhiyunphysically capable of moving within, as a function of the screen pScr, 2402*4882a593Smuzhiyunthe device-independent cursor pCurs, and a box that DIX hypothetically 2403*4882a593Smuzhiyunwould want the hot spot confined within, pHotBox. This routine is for 2404*4882a593Smuzhiyuninforming DIX only; it alters no state within DDX.</para> 2405*4882a593Smuzhiyun<para> 2406*4882a593Smuzhiyun<blockquote><programlisting> 2407*4882a593Smuzhiyun 2408*4882a593Smuzhiyun Bool pScreen->SetCursorPosition( pScr, newx, newy, generateEvent) 2409*4882a593Smuzhiyun ScreenPtr pScr; 2410*4882a593Smuzhiyun int newx; 2411*4882a593Smuzhiyun int newy; 2412*4882a593Smuzhiyun Bool generateEvent; 2413*4882a593Smuzhiyun 2414*4882a593Smuzhiyun</programlisting></blockquote> 2415*4882a593SmuzhiyunSetCursorPosition should artificially move the cursor as though the 2416*4882a593Smuzhiyunuser had jerked the pointing device very quickly. This is called in 2417*4882a593Smuzhiyunresponse to the WarpPointer request from the client, and at other 2418*4882a593Smuzhiyuntimes. If generateEvent is True, the device should decide whether or 2419*4882a593Smuzhiyunnot to call ProcessInputEvents() and then it must call 2420*4882a593SmuzhiyunDevicePtr->processInputProc. Its effects are, of course, limited in 2421*4882a593Smuzhiyunvalue for absolute pointing devices such as a tablet.</para> 2422*4882a593Smuzhiyun<para> 2423*4882a593Smuzhiyun<blockquote><programlisting> 2424*4882a593Smuzhiyun 2425*4882a593Smuzhiyun void NewCurrentScreen(newScreen, x, y) 2426*4882a593Smuzhiyun ScreenPtr newScreen; 2427*4882a593Smuzhiyun int x,y; 2428*4882a593Smuzhiyun 2429*4882a593Smuzhiyun</programlisting></blockquote> 2430*4882a593SmuzhiyunIf your ddx provides some mechanism for the user to magically move the 2431*4882a593Smuzhiyunpointer between multiple screens, you need to inform DIX when this 2432*4882a593Smuzhiyunoccurs. You should call NewCurrentScreen to accomplish this, specifying 2433*4882a593Smuzhiyunthe new screen and the new x and y coordinates of the pointer on that screen.</para> 2434*4882a593Smuzhiyun</section> 2435*4882a593Smuzhiyun<section> 2436*4882a593Smuzhiyun <title>Visuals, Depths and Pixmap Formats for Screens</title> 2437*4882a593Smuzhiyun<para> 2438*4882a593SmuzhiyunThe "depth" of a image is the number of bits that are used per pixel to display it.</para> 2439*4882a593Smuzhiyun<para> 2440*4882a593SmuzhiyunThe "bits per pixel" of a pixmap image that is sent over the client 2441*4882a593Smuzhiyunbyte stream is a number that is either 4, 8, 16, 24 or 32. It is the 2442*4882a593Smuzhiyunnumber of bits used per pixel in Z format. For instance, a pixmap 2443*4882a593Smuzhiyunimage that has a depth of six is best sent in Z format as 8 bits per 2444*4882a593Smuzhiyunpixel.</para> 2445*4882a593Smuzhiyun<para> 2446*4882a593SmuzhiyunA "pixmap image format" or a "pixmap format" is a description of the 2447*4882a593Smuzhiyunformat of a pixmap image as it is sent over the byte stream. For each 2448*4882a593Smuzhiyundepth available on a server, there is one and only one pixmap format. 2449*4882a593SmuzhiyunThis pixmap image format gives the bits per pixel and the scanline 2450*4882a593Smuzhiyunpadding unit. (For instance, are pixel rows padded to bytes, 16-bit 2451*4882a593Smuzhiyunwords, or 32-bit words?)</para> 2452*4882a593Smuzhiyun<para> 2453*4882a593SmuzhiyunFor each screen, you must decide upon what depth(s) it supports. You 2454*4882a593Smuzhiyunshould only count the number of bits used for the actual image. Some 2455*4882a593Smuzhiyundisplays store additional bits to indicate what window this pixel is 2456*4882a593Smuzhiyunin, how close this object is to a viewer, transparency, and other 2457*4882a593Smuzhiyundata; do not count these bits.</para> 2458*4882a593Smuzhiyun<para> 2459*4882a593SmuzhiyunA "display class" tells whether the display is monochrome or color, 2460*4882a593Smuzhiyunwhether there is a lookup table, and how the lookup table works.</para> 2461*4882a593Smuzhiyun<para> 2462*4882a593SmuzhiyunA "visual" is a combination of depth, display class, and a description 2463*4882a593Smuzhiyunof how the pixel values result in a color on the screen. Each visual 2464*4882a593Smuzhiyunhas a set of masks and offsets that are used to separate a pixel value 2465*4882a593Smuzhiyuninto its red, green, and blue components and a count of the number of 2466*4882a593Smuzhiyuncolormap entries. Some of these fields are only meaningful when the 2467*4882a593Smuzhiyunclass dictates so. Each visual also has a screen ID telling which 2468*4882a593Smuzhiyunscreen it is usable on. Note that the depth does not imply the number 2469*4882a593Smuzhiyunof map_entries; for instance, a display can have 8 bits per pixel but 2470*4882a593Smuzhiyunonly 254 colormap entries for use by applications (the other two being 2471*4882a593Smuzhiyunreserved by hardware for the cursor).</para> 2472*4882a593Smuzhiyun<para> 2473*4882a593SmuzhiyunEach visual is identified by a 32-bit visual ID which the client uses 2474*4882a593Smuzhiyunto choose what visual is desired on a given window. Clients can be 2475*4882a593Smuzhiyunusing more than one visual on the same screen at the same time.</para> 2476*4882a593Smuzhiyun<para> 2477*4882a593SmuzhiyunThe class of a display describes how this translation takes place. 2478*4882a593SmuzhiyunThere are three ways to do the translation. 2479*4882a593Smuzhiyun<itemizedlist> 2480*4882a593Smuzhiyun<listitem><para> 2481*4882a593SmuzhiyunPseudo - The pixel value, as a whole, is looked up 2482*4882a593Smuzhiyunin a table of length map_entries to 2483*4882a593Smuzhiyundetermine the color to display.</para></listitem> 2484*4882a593Smuzhiyun<listitem><para> 2485*4882a593SmuzhiyunTrue - The 2486*4882a593Smuzhiyunpixel value is broken up into red, green, and blue fields, each of which 2487*4882a593Smuzhiyunare looked up in separate red, green, and blue lookup tables, 2488*4882a593Smuzhiyuneach of length map_entries.</para></listitem> 2489*4882a593Smuzhiyun<listitem><para> 2490*4882a593SmuzhiyunGray - The pixel value is looked up in a table of length map_entries to 2491*4882a593Smuzhiyundetermine a gray level to display.</para></listitem> 2492*4882a593Smuzhiyun</itemizedlist> 2493*4882a593Smuzhiyun</para> 2494*4882a593Smuzhiyun<para> 2495*4882a593SmuzhiyunIn addition, the lookup table can be static (resulting colors are fixed for each 2496*4882a593Smuzhiyunpixel value) 2497*4882a593Smuzhiyunor dynamic (lookup entries are under control of the client program). 2498*4882a593SmuzhiyunThis leads to a total of six classes: 2499*4882a593Smuzhiyun<itemizedlist> 2500*4882a593Smuzhiyun<listitem><para> 2501*4882a593SmuzhiyunStatic Gray - The pixel value (of however many bits) determines directly the 2502*4882a593Smuzhiyunlevel of gray 2503*4882a593Smuzhiyunthat the pixel assumes.</para></listitem> 2504*4882a593Smuzhiyun<listitem><para> 2505*4882a593SmuzhiyunGray Scale - The pixel value is fed through a lookup table to arrive at the level 2506*4882a593Smuzhiyunof gray to display 2507*4882a593Smuzhiyunfor the given pixel.</para></listitem> 2508*4882a593Smuzhiyun<listitem><para> 2509*4882a593SmuzhiyunStatic Color - The pixel value is fed through a fixed lookup table that yields the 2510*4882a593Smuzhiyuncolor to display 2511*4882a593Smuzhiyunfor that pixel.</para></listitem> 2512*4882a593Smuzhiyun<listitem><para> 2513*4882a593SmuzhiyunPseudoColor - The whole pixel value is fed through a programmable lookup 2514*4882a593Smuzhiyuntable that has one 2515*4882a593Smuzhiyuncolor (including red, green, and blue intensities) for each possible pixel value, 2516*4882a593Smuzhiyunand that color is displayed.</para></listitem> 2517*4882a593Smuzhiyun<listitem><para> 2518*4882a593SmuzhiyunTrue Color - Each pixel value consists of one or more bits 2519*4882a593Smuzhiyunthat directly determine each primary color intensity after being fed through 2520*4882a593Smuzhiyuna fixed table.</para></listitem> 2521*4882a593Smuzhiyun<listitem><para> 2522*4882a593SmuzhiyunDirect Color - Each pixel value consists of one or more bits for each primary color. 2523*4882a593SmuzhiyunEach primary color value is individually looked up in a table for that primary 2524*4882a593Smuzhiyuncolor, yielding 2525*4882a593Smuzhiyunan intensity for that primary color. 2526*4882a593SmuzhiyunFor each pixel, the red value is looked up in the 2527*4882a593Smuzhiyunred table, the green value in the green table, and 2528*4882a593Smuzhiyunthe blue value in the blue table.</para></listitem> 2529*4882a593Smuzhiyun</itemizedlist> 2530*4882a593Smuzhiyun</para> 2531*4882a593Smuzhiyun<para> 2532*4882a593SmuzhiyunHere are some examples: 2533*4882a593Smuzhiyun<itemizedlist> 2534*4882a593Smuzhiyun<listitem><para> 2535*4882a593SmuzhiyunA simple monochrome 1 bit per pixel display is Static Gray.</para></listitem> 2536*4882a593Smuzhiyun<listitem><para> 2537*4882a593SmuzhiyunA display that has 2 bits per pixel for a choice 2538*4882a593Smuzhiyunbetween the colors of black, white, green and violet is Static Color.</para></listitem> 2539*4882a593Smuzhiyun<listitem><para> 2540*4882a593SmuzhiyunA display that has three bits per pixel, where 2541*4882a593Smuzhiyuneach bit turns on or off one of the red, green or 2542*4882a593Smuzhiyunblue guns, is in the True Color class.</para></listitem> 2543*4882a593Smuzhiyun<listitem><para> 2544*4882a593SmuzhiyunIf you take the last example and scramble the 2545*4882a593Smuzhiyuncorrespondence between pixel values and colors 2546*4882a593Smuzhiyunit becomes a Static Color display.</para></listitem> 2547*4882a593Smuzhiyun</itemizedlist></para> 2548*4882a593Smuzhiyun<para> 2549*4882a593SmuzhiyunA display has 8 bits per pixel. The 8 bits select one entry out of 256 entries 2550*4882a593Smuzhiyunin a lookup table, each entry consisting of 24 bits (8bits each for red, green, 2551*4882a593Smuzhiyunand blue). 2552*4882a593SmuzhiyunThe display can show any 256 of 16 million colors on the screen at once. 2553*4882a593SmuzhiyunThis is a pseudocolor display. 2554*4882a593SmuzhiyunThe client application gets to fill the lookup table in this class of display.</para> 2555*4882a593Smuzhiyun<para> 2556*4882a593SmuzhiyunImagine the same hardware from the last example. 2557*4882a593SmuzhiyunYour server software allows the user, on the 2558*4882a593Smuzhiyuncommand line that starts up the server 2559*4882a593Smuzhiyunprogram, 2560*4882a593Smuzhiyunto fill the lookup table to his liking once and for all. 2561*4882a593SmuzhiyunFrom then on, the server software would not change the lookup table 2562*4882a593Smuzhiyununtil it exits. 2563*4882a593SmuzhiyunFor instance, the default might be a lookup table with a reasonable sample of 2564*4882a593Smuzhiyuncolors from throughout the color space. 2565*4882a593SmuzhiyunBut the user could specify that the table be filled with 256 steps of gray scale 2566*4882a593Smuzhiyunbecause he knew ahead of time he would be manipulating a lot of black-and-white 2567*4882a593Smuzhiyunscanned photographs 2568*4882a593Smuzhiyunand not very many color things. 2569*4882a593SmuzhiyunClients would be presented with this unchangeable lookup table. 2570*4882a593SmuzhiyunAlthough the hardware qualifies as a PseudoColor display, 2571*4882a593Smuzhiyunthe facade presented to the X client is that this is a Static Color display.</para> 2572*4882a593Smuzhiyun<para> 2573*4882a593SmuzhiyunYou have to decide what kind of display you have or want 2574*4882a593Smuzhiyunto pretend you have. 2575*4882a593SmuzhiyunWhen you initialize the screen(s), this class value must be set in the 2576*4882a593SmuzhiyunVisualRec data structure along with other display characteristics like the 2577*4882a593Smuzhiyundepth and other numbers.</para> 2578*4882a593Smuzhiyun<para> 2579*4882a593SmuzhiyunThe allowable DepthRec's and VisualRec's are pointed to by fields in the ScreenRec. 2580*4882a593SmuzhiyunThese are set up when InitOutput() is called; you should malloc() appropriate blocks 2581*4882a593Smuzhiyunor use static variables initialized to the correct values.</para> 2582*4882a593Smuzhiyun</section> 2583*4882a593Smuzhiyun<section> 2584*4882a593Smuzhiyun<title>Colormaps for Screens</title> 2585*4882a593Smuzhiyun<para> 2586*4882a593SmuzhiyunA colormap is a device-independent 2587*4882a593Smuzhiyunmapping between pixel values and colors displayed on the screen.</para> 2588*4882a593Smuzhiyun<para> 2589*4882a593SmuzhiyunDifferent windows on the same screen can have different 2590*4882a593Smuzhiyuncolormaps at the same time. 2591*4882a593SmuzhiyunAt any given time, the most recently installed 2592*4882a593Smuzhiyuncolormap(s) will be in use in the server 2593*4882a593Smuzhiyunso that its (their) windows' colors will be guaranteed to be correct. 2594*4882a593SmuzhiyunOther windows may be off-color. 2595*4882a593SmuzhiyunAlthough this may seem to be chaotic, in practice most clients 2596*4882a593Smuzhiyunuse the default colormap for the screen.</para> 2597*4882a593Smuzhiyun<para> 2598*4882a593SmuzhiyunThe default colormap for a screen is initialized when the screen is initialized. 2599*4882a593SmuzhiyunIt always remains in existence and is not owned by any regular client. It 2600*4882a593Smuzhiyunis owned by client 0 (the server itself). 2601*4882a593SmuzhiyunMany clients will simply use this default colormap for their drawing. 2602*4882a593SmuzhiyunDepending upon the class of the screen, the entries in this colormap may 2603*4882a593Smuzhiyunbe modifiable by client applications.</para> 2604*4882a593Smuzhiyun</section> 2605*4882a593Smuzhiyun<section> 2606*4882a593Smuzhiyun <title>Colormap Routines</title> 2607*4882a593Smuzhiyun<para> 2608*4882a593SmuzhiyunYou need to implement the following routines to handle the device-dependent 2609*4882a593Smuzhiyunaspects of color maps. You will end up placing pointers to these procedures 2610*4882a593Smuzhiyunin your ScreenRec data structure(s). The sample server implementations of 2611*4882a593Smuzhiyunmany of these routines are in fbcmap.c.</para> 2612*4882a593Smuzhiyun<para> 2613*4882a593Smuzhiyun<blockquote><programlisting> 2614*4882a593Smuzhiyun 2615*4882a593Smuzhiyun Bool pScreen->CreateColormap(pColormap) 2616*4882a593Smuzhiyun ColormapPtr pColormap; 2617*4882a593Smuzhiyun 2618*4882a593Smuzhiyun</programlisting></blockquote> 2619*4882a593SmuzhiyunThis routine is called by the DIX CreateColormap routine after it has allocated 2620*4882a593Smuzhiyunall the data for the new colormap and just before it returns to the dispatcher. 2621*4882a593SmuzhiyunIt is the DDX layer's chance to initialize the colormap, particularly if it is 2622*4882a593Smuzhiyuna static map. See the following 2623*4882a593Smuzhiyunsection for more details on initializing colormaps. 2624*4882a593SmuzhiyunThe routine returns FALSE if creation failed, such as due to memory 2625*4882a593Smuzhiyunlimitations. 2626*4882a593SmuzhiyunNotice that the colormap has a devPriv field from which you can hang any 2627*4882a593Smuzhiyuncolormap specific storage you need. Since each colormap might need special 2628*4882a593Smuzhiyuninformation, we attached the field to the colormap and not the visual.</para> 2629*4882a593Smuzhiyun<para> 2630*4882a593Smuzhiyun<blockquote><programlisting> 2631*4882a593Smuzhiyun 2632*4882a593Smuzhiyun void pScreen->DestroyColormap(pColormap) 2633*4882a593Smuzhiyun ColormapPtr pColormap; 2634*4882a593Smuzhiyun 2635*4882a593Smuzhiyun</programlisting></blockquote> 2636*4882a593SmuzhiyunThis routine is called by the DIX FreeColormap routine after it has uninstalled 2637*4882a593Smuzhiyunthe colormap and notified all interested parties, and before it has freed 2638*4882a593Smuzhiyunany of the colormap storage. 2639*4882a593SmuzhiyunIt is the DDX layer's chance to free any data it added to the colormap.</para> 2640*4882a593Smuzhiyun<para> 2641*4882a593Smuzhiyun<blockquote><programlisting> 2642*4882a593Smuzhiyun 2643*4882a593Smuzhiyun void pScreen->InstallColormap(pColormap) 2644*4882a593Smuzhiyun ColormapPtr pColormap; 2645*4882a593Smuzhiyun 2646*4882a593Smuzhiyun</programlisting></blockquote> 2647*4882a593SmuzhiyunInstallColormap should 2648*4882a593Smuzhiyunfill a lookup table on the screen with which the colormap is associated with 2649*4882a593Smuzhiyunthe colors in pColormap. 2650*4882a593SmuzhiyunIf there is only one hardware lookup table for the screen, then all colors on 2651*4882a593Smuzhiyunthe screen may change simultaneously.</para> 2652*4882a593Smuzhiyun<para> 2653*4882a593SmuzhiyunIn the more general case of multiple hardware lookup tables, 2654*4882a593Smuzhiyunthis may cause some other colormap to be 2655*4882a593Smuzhiyununinstalled, meaning that windows that subscribed to the colormap 2656*4882a593Smuzhiyunthat was uninstalled may end up being off-color. 2657*4882a593SmuzhiyunSee the note, below, about uninstalling maps.</para> 2658*4882a593Smuzhiyun<para> 2659*4882a593Smuzhiyun<blockquote><programlisting> 2660*4882a593Smuzhiyun 2661*4882a593Smuzhiyun void pScreen->UninstallColormap(pColormap) 2662*4882a593Smuzhiyun ColormapPtr pColormap; 2663*4882a593Smuzhiyun 2664*4882a593Smuzhiyun</programlisting></blockquote> 2665*4882a593SmuzhiyunUninstallColormap should 2666*4882a593Smuzhiyunremove pColormap from screen pColormap->pScreen. 2667*4882a593SmuzhiyunSome other map, such as the default map if possible, 2668*4882a593Smuzhiyunshould be installed in place of pColormap if applicable. 2669*4882a593SmuzhiyunIf 2670*4882a593SmuzhiyunpColormap is the default map, do nothing. 2671*4882a593SmuzhiyunIf any client has requested ColormapNotify events, the DDX layer must notify the client. 2672*4882a593Smuzhiyun(The routine WalkTree() is 2673*4882a593Smuzhiyunbe used to find such windows. The DIX routines TellNoMap(), 2674*4882a593SmuzhiyunTellNewMap() and TellGainedMap() are provided to be used as 2675*4882a593Smuzhiyunthe procedure parameter to WalkTree. These procedures are in 2676*4882a593SmuzhiyunXserver/dix/colormap.c.)</para> 2677*4882a593Smuzhiyun<para> 2678*4882a593Smuzhiyun<blockquote><programlisting> 2679*4882a593Smuzhiyun 2680*4882a593Smuzhiyun int pScreen->ListInstalledColormaps(pScreen, pCmapList) 2681*4882a593Smuzhiyun ScreenPtr pScreen; 2682*4882a593Smuzhiyun XID *pCmapList; 2683*4882a593Smuzhiyun 2684*4882a593Smuzhiyun 2685*4882a593Smuzhiyun</programlisting></blockquote> 2686*4882a593SmuzhiyunListInstalledColormaps fills the pCmapList in with the resource ids 2687*4882a593Smuzhiyunof the installed maps and returns a count of installed maps. 2688*4882a593SmuzhiyunpCmapList will point to an array of size MaxInstalledMaps that was allocated 2689*4882a593Smuzhiyunby the caller.</para> 2690*4882a593Smuzhiyun<para> 2691*4882a593Smuzhiyun<blockquote><programlisting> 2692*4882a593Smuzhiyun 2693*4882a593Smuzhiyun void pScreen->StoreColors (pmap, ndef, pdefs) 2694*4882a593Smuzhiyun ColormapPtr pmap; 2695*4882a593Smuzhiyun int ndef; 2696*4882a593Smuzhiyun xColorItem *pdefs; 2697*4882a593Smuzhiyun 2698*4882a593Smuzhiyun</programlisting></blockquote> 2699*4882a593SmuzhiyunStoreColors changes some of the entries in the colormap pmap. 2700*4882a593SmuzhiyunThe number of entries to change are ndef, and pdefs points to the information 2701*4882a593Smuzhiyundescribing what to change. 2702*4882a593SmuzhiyunNote that partial changes of entries in the colormap are allowed. 2703*4882a593SmuzhiyunOnly the colors 2704*4882a593Smuzhiyunindicated in the flags field of each xColorItem need to be changed. 2705*4882a593SmuzhiyunHowever, all three color fields will be sent with the proper value for the 2706*4882a593Smuzhiyunbenefit of screens that may not be able to set part of a colormap value. 2707*4882a593SmuzhiyunIf the screen is a static class, this routine does nothing. 2708*4882a593SmuzhiyunThe structure of colormap entries is nontrivial; see colormapst.h 2709*4882a593Smuzhiyunand the definition of xColorItem in Xproto.h for 2710*4882a593Smuzhiyunmore details.</para> 2711*4882a593Smuzhiyun<para> 2712*4882a593Smuzhiyun<blockquote><programlisting> 2713*4882a593Smuzhiyun 2714*4882a593Smuzhiyun void pScreen->ResolveColor(pRed, pGreen, pBlue, pVisual) 2715*4882a593Smuzhiyun unsigned short *pRed, *pGreen, *pBlue; 2716*4882a593Smuzhiyun VisualPtr pVisual; 2717*4882a593Smuzhiyun 2718*4882a593Smuzhiyun 2719*4882a593Smuzhiyun</programlisting></blockquote> 2720*4882a593SmuzhiyunGiven a requested color, ResolveColor returns the nearest color that this hardware is 2721*4882a593Smuzhiyuncapable of displaying on this visual. 2722*4882a593SmuzhiyunIn other words, this rounds off each value, in place, to the number of bits 2723*4882a593Smuzhiyunper primary color that your screen can use. 2724*4882a593SmuzhiyunRemember that each screen has one of these routines. 2725*4882a593SmuzhiyunThe level of roundoff should be what you would expect from the value 2726*4882a593Smuzhiyunyou put in the bits_per_rgb field of the pVisual.</para> 2727*4882a593Smuzhiyun<para> 2728*4882a593SmuzhiyunEach value is an unsigned value ranging from 0 to 65535. 2729*4882a593SmuzhiyunThe bits least likely to be used are the lowest ones.</para> 2730*4882a593Smuzhiyun<para> 2731*4882a593SmuzhiyunFor example, if you had a pseudocolor display 2732*4882a593Smuzhiyunwith any number of bits per pixel 2733*4882a593Smuzhiyunthat had a lookup table supplying 6 bits for each color gun 2734*4882a593Smuzhiyun(a total of 256K different colors), you would 2735*4882a593Smuzhiyunround off each value to 6 bits. Please don't simply truncate these values 2736*4882a593Smuzhiyunto the upper 6 bits, scale the result so that the maximum value seen 2737*4882a593Smuzhiyunby the client will be 65535 for each primary. This makes color values 2738*4882a593Smuzhiyunmore portable between different depth displays (a 6-bit truncated white 2739*4882a593Smuzhiyunwill not look white on an 8-bit display).</para> 2740*4882a593Smuzhiyun<section> 2741*4882a593Smuzhiyun<title>Initializing a Colormap</title> 2742*4882a593Smuzhiyun<para> 2743*4882a593SmuzhiyunWhen a client requests a new colormap and when the server creates the default 2744*4882a593Smuzhiyuncolormap, the procedure CreateColormap in the DIX layer is invoked. 2745*4882a593SmuzhiyunThat procedure allocates memory for the colormap and related storage such as 2746*4882a593Smuzhiyunthe lists of which client owns which pixels. 2747*4882a593SmuzhiyunIt then sets a bit, BeingCreated, in the flags field of the ColormapRec 2748*4882a593Smuzhiyunand calls the DDX layer's CreateColormap routine. 2749*4882a593SmuzhiyunThis is your chance to initialize the colormap. 2750*4882a593SmuzhiyunIf the colormap is static, which you can tell by looking at the class field, 2751*4882a593Smuzhiyunyou will want to fill in each color cell to match the hardwares notion of the 2752*4882a593Smuzhiyuncolor for that pixel. 2753*4882a593SmuzhiyunIf the colormap is the default for the screen, which you can tell by looking 2754*4882a593Smuzhiyunat the IsDefault bit in the flags field, you should allocate BlackPixel 2755*4882a593Smuzhiyunand WhitePixel to match the values you set in the pScreen structure. 2756*4882a593Smuzhiyun(Of course, you picked those values to begin with.)</para> 2757*4882a593Smuzhiyun<para> 2758*4882a593SmuzhiyunYou can also wait and use AllocColor() to allocate blackPixel 2759*4882a593Smuzhiyunand whitePixel after the default colormap has been created. 2760*4882a593SmuzhiyunIf the default colormap is static and you initialized it in 2761*4882a593SmuzhiyunpScreen->CreateColormap, then use can use AllocColor afterwards 2762*4882a593Smuzhiyunto choose pixel values with the closest rgb values to those 2763*4882a593Smuzhiyundesired for blackPixel and whitePixel. 2764*4882a593SmuzhiyunIf the default colormap is dynamic and uninitialized, then 2765*4882a593Smuzhiyunthe rgb values you request will be obeyed, and AllocColor will 2766*4882a593Smuzhiyunagain choose pixel values for you. 2767*4882a593SmuzhiyunThese pixel values can then be stored into the screen.</para> 2768*4882a593Smuzhiyun<para> 2769*4882a593SmuzhiyunThere are two ways to fill in the colormap. 2770*4882a593SmuzhiyunThe simplest way is to use the DIX function AllocColor. 2771*4882a593Smuzhiyun<blockquote><programlisting> 2772*4882a593Smuzhiyun 2773*4882a593Smuzhiyunint AllocColor (pmap, pred, pgreen, pblue, pPix, client) 2774*4882a593Smuzhiyun ColormapPtr pmap; 2775*4882a593Smuzhiyun unsigned short *pred, *pgreen, *pblue; 2776*4882a593Smuzhiyun Pixel *pPix; 2777*4882a593Smuzhiyun int client; 2778*4882a593Smuzhiyun 2779*4882a593Smuzhiyun</programlisting></blockquote> 2780*4882a593SmuzhiyunThis takes three pointers to 16 bit color values and a pointer to a suggested 2781*4882a593Smuzhiyunpixel value. The pixel value is either an index into one colormap or a 2782*4882a593Smuzhiyuncombination of three indices depending on the type of pmap. 2783*4882a593SmuzhiyunIf your colormap starts out empty, and you don't deliberately pick the same 2784*4882a593Smuzhiyunvalue twice, you will always get your suggested pixel. 2785*4882a593SmuzhiyunThe truly nervous could check that the value returned in *pPix is the one 2786*4882a593SmuzhiyunAllocColor was called with. 2787*4882a593SmuzhiyunIf you don't care which pixel is used, or would like them sequentially 2788*4882a593Smuzhiyunallocated from entry 0, set *pPix to 0. This will find the first free 2789*4882a593Smuzhiyunpixel and use that.</para> 2790*4882a593Smuzhiyun<para> 2791*4882a593SmuzhiyunAllocColor will take care of all the bookkeeping and will 2792*4882a593Smuzhiyuncall StoreColors to get the colormap rgb values initialized. 2793*4882a593SmuzhiyunThe hardware colormap will be changed whenever this colormap 2794*4882a593Smuzhiyunis installed.</para> 2795*4882a593Smuzhiyun<para> 2796*4882a593SmuzhiyunIf for some reason AllocColor doesn't do what you want, you can do your 2797*4882a593Smuzhiyunown bookkeeping and call StoreColors yourself. This is much more difficult 2798*4882a593Smuzhiyunand shouldn't be necessary for most devices.</para> 2799*4882a593Smuzhiyun</section> 2800*4882a593Smuzhiyun</section> 2801*4882a593Smuzhiyun<section> 2802*4882a593Smuzhiyun <title>Fonts for Screens</title> 2803*4882a593Smuzhiyun<para> 2804*4882a593SmuzhiyunA font is a set of bitmaps that depict the symbols in a character set. 2805*4882a593SmuzhiyunEach font is for only one typeface in a given size, in other words, 2806*4882a593Smuzhiyunjust one bitmap for each character. Parallel fonts may be available 2807*4882a593Smuzhiyunin a variety of sizes and variations, including "bold" and "italic." 2808*4882a593SmuzhiyunX supports fonts for 8-bit and 16-bit character codes (for oriental 2809*4882a593Smuzhiyunlanguages that have more than 256 characters in the font). Glyphs are 2810*4882a593Smuzhiyunbitmaps for individual characters.</para> 2811*4882a593Smuzhiyun<para> 2812*4882a593SmuzhiyunThe source comes with some useful font files in an ASCII, plain-text 2813*4882a593Smuzhiyunformat that should be comprehensible on a wide variety of operating 2814*4882a593Smuzhiyunsystems. The text format, referred to as BDF, is a slight extension 2815*4882a593Smuzhiyunof the current Adobe 2.1 Bitmap Distribution Format (Adobe Systems, 2816*4882a593SmuzhiyunInc.).</para> 2817*4882a593Smuzhiyun<para> 2818*4882a593SmuzhiyunA short paper in PostScript format is included with the sample server 2819*4882a593Smuzhiyunthat defines BDF. It includes helpful pictures, which is why it is 2820*4882a593Smuzhiyundone in PostScript and is not included in this document.</para> 2821*4882a593Smuzhiyun<para> 2822*4882a593SmuzhiyunYour implementation should include some sort of font compiler to read 2823*4882a593Smuzhiyunthese files and generate binary files that are directly usable by your 2824*4882a593Smuzhiyunserver implementation. The sample server comes with the source for a 2825*4882a593Smuzhiyunfont compiler.</para> 2826*4882a593Smuzhiyun<para> 2827*4882a593SmuzhiyunIt is important the font properties contained in the BDF files are 2828*4882a593Smuzhiyunpreserved across any font compilation. In particular, copyright 2829*4882a593Smuzhiyuninformation cannot be casually tossed aside without legal 2830*4882a593Smuzhiyunramifications. Other properties will be important to some 2831*4882a593Smuzhiyunsophisticated applications.</para> 2832*4882a593Smuzhiyun<para> 2833*4882a593SmuzhiyunAll clients get font information from the server. Therefore, your 2834*4882a593Smuzhiyunserver can support any fonts it wants to. It should probably support 2835*4882a593Smuzhiyunat least the fonts supplied with the X11 tape. In principle, you can 2836*4882a593Smuzhiyunconvert fonts from other sources or dream up your own fonts for use on 2837*4882a593Smuzhiyunyour server.</para> 2838*4882a593Smuzhiyun<section> 2839*4882a593Smuzhiyun<title>Portable Compiled Format</title> 2840*4882a593Smuzhiyun<para> 2841*4882a593SmuzhiyunA font compiler is supplied with the sample server. It has 2842*4882a593Smuzhiyuncompile-time switches to convert the BDF files into a portable binary 2843*4882a593Smuzhiyunform, called Portable Compiled Format or PCF. This allows for an 2844*4882a593Smuzhiyunarbitrary data format inside the file, and by describing the details 2845*4882a593Smuzhiyunof the format in the header of the file, any PCF file can be read by 2846*4882a593Smuzhiyunany PCF reading client. By selecting the format which matches the 2847*4882a593Smuzhiyunrequired internal format for your renderer, the PCF reader can avoid 2848*4882a593Smuzhiyunreformatting the data each time it is read in. The font compiler 2849*4882a593Smuzhiyunshould be quite portable.</para> 2850*4882a593Smuzhiyun<para> 2851*4882a593SmuzhiyunThe fonts included with the tape are stored in fonts/bdf. The 2852*4882a593Smuzhiyunfont compiler is found in fonts/tools/bdftopcf.</para> 2853*4882a593Smuzhiyun</section> 2854*4882a593Smuzhiyun<section> 2855*4882a593Smuzhiyun <title>Font Realization</title> 2856*4882a593Smuzhiyun<para> 2857*4882a593SmuzhiyunEach screen configured into the server 2858*4882a593Smuzhiyunhas an opportunity at font-load time 2859*4882a593Smuzhiyunto "realize" a font into some internal format if necessary. 2860*4882a593SmuzhiyunThis happens every time the font is loaded into memory.</para> 2861*4882a593Smuzhiyun<para> 2862*4882a593SmuzhiyunA font (FontRec in Xserver/include/dixfontstr.h) is 2863*4882a593Smuzhiyuna device-independent structure containing a device-independent 2864*4882a593Smuzhiyunrepresentation of the font. When a font is created, it is "realized" 2865*4882a593Smuzhiyunfor each screen. At this point, the screen has the chance to convert 2866*4882a593Smuzhiyunthe font into some other format. The DDX layer can also put information 2867*4882a593Smuzhiyunin the devPrivate storage.</para> 2868*4882a593Smuzhiyun<para> 2869*4882a593Smuzhiyun<blockquote><programlisting> 2870*4882a593Smuzhiyun 2871*4882a593Smuzhiyun Bool pScreen->RealizeFont(pScr, pFont) 2872*4882a593Smuzhiyun ScreenPtr pScr; 2873*4882a593Smuzhiyun FontPtr pFont; 2874*4882a593Smuzhiyun 2875*4882a593Smuzhiyun Bool pScreen->UnrealizeFont(pScr, pFont) 2876*4882a593Smuzhiyun ScreenPtr pScr; 2877*4882a593Smuzhiyun FontPtr pFont; 2878*4882a593Smuzhiyun 2879*4882a593Smuzhiyun</programlisting></blockquote> 2880*4882a593SmuzhiyunRealizeFont and UnrealizeFont should calculate and allocate these extra data structures and 2881*4882a593Smuzhiyundispose of them when no longer needed. 2882*4882a593SmuzhiyunThese are called in response to OpenFont and CloseFont requests from 2883*4882a593Smuzhiyunthe client. 2884*4882a593SmuzhiyunThe sample server implementation is in fbscreen.c (which does very little).</para> 2885*4882a593Smuzhiyun</section> 2886*4882a593Smuzhiyun</section> 2887*4882a593Smuzhiyun<section> 2888*4882a593Smuzhiyun <title>Other Screen Routines</title> 2889*4882a593Smuzhiyun<para> 2890*4882a593SmuzhiyunYou must supply several other screen-specific routines for 2891*4882a593Smuzhiyunyour X server implementation. 2892*4882a593SmuzhiyunSome of these are described in other sections: 2893*4882a593Smuzhiyun<itemizedlist> 2894*4882a593Smuzhiyun<listitem><para> 2895*4882a593SmuzhiyunGetImage() is described in the Drawing Primitives section.</para></listitem> 2896*4882a593Smuzhiyun<listitem><para> 2897*4882a593SmuzhiyunGetSpans() is described in the Pixblit routine section.</para></listitem> 2898*4882a593Smuzhiyun<listitem><para> 2899*4882a593SmuzhiyunSeveral window and pixmap manipulation procedures are 2900*4882a593Smuzhiyundescribed in the Window section under Drawables.</para></listitem> 2901*4882a593Smuzhiyun<listitem><para> 2902*4882a593SmuzhiyunThe CreateGC() routine is described under Graphics Contexts.</para></listitem> 2903*4882a593Smuzhiyun</itemizedlist> 2904*4882a593Smuzhiyun</para> 2905*4882a593Smuzhiyun<para> 2906*4882a593Smuzhiyun<blockquote><programlisting> 2907*4882a593Smuzhiyun 2908*4882a593Smuzhiyun void pScreen->QueryBestSize(kind, pWidth, pHeight) 2909*4882a593Smuzhiyun int kind; 2910*4882a593Smuzhiyun unsigned short *pWidth, *pHeight; 2911*4882a593Smuzhiyun ScreenPtr pScreen; 2912*4882a593Smuzhiyun 2913*4882a593Smuzhiyun</programlisting></blockquote> 2914*4882a593SmuzhiyunQueryBestSize() returns the best sizes for cursors, tiles, and stipples 2915*4882a593Smuzhiyunin response to client requests. 2916*4882a593Smuzhiyunkind is one of the defined constants CursorShape, TileShape, or StippleShape 2917*4882a593Smuzhiyun(defined in X.h). 2918*4882a593SmuzhiyunFor CursorShape, return the maximum width and 2919*4882a593Smuzhiyunheight for cursors that you can handle. 2920*4882a593SmuzhiyunFor TileShape and StippleShape, start with the suggested values in pWidth 2921*4882a593Smuzhiyunand pHeight and modify them in place to be optimal values that are 2922*4882a593Smuzhiyungreater than or equal to the suggested values. 2923*4882a593SmuzhiyunThe sample server implementation is in Xserver/fb/fbscreen.c.</para> 2924*4882a593Smuzhiyun<para> 2925*4882a593Smuzhiyun<blockquote><programlisting> 2926*4882a593Smuzhiyun 2927*4882a593Smuzhiyun pScreen->SourceValidate(pDrawable, x, y, width, height) 2928*4882a593Smuzhiyun DrawablePtr pDrawable; 2929*4882a593Smuzhiyun int x, y, width, height; 2930*4882a593Smuzhiyun unsigned int subWindowMode; 2931*4882a593Smuzhiyun 2932*4882a593Smuzhiyun</programlisting></blockquote> 2933*4882a593SmuzhiyunSourceValidate should be called by any primitive that reads from pDrawable. 2934*4882a593SmuzhiyunIf you know that 2935*4882a593Smuzhiyunyou will never need SourceValidate, you can avoid this check. Currently, 2936*4882a593SmuzhiyunSourceValidate is used by the mi software cursor code to remove the cursor 2937*4882a593Smuzhiyunfrom the screen when the source rectangle overlaps the cursor position. 2938*4882a593Smuzhiyunx,y,width,height describe the source rectangle (source relative, that is) 2939*4882a593Smuzhiyunfor the copy operation. subWindowMode comes from the GC or source Picture. 2940*4882a593Smuzhiyun</para> 2941*4882a593Smuzhiyun<para> 2942*4882a593Smuzhiyun<blockquote><programlisting> 2943*4882a593Smuzhiyun 2944*4882a593Smuzhiyun Bool pScreen->SaveScreen(pScreen, on) 2945*4882a593Smuzhiyun ScreenPtr pScreen; 2946*4882a593Smuzhiyun int on; 2947*4882a593Smuzhiyun 2948*4882a593Smuzhiyun</programlisting></blockquote> 2949*4882a593SmuzhiyunSaveScreen() is used for Screen Saver support (see WaitForSomething()). 2950*4882a593SmuzhiyunpScreen is the screen to save.</para> 2951*4882a593Smuzhiyun<para> 2952*4882a593Smuzhiyun<blockquote><programlisting> 2953*4882a593Smuzhiyun 2954*4882a593Smuzhiyun Bool pScreen->CloseScreen(pScreen) 2955*4882a593Smuzhiyun ScreenPtr pScreen; 2956*4882a593Smuzhiyun 2957*4882a593Smuzhiyun</programlisting></blockquote> 2958*4882a593SmuzhiyunWhen the server is reset, it calls this routine for each screen.</para> 2959*4882a593Smuzhiyun<para> 2960*4882a593Smuzhiyun<blockquote><programlisting> 2961*4882a593Smuzhiyun 2962*4882a593Smuzhiyun Bool pScreen->CreateScreenResources(pScreen) 2963*4882a593Smuzhiyun ScreenPtr pScreen; 2964*4882a593Smuzhiyun 2965*4882a593Smuzhiyun</programlisting></blockquote> 2966*4882a593SmuzhiyunIf this routine is not NULL, it will be called once per screen per 2967*4882a593Smuzhiyunserver initialization/reset after all modules have had a chance to 2968*4882a593Smuzhiyunrequest private space on all structures that support them (see 2969*4882a593Smuzhiyun<xref linkend="wrappers_and_privates"/> below). You may create resources 2970*4882a593Smuzhiyunin this function instead of in the 2971*4882a593Smuzhiyunscreen init function passed to AddScreen in order to guarantee that 2972*4882a593Smuzhiyunall pre-allocated space requests have been registered first. With the 2973*4882a593Smuzhiyunnew devPrivates mechanism, this is not strictly necessary, however. 2974*4882a593SmuzhiyunThis routine returns TRUE if successful.</para> 2975*4882a593Smuzhiyun</section> 2976*4882a593Smuzhiyun</section> 2977*4882a593Smuzhiyun<section> 2978*4882a593Smuzhiyun<title>Drawables</title> 2979*4882a593Smuzhiyun<para> 2980*4882a593SmuzhiyunA drawable is a descriptor of a surface that graphics are drawn into, either 2981*4882a593Smuzhiyuna window on the screen or a pixmap in memory.</para> 2982*4882a593Smuzhiyun<para> 2983*4882a593SmuzhiyunEach drawable has a type, class, 2984*4882a593SmuzhiyunScreenPtr for the screen it is associated with, depth, position, size, 2985*4882a593Smuzhiyunand serial number. 2986*4882a593SmuzhiyunThe type is one of the defined constants DRAWABLE_PIXMAP, 2987*4882a593SmuzhiyunDRAWABLE_WINDOW and UNDRAWABLE_WINDOW. 2988*4882a593Smuzhiyun(An undrawable window is used for window class InputOnly.) 2989*4882a593SmuzhiyunThe serial number is guaranteed to be unique across drawables, and 2990*4882a593Smuzhiyunis used in determining 2991*4882a593Smuzhiyunthe validity of the clipping information in a GC. 2992*4882a593SmuzhiyunThe screen selects the set of procedures used to manipulate and draw into the 2993*4882a593Smuzhiyundrawable. Position is used (currently) only by windows; pixmaps must 2994*4882a593Smuzhiyunset these fields to 0,0 as this reduces the amount of conditional code 2995*4882a593Smuzhiyunexecuted throughout the mi code. Size indicates the actual client-specified 2996*4882a593Smuzhiyunsize of the drawable. 2997*4882a593SmuzhiyunThere are, in fact, no other fields that a window drawable and pixmap 2998*4882a593Smuzhiyundrawable have in common besides those mentioned here.</para> 2999*4882a593Smuzhiyun<para> 3000*4882a593SmuzhiyunBoth PixmapRecs and WindowRecs are structs that start with a drawable 3001*4882a593Smuzhiyunand continue on with more fields. Pixmaps have a single pointer field 3002*4882a593Smuzhiyunnamed devPrivate which usually points to the pixmap data but could conceivably be 3003*4882a593Smuzhiyunused for anything that DDX wants. Both windows and pixmaps also have a 3004*4882a593SmuzhiyundevPrivates field which can be used for DDX specific data (see <xref linkend="wrappers_and_privates"/> 3005*4882a593Smuzhiyunbelow). This is done because different graphics hardware has 3006*4882a593Smuzhiyundifferent requirements for management; if the graphics is always 3007*4882a593Smuzhiyunhandled by a processor with an independent address space, there is no 3008*4882a593Smuzhiyunpoint having a pointer to the bit image itself.</para> 3009*4882a593Smuzhiyun<para> 3010*4882a593SmuzhiyunThe definition of a drawable and a pixmap can be found in the file 3011*4882a593SmuzhiyunXserver/include/pixmapstr.h. 3012*4882a593SmuzhiyunThe definition of a window can be found in the file Xserver/include/windowstr.h.</para> 3013*4882a593Smuzhiyun<section> 3014*4882a593Smuzhiyun <title>Pixmaps</title> 3015*4882a593Smuzhiyun<para> 3016*4882a593SmuzhiyunA pixmap is a three-dimensional array of bits stored somewhere offscreen, 3017*4882a593Smuzhiyunrather than in the visible portion of the screen's display frame buffer. It 3018*4882a593Smuzhiyuncan be used as a source or destination in graphics operations. There is no 3019*4882a593Smuzhiyunimplied interpretation of the pixel values in a pixmap, because it has no 3020*4882a593Smuzhiyunassociated visual or colormap. There is only a depth that indicates the 3021*4882a593Smuzhiyunnumber of significant bits per pixel. Also, there is no implied physical 3022*4882a593Smuzhiyunsize for each pixel; all graphic units are in numbers of pixels. Therefore, 3023*4882a593Smuzhiyuna pixmap alone does not constitute a complete image; it represents only a 3024*4882a593Smuzhiyunrectangular array of pixel values.</para> 3025*4882a593Smuzhiyun<para> 3026*4882a593SmuzhiyunNote that the pixmap data structure is reference-counted.</para> 3027*4882a593Smuzhiyun<para> 3028*4882a593SmuzhiyunThe server implementation is free to put the pixmap data 3029*4882a593Smuzhiyunanywhere it sees fit, according to its graphics hardware setup. Many 3030*4882a593Smuzhiyunimplementations will simply have the data dynamically allocated in the 3031*4882a593Smuzhiyunserver's address space. More sophisticated implementations may put the 3032*4882a593Smuzhiyundata in undisplayed framebuffer storage.</para> 3033*4882a593Smuzhiyun<para> 3034*4882a593SmuzhiyunIn addition to dynamic devPrivates (see <xref linkend="wrappers_and_privates"/> 3035*4882a593Smuzhiyunbelow), the pixmap data structure has two fields that are private to 3036*4882a593Smuzhiyunthe device. Although you can use them for anything you want, they 3037*4882a593Smuzhiyunhave intended purposes. devKind is intended to be a device specific 3038*4882a593Smuzhiyunindication of the pixmap location (host memory, off-screen, etc.). In 3039*4882a593Smuzhiyunthe sample server, since all pixmaps are in memory, devKind stores the 3040*4882a593Smuzhiyunwidth of the pixmap in bitmap scanline units. devPrivate is usually 3041*4882a593Smuzhiyuna pointer to the bits in the pixmap.</para> 3042*4882a593Smuzhiyun<para> 3043*4882a593SmuzhiyunA bitmap is a pixmap that is one bit deep.</para> 3044*4882a593Smuzhiyun<para> 3045*4882a593Smuzhiyun<blockquote><programlisting> 3046*4882a593Smuzhiyun 3047*4882a593Smuzhiyun PixmapPtr pScreen->CreatePixmap(pScreen, width, height, depth) 3048*4882a593Smuzhiyun ScreenPtr pScreen; 3049*4882a593Smuzhiyun int width, height, depth; 3050*4882a593Smuzhiyun 3051*4882a593Smuzhiyun</programlisting></blockquote> 3052*4882a593SmuzhiyunThis ScreenRec procedure must create a pixmap of the size 3053*4882a593Smuzhiyunrequested. 3054*4882a593SmuzhiyunIt must allocate a PixmapRec and fill in all of the fields. 3055*4882a593SmuzhiyunThe reference count field must be set to 1. 3056*4882a593SmuzhiyunIf width or height are zero, no space should be allocated 3057*4882a593Smuzhiyunfor the pixmap data, and if the implementation is using the 3058*4882a593SmuzhiyundevPrivate field as a pointer to the pixmap data, it should be 3059*4882a593Smuzhiyunset to NULL. 3060*4882a593SmuzhiyunIf successful, it returns a pointer to the new pixmap; if not, it returns NULL. 3061*4882a593SmuzhiyunSee Xserver/fb/fbpixmap.c for the sample server implementation.</para> 3062*4882a593Smuzhiyun<para> 3063*4882a593Smuzhiyun<blockquote><programlisting> 3064*4882a593Smuzhiyun 3065*4882a593Smuzhiyun Bool pScreen->DestroyPixmap(pPixmap) 3066*4882a593Smuzhiyun PixmapPtr pPixmap; 3067*4882a593Smuzhiyun 3068*4882a593Smuzhiyun</programlisting></blockquote> 3069*4882a593SmuzhiyunThis ScreenRec procedure must "destroy" a pixmap. 3070*4882a593SmuzhiyunIt should decrement the reference count and, if zero, it 3071*4882a593Smuzhiyunmust deallocate the PixmapRec and all attached devPrivate blocks. 3072*4882a593SmuzhiyunIf successful, it returns TRUE. 3073*4882a593SmuzhiyunSee Xserver/fb/fbpixmap.c for the sample server implementation.</para> 3074*4882a593Smuzhiyun<para> 3075*4882a593Smuzhiyun<blockquote><programlisting> 3076*4882a593Smuzhiyun 3077*4882a593Smuzhiyun Bool 3078*4882a593Smuzhiyun pScreen->ModifyPixmapHeader(pPixmap, width, height, depth, bitsPerPixel, devKind, pPixData) 3079*4882a593Smuzhiyun PixmapPtr pPixmap; 3080*4882a593Smuzhiyun int width; 3081*4882a593Smuzhiyun int height; 3082*4882a593Smuzhiyun int depth; 3083*4882a593Smuzhiyun int bitsPerPixel; 3084*4882a593Smuzhiyun int devKind; 3085*4882a593Smuzhiyun pointer pPixData; 3086*4882a593Smuzhiyun 3087*4882a593Smuzhiyun</programlisting></blockquote> 3088*4882a593SmuzhiyunThis routine takes a pixmap header and initializes the fields of the PixmapRec to the 3089*4882a593Smuzhiyunparameters of the same name. pPixmap must have been created via 3090*4882a593SmuzhiyunpScreen->CreatePixmap with a zero width or height to avoid 3091*4882a593Smuzhiyunallocating space for the pixmap data. pPixData is assumed to be the 3092*4882a593Smuzhiyunpixmap data; it will be stored in an implementation-dependent place 3093*4882a593Smuzhiyun(usually pPixmap->devPrivate.ptr). This routine returns 3094*4882a593SmuzhiyunTRUE if successful. See Xserver/mi/miscrinit.c for the sample 3095*4882a593Smuzhiyunserver implementation.</para> 3096*4882a593Smuzhiyun<para> 3097*4882a593Smuzhiyun<blockquote><programlisting> 3098*4882a593Smuzhiyun 3099*4882a593Smuzhiyun PixmapPtr 3100*4882a593Smuzhiyun GetScratchPixmapHeader(pScreen, width, height, depth, bitsPerPixel, devKind, pPixData) 3101*4882a593Smuzhiyun ScreenPtr pScreen; 3102*4882a593Smuzhiyun int width; 3103*4882a593Smuzhiyun int height; 3104*4882a593Smuzhiyun int depth; 3105*4882a593Smuzhiyun int bitsPerPixel; 3106*4882a593Smuzhiyun int devKind; 3107*4882a593Smuzhiyun pointer pPixData; 3108*4882a593Smuzhiyun 3109*4882a593Smuzhiyun void FreeScratchPixmapHeader(pPixmap) 3110*4882a593Smuzhiyun PixmapPtr pPixmap; 3111*4882a593Smuzhiyun 3112*4882a593Smuzhiyun</programlisting></blockquote> 3113*4882a593SmuzhiyunDDX should use these two DIX routines when it has a buffer of raw 3114*4882a593Smuzhiyunimage data that it wants to manipulate as a pixmap temporarily, 3115*4882a593Smuzhiyunusually so that some other part of the server can be leveraged to 3116*4882a593Smuzhiyunperform some operation on the data. The data should be passed in 3117*4882a593SmuzhiyunpPixData, and will be stored in an implementation-dependent place 3118*4882a593Smuzhiyun(usually pPixmap->devPrivate.ptr). The other 3119*4882a593Smuzhiyunfields go into the corresponding PixmapRec fields. 3120*4882a593SmuzhiyunIf successful, GetScratchPixmapHeader returns a valid PixmapPtr which can 3121*4882a593Smuzhiyunbe used anywhere the server expects a pixmap, else 3122*4882a593Smuzhiyunit returns NULL. The pixmap should be released when no longer needed 3123*4882a593Smuzhiyun(usually within the same function that allocated it) 3124*4882a593Smuzhiyunwith FreeScratchPixmapHeader.</para> 3125*4882a593Smuzhiyun</section> 3126*4882a593Smuzhiyun<section> 3127*4882a593Smuzhiyun <title>Windows</title> 3128*4882a593Smuzhiyun<para> 3129*4882a593SmuzhiyunA window is a visible, or potentially visible, rectangle on the screen. 3130*4882a593SmuzhiyunDIX windowing functions maintain an internal n-ary tree data structure, which 3131*4882a593Smuzhiyunrepresents the current relationships of the mapped windows. 3132*4882a593SmuzhiyunWindows that are contained in another window are children of that window and 3133*4882a593Smuzhiyunare clipped to the boundaries of the parent. 3134*4882a593SmuzhiyunThe root window in the tree is the window for the entire screen. 3135*4882a593SmuzhiyunSibling windows constitute a doubly-linked list; the parent window has a pointer 3136*4882a593Smuzhiyunto the head and tail of this list. 3137*4882a593SmuzhiyunEach child also has a pointer to its parent.</para> 3138*4882a593Smuzhiyun<para> 3139*4882a593SmuzhiyunThe border of a window is drawn by a DDX procedure when DIX requests that it 3140*4882a593Smuzhiyunbe drawn. The contents of the window is drawn by the client through 3141*4882a593Smuzhiyunrequests to the server.</para> 3142*4882a593Smuzhiyun<para> 3143*4882a593SmuzhiyunWindow painting is orchestrated through an expose event system. 3144*4882a593SmuzhiyunWhen a region is exposed, 3145*4882a593SmuzhiyunDIX generates an expose event, telling the client to repaint the window and 3146*4882a593Smuzhiyunpassing the region that is the minimal area needed to be repainted.</para> 3147*4882a593Smuzhiyun<para> 3148*4882a593SmuzhiyunAs a favor to clients, the server may retain 3149*4882a593Smuzhiyunthe output to the hidden parts of windows 3150*4882a593Smuzhiyunin off-screen memory; this is called "backing store". 3151*4882a593SmuzhiyunWhen a part of such a window becomes exposed, it 3152*4882a593Smuzhiyuncan quickly move pixels into place instead of 3153*4882a593Smuzhiyuntriggering an expose event and waiting for a client on the other 3154*4882a593Smuzhiyunend of the network to respond. 3155*4882a593SmuzhiyunEven if the network response is insignificant, the time to 3156*4882a593Smuzhiyunintelligently paint a section of a window is usually more than 3157*4882a593Smuzhiyunthe time to just copy already-painted sections. 3158*4882a593SmuzhiyunAt best, the repainting involves blanking out the area to a background color, 3159*4882a593Smuzhiyunwhich will take about the 3160*4882a593Smuzhiyunsame amount of time. 3161*4882a593SmuzhiyunIn this way, backing store can dramatically increase the 3162*4882a593Smuzhiyunperformance of window moves.</para> 3163*4882a593Smuzhiyun<para> 3164*4882a593SmuzhiyunOn the other hand, backing store can be quite complex, because 3165*4882a593Smuzhiyunall graphics drawn to hidden areas must be intercepted and redirected 3166*4882a593Smuzhiyunto the off-screen window sections. 3167*4882a593SmuzhiyunNot only can this be complicated for the server programmer, 3168*4882a593Smuzhiyunbut it can also impact window painting performance. 3169*4882a593SmuzhiyunThe backing store implementation can choose, at any time, to 3170*4882a593Smuzhiyunforget pieces of backing that are written into, relying instead upon 3171*4882a593Smuzhiyunexpose events to repaint for simplicity.</para> 3172*4882a593Smuzhiyun<para> 3173*4882a593SmuzhiyunIn X, the decision to use the backing-store scheme is made 3174*4882a593Smuzhiyunby you, the server implementor. The sample server implements 3175*4882a593Smuzhiyunbacking store "for free" by reusing the infrastructure for the Composite 3176*4882a593Smuzhiyunextension. As a side effect, it treats the WhenMapped and Always hints 3177*4882a593Smuzhiyunas equivalent. However, it will never forget pixel contents when the 3178*4882a593Smuzhiyunwindow is mapped.</para> 3179*4882a593Smuzhiyun<para> 3180*4882a593SmuzhiyunWhen a window operation is requested by the client, 3181*4882a593Smuzhiyunsuch as a window being created or moved, 3182*4882a593Smuzhiyuna new state is computed. 3183*4882a593SmuzhiyunDuring this transition, DIX informs DDX what rectangles in what windows are about to 3184*4882a593Smuzhiyunbecome obscured and what rectangles in what windows have become exposed. 3185*4882a593SmuzhiyunThis provides a hook for the implementation of backing store. 3186*4882a593SmuzhiyunIf DDX is unable to restore exposed regions, DIX generates expose 3187*4882a593Smuzhiyunevents to the client. 3188*4882a593SmuzhiyunIt is then the client's responsibility to paint the 3189*4882a593Smuzhiyunwindow parts that were exposed but not restored.</para> 3190*4882a593Smuzhiyun<para> 3191*4882a593SmuzhiyunIf a window is resized, pixels sometimes need to be 3192*4882a593Smuzhiyunmoved, depending upon 3193*4882a593Smuzhiyunthe application. 3194*4882a593SmuzhiyunThe client can request "Gravity" so that 3195*4882a593Smuzhiyuncertain blocks of the window are 3196*4882a593Smuzhiyunmoved as a result of a resize. 3197*4882a593SmuzhiyunFor instance, if the window has controls or other items 3198*4882a593Smuzhiyunthat always hang on the edge of the 3199*4882a593Smuzhiyunwindow, and that edge is moved as a result of the resize, 3200*4882a593Smuzhiyunthen those pixels should be moved 3201*4882a593Smuzhiyunto avoid having the client repaint it. 3202*4882a593SmuzhiyunIf the client needs to repaint it anyway, such an operation takes 3203*4882a593Smuzhiyuntime, so it is desirable 3204*4882a593Smuzhiyunfor the server to approximate the appearance of the window as best 3205*4882a593Smuzhiyunit can while waiting for the client 3206*4882a593Smuzhiyunto do it perfectly. 3207*4882a593SmuzhiyunGravity is used for that, also.</para> 3208*4882a593Smuzhiyun<para> 3209*4882a593SmuzhiyunThe window has several fields used in drawing 3210*4882a593Smuzhiyunoperations: 3211*4882a593Smuzhiyun<itemizedlist> 3212*4882a593Smuzhiyun<listitem><para> 3213*4882a593SmuzhiyunclipList - This region, in conjunction with 3214*4882a593Smuzhiyunthe client clip region in the gc, is used to clip output. 3215*4882a593SmuzhiyunclipList has the window's children subtracted from it, in addition to pieces of sibling windows 3216*4882a593Smuzhiyunthat overlap this window. To get the list with the 3217*4882a593Smuzhiyunchildren included (subwindow-mode is IncludeInferiors), 3218*4882a593Smuzhiyunthe routine NotClippedByChildren(pWin) returns the unclipped region.</para></listitem> 3219*4882a593Smuzhiyun<listitem><para> 3220*4882a593SmuzhiyunborderClip is the region used by CopyWindow and 3221*4882a593Smuzhiyunincludes the area of the window, its children, and the border, but with the 3222*4882a593Smuzhiyunoverlapping areas of sibling children removed.</para></listitem> 3223*4882a593Smuzhiyun</itemizedlist> 3224*4882a593SmuzhiyunMost of the other fields are for DIX use only.</para> 3225*4882a593Smuzhiyun<section> 3226*4882a593Smuzhiyun<title>Window Procedures in the ScreenRec</title> 3227*4882a593Smuzhiyun<para> 3228*4882a593SmuzhiyunYou should implement 3229*4882a593Smuzhiyunall of the following procedures and store pointers to them in the screen record.</para> 3230*4882a593Smuzhiyun<para> 3231*4882a593SmuzhiyunThe device-independent portion of the server "owns" the window tree. 3232*4882a593SmuzhiyunHowever, clever hardware might want to know the relationship of 3233*4882a593Smuzhiyunmapped windows. There are pointers to procedures 3234*4882a593Smuzhiyunin the ScreenRec data structure that are called to give the hardware 3235*4882a593Smuzhiyuna chance to update its internal state. These are helpers and 3236*4882a593Smuzhiyunhints to DDX only; 3237*4882a593Smuzhiyunthey do not change the window tree, which is only changed by DIX.</para> 3238*4882a593Smuzhiyun<para> 3239*4882a593Smuzhiyun<blockquote><programlisting> 3240*4882a593Smuzhiyun 3241*4882a593Smuzhiyun Bool pScreen->CreateWindow(pWin) 3242*4882a593Smuzhiyun WindowPtr pWin; 3243*4882a593Smuzhiyun 3244*4882a593Smuzhiyun</programlisting></blockquote> 3245*4882a593SmuzhiyunThis routine is a hook for when DIX creates a window. 3246*4882a593SmuzhiyunIt should fill in the "Window Procedures in the WindowRec" below 3247*4882a593Smuzhiyunand also allocate the devPrivate block for it.</para> 3248*4882a593Smuzhiyun<para> 3249*4882a593SmuzhiyunSee Xserver/fb/fbwindow.c for the sample server implementation.</para> 3250*4882a593Smuzhiyun<para> 3251*4882a593Smuzhiyun<blockquote><programlisting> 3252*4882a593Smuzhiyun 3253*4882a593Smuzhiyun Bool pScreen->DestroyWindow(pWin); 3254*4882a593Smuzhiyun WindowPtr pWin; 3255*4882a593Smuzhiyun 3256*4882a593Smuzhiyun</programlisting></blockquote> 3257*4882a593SmuzhiyunThis routine is a hook for when DIX destroys a window. 3258*4882a593SmuzhiyunIt should deallocate the devPrivate block for it and any other blocks that need 3259*4882a593Smuzhiyunto be freed, besides doing other cleanup actions.</para> 3260*4882a593Smuzhiyun<para> 3261*4882a593SmuzhiyunSee Xserver/fb/fbwindow.c for the sample server implementation.</para> 3262*4882a593Smuzhiyun<para> 3263*4882a593Smuzhiyun<blockquote><programlisting> 3264*4882a593Smuzhiyun 3265*4882a593Smuzhiyun Bool pScreen->PositionWindow(pWin, x, y); 3266*4882a593Smuzhiyun WindowPtr pWin; 3267*4882a593Smuzhiyun int x, y; 3268*4882a593Smuzhiyun 3269*4882a593Smuzhiyun</programlisting></blockquote> 3270*4882a593SmuzhiyunThis routine is a hook for when DIX moves or resizes a window. 3271*4882a593SmuzhiyunIt should do whatever private operations need to be done when a window is moved or resized. 3272*4882a593SmuzhiyunFor instance, if DDX keeps a pixmap tile used for drawing the background 3273*4882a593Smuzhiyunor border, and it keeps the tile rotated such that it is longword 3274*4882a593Smuzhiyunaligned to longword locations in the frame buffer, then you should rotate your tiles here. 3275*4882a593SmuzhiyunThe actual graphics involved in moving the pixels on the screen and drawing the 3276*4882a593Smuzhiyunborder are handled by CopyWindow(), below.</para> 3277*4882a593Smuzhiyun<para> 3278*4882a593SmuzhiyunSee Xserver/fb/fbwindow.c for the sample server implementation.</para> 3279*4882a593Smuzhiyun<para> 3280*4882a593Smuzhiyun<blockquote><programlisting> 3281*4882a593Smuzhiyun 3282*4882a593Smuzhiyun Bool pScreen->RealizeWindow(pWin); 3283*4882a593Smuzhiyun WindowPtr pWin; 3284*4882a593Smuzhiyun 3285*4882a593Smuzhiyun Bool pScreen->UnrealizeWindow(pWin); 3286*4882a593Smuzhiyun WindowPtr pWin; 3287*4882a593Smuzhiyun 3288*4882a593Smuzhiyun</programlisting></blockquote> 3289*4882a593SmuzhiyunThese routines are hooks for when DIX maps (makes visible) and unmaps 3290*4882a593Smuzhiyun(makes invisible) a window. It should do whatever private operations 3291*4882a593Smuzhiyunneed to be done when these happen, such as allocating or deallocating 3292*4882a593Smuzhiyunstructures that are only needed for visible windows. RealizeWindow 3293*4882a593Smuzhiyundoes NOT draw the window border, background or contents; 3294*4882a593SmuzhiyunUnrealizeWindow does NOT erase the window or generate exposure events 3295*4882a593Smuzhiyunfor underlying windows; this is taken care of by DIX. DIX does, 3296*4882a593Smuzhiyunhowever, call PaintWindowBackground() and PaintWindowBorder() to 3297*4882a593Smuzhiyunperform some of these.</para> 3298*4882a593Smuzhiyun<para> 3299*4882a593Smuzhiyun<blockquote><programlisting> 3300*4882a593Smuzhiyun 3301*4882a593Smuzhiyun Bool pScreen->ChangeWindowAttributes(pWin, vmask) 3302*4882a593Smuzhiyun WindowPtr pWin; 3303*4882a593Smuzhiyun unsigned long vmask; 3304*4882a593Smuzhiyun 3305*4882a593Smuzhiyun</programlisting></blockquote> 3306*4882a593SmuzhiyunChangeWindowAttributes is called whenever DIX changes window 3307*4882a593Smuzhiyunattributes, such as the size, front-to-back ordering, title, or 3308*4882a593Smuzhiyunanything of lesser severity that affects the window itself. The 3309*4882a593Smuzhiyunsample server implements this routine. It computes accelerators for 3310*4882a593Smuzhiyunquickly putting up background and border tiles. (See description of 3311*4882a593Smuzhiyunthe set of routines stored in the WindowRec.)</para> 3312*4882a593Smuzhiyun<para> 3313*4882a593Smuzhiyun<blockquote><programlisting> 3314*4882a593Smuzhiyun 3315*4882a593Smuzhiyun int pScreen->ValidateTree(pParent, pChild, kind) 3316*4882a593Smuzhiyun WindowPtr pParent, pChild; 3317*4882a593Smuzhiyun VTKind kind; 3318*4882a593Smuzhiyun 3319*4882a593Smuzhiyun</programlisting></blockquote> 3320*4882a593SmuzhiyunValidateTree calculates the clipping region for the parent window and 3321*4882a593Smuzhiyunall of its children. This routine must be provided. The sample server 3322*4882a593Smuzhiyunhas a machine-independent version in Xserver/mi/mivaltree.c. This is 3323*4882a593Smuzhiyuna very difficult routine to replace.</para> 3324*4882a593Smuzhiyun<para> 3325*4882a593Smuzhiyun<blockquote><programlisting> 3326*4882a593Smuzhiyun 3327*4882a593Smuzhiyun void pScreen->PostValidateTree(pParent, pChild, kind) 3328*4882a593Smuzhiyun WindowPtr pParent, pChild; 3329*4882a593Smuzhiyun VTKind kind; 3330*4882a593Smuzhiyun 3331*4882a593Smuzhiyun</programlisting></blockquote> 3332*4882a593SmuzhiyunIf this routine is not NULL, DIX calls it shortly after calling 3333*4882a593SmuzhiyunValidateTree, passing it the same arguments. This is useful for 3334*4882a593Smuzhiyunmanaging multi-layered framebuffers. 3335*4882a593SmuzhiyunThe sample server sets this to NULL.</para> 3336*4882a593Smuzhiyun<para> 3337*4882a593Smuzhiyun<blockquote><programlisting> 3338*4882a593Smuzhiyun 3339*4882a593Smuzhiyun void pScreen->WindowExposures(pWin, pRegion, pBSRegion) 3340*4882a593Smuzhiyun WindowPtr pWin; 3341*4882a593Smuzhiyun RegionPtr pRegion; 3342*4882a593Smuzhiyun RegionPtr pBSRegion; 3343*4882a593Smuzhiyun 3344*4882a593Smuzhiyun</programlisting></blockquote> 3345*4882a593SmuzhiyunThe WindowExposures() routine 3346*4882a593Smuzhiyunpaints the border and generates exposure events for the window. 3347*4882a593SmuzhiyunpRegion is an unoccluded region of the window, and pBSRegion is an 3348*4882a593Smuzhiyunoccluded region that has backing store. 3349*4882a593SmuzhiyunSince exposure events include a rectangle describing what was exposed, 3350*4882a593Smuzhiyunthis routine may have to send back a series of exposure events, one for 3351*4882a593Smuzhiyuneach rectangle of the region. 3352*4882a593SmuzhiyunThe count field in the expose event is a hint to the 3353*4882a593Smuzhiyunclient as to the number of 3354*4882a593Smuzhiyunregions that are after this one. 3355*4882a593SmuzhiyunThis routine must be provided. The sample 3356*4882a593Smuzhiyunserver has a machine-independent version in Xserver/mi/miexpose.c.</para> 3357*4882a593Smuzhiyun<para> 3358*4882a593Smuzhiyun<blockquote><programlisting> 3359*4882a593Smuzhiyun 3360*4882a593Smuzhiyun void pScreen->ClipNotify (pWin, dx, dy) 3361*4882a593Smuzhiyun WindowPtr pWin; 3362*4882a593Smuzhiyun int dx, dy; 3363*4882a593Smuzhiyun 3364*4882a593Smuzhiyun</programlisting></blockquote> 3365*4882a593SmuzhiyunWhenever the cliplist for a window is changed, this function is called to 3366*4882a593Smuzhiyunperform whatever hardware manipulations might be necessary. When called, 3367*4882a593Smuzhiyunthe clip list and border clip regions in the window are set to the new 3368*4882a593Smuzhiyunvalues. dx,dy are the distance that the window has been moved (if at all).</para> 3369*4882a593Smuzhiyun</section> 3370*4882a593Smuzhiyun<section> 3371*4882a593Smuzhiyun <title>Window Painting Procedures</title> 3372*4882a593Smuzhiyun<para> 3373*4882a593SmuzhiyunIn addition to the procedures listed above, there are two routines which 3374*4882a593Smuzhiyunmanipulate the actual window image directly. 3375*4882a593SmuzhiyunIn the sample server, mi implementations will work for 3376*4882a593Smuzhiyunmost purposes and fb routines speed up situations, such 3377*4882a593Smuzhiyunas solid backgrounds/borders or tiles that are 8, 16 or 32 pixels square.</para> 3378*4882a593Smuzhiyun<para> 3379*4882a593Smuzhiyun<blockquote><programlisting> 3380*4882a593Smuzhiyun 3381*4882a593Smuzhiyun void pScreen->ClearToBackground(pWin, x, y, w, h, generateExposures); 3382*4882a593Smuzhiyun WindowPtr pWin; 3383*4882a593Smuzhiyun int x, y, w, h; 3384*4882a593Smuzhiyun Bool generateExposures; 3385*4882a593Smuzhiyun 3386*4882a593Smuzhiyun</programlisting></blockquote> 3387*4882a593SmuzhiyunThis routine is called on a window in response to a ClearToBackground request 3388*4882a593Smuzhiyunfrom the client. 3389*4882a593SmuzhiyunThis request has two different but related functions, depending upon generateExposures.</para> 3390*4882a593Smuzhiyun<para> 3391*4882a593SmuzhiyunIf generateExposures is true, the client is declaring that the given rectangle 3392*4882a593Smuzhiyunon the window is incorrectly painted and needs to be repainted. 3393*4882a593SmuzhiyunThe sample server implementation calculates the exposure region 3394*4882a593Smuzhiyunand hands it to the DIX procedure HandleExposures(), which 3395*4882a593Smuzhiyuncalls the WindowExposures() routine, below, for the window 3396*4882a593Smuzhiyunand all of its child windows.</para> 3397*4882a593Smuzhiyun<para> 3398*4882a593SmuzhiyunIf generateExposures is false, the client is trying to simply erase part 3399*4882a593Smuzhiyunof the window to the background fill style. 3400*4882a593SmuzhiyunClearToBackground should write the background color or tile to the 3401*4882a593Smuzhiyunrectangle in question (probably using PaintWindowBackground). 3402*4882a593SmuzhiyunIf w or h is zero, it clears all the way to the right or lower edge of the window.</para> 3403*4882a593Smuzhiyun<para> 3404*4882a593SmuzhiyunThe sample server implementation is in Xserver/mi/miwindow.c.</para> 3405*4882a593Smuzhiyun<para> 3406*4882a593Smuzhiyun<blockquote><programlisting> 3407*4882a593Smuzhiyun 3408*4882a593Smuzhiyun void pScreen->CopyWindow(pWin, oldpt, oldRegion); 3409*4882a593Smuzhiyun WindowPtr pWin; 3410*4882a593Smuzhiyun DDXPointRec oldpt; 3411*4882a593Smuzhiyun RegionPtr oldRegion; 3412*4882a593Smuzhiyun 3413*4882a593Smuzhiyun</programlisting></blockquote> 3414*4882a593SmuzhiyunCopyWindow is called when a window is moved, and graphically moves to 3415*4882a593Smuzhiyunpixels of a window on the screen. It should not change any other 3416*4882a593Smuzhiyunstate within DDX (see PositionWindow(), above).</para> 3417*4882a593Smuzhiyun<para> 3418*4882a593Smuzhiyunoldpt is the old location of the upper-left corner. oldRegion is the 3419*4882a593Smuzhiyunold region it is coming from. The new location and new region is 3420*4882a593Smuzhiyunstored in the WindowRec. oldRegion might modified in place by this 3421*4882a593Smuzhiyunroutine (the sample implementation does this).</para> 3422*4882a593Smuzhiyun<para> 3423*4882a593SmuzhiyunCopyArea could be used, except that this operation has more 3424*4882a593Smuzhiyuncomplications. First of all, you do not want to copy a rectangle onto 3425*4882a593Smuzhiyuna rectangle. The original window may be obscured by other windows, 3426*4882a593Smuzhiyunand the new window location may be similarly obscured. Second, some 3427*4882a593Smuzhiyunhardware supports multiple windows with multiple depths, and your 3428*4882a593Smuzhiyunroutine needs to take care of that.</para> 3429*4882a593Smuzhiyun<para> 3430*4882a593SmuzhiyunThe pixels in oldRegion (with reference point oldpt) are copied to the 3431*4882a593Smuzhiyunwindow's new region (pWin->borderClip). pWin->borderClip is gotten 3432*4882a593Smuzhiyundirectly from the window, rather than passing it as a parameter.</para> 3433*4882a593Smuzhiyun<para> 3434*4882a593SmuzhiyunThe sample server implementation is in Xserver/fb/fbwindow.c.</para> 3435*4882a593Smuzhiyun</section> 3436*4882a593Smuzhiyun<section> 3437*4882a593Smuzhiyun<title>Screen Operations for Multi-Layered Framebuffers</title> 3438*4882a593Smuzhiyun<para> 3439*4882a593SmuzhiyunThe following screen functions are useful if you have a framebuffer with 3440*4882a593Smuzhiyunmultiple sets of independent bit planes, e.g. overlays or underlays in 3441*4882a593Smuzhiyunaddition to the "main" planes. If you have a simple single-layer 3442*4882a593Smuzhiyunframebuffer, you should probably use the mi versions of these routines 3443*4882a593Smuzhiyunin mi/miwindow.c. This can be easily accomplished by calling miScreenInit.</para> 3444*4882a593Smuzhiyun<para> 3445*4882a593Smuzhiyun<blockquote><programlisting> 3446*4882a593Smuzhiyun 3447*4882a593Smuzhiyun void pScreen->MarkWindow(pWin) 3448*4882a593Smuzhiyun WindowPtr pWin; 3449*4882a593Smuzhiyun 3450*4882a593Smuzhiyun</programlisting></blockquote> 3451*4882a593SmuzhiyunThis formerly dix function MarkWindow has moved to ddx and is accessed 3452*4882a593Smuzhiyunvia this screen function. This function should store something, 3453*4882a593Smuzhiyunusually a pointer to a device-dependent structure, in pWin->valdata so 3454*4882a593Smuzhiyunthat ValidateTree has the information it needs to validate the window.</para> 3455*4882a593Smuzhiyun<para> 3456*4882a593Smuzhiyun<blockquote><programlisting> 3457*4882a593Smuzhiyun 3458*4882a593Smuzhiyun Bool pScreen->MarkOverlappedWindows(parent, firstChild, ppLayerWin) 3459*4882a593Smuzhiyun WindowPtr parent; 3460*4882a593Smuzhiyun WindowPtr firstChild; 3461*4882a593Smuzhiyun WindowPtr * ppLayerWin; 3462*4882a593Smuzhiyun 3463*4882a593Smuzhiyun</programlisting></blockquote> 3464*4882a593SmuzhiyunThis formerly dix function MarkWindow has moved to ddx and is accessed 3465*4882a593Smuzhiyunvia this screen function. In the process, it has grown another 3466*4882a593Smuzhiyunparameter: ppLayerWin, which is filled in with a pointer to the window 3467*4882a593Smuzhiyunat which save under marking and ValidateTree should begin. In the 3468*4882a593Smuzhiyunsingle-layered framebuffer case, pLayerWin == pWin.</para> 3469*4882a593Smuzhiyun<para> 3470*4882a593Smuzhiyun<blockquote><programlisting> 3471*4882a593Smuzhiyun 3472*4882a593Smuzhiyun Bool pScreen->ChangeSaveUnder(pLayerWin, firstChild) 3473*4882a593Smuzhiyun WindowPtr pLayerWin; 3474*4882a593Smuzhiyun WindowPtr firstChild; 3475*4882a593Smuzhiyun 3476*4882a593Smuzhiyun</programlisting></blockquote> 3477*4882a593SmuzhiyunThe dix functions ChangeSaveUnder and CheckSaveUnder have moved to ddx and 3478*4882a593Smuzhiyunare accessed via this screen function. pLayerWin should be the window 3479*4882a593Smuzhiyunreturned in the ppLayerWin parameter of MarkOverlappedWindows. The function 3480*4882a593Smuzhiyunmay turn on backing store for windows that might be covered, and may partially 3481*4882a593Smuzhiyunturn off backing store for windows. It returns TRUE if PostChangeSaveUnder 3482*4882a593Smuzhiyunneeds to be called to finish turning off backing store.</para> 3483*4882a593Smuzhiyun<para> 3484*4882a593Smuzhiyun<blockquote><programlisting> 3485*4882a593Smuzhiyun 3486*4882a593Smuzhiyun void pScreen->PostChangeSaveUnder(pLayerWin, firstChild) 3487*4882a593Smuzhiyun WindowPtr pLayerWin; 3488*4882a593Smuzhiyun WindowPtr firstChild; 3489*4882a593Smuzhiyun 3490*4882a593Smuzhiyun</programlisting></blockquote> 3491*4882a593SmuzhiyunThe dix function DoChangeSaveUnder has moved to ddx and is accessed via 3492*4882a593Smuzhiyunthis screen function. This function completes the job of turning off 3493*4882a593Smuzhiyunbacking store that was started by ChangeSaveUnder.</para> 3494*4882a593Smuzhiyun<para> 3495*4882a593Smuzhiyun<blockquote><programlisting> 3496*4882a593Smuzhiyun 3497*4882a593Smuzhiyun void pScreen->MoveWindow(pWin, x, y, pSib, kind) 3498*4882a593Smuzhiyun WindowPtr pWin; 3499*4882a593Smuzhiyun int x; 3500*4882a593Smuzhiyun int y; 3501*4882a593Smuzhiyun WindowPtr pSib; 3502*4882a593Smuzhiyun VTKind kind; 3503*4882a593Smuzhiyun 3504*4882a593Smuzhiyun</programlisting></blockquote> 3505*4882a593SmuzhiyunThe formerly dix function MoveWindow has moved to ddx and is accessed via 3506*4882a593Smuzhiyunthis screen function. The new position of the window is given by 3507*4882a593Smuzhiyunx,y. kind is VTMove if the window is only moving, or VTOther if 3508*4882a593Smuzhiyunthe border is also changing.</para> 3509*4882a593Smuzhiyun<para> 3510*4882a593Smuzhiyun<blockquote><programlisting> 3511*4882a593Smuzhiyun 3512*4882a593Smuzhiyun void pScreen->ResizeWindow(pWin, x, y, w, h, pSib) 3513*4882a593Smuzhiyun WindowPtr pWin; 3514*4882a593Smuzhiyun int x; 3515*4882a593Smuzhiyun int y; 3516*4882a593Smuzhiyun unsigned int w; 3517*4882a593Smuzhiyun unsigned int h; 3518*4882a593Smuzhiyun WindowPtr pSib; 3519*4882a593Smuzhiyun 3520*4882a593Smuzhiyun</programlisting></blockquote> 3521*4882a593SmuzhiyunThe formerly dix function SlideAndSizeWindow has moved to ddx and is accessed via 3522*4882a593Smuzhiyunthis screen function. The new position is given by x,y. The new size 3523*4882a593Smuzhiyunis given by w,h.</para> 3524*4882a593Smuzhiyun<para> 3525*4882a593Smuzhiyun<blockquote><programlisting> 3526*4882a593Smuzhiyun 3527*4882a593Smuzhiyun WindowPtr pScreen->GetLayerWindow(pWin) 3528*4882a593Smuzhiyun WindowPtr pWin 3529*4882a593Smuzhiyun 3530*4882a593Smuzhiyun</programlisting></blockquote> 3531*4882a593SmuzhiyunThis is a new function which returns a child of the layer parent of pWin.</para> 3532*4882a593Smuzhiyun<para> 3533*4882a593Smuzhiyun<blockquote><programlisting> 3534*4882a593Smuzhiyun 3535*4882a593Smuzhiyun void pScreen->HandleExposures(pWin) 3536*4882a593Smuzhiyun WindowPtr pWin; 3537*4882a593Smuzhiyun 3538*4882a593Smuzhiyun</programlisting></blockquote> 3539*4882a593SmuzhiyunThe formerly dix function HandleExposures has moved to ddx and is accessed via 3540*4882a593Smuzhiyunthis screen function. This function is called after ValidateTree and 3541*4882a593Smuzhiyunuses the information contained in valdata to send exposures to windows.</para> 3542*4882a593Smuzhiyun<para> 3543*4882a593Smuzhiyun<blockquote><programlisting> 3544*4882a593Smuzhiyun 3545*4882a593Smuzhiyun void pScreen->ReparentWindow(pWin, pPriorParent) 3546*4882a593Smuzhiyun WindowPtr pWin; 3547*4882a593Smuzhiyun WindowPtr pPriorParent; 3548*4882a593Smuzhiyun 3549*4882a593Smuzhiyun</programlisting></blockquote> 3550*4882a593SmuzhiyunThis function will be called when a window is reparented. At the time of 3551*4882a593Smuzhiyunthe call, pWin will already be spliced into its new position in the 3552*4882a593Smuzhiyunwindow tree, and pPriorParent is its previous parent. This function 3553*4882a593Smuzhiyuncan be NULL.</para> 3554*4882a593Smuzhiyun<para> 3555*4882a593Smuzhiyun<blockquote><programlisting> 3556*4882a593Smuzhiyun 3557*4882a593Smuzhiyun void pScreen->SetShape(pWin) 3558*4882a593Smuzhiyun WindowPtr pWin; 3559*4882a593Smuzhiyun 3560*4882a593Smuzhiyun</programlisting></blockquote> 3561*4882a593SmuzhiyunThe formerly dix function SetShape has moved to ddx and is accessed via 3562*4882a593Smuzhiyunthis screen function. The window's new shape will have already been 3563*4882a593Smuzhiyunstored in the window when this function is called.</para> 3564*4882a593Smuzhiyun<para> 3565*4882a593Smuzhiyun<blockquote><programlisting> 3566*4882a593Smuzhiyun 3567*4882a593Smuzhiyun void pScreen->ChangeBorderWidth(pWin, width) 3568*4882a593Smuzhiyun WindowPtr pWin; 3569*4882a593Smuzhiyun unsigned int width; 3570*4882a593Smuzhiyun 3571*4882a593Smuzhiyun</programlisting></blockquote> 3572*4882a593SmuzhiyunThe formerly dix function ChangeBorderWidth has moved to ddx and is accessed via 3573*4882a593Smuzhiyunthis screen function. The new border width is given by width.</para> 3574*4882a593Smuzhiyun<para> 3575*4882a593Smuzhiyun<blockquote><programlisting> 3576*4882a593Smuzhiyun 3577*4882a593Smuzhiyun void pScreen->MarkUnrealizedWindow(pChild, pWin, fromConfigure) 3578*4882a593Smuzhiyun WindowPtr pChild; 3579*4882a593Smuzhiyun WindowPtr pWin; 3580*4882a593Smuzhiyun Bool fromConfigure; 3581*4882a593Smuzhiyun 3582*4882a593Smuzhiyun</programlisting></blockquote> 3583*4882a593SmuzhiyunThis function is called for windows that are being unrealized as part of 3584*4882a593Smuzhiyunan UnrealizeTree. pChild is the window being unrealized, pWin is an 3585*4882a593Smuzhiyunancestor, and the fromConfigure value is simply propagated from UnrealizeTree.</para> 3586*4882a593Smuzhiyun</section> 3587*4882a593Smuzhiyun</section> 3588*4882a593Smuzhiyun</section> 3589*4882a593Smuzhiyun<section> 3590*4882a593Smuzhiyun<title>Graphics Contexts and Validation</title> 3591*4882a593Smuzhiyun<para> 3592*4882a593SmuzhiyunThis graphics context (GC) contains state variables such as foreground and 3593*4882a593Smuzhiyunbackground pixel value (color), the current line style and width, 3594*4882a593Smuzhiyunthe current tile or stipple for pattern generation, the current font for text 3595*4882a593Smuzhiyungeneration, and other similar attributes.</para> 3596*4882a593Smuzhiyun<para> 3597*4882a593SmuzhiyunIn many graphics systems, the equivalent of the graphics context and the 3598*4882a593Smuzhiyundrawable are combined as one entity. 3599*4882a593SmuzhiyunThe main distinction between the two kinds of status is that a drawable 3600*4882a593Smuzhiyundescribes a writing surface and the writings that may have already been done 3601*4882a593Smuzhiyunon it, whereas a graphics context describes the drawing process. 3602*4882a593SmuzhiyunA drawable is like a chalkboard. 3603*4882a593SmuzhiyunA GC is like a piece of chalk.</para> 3604*4882a593Smuzhiyun<para> 3605*4882a593SmuzhiyunUnlike many similar systems, there is no "current pen location." 3606*4882a593SmuzhiyunEvery graphic operation is accompanied by the coordinates where it is to happen.</para> 3607*4882a593Smuzhiyun<para> 3608*4882a593SmuzhiyunThe GC also includes two vectors of procedure pointers, the first 3609*4882a593Smuzhiyunoperate on the GC itself and are called GC funcs. The second, called 3610*4882a593SmuzhiyunGC ops, 3611*4882a593Smuzhiyuncontains the functions that carry out the fundamental graphic operations 3612*4882a593Smuzhiyunsuch as drawing lines, polygons, arcs, text, and copying bitmaps. 3613*4882a593SmuzhiyunThe DDX graphic software can, if it 3614*4882a593Smuzhiyunwants to be smart, change these two vectors of procedure pointers 3615*4882a593Smuzhiyunto take advantage of hardware/firmware in the server machine, which can do 3616*4882a593Smuzhiyuna better job under certain circumstances. To reduce the amount of memory 3617*4882a593Smuzhiyunconsumed by each GC, it is wise to create a few "boilerplate" GC ops vectors 3618*4882a593Smuzhiyunwhich can be shared by every GC which matches the constraints for that set. 3619*4882a593SmuzhiyunAlso, it is usually reasonable to have every GC created by a particular 3620*4882a593Smuzhiyunmodule to share a common set of GC funcs. Samples of this sort of 3621*4882a593Smuzhiyunsharing can be seen in fb/fbgc.c.</para> 3622*4882a593Smuzhiyun<para> 3623*4882a593SmuzhiyunThe DDX software is notified any time the client (or DIX) uses a changed GC. 3624*4882a593SmuzhiyunFor instance, if the hardware has special support for drawing fixed-width 3625*4882a593Smuzhiyunfonts, DDX can intercept changes to the current font in a GC just before 3626*4882a593Smuzhiyundrawing is done. It can plug into either a fixed-width procedure that makes 3627*4882a593Smuzhiyunthe hardware draw characters, or a variable-width procedure that carefully 3628*4882a593Smuzhiyunlays out glyphs by hand in software, depending upon the new font that is 3629*4882a593Smuzhiyunselected.</para> 3630*4882a593Smuzhiyun<para> 3631*4882a593SmuzhiyunA definition of these structures can be found in the file 3632*4882a593SmuzhiyunXserver/include/gcstruct.h.</para> 3633*4882a593Smuzhiyun<para> 3634*4882a593SmuzhiyunAlso included in each GC is support for dynamic devPrivates, which the 3635*4882a593SmuzhiyunDDX can use for any purpose (see <xref linkend="wrappers_and_privates"/> below).</para> 3636*4882a593Smuzhiyun<para> 3637*4882a593SmuzhiyunThe DIX routines available for manipulating GCs are 3638*4882a593SmuzhiyunCreateGC, ChangeGC, ChangeGCXIDs, CopyGC, SetClipRects, SetDashes, and FreeGC. 3639*4882a593Smuzhiyun<blockquote><programlisting> 3640*4882a593Smuzhiyun 3641*4882a593Smuzhiyun GCPtr CreateGC(pDrawable, mask, pval, pStatus) 3642*4882a593Smuzhiyun DrawablePtr pDrawable; 3643*4882a593Smuzhiyun BITS32 mask; 3644*4882a593Smuzhiyun XID *pval; 3645*4882a593Smuzhiyun int *pStatus; 3646*4882a593Smuzhiyun 3647*4882a593Smuzhiyun int ChangeGC(client, pGC, mask, pUnion) 3648*4882a593Smuzhiyun ClientPtr client; 3649*4882a593Smuzhiyun GCPtr pGC; 3650*4882a593Smuzhiyun BITS32 mask; 3651*4882a593Smuzhiyun ChangeGCValPtr pUnion; 3652*4882a593Smuzhiyun 3653*4882a593Smuzhiyun int ChangeGCXIDs(client, pGC, mask, pC32) 3654*4882a593Smuzhiyun ClientPtr client; 3655*4882a593Smuzhiyun GCPtr pGC; 3656*4882a593Smuzhiyun BITS32 mask; 3657*4882a593Smuzhiyun CARD32 *pC32; 3658*4882a593Smuzhiyun 3659*4882a593Smuzhiyun int CopyGC(pgcSrc, pgcDst, mask) 3660*4882a593Smuzhiyun GCPtr pgcSrc; 3661*4882a593Smuzhiyun GCPtr pgcDst; 3662*4882a593Smuzhiyun BITS32 mask; 3663*4882a593Smuzhiyun 3664*4882a593Smuzhiyun int SetClipRects(pGC, xOrigin, yOrigin, nrects, prects, ordering) 3665*4882a593Smuzhiyun GCPtr pGC; 3666*4882a593Smuzhiyun int xOrigin, yOrigin; 3667*4882a593Smuzhiyun int nrects; 3668*4882a593Smuzhiyun xRectangle *prects; 3669*4882a593Smuzhiyun int ordering; 3670*4882a593Smuzhiyun 3671*4882a593Smuzhiyun SetDashes(pGC, offset, ndash, pdash) 3672*4882a593Smuzhiyun GCPtr pGC; 3673*4882a593Smuzhiyun unsigned offset; 3674*4882a593Smuzhiyun unsigned ndash; 3675*4882a593Smuzhiyun unsigned char *pdash; 3676*4882a593Smuzhiyun 3677*4882a593Smuzhiyun int FreeGC(pGC, gid) 3678*4882a593Smuzhiyun GCPtr pGC; 3679*4882a593Smuzhiyun GContext gid; 3680*4882a593Smuzhiyun 3681*4882a593Smuzhiyun</programlisting></blockquote> 3682*4882a593Smuzhiyun</para> 3683*4882a593Smuzhiyun<para> 3684*4882a593SmuzhiyunAs a convenience, each Screen structure contains an array of 3685*4882a593SmuzhiyunGCs that are preallocated, one at each depth the screen supports. 3686*4882a593SmuzhiyunThese are particularly useful in the mi code. Two DIX routines 3687*4882a593Smuzhiyunmust be used to get these GCs: 3688*4882a593Smuzhiyun<blockquote><programlisting> 3689*4882a593Smuzhiyun 3690*4882a593Smuzhiyun GCPtr GetScratchGC(depth, pScreen) 3691*4882a593Smuzhiyun int depth; 3692*4882a593Smuzhiyun ScreenPtr pScreen; 3693*4882a593Smuzhiyun 3694*4882a593Smuzhiyun FreeScratchGC(pGC) 3695*4882a593Smuzhiyun GCPtr pGC; 3696*4882a593Smuzhiyun 3697*4882a593Smuzhiyun</programlisting></blockquote> 3698*4882a593SmuzhiyunAlways use these two routines, don't try to extract the scratch 3699*4882a593SmuzhiyunGC yourself -- someone else might be using it, so a new one must 3700*4882a593Smuzhiyunbe created on the fly.</para> 3701*4882a593Smuzhiyun<para> 3702*4882a593SmuzhiyunIf you need a GC for a very long time, say until the server is restarted, 3703*4882a593Smuzhiyunyou should not take one from the pool used by GetScratchGC, but should 3704*4882a593Smuzhiyunget your own using CreateGC or CreateScratchGC. 3705*4882a593SmuzhiyunThis leaves the ones in the pool free for routines that only need it for 3706*4882a593Smuzhiyuna little while and don't want to pay a heavy cost to get it. 3707*4882a593Smuzhiyun<blockquote><programlisting> 3708*4882a593Smuzhiyun 3709*4882a593Smuzhiyun GCPtr CreateScratchGC(pScreen, depth) 3710*4882a593Smuzhiyun ScreenPtr pScreen; 3711*4882a593Smuzhiyun int depth; 3712*4882a593Smuzhiyun 3713*4882a593Smuzhiyun</programlisting></blockquote> 3714*4882a593SmuzhiyunNULL is returned if the GC cannot be created. 3715*4882a593SmuzhiyunThe GC returned can be freed with FreeScratchGC.</para> 3716*4882a593Smuzhiyun<section> 3717*4882a593Smuzhiyun <title>Details of Operation</title> 3718*4882a593Smuzhiyun<para> 3719*4882a593SmuzhiyunAt screen initialization, a screen must supply a GC creation procedure. 3720*4882a593SmuzhiyunAt GC creation, the screen must fill in GC funcs and GC ops vectors 3721*4882a593Smuzhiyun(Xserver/include/gcstruct.h). For any particular GC, the func vector 3722*4882a593Smuzhiyunmust remain constant, while the op vector may vary. This invariant is to 3723*4882a593Smuzhiyunensure that Wrappers work correctly.</para> 3724*4882a593Smuzhiyun<para> 3725*4882a593SmuzhiyunWhen a client request is processed that results in a change 3726*4882a593Smuzhiyunto the GC, the device-independent state of the GC is updated. 3727*4882a593SmuzhiyunThis includes a record of the state that changed. 3728*4882a593SmuzhiyunThen the ChangeGC GC func is called. 3729*4882a593SmuzhiyunThis is useful for graphics subsystems that are able to process 3730*4882a593Smuzhiyunstate changes in parallel with the server CPU. 3731*4882a593SmuzhiyunDDX may opt not to take any action at GC-modify time. 3732*4882a593SmuzhiyunThis is more efficient if multiple GC-modify requests occur 3733*4882a593Smuzhiyunbetween draws using a given GC.</para> 3734*4882a593Smuzhiyun<para> 3735*4882a593SmuzhiyunValidation occurs at the first draw operation that specifies the GC after 3736*4882a593Smuzhiyunthat GC was modified. DIX calls then the ValidateGC GC func. DDX should 3737*4882a593Smuzhiyunthen update its internal state. DDX internal state may be stored as one or 3738*4882a593Smuzhiyunmore of the following: 1) device private block on the GC; 2) hardware 3739*4882a593Smuzhiyunstate; 3) changes to the GC ops.</para> 3740*4882a593Smuzhiyun<para> 3741*4882a593SmuzhiyunThe GC contains a serial number, which is loaded with a number fetched from 3742*4882a593Smuzhiyunthe window that was drawn into the last time the GC was used. The serial 3743*4882a593Smuzhiyunnumber in the drawable is changed when the drawable's 3744*4882a593SmuzhiyunclipList or absCorner changes. Thus, by 3745*4882a593Smuzhiyuncomparing the GC serial number with the drawable serial number, DIX can 3746*4882a593Smuzhiyunforce a validate if the drawable has been changed since the last time it 3747*4882a593Smuzhiyunwas used with this GC.</para> 3748*4882a593Smuzhiyun<para> 3749*4882a593SmuzhiyunIn addition, the drawable serial number is always guaranteed to have the 3750*4882a593Smuzhiyunmost significant bit set to 0. Thus, the DDX layer can set the most 3751*4882a593Smuzhiyunsignificant bit of the serial number to 1 in a GC to force a validate the next time 3752*4882a593Smuzhiyunthe GC is used. DIX also uses this technique to indicate that a change has 3753*4882a593Smuzhiyunbeen made to the GC by way of a SetGC, a SetDashes or a SetClip request.</para> 3754*4882a593Smuzhiyun</section> 3755*4882a593Smuzhiyun<section> 3756*4882a593Smuzhiyun <title>GC Handling Routines</title> 3757*4882a593Smuzhiyun<para> 3758*4882a593SmuzhiyunThe ScreenRec data structure has a pointer for 3759*4882a593SmuzhiyunCreateGC(). 3760*4882a593Smuzhiyun<blockquote><programlisting> 3761*4882a593Smuzhiyun 3762*4882a593Smuzhiyun Bool pScreen->CreateGC(pGC) 3763*4882a593Smuzhiyun GCPtr pGC; 3764*4882a593Smuzhiyun</programlisting></blockquote> 3765*4882a593SmuzhiyunThis routine must fill in the fields of 3766*4882a593Smuzhiyuna dynamically allocated GC that is passed in. 3767*4882a593SmuzhiyunIt does NOT allocate the GC record itself or fill 3768*4882a593Smuzhiyunin the defaults; DIX does that.</para> 3769*4882a593Smuzhiyun<para> 3770*4882a593SmuzhiyunThis must fill in both the GC funcs and ops; none of the drawing 3771*4882a593Smuzhiyunfunctions will be called before the GC has been validated, 3772*4882a593Smuzhiyunbut the others (dealing with allocating of clip regions, 3773*4882a593Smuzhiyunchanging and destroying the GC, etc.) might be.</para> 3774*4882a593Smuzhiyun<para> 3775*4882a593SmuzhiyunThe GC funcs vector contains pointers to 7 3776*4882a593Smuzhiyunroutines and a devPrivate field: 3777*4882a593Smuzhiyun<blockquote><programlisting> 3778*4882a593Smuzhiyun 3779*4882a593Smuzhiyun pGC->funcs->ChangeGC(pGC, changes) 3780*4882a593Smuzhiyun GCPtr pGC; 3781*4882a593Smuzhiyun unsigned long changes; 3782*4882a593Smuzhiyun 3783*4882a593Smuzhiyun</programlisting></blockquote> 3784*4882a593SmuzhiyunThis GC func is called immediately after a field in the GC is changed. 3785*4882a593Smuzhiyunchanges is a bit mask indicating the changed fields of the GC in this 3786*4882a593Smuzhiyunrequest.</para> 3787*4882a593Smuzhiyun<para> 3788*4882a593SmuzhiyunThe ChangeGC routine is useful if you have a system where 3789*4882a593Smuzhiyunstate-changes to the GC can be swallowed immediately by your graphics 3790*4882a593Smuzhiyunsystem, and a validate is not necessary.</para> 3791*4882a593Smuzhiyun<para> 3792*4882a593Smuzhiyun<blockquote><programlisting> 3793*4882a593Smuzhiyun 3794*4882a593Smuzhiyun pGC->funcs->ValidateGC(pGC, changes, pDraw) 3795*4882a593Smuzhiyun GCPtr pGC; 3796*4882a593Smuzhiyun unsigned long changes; 3797*4882a593Smuzhiyun DrawablePtr pDraw; 3798*4882a593Smuzhiyun 3799*4882a593Smuzhiyun</programlisting></blockquote> 3800*4882a593SmuzhiyunValidateGC is called by DIX just before the GC will be used when one 3801*4882a593Smuzhiyunof many possible changes to the GC or the graphics system has 3802*4882a593Smuzhiyunhappened. It can modify devPrivates data attached to the GC, 3803*4882a593Smuzhiyunchange the op vector, or change hardware according to the 3804*4882a593Smuzhiyunvalues in the GC. It may not change the device-independent portion of 3805*4882a593Smuzhiyunthe GC itself.</para> 3806*4882a593Smuzhiyun<para> 3807*4882a593SmuzhiyunIn almost all cases, your ValidateGC() procedure should take the 3808*4882a593Smuzhiyunregions that drawing needs to be clipped to and combine them into a 3809*4882a593Smuzhiyuncomposite clip region, which you keep a pointer to in the private part 3810*4882a593Smuzhiyunof the GC. In this way, your drawing primitive routines (and whatever 3811*4882a593Smuzhiyunis below them) can easily determine what to clip and where. You 3812*4882a593Smuzhiyunshould combine the regions clientClip (the region that the client 3813*4882a593Smuzhiyundesires to clip output to) and the region returned by 3814*4882a593SmuzhiyunNotClippedByChildren(), in DIX. An example is in Xserver/fb/fbgc.c.</para> 3815*4882a593Smuzhiyun<para> 3816*4882a593SmuzhiyunSome kinds of extension software may cause this routine to be called 3817*4882a593Smuzhiyunmore than originally intended; you should not rely on algorithms that 3818*4882a593Smuzhiyunwill break under such circumstances.</para> 3819*4882a593Smuzhiyun<para> 3820*4882a593SmuzhiyunSee the Strategies document for more information on creatively using 3821*4882a593Smuzhiyunthis routine.</para> 3822*4882a593Smuzhiyun<para> 3823*4882a593Smuzhiyun<blockquote><programlisting> 3824*4882a593Smuzhiyun 3825*4882a593Smuzhiyun pGC->funcs->CopyGC(pGCSrc, mask, pGCDst) 3826*4882a593Smuzhiyun GCPtr pGCSrc; 3827*4882a593Smuzhiyun unsigned long mask; 3828*4882a593Smuzhiyun GCPtr pGCDst; 3829*4882a593Smuzhiyun 3830*4882a593Smuzhiyun</programlisting></blockquote> 3831*4882a593SmuzhiyunThis routine is called by DIX when a GC is being copied to another GC. 3832*4882a593SmuzhiyunThis is for situations where dynamically allocated chunks of memory 3833*4882a593Smuzhiyunare stored in the GC's dynamic devPrivates and need to be transferred to 3834*4882a593Smuzhiyunthe destination GC.</para> 3835*4882a593Smuzhiyun<para> 3836*4882a593Smuzhiyun<blockquote><programlisting> 3837*4882a593Smuzhiyun 3838*4882a593Smuzhiyun pGC->funcs->DestroyGC(pGC) 3839*4882a593Smuzhiyun GCPtr pGC; 3840*4882a593Smuzhiyun 3841*4882a593Smuzhiyun</programlisting></blockquote> 3842*4882a593SmuzhiyunThis routine is called before the GC is destroyed for the 3843*4882a593Smuzhiyunentity interested in this GC to clean up after itself. 3844*4882a593SmuzhiyunThis routine is responsible for freeing any auxiliary storage allocated.</para> 3845*4882a593Smuzhiyun</section> 3846*4882a593Smuzhiyun<section> 3847*4882a593Smuzhiyun <title>GC Clip Region Routines</title> 3848*4882a593Smuzhiyun<para> 3849*4882a593SmuzhiyunThe GC clientClip field requires three procedures to manage it. These 3850*4882a593Smuzhiyunprocedures are in the GC funcs vector. The underlying principle is that dix 3851*4882a593Smuzhiyunknows nothing about the internals of the clipping information, (except when 3852*4882a593Smuzhiyunit has come from the client), and so calls ddX whenever it needs to copy, 3853*4882a593Smuzhiyunset, or destroy such information. It could have been possible for dix not 3854*4882a593Smuzhiyunto allow ddX to touch the field in the GC, and require it to keep its own 3855*4882a593Smuzhiyuncopy in devPriv, but since clip masks can be very large, this seems like a 3856*4882a593Smuzhiyunbad idea. Thus, the server allows ddX to do whatever it wants to the 3857*4882a593SmuzhiyunclientClip field of the GC, but requires it to do all manipulation itself.</para> 3858*4882a593Smuzhiyun<para> 3859*4882a593Smuzhiyun<blockquote><programlisting> 3860*4882a593Smuzhiyun 3861*4882a593Smuzhiyun void pGC->funcs->ChangeClip(pGC, type, pValue, nrects) 3862*4882a593Smuzhiyun GCPtr pGC; 3863*4882a593Smuzhiyun int type; 3864*4882a593Smuzhiyun char *pValue; 3865*4882a593Smuzhiyun int nrects; 3866*4882a593Smuzhiyun 3867*4882a593Smuzhiyun</programlisting></blockquote> 3868*4882a593SmuzhiyunThis routine is called whenever the client changes the client clip 3869*4882a593Smuzhiyunregion. The pGC points to the GC involved, the type tells what form 3870*4882a593Smuzhiyunthe region has been sent in. If type is CT_NONE, then there is no 3871*4882a593Smuzhiyunclient clip. If type is CT_UNSORTED, CT_YBANDED or CT_YXBANDED, then 3872*4882a593SmuzhiyunpValue pointer to a list of rectangles, nrects long. If type is 3873*4882a593SmuzhiyunCT_REGION, then pValue pointer to a RegionRec from the mi region code. 3874*4882a593SmuzhiyunIf type is CT_PIXMAP pValue is a pointer to a pixmap. (The defines 3875*4882a593Smuzhiyunfor CT_NONE, etc. are in Xserver/include/gc.h.) This routine is 3876*4882a593Smuzhiyunresponsible for incrementing any necessary reference counts (e.g. for 3877*4882a593Smuzhiyuna pixmap clip mask) for the new clipmask and freeing anything that 3878*4882a593Smuzhiyunused to be in the GC's clipMask field. The lists of rectangles passed 3879*4882a593Smuzhiyunin can be freed with free(), the regions can be destroyed with the 3880*4882a593SmuzhiyunRegionDestroy field in the screen, and pixmaps can be destroyed by 3881*4882a593Smuzhiyuncalling the screen's DestroyPixmap function. DIX and MI code expect 3882*4882a593Smuzhiyunwhat they pass in to this to be freed or otherwise inaccessible, and 3883*4882a593Smuzhiyunwill never look inside what's been put in the GC. This is a good 3884*4882a593Smuzhiyunplace to be wary of storage leaks.</para> 3885*4882a593Smuzhiyun<para> 3886*4882a593SmuzhiyunIn the sample server, this routine transforms either the bitmap or the 3887*4882a593Smuzhiyunrectangle list into a region, so that future routines will have a more 3888*4882a593Smuzhiyunpredictable starting point to work from. (The validate routine must 3889*4882a593Smuzhiyuntake this client clip region and merge it with other regions to arrive 3890*4882a593Smuzhiyunat a composite clip region before any drawing is done.)</para> 3891*4882a593Smuzhiyun<para> 3892*4882a593Smuzhiyun<blockquote><programlisting> 3893*4882a593Smuzhiyun 3894*4882a593Smuzhiyun void pGC->funcs->DestroyClip(pGC) 3895*4882a593Smuzhiyun GCPtr pGC; 3896*4882a593Smuzhiyun 3897*4882a593Smuzhiyun</programlisting></blockquote> 3898*4882a593SmuzhiyunThis routine is called whenever the client clip region must be destroyed. 3899*4882a593SmuzhiyunThe pGC points to the GC involved. This call should set the clipType 3900*4882a593Smuzhiyunfield of the GC to CT_NONE. 3901*4882a593SmuzhiyunIn the sample server, the pointer to the client clip region is set to NULL 3902*4882a593Smuzhiyunby this routine after destroying the region, so that other software 3903*4882a593Smuzhiyun(including ChangeClip() above) will recognize that there is no client clip region.</para> 3904*4882a593Smuzhiyun<para> 3905*4882a593Smuzhiyun<blockquote><programlisting> 3906*4882a593Smuzhiyun 3907*4882a593Smuzhiyun void pGC->funcs->CopyClip(pgcDst, pgcSrc) 3908*4882a593Smuzhiyun GCPtr pgcDst, pgcSrc; 3909*4882a593Smuzhiyun 3910*4882a593Smuzhiyun</programlisting></blockquote> 3911*4882a593SmuzhiyunThis routine makes a copy of the clipMask and clipType from pgcSrc 3912*4882a593Smuzhiyuninto pgcDst. It is responsible for destroying any previous clipMask 3913*4882a593Smuzhiyunin pgcDst. The clip mask in the source can be the same as the 3914*4882a593Smuzhiyunclip mask in the dst (clients do the strangest things), so care must 3915*4882a593Smuzhiyunbe taken when destroying things. This call is required because dix 3916*4882a593Smuzhiyundoes not know how to copy the clip mask from pgcSrc.</para> 3917*4882a593Smuzhiyun</section> 3918*4882a593Smuzhiyun</section> 3919*4882a593Smuzhiyun<section> 3920*4882a593Smuzhiyun <title>Drawing Primitives</title> 3921*4882a593Smuzhiyun<para> 3922*4882a593SmuzhiyunThe X protocol (rules for the byte stream that goes between client and server) 3923*4882a593Smuzhiyundoes all graphics using primitive 3924*4882a593Smuzhiyunoperations, which are called Drawing Primitives. 3925*4882a593SmuzhiyunThese include line drawing, area filling, arcs, and text drawing. 3926*4882a593SmuzhiyunYour implementation must supply 16 routines 3927*4882a593Smuzhiyunto perform these on your hardware. 3928*4882a593Smuzhiyun(The number 16 is arbitrary.)</para> 3929*4882a593Smuzhiyun<para> 3930*4882a593SmuzhiyunMore specifically, 16 procedure pointers are in each 3931*4882a593SmuzhiyunGC op vector. 3932*4882a593SmuzhiyunAt any given time, ALL of them MUST point to a valid procedure that 3933*4882a593Smuzhiyunattempts to do the operation assigned, although 3934*4882a593Smuzhiyunthe procedure pointers may change and may 3935*4882a593Smuzhiyunpoint to different procedures to carry out the same operation. 3936*4882a593SmuzhiyunA simple server will leave them all pointing to the same 16 routines, while 3937*4882a593Smuzhiyuna more optimized implementation will switch each from one 3938*4882a593Smuzhiyunprocedure to another, depending upon what is most optimal 3939*4882a593Smuzhiyunfor the current GC and drawable.</para> 3940*4882a593Smuzhiyun<para> 3941*4882a593SmuzhiyunThe sample server contains a considerable chunk of code called the 3942*4882a593Smuzhiyunmi (machine independent) 3943*4882a593Smuzhiyunroutines, which serve as drawing primitive routines. 3944*4882a593SmuzhiyunMany server implementations will be able to use these as-is, 3945*4882a593Smuzhiyunbecause they work for arbitrary depths. 3946*4882a593SmuzhiyunThey make no assumptions about the formats of pixmaps 3947*4882a593Smuzhiyunand frame buffers, since they call a set of routines 3948*4882a593Smuzhiyunknown as the "Pixblit Routines" (see next section). 3949*4882a593SmuzhiyunThey do assume that the way to draw is 3950*4882a593Smuzhiyunthrough these low-level routines that apply pixel values rows at a time. 3951*4882a593SmuzhiyunIf your hardware or firmware gives more performance when 3952*4882a593Smuzhiyunthings are done differently, you will want to take this fact into account 3953*4882a593Smuzhiyunand rewrite some or all of the drawing primitives to fit your needs.</para> 3954*4882a593Smuzhiyun<section> 3955*4882a593Smuzhiyun <title>GC Components</title> 3956*4882a593Smuzhiyun<para> 3957*4882a593SmuzhiyunThis section describes the fields in the GC that affect each drawing primitive. 3958*4882a593SmuzhiyunThe only primitive that is not affected is GetImage, which does not use a GC 3959*4882a593Smuzhiyunbecause its destination is a protocol-style bit image. 3960*4882a593SmuzhiyunSince each drawing primitive mirrors exactly the X protocol request of the 3961*4882a593Smuzhiyunsame name, you should refer to the X protocol specification document 3962*4882a593Smuzhiyunfor more details.</para> 3963*4882a593Smuzhiyun<para> 3964*4882a593SmuzhiyunALL of these routines MUST CLIP to the 3965*4882a593Smuzhiyunappropriate regions in the drawable. 3966*4882a593SmuzhiyunSince there are many regions to clip to simultaneously, 3967*4882a593Smuzhiyunyour ValidateGC routine should combine these into a unified 3968*4882a593Smuzhiyunclip region to which your drawing routines can quickly refer. 3969*4882a593SmuzhiyunThis is exactly what the fb routines supplied with the sample server 3970*4882a593Smuzhiyundo. 3971*4882a593SmuzhiyunThe mi implementation passes responsibility for clipping while drawing 3972*4882a593Smuzhiyundown to the Pixblit routines.</para> 3973*4882a593Smuzhiyun<para> 3974*4882a593SmuzhiyunAlso, all of them must adhere to the current plane mask. 3975*4882a593SmuzhiyunThe plane mask has one bit for every bit plane in the drawable; 3976*4882a593Smuzhiyunonly planes with 1 bits in the mask are affected by any drawing operation.</para> 3977*4882a593Smuzhiyun<para> 3978*4882a593SmuzhiyunAll functions except for ImageText calls must obey the alu function. 3979*4882a593SmuzhiyunThis is usually Copy, but could be any of the allowable 16 raster-ops.</para> 3980*4882a593Smuzhiyun<para> 3981*4882a593SmuzhiyunAll of the functions, except for CopyArea, might use the current 3982*4882a593Smuzhiyunforeground and background pixel values. 3983*4882a593SmuzhiyunEach pixel value is 32 bits. 3984*4882a593SmuzhiyunThese correspond to foreground and background colors, but you have 3985*4882a593Smuzhiyunto run them through the colormap to find out what color the pixel values 3986*4882a593Smuzhiyunrepresent. Do not worry about the color, just apply the pixel value.</para> 3987*4882a593Smuzhiyun<para> 3988*4882a593SmuzhiyunThe routines that draw lines (PolyLine, PolySegment, PolyRect, and PolyArc) 3989*4882a593Smuzhiyunuse the line width, line style, cap style, and join style. 3990*4882a593SmuzhiyunLine width is in pixels. 3991*4882a593SmuzhiyunThe line style specifies whether it is solid or dashed, and what kind of dash. 3992*4882a593SmuzhiyunThe cap style specifies whether Rounded, Butt, etc. 3993*4882a593SmuzhiyunThe join style specifies whether joins between joined lines are Miter, Round or Beveled. 3994*4882a593SmuzhiyunWhen lines cross as part of the same polyline, they are assumed to be drawn once. 3995*4882a593Smuzhiyun(See the X protocol specification for more details.)</para> 3996*4882a593Smuzhiyun<para> 3997*4882a593SmuzhiyunZero-width lines are NOT meant to be really zero width; this is the client's way 3998*4882a593Smuzhiyunof telling you that you can optimize line drawing with little regard to 3999*4882a593Smuzhiyunthe end caps and joins. 4000*4882a593SmuzhiyunThey are called "thin" lines and are meant to be one pixel wide. 4001*4882a593SmuzhiyunThese are frequently done in hardware or in a streamlined assembly language 4002*4882a593Smuzhiyunroutine.</para> 4003*4882a593Smuzhiyun<para> 4004*4882a593SmuzhiyunLines with widths greater than zero, though, must all be drawn with the same 4005*4882a593Smuzhiyunalgorithm, because client software assumes that every jag on every 4006*4882a593Smuzhiyunline at an angle will come at the same place. 4007*4882a593SmuzhiyunTwo lines that should have 4008*4882a593Smuzhiyunone pixel in the space between them 4009*4882a593Smuzhiyun(because of their distance apart and their widths) should have such a one-pixel line 4010*4882a593Smuzhiyunof space between them if drawn, regardless of angle.</para> 4011*4882a593Smuzhiyun<para> 4012*4882a593SmuzhiyunThe solid area fill routines (FillPolygon, PolyFillRect, PolyFillArc) 4013*4882a593Smuzhiyunall use the fill rule, which specifies subtle interpretations of 4014*4882a593Smuzhiyunwhat points are inside and what are outside of a given polygon. 4015*4882a593SmuzhiyunThe PolyFillArc routine also uses the arc mode, which specifies 4016*4882a593Smuzhiyunwhether to fill pie segments or single-edge slices of an ellipse.</para> 4017*4882a593Smuzhiyun<para> 4018*4882a593SmuzhiyunThe line drawing, area fill, and PolyText routines must all 4019*4882a593Smuzhiyunapply the correct "fill style." 4020*4882a593SmuzhiyunThis can be either a solid foreground color, a transparent stipple, 4021*4882a593Smuzhiyunan opaque stipple, or a tile. 4022*4882a593SmuzhiyunStipples are bitmaps where the 1 bits represent that the foreground color is written, 4023*4882a593Smuzhiyunand 0 bits represent that either the pixel is left alone (transparent) or that 4024*4882a593Smuzhiyunthe background color is written (opaque). 4025*4882a593SmuzhiyunA tile is a pixmap of the full depth of the GC that is applied in its full glory to all areas. 4026*4882a593SmuzhiyunThe stipple and tile patterns can be any rectangular size, although some implementations 4027*4882a593Smuzhiyunwill be faster for certain sizes such as 8x8 or 32x32. 4028*4882a593SmuzhiyunThe mi implementation passes this responsibility down to the Pixblit routines.</para> 4029*4882a593Smuzhiyun<para> 4030*4882a593SmuzhiyunSee the X protocol document for full details. 4031*4882a593SmuzhiyunThe description of the CreateGC request has a very good, detailed description of these 4032*4882a593Smuzhiyunattributes.</para> 4033*4882a593Smuzhiyun</section> 4034*4882a593Smuzhiyun<section> 4035*4882a593Smuzhiyun<title>The Primitives</title> 4036*4882a593Smuzhiyun<para> 4037*4882a593SmuzhiyunThe Drawing Primitives are as follows: 4038*4882a593Smuzhiyun 4039*4882a593Smuzhiyun<blockquote><programlisting> 4040*4882a593Smuzhiyun 4041*4882a593Smuzhiyun RegionPtr pGC->ops->CopyArea(src, dst, pGC, srcx, srcy, w, h, dstx, dsty) 4042*4882a593Smuzhiyun DrawablePtr dst, src; 4043*4882a593Smuzhiyun GCPtr pGC; 4044*4882a593Smuzhiyun int srcx, srcy, w, h, dstx, dsty; 4045*4882a593Smuzhiyun 4046*4882a593Smuzhiyun</programlisting></blockquote> 4047*4882a593SmuzhiyunCopyArea copies a rectangle of pixels from one drawable to another of 4048*4882a593Smuzhiyunthe same depth. To effect scrolling, this must be able to copy from 4049*4882a593Smuzhiyunany drawable to itself, overlapped. No squeezing or stretching is done 4050*4882a593Smuzhiyunbecause the source and destination are the same size. However, 4051*4882a593Smuzhiyuneverything is still clipped to the clip regions of the destination 4052*4882a593Smuzhiyundrawable.</para> 4053*4882a593Smuzhiyun<para> 4054*4882a593SmuzhiyunIf pGC->graphicsExposures is True, any portions of the destination which 4055*4882a593Smuzhiyunwere not valid in the source (either occluded by covering windows, or 4056*4882a593Smuzhiyunoutside the bounds of the drawable) should be collected together and 4057*4882a593Smuzhiyunreturned as a region (if this resultant region is empty, NULL can be 4058*4882a593Smuzhiyunreturned instead). Furthermore, the invalid bits of the source are 4059*4882a593Smuzhiyunnot copied to the destination and (when the destination is a window) 4060*4882a593Smuzhiyunare filled with the background tile. The sample routine 4061*4882a593SmuzhiyunmiHandleExposures generates the appropriate return value and fills the 4062*4882a593Smuzhiyuninvalid area using pScreen->PaintWindowBackground.</para> 4063*4882a593Smuzhiyun<para> 4064*4882a593SmuzhiyunFor instance, imagine a window that is partially obscured by other 4065*4882a593Smuzhiyunwindows in front of it. As text is scrolled on your window, the pixels 4066*4882a593Smuzhiyunthat are scrolled out from under obscuring windows will not be 4067*4882a593Smuzhiyunavailable on the screen to copy to the right places, and so an exposure 4068*4882a593Smuzhiyunevent must be sent for the client to correctly repaint them. Of 4069*4882a593Smuzhiyuncourse, if you implement backing store, you could do this without resorting 4070*4882a593Smuzhiyunto exposure events.</para> 4071*4882a593Smuzhiyun<para> 4072*4882a593SmuzhiyunAn example implementation is fbCopyArea() in Xserver/fb/fbcopy.c.</para> 4073*4882a593Smuzhiyun<para> 4074*4882a593Smuzhiyun<blockquote><programlisting> 4075*4882a593Smuzhiyun 4076*4882a593Smuzhiyun RegionPtr pGC->ops->CopyPlane(src, dst, pGC, srcx, srcy, w, h, dstx, dsty, plane) 4077*4882a593Smuzhiyun DrawablePtr dst, src; 4078*4882a593Smuzhiyun GCPtr pGC; 4079*4882a593Smuzhiyun int srcx, srcy, w, h, dstx, dsty; 4080*4882a593Smuzhiyun unsigned long plane; 4081*4882a593Smuzhiyun 4082*4882a593Smuzhiyun</programlisting></blockquote> 4083*4882a593SmuzhiyunCopyPlane must copy one plane of a rectangle from the source drawable 4084*4882a593Smuzhiyunonto the destination drawable. Because this routine only copies one 4085*4882a593Smuzhiyunbit out of each pixel, it can copy between drawables of different 4086*4882a593Smuzhiyundepths. This is the only way of copying between drawables of 4087*4882a593Smuzhiyundifferent depths, except for copying bitmaps to pixmaps and applying 4088*4882a593Smuzhiyunforeground and background colors to it. All other conditions of 4089*4882a593SmuzhiyunCopyArea apply to CopyPlane too.</para> 4090*4882a593Smuzhiyun<para> 4091*4882a593SmuzhiyunAn example implementation is fbCopyPlane() in 4092*4882a593SmuzhiyunXserver/fb/fbcopy.c.</para> 4093*4882a593Smuzhiyun<para> 4094*4882a593Smuzhiyun<blockquote><programlisting> 4095*4882a593Smuzhiyun 4096*4882a593Smuzhiyun void pGC->ops->PolyPoint(dst, pGC, mode, n, pPoint) 4097*4882a593Smuzhiyun DrawablePtr dst; 4098*4882a593Smuzhiyun GCPtr pGC; 4099*4882a593Smuzhiyun int mode; 4100*4882a593Smuzhiyun int n; 4101*4882a593Smuzhiyun DDXPointPtr pPoint; 4102*4882a593Smuzhiyun 4103*4882a593Smuzhiyun</programlisting></blockquote> 4104*4882a593SmuzhiyunPolyPoint draws a set of one-pixel dots (foreground color) 4105*4882a593Smuzhiyunat the locations given in the array. 4106*4882a593Smuzhiyunmode is one of the defined constants Origin (absolute coordinates) or Previous 4107*4882a593Smuzhiyun(each coordinate is relative to the last). 4108*4882a593SmuzhiyunNote that this does not use the background color or any tiles or stipples.</para> 4109*4882a593Smuzhiyun<para> 4110*4882a593SmuzhiyunExample implementations are fbPolyPoint() in Xserver/fb/fbpoint.c and 4111*4882a593SmuzhiyunmiPolyPoint in Xserver/mi/mipolypnt.c.</para> 4112*4882a593Smuzhiyun<para> 4113*4882a593Smuzhiyun<blockquote><programlisting> 4114*4882a593Smuzhiyun 4115*4882a593Smuzhiyun void pGC->ops->Polylines(dst, pGC, mode, n, pPoint) 4116*4882a593Smuzhiyun DrawablePtr dst; 4117*4882a593Smuzhiyun GCPtr pGC; 4118*4882a593Smuzhiyun int mode; 4119*4882a593Smuzhiyun int n; 4120*4882a593Smuzhiyun DDXPointPtr pPoint; 4121*4882a593Smuzhiyun 4122*4882a593Smuzhiyun</programlisting></blockquote> 4123*4882a593SmuzhiyunSimilar to PolyPoint, Polylines draws lines between the locations given in the array. 4124*4882a593SmuzhiyunZero-width lines are NOT meant to be really zero width; this is the client's way of 4125*4882a593Smuzhiyuntelling you that you can maximally optimize line drawing with little regard to 4126*4882a593Smuzhiyunthe end caps and joins. 4127*4882a593Smuzhiyunmode is one of the defined constants Previous or Origin, depending upon 4128*4882a593Smuzhiyunwhether the points are each relative to the last or are absolute.</para> 4129*4882a593Smuzhiyun<para> 4130*4882a593SmuzhiyunExample implementations are miWideLine() and miWideDash() in 4131*4882a593Smuzhiyunmi/miwideline.c and miZeroLine() in mi/mizerline.c.</para> 4132*4882a593Smuzhiyun<para> 4133*4882a593Smuzhiyun<blockquote><programlisting> 4134*4882a593Smuzhiyun 4135*4882a593Smuzhiyun void pGC->ops->PolySegment(dst, pGC, n, pPoint) 4136*4882a593Smuzhiyun DrawablePtr dst; 4137*4882a593Smuzhiyun GCPtr pGC; 4138*4882a593Smuzhiyun int n; 4139*4882a593Smuzhiyun xSegment *pSegments; 4140*4882a593Smuzhiyun 4141*4882a593Smuzhiyun</programlisting></blockquote> 4142*4882a593SmuzhiyunPolySegments draws unconnected 4143*4882a593Smuzhiyunlines between pairs of points in the array; the array must be of 4144*4882a593Smuzhiyuneven size; no interconnecting lines are drawn.</para> 4145*4882a593Smuzhiyun<para> 4146*4882a593SmuzhiyunAn example implementation is miPolySegment() in mipolyseg.c.</para> 4147*4882a593Smuzhiyun<para> 4148*4882a593Smuzhiyun<blockquote><programlisting> 4149*4882a593Smuzhiyun 4150*4882a593Smuzhiyun void pGC->ops->PolyRectangle(dst, pGC, n, pRect) 4151*4882a593Smuzhiyun DrawablePtr dst; 4152*4882a593Smuzhiyun GCPtr pGC; 4153*4882a593Smuzhiyun int n; 4154*4882a593Smuzhiyun xRectangle *pRect; 4155*4882a593Smuzhiyun 4156*4882a593Smuzhiyun</programlisting></blockquote> 4157*4882a593SmuzhiyunPolyRectangle draws outlines of rectangles for each rectangle in the array.</para> 4158*4882a593Smuzhiyun<para> 4159*4882a593SmuzhiyunAn example implementation is miPolyRectangle() in Xserver/mi/mipolyrect.c.</para> 4160*4882a593Smuzhiyun<para> 4161*4882a593Smuzhiyun<blockquote><programlisting> 4162*4882a593Smuzhiyun 4163*4882a593Smuzhiyun void pGC->ops->PolyArc(dst, pGC, n, pArc) 4164*4882a593Smuzhiyun DrawablePtr dst; 4165*4882a593Smuzhiyun GCPtr pGC; 4166*4882a593Smuzhiyun int n; 4167*4882a593Smuzhiyun xArc*pArc; 4168*4882a593Smuzhiyun 4169*4882a593Smuzhiyun</programlisting></blockquote> 4170*4882a593SmuzhiyunPolyArc draws connected conic arcs according to the descriptions in the array. 4171*4882a593SmuzhiyunSee the protocol specification for more details.</para> 4172*4882a593Smuzhiyun<para> 4173*4882a593SmuzhiyunExample implementations are miZeroPolyArc in Xserver/mi/mizerarc. and 4174*4882a593SmuzhiyunmiPolyArc() in Xserver/mi/miarc.c.</para> 4175*4882a593Smuzhiyun<para> 4176*4882a593Smuzhiyun<blockquote><programlisting> 4177*4882a593Smuzhiyun 4178*4882a593Smuzhiyun void pGC->ops->FillPolygon(dst, pGC, shape, mode, count, pPoint) 4179*4882a593Smuzhiyun DrawablePtr dst; 4180*4882a593Smuzhiyun GCPtr pGC; 4181*4882a593Smuzhiyun int shape; 4182*4882a593Smuzhiyun int mode; 4183*4882a593Smuzhiyun int count; 4184*4882a593Smuzhiyun DDXPointPtr pPoint; 4185*4882a593Smuzhiyun 4186*4882a593Smuzhiyun</programlisting></blockquote> 4187*4882a593SmuzhiyunFillPolygon fills a polygon specified by the points in the array 4188*4882a593Smuzhiyunwith the appropriate fill style. 4189*4882a593SmuzhiyunIf necessary, an extra border line is assumed between the starting and ending lines. 4190*4882a593SmuzhiyunThe shape can be used as a hint 4191*4882a593Smuzhiyunto optimize filling; it indicates whether it is convex (all interior angles 4192*4882a593Smuzhiyunless than 180), nonconvex (some interior angles greater than 180 but 4193*4882a593Smuzhiyunborder does not cross itself), or complex (border crosses itself). 4194*4882a593SmuzhiyunYou can choose appropriate algorithms or hardware based upon mode. 4195*4882a593Smuzhiyunmode is one of the defined constants Previous or Origin, depending upon 4196*4882a593Smuzhiyunwhether the points are each relative to the last or are absolute.</para> 4197*4882a593Smuzhiyun<para> 4198*4882a593SmuzhiyunAn example implementation is miFillPolygon() in Xserver/mi/mipoly.c.</para> 4199*4882a593Smuzhiyun<para> 4200*4882a593Smuzhiyun<blockquote><programlisting> 4201*4882a593Smuzhiyun 4202*4882a593Smuzhiyun void pGC->ops->PolyFillRect(dst, pGC, n, pRect) 4203*4882a593Smuzhiyun DrawablePtr dst; 4204*4882a593Smuzhiyun GCPtr pGC; 4205*4882a593Smuzhiyun int n; 4206*4882a593Smuzhiyun xRectangle *pRect; 4207*4882a593Smuzhiyun 4208*4882a593Smuzhiyun</programlisting></blockquote> 4209*4882a593SmuzhiyunPolyFillRect fills multiple rectangles.</para> 4210*4882a593Smuzhiyun<para> 4211*4882a593SmuzhiyunExample implementations are fbPolyFillRect() in Xserver/fb/fbfillrect.c and 4212*4882a593SmuzhiyunmiPolyFillRect() in Xserver/mi/mifillrct.c.</para> 4213*4882a593Smuzhiyun<para> 4214*4882a593Smuzhiyun<blockquote><programlisting> 4215*4882a593Smuzhiyun 4216*4882a593Smuzhiyun void pGC->ops->PolyFillArc(dst, pGC, n, pArc) 4217*4882a593Smuzhiyun DrawablePtr dst; 4218*4882a593Smuzhiyun GCPtr pGC; 4219*4882a593Smuzhiyun int n; 4220*4882a593Smuzhiyun xArc *pArc; 4221*4882a593Smuzhiyun 4222*4882a593Smuzhiyun</programlisting></blockquote> 4223*4882a593SmuzhiyunPolyFillArc fills a shape for each arc in the 4224*4882a593Smuzhiyunlist that is bounded by the arc and one or two 4225*4882a593Smuzhiyunline segments with the current fill style.</para> 4226*4882a593Smuzhiyun<para> 4227*4882a593SmuzhiyunAn example implementation is miPolyFillArc() in Xserver/mi/mifillarc.c.</para> 4228*4882a593Smuzhiyun<para> 4229*4882a593Smuzhiyun<blockquote><programlisting> 4230*4882a593Smuzhiyun 4231*4882a593Smuzhiyun void pGC->ops->PutImage(dst, pGC, depth, x, y, w, h, leftPad, format, pBinImage) 4232*4882a593Smuzhiyun DrawablePtr dst; 4233*4882a593Smuzhiyun GCPtr pGC; 4234*4882a593Smuzhiyun int x, y, w, h; 4235*4882a593Smuzhiyun int format; 4236*4882a593Smuzhiyun char *pBinImage; 4237*4882a593Smuzhiyun 4238*4882a593Smuzhiyun</programlisting></blockquote> 4239*4882a593SmuzhiyunPutImage copies a pixmap image into the drawable. The pixmap image 4240*4882a593Smuzhiyunmust be in X protocol format (either Bitmap, XYPixmap, or ZPixmap), 4241*4882a593Smuzhiyunand format tells the format. (See the X protocol specification for 4242*4882a593Smuzhiyundetails on these formats). You must be able to accept all three 4243*4882a593Smuzhiyunformats, because the client gets to decide which format to send. 4244*4882a593SmuzhiyunEither the drawable and the pixmap image have the same depth, or the 4245*4882a593Smuzhiyunsource pixmap image must be a Bitmap. If a Bitmap, the foreground and 4246*4882a593Smuzhiyunbackground colors will be applied to the destination.</para> 4247*4882a593Smuzhiyun<para> 4248*4882a593SmuzhiyunAn example implementation is fbPutImage() in Xserver/fb/fbimage.c.</para> 4249*4882a593Smuzhiyun<para> 4250*4882a593Smuzhiyun<blockquote><programlisting> 4251*4882a593Smuzhiyun 4252*4882a593Smuzhiyun void pScreen->GetImage(src, x, y, w, h, format, planeMask, pBinImage) 4253*4882a593Smuzhiyun DrawablePtr src; 4254*4882a593Smuzhiyun int x, y, w, h; 4255*4882a593Smuzhiyun unsigned int format; 4256*4882a593Smuzhiyun unsigned long planeMask; 4257*4882a593Smuzhiyun char *pBinImage; 4258*4882a593Smuzhiyun 4259*4882a593Smuzhiyun</programlisting></blockquote> 4260*4882a593SmuzhiyunGetImage copies the bits from the source drawable into 4261*4882a593Smuzhiyunthe destination pointer. The bits are written into the buffer 4262*4882a593Smuzhiyunaccording to the server-defined pixmap padding rules. 4263*4882a593SmuzhiyunpBinImage is guaranteed to be big enough to hold all 4264*4882a593Smuzhiyunthe bits that must be written.</para> 4265*4882a593Smuzhiyun<para> 4266*4882a593SmuzhiyunThis routine does not correspond exactly to the X protocol GetImage 4267*4882a593Smuzhiyunrequest, since DIX has to break the reply up into buffers of a size 4268*4882a593Smuzhiyunrequested by the transport layer. If format is ZPixmap, the bits are 4269*4882a593Smuzhiyunwritten in the ZFormat for the depth of the drawable; if there is a 0 4270*4882a593Smuzhiyunbit in the planeMask for a particular plane, all pixels must have the 4271*4882a593Smuzhiyunbit in that plane equal to 0. If format is XYPixmap, planemask is 4272*4882a593Smuzhiyunguaranteed to have a single bit set; the bits should be written in 4273*4882a593SmuzhiyunBitmap format, which is the format for a single plane of an XYPixmap.</para> 4274*4882a593Smuzhiyun<para> 4275*4882a593SmuzhiyunAn example implementation is miGetImage() in Xserver/mi/mibitblt.c. 4276*4882a593Smuzhiyun<blockquote><programlisting> 4277*4882a593Smuzhiyun 4278*4882a593Smuzhiyun void pGC->ops->ImageText8(pDraw, pGC, x, y, count, chars) 4279*4882a593Smuzhiyun DrawablePtr pDraw; 4280*4882a593Smuzhiyun GCPtr pGC; 4281*4882a593Smuzhiyun int x, y; 4282*4882a593Smuzhiyun int count; 4283*4882a593Smuzhiyun char *chars; 4284*4882a593Smuzhiyun 4285*4882a593Smuzhiyun</programlisting></blockquote> 4286*4882a593SmuzhiyunImageText8 draws text. The text is drawn in the foreground color; the 4287*4882a593Smuzhiyunbackground color fills the remainder of the character rectangles. The 4288*4882a593Smuzhiyuncoordinates specify the baseline and start of the text.</para> 4289*4882a593Smuzhiyun<para> 4290*4882a593SmuzhiyunAn example implementation is miImageText8() in Xserver/mi/mipolytext.c.</para> 4291*4882a593Smuzhiyun<para> 4292*4882a593Smuzhiyun<blockquote><programlisting> 4293*4882a593Smuzhiyun 4294*4882a593Smuzhiyun int pGC->ops->PolyText8(pDraw, pGC, x, y, count, chars) 4295*4882a593Smuzhiyun DrawablePtr pDraw; 4296*4882a593Smuzhiyun GCPtr pGC; 4297*4882a593Smuzhiyun int x, y; 4298*4882a593Smuzhiyun int count; 4299*4882a593Smuzhiyun char *chars; 4300*4882a593Smuzhiyun 4301*4882a593Smuzhiyun</programlisting></blockquote> 4302*4882a593SmuzhiyunPolyText8 works like ImageText8, except it draws with 4303*4882a593Smuzhiyunthe current fill style for special effects such as 4304*4882a593Smuzhiyunshaded text. 4305*4882a593SmuzhiyunSee the X protocol specification for more details.</para> 4306*4882a593Smuzhiyun<para> 4307*4882a593SmuzhiyunAn example implementation is miPolyText8() in Xserver/mi/mipolytext.c.</para> 4308*4882a593Smuzhiyun<para> 4309*4882a593Smuzhiyun<blockquote><programlisting> 4310*4882a593Smuzhiyun 4311*4882a593Smuzhiyun int pGC->ops->PolyText16(pDraw, pGC, x, y, count, chars) 4312*4882a593Smuzhiyun DrawablePtr pDraw; 4313*4882a593Smuzhiyun GCPtr pGC; 4314*4882a593Smuzhiyun int x, y; 4315*4882a593Smuzhiyun int count; 4316*4882a593Smuzhiyun unsigned short *chars; 4317*4882a593Smuzhiyun 4318*4882a593Smuzhiyun void pGC->ops->ImageText16(pDraw, pGC, x, y, count, chars) 4319*4882a593Smuzhiyun DrawablePtr pDraw; 4320*4882a593Smuzhiyun GCPtr pGC; 4321*4882a593Smuzhiyun int x, y; 4322*4882a593Smuzhiyun int count; 4323*4882a593Smuzhiyun unsigned short *chars; 4324*4882a593Smuzhiyun 4325*4882a593Smuzhiyun</programlisting></blockquote> 4326*4882a593SmuzhiyunThese two routines are the same as the "8" versions, 4327*4882a593Smuzhiyunexcept that they are for 16-bit character codes (useful 4328*4882a593Smuzhiyunfor oriental writing systems).</para> 4329*4882a593Smuzhiyun<para> 4330*4882a593SmuzhiyunThe primary difference is in the way the character information is 4331*4882a593Smuzhiyunlooked up. The 8-bit and the 16-bit versions obviously have different 4332*4882a593Smuzhiyunkinds of character values to look up; the main goal of the lookup is 4333*4882a593Smuzhiyunto provide a pointer to the CharInfo structs for the characters to 4334*4882a593Smuzhiyundraw and to pass these pointers to the Glyph routines. Given a 4335*4882a593SmuzhiyunCharInfo struct, lower-level software can draw the glyph desired with 4336*4882a593Smuzhiyunlittle concern for other characteristics of the font.</para> 4337*4882a593Smuzhiyun<para> 4338*4882a593Smuzhiyun16-bit character fonts have a row-and-column scheme, where the 2bytes 4339*4882a593Smuzhiyunof the character code constitute the row and column in a square matrix 4340*4882a593Smuzhiyunof CharInfo structs. Each font has row and column minimum and maximum 4341*4882a593Smuzhiyunvalues; the CharInfo structures form a two-dimensional matrix.</para> 4342*4882a593Smuzhiyun<para> 4343*4882a593SmuzhiyunExample implementations are miPolyText16() and 4344*4882a593SmuzhiyunmiImageText16() in Xserver/mi/mipolytext.c.</para> 4345*4882a593Smuzhiyun<para> 4346*4882a593SmuzhiyunSee the X protocol specification for more details on these graphic operations.</para> 4347*4882a593Smuzhiyun<para> 4348*4882a593SmuzhiyunThere is a hook in the GC ops, called LineHelper, that used to be used in the 4349*4882a593Smuzhiyunsample implementation by the code for wide lines. It no longer servers any 4350*4882a593Smuzhiyunpurpose in the sample servers, but still exists, #ifdef'ed by NEED_LINEHELPER, 4351*4882a593Smuzhiyunin case someone needs it.</para> 4352*4882a593Smuzhiyun</section> 4353*4882a593Smuzhiyun</section> 4354*4882a593Smuzhiyun<section> 4355*4882a593Smuzhiyun <title>Pixblit Procedures</title> 4356*4882a593Smuzhiyun<para> 4357*4882a593SmuzhiyunThe Drawing Primitive functions must be defined for your server. 4358*4882a593SmuzhiyunOne possible way to do this is to use the mi routines from the sample server. 4359*4882a593SmuzhiyunIf you choose to use the mi routines (even part of them!) you must implement 4360*4882a593Smuzhiyunthese Pixblit routines. 4361*4882a593SmuzhiyunThese routines read and write pixel values 4362*4882a593Smuzhiyunand deal directly with the image data.</para> 4363*4882a593Smuzhiyun<para> 4364*4882a593SmuzhiyunThe Pixblit routines for the sample server are part of the "fb" 4365*4882a593Smuzhiyunroutines. As with the mi routines, the fb routines are 4366*4882a593Smuzhiyunportable but are not as portable as the mi routines.</para> 4367*4882a593Smuzhiyun<para> 4368*4882a593SmuzhiyunThe fb subsystem is a depth-independent framebuffer core, capable of 4369*4882a593Smuzhiyunoperating at any depth from 1 to 32, based on the depth of the window 4370*4882a593Smuzhiyunor pixmap it is currently operating on. In particular, this means it 4371*4882a593Smuzhiyuncan support pixmaps of multiple depths on the same screen. It supplies 4372*4882a593Smuzhiyunboth Pixblit routines and higher-level optimized implementations of the 4373*4882a593SmuzhiyunDrawing Primitive routines. It does make the assumption that the pixel 4374*4882a593Smuzhiyundata it touches is available in the server's address space.</para> 4375*4882a593Smuzhiyun<para> 4376*4882a593SmuzhiyunIn other words, if you have a "normal" frame buffer type display, you 4377*4882a593Smuzhiyuncan probably use the fb code, and the mi code. If you 4378*4882a593Smuzhiyunhave a stranger hardware, you will have to supply your own Pixblit 4379*4882a593Smuzhiyunroutines, but you can use the mi routines on top of them. If you have 4380*4882a593Smuzhiyunbetter ways of doing some of the Drawing Primitive functions, then you 4381*4882a593Smuzhiyunmay want to supply some of your own Drawing Primitive routines. (Even 4382*4882a593Smuzhiyunpeople who write their own Drawing Primitives save at least some of 4383*4882a593Smuzhiyunthe mi code for certain special cases that their hardware or library 4384*4882a593Smuzhiyunor fancy algorithm does not handle.)</para> 4385*4882a593Smuzhiyun<para> 4386*4882a593SmuzhiyunThe client, DIX, and the machine-independent routines do not carry the 4387*4882a593Smuzhiyunfinal responsibility of clipping. They all depend upon the Pixblit 4388*4882a593Smuzhiyunroutines to do their clipping for them. The rule is, if you touch the 4389*4882a593Smuzhiyunframe buffer, you clip.</para> 4390*4882a593Smuzhiyun<para> 4391*4882a593Smuzhiyun(The higher level routines may decide to clip at a high level, but 4392*4882a593Smuzhiyunthis is only for increased performance and cannot substitute for 4393*4882a593Smuzhiyunbottom-level clipping. For instance, the mi routines, DIX, or the 4394*4882a593Smuzhiyunclient may decide to check all character strings to be drawn and chop 4395*4882a593Smuzhiyunoff all characters that would not be displayed. If so, it must retain 4396*4882a593Smuzhiyunthe character on the edge that is partly displayed so that the Pixblit 4397*4882a593Smuzhiyunroutines can clip off precisely at the right place.)</para> 4398*4882a593Smuzhiyun<para> 4399*4882a593SmuzhiyunTo make this easier, all of the reasons to clip can be combined into 4400*4882a593Smuzhiyunone region in your ValidateGC procedure. You take this composite clip 4401*4882a593Smuzhiyunregion with you into the Pixblit routines. (The sample server does 4402*4882a593Smuzhiyunthis.)</para> 4403*4882a593Smuzhiyun<para> 4404*4882a593SmuzhiyunAlso, FillSpans() has to apply tile and stipple patterns. The 4405*4882a593Smuzhiyunpatterns are all aligned to the window origin so that when two people 4406*4882a593Smuzhiyunwrite patches that are contiguous, they will merge nicely. (Really, 4407*4882a593Smuzhiyunthey are aligned to the patOrg point in the GC. This defaults to (0, 4408*4882a593Smuzhiyun0) but can be set by the client to anything.)</para> 4409*4882a593Smuzhiyun<para> 4410*4882a593SmuzhiyunHowever, the mi routines can translate (relocate) the points from 4411*4882a593Smuzhiyunwindow-relative to screen-relative if desired. If you set the 4412*4882a593SmuzhiyunmiTranslate field in the GC (set it in the CreateGC or ValidateGC 4413*4882a593Smuzhiyunroutine), then the mi output routines will translate all coordinates. 4414*4882a593SmuzhiyunIf it is false, then the coordinates will be passed window-relative. 4415*4882a593SmuzhiyunScreens with no hardware translation will probably set miTranslate to 4416*4882a593SmuzhiyunTRUE, so that geometry (e.g. polygons, rectangles) can be translated, 4417*4882a593Smuzhiyunrather than having the resulting list of scanlines translated; this is 4418*4882a593Smuzhiyungood because the list vertices in a drawing request will generally be 4419*4882a593Smuzhiyunmuch smaller than the list of scanlines it produces. Similarly, 4420*4882a593Smuzhiyunhardware that does translation can set miTranslate to FALSE, and avoid 4421*4882a593Smuzhiyunthe extra addition per vertex, which can be (but is not always) 4422*4882a593Smuzhiyunimportant for getting the highest possible performance. (Contrast the 4423*4882a593Smuzhiyunbehavior of GetSpans, which is not expected to be called as often, and 4424*4882a593Smuzhiyunso has different constraints.) The miTranslate field is settable in 4425*4882a593Smuzhiyuneach GC, if , for example, you are mixing several kinds of 4426*4882a593Smuzhiyundestinations (offscreen pixmaps, main memory pixmaps, backing store, 4427*4882a593Smuzhiyunand windows), all of which have different requirements, on one screen.</para> 4428*4882a593Smuzhiyun<para> 4429*4882a593SmuzhiyunAs with other drawing routines, there are fields in the GC to direct 4430*4882a593Smuzhiyunhigher code to the correct routine to execute for each function. In 4431*4882a593Smuzhiyunthis way, you can optimize for special cases, for example, drawing 4432*4882a593Smuzhiyunsolids versus drawing stipples.</para> 4433*4882a593Smuzhiyun<para> 4434*4882a593SmuzhiyunThe Pixblit routines are broken up into three sets. The Span routines 4435*4882a593Smuzhiyunsimply fill in rows of pixels. The Glyph routines fill in character 4436*4882a593Smuzhiyunglyphs. The PushPixels routine is a three-input bitblt for more 4437*4882a593Smuzhiyunsophisticated image creation.</para> 4438*4882a593Smuzhiyun<para> 4439*4882a593SmuzhiyunIt turns out that the Glyph and PushPixels routines actually have a 4440*4882a593Smuzhiyunmachine-independent implementation that depends upon the Span 4441*4882a593Smuzhiyunroutines. If you are really pressed for time, you can use these 4442*4882a593Smuzhiyunversions, although they are quite slow.</para> 4443*4882a593Smuzhiyun<section> 4444*4882a593Smuzhiyun<title>Span Routines</title> 4445*4882a593Smuzhiyun<para> 4446*4882a593SmuzhiyunFor these routines, all graphic operations have been reduced to "spans." 4447*4882a593SmuzhiyunA span is a horizontal row of pixels. 4448*4882a593SmuzhiyunIf you can design these routines which write into and read from 4449*4882a593Smuzhiyunrows of pixels at a time, you can use the mi routines.</para> 4450*4882a593Smuzhiyun<para> 4451*4882a593SmuzhiyunEach routine takes 4452*4882a593Smuzhiyuna destination drawable to draw into, a GC to use while drawing, 4453*4882a593Smuzhiyunthe number of spans to do, and two pointers to arrays that indicate the list 4454*4882a593Smuzhiyunof starting points and the list of widths of spans.</para> 4455*4882a593Smuzhiyun<para> 4456*4882a593Smuzhiyun<blockquote><programlisting> 4457*4882a593Smuzhiyun 4458*4882a593Smuzhiyun void pGC->ops->FillSpans(dst, pGC, nSpans, pPoints, pWidths, sorted) 4459*4882a593Smuzhiyun DrawablePtr dst; 4460*4882a593Smuzhiyun GCPtr pGC; 4461*4882a593Smuzhiyun int nSpans; 4462*4882a593Smuzhiyun DDXPointPtr pPoints; 4463*4882a593Smuzhiyun int *pWidths; 4464*4882a593Smuzhiyun int sorted; 4465*4882a593Smuzhiyun 4466*4882a593Smuzhiyun</programlisting></blockquote> 4467*4882a593SmuzhiyunFillSpans should fill horizontal rows of pixels with 4468*4882a593Smuzhiyunthe appropriate patterns, stipples, etc., 4469*4882a593Smuzhiyunbased on the values in the GC. 4470*4882a593SmuzhiyunThe starting points are in the array at pPoints; the widths are in pWidths. 4471*4882a593SmuzhiyunIf sorted is true, the scan lines are in increasing y order, in which case 4472*4882a593Smuzhiyunyou may be able to make assumptions and optimizations.</para> 4473*4882a593Smuzhiyun<para> 4474*4882a593SmuzhiyunGC components: alu, clipOrg, clientClip, and fillStyle.</para> 4475*4882a593Smuzhiyun<para> 4476*4882a593SmuzhiyunGC mode-dependent components: fgPixel (for fillStyle Solid); tile, patOrg 4477*4882a593Smuzhiyun(for fillStyle Tile); stipple, patOrg, fgPixel (for fillStyle Stipple); 4478*4882a593Smuzhiyunand stipple, patOrg, fgPixel and bgPixel (for fillStyle OpaqueStipple).</para> 4479*4882a593Smuzhiyun<para> 4480*4882a593Smuzhiyun<blockquote><programlisting> 4481*4882a593Smuzhiyun 4482*4882a593Smuzhiyun void pGC->ops->SetSpans(pDrawable, pGC, pSrc, ppt, pWidths, nSpans, sorted) 4483*4882a593Smuzhiyun DrawablePtr pDrawable; 4484*4882a593Smuzhiyun GCPtr pGC; 4485*4882a593Smuzhiyun char *pSrc; 4486*4882a593Smuzhiyun DDXPointPtr pPoints; 4487*4882a593Smuzhiyun int *pWidths; 4488*4882a593Smuzhiyun int nSpans; 4489*4882a593Smuzhiyun int sorted; 4490*4882a593Smuzhiyun 4491*4882a593Smuzhiyun</programlisting></blockquote> 4492*4882a593SmuzhiyunFor each span, this routine should copy pWidths bits from pSrc to 4493*4882a593SmuzhiyunpDrawable at pPoints using the raster-op from the GC. 4494*4882a593SmuzhiyunIf sorted is true, the scan lines are in increasing y order. 4495*4882a593SmuzhiyunThe pixels in pSrc are 4496*4882a593Smuzhiyunpadded according to the screen's padding rules. 4497*4882a593SmuzhiyunThese 4498*4882a593Smuzhiyuncan be used to support 4499*4882a593Smuzhiyuninteresting extension libraries, for example, shaded primitives. It does not 4500*4882a593Smuzhiyunuse the tile and stipple.</para> 4501*4882a593Smuzhiyun<para> 4502*4882a593SmuzhiyunGC components: alu, clipOrg, and clientClip</para> 4503*4882a593Smuzhiyun<para> 4504*4882a593SmuzhiyunThe above functions are expected to handle all modifiers in the current 4505*4882a593SmuzhiyunGC. Therefore, it is expedient to have 4506*4882a593Smuzhiyundifferent routines to quickly handle common special cases 4507*4882a593Smuzhiyunand reload the procedure pointers 4508*4882a593Smuzhiyunat validate time, as with the other output functions.</para> 4509*4882a593Smuzhiyun<para> 4510*4882a593Smuzhiyun<blockquote><programlisting> 4511*4882a593Smuzhiyun 4512*4882a593Smuzhiyun void pScreen->GetSpans(pDrawable, wMax, pPoints, pWidths, nSpans) 4513*4882a593Smuzhiyun DrawablePtr pDrawable; 4514*4882a593Smuzhiyun int wMax; 4515*4882a593Smuzhiyun DDXPointPtr pPoints; 4516*4882a593Smuzhiyun int *pWidths; 4517*4882a593Smuzhiyun int nSpans; 4518*4882a593Smuzhiyun char *pDst; 4519*4882a593Smuzhiyun 4520*4882a593Smuzhiyun</programlisting></blockquote> 4521*4882a593SmuzhiyunFor each span, GetSpans gets bits from the drawable starting at pPoints 4522*4882a593Smuzhiyunand continuing for pWidths bits. 4523*4882a593SmuzhiyunEach scanline returned will be server-scanline padded. 4524*4882a593SmuzhiyunThe routine can return NULL if memory cannot be allocated to hold the 4525*4882a593Smuzhiyunresult.</para> 4526*4882a593Smuzhiyun<para> 4527*4882a593SmuzhiyunGetSpans never translates -- for a window, the coordinates are already 4528*4882a593Smuzhiyunscreen-relative. Consider the case of hardware that doesn't do 4529*4882a593Smuzhiyuntranslation: the mi code that calls ddX will translate each shape 4530*4882a593Smuzhiyun(rectangle, polygon,. etc.) before scan-converting it, which requires 4531*4882a593Smuzhiyunmany fewer additions that having GetSpans translate each span does. 4532*4882a593SmuzhiyunConversely, consider hardware that does translate: it can set its 4533*4882a593Smuzhiyuntranslation point to (0, 0) and get each span, and the only penalty is 4534*4882a593Smuzhiyunthe small number of additions required to translate each shape being 4535*4882a593Smuzhiyunscan-converted by the calling code. Contrast the behavior of 4536*4882a593SmuzhiyunFillSpans and SetSpans (discussed above under miTranslate), which are 4537*4882a593Smuzhiyunexpected to be used more often.</para> 4538*4882a593Smuzhiyun<para> 4539*4882a593SmuzhiyunThus, the penalty to hardware that does hardware translation is 4540*4882a593Smuzhiyunnegligible, and code that wants to call GetSpans() is greatly 4541*4882a593Smuzhiyunsimplified, both for extensions and the machine-independent core 4542*4882a593Smuzhiyunimplementation.</para> 4543*4882a593Smuzhiyun<section> 4544*4882a593Smuzhiyun <title>Glyph Routines</title> 4545*4882a593Smuzhiyun<para> 4546*4882a593SmuzhiyunThe Glyph routines draw individual character glyphs for text drawing requests.</para> 4547*4882a593Smuzhiyun<para> 4548*4882a593SmuzhiyunYou have a choice in implementing these routines. You can use the mi 4549*4882a593Smuzhiyunversions; they depend ultimately upon the span routines. Although 4550*4882a593Smuzhiyuntext drawing will work, it will be very slow.</para> 4551*4882a593Smuzhiyun<para> 4552*4882a593Smuzhiyun<blockquote><programlisting> 4553*4882a593Smuzhiyun 4554*4882a593Smuzhiyun void pGC->ops->PolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) 4555*4882a593Smuzhiyun DrawablePtr pDrawable; 4556*4882a593Smuzhiyun GCPtr pGC; 4557*4882a593Smuzhiyun int x , y; 4558*4882a593Smuzhiyun unsigned int nglyph; 4559*4882a593Smuzhiyun CharInfoRec **ppci; /* array of character info */ 4560*4882a593Smuzhiyun pointer unused; /* unused since R5 */ 4561*4882a593Smuzhiyun 4562*4882a593Smuzhiyun</programlisting></blockquote> 4563*4882a593SmuzhiyunGC components: alu, clipOrg, clientClip, font, and fillStyle.</para> 4564*4882a593Smuzhiyun<para> 4565*4882a593SmuzhiyunGC mode-dependent components: fgPixel (for fillStyle Solid); tile, patOrg 4566*4882a593Smuzhiyun(for fillStyle Tile); stipple, patOrg, fgPixel (for fillStyle Stipple); 4567*4882a593Smuzhiyunand stipple, patOrg, fgPixel and bgPixel (for fillStyle OpaqueStipple).</para> 4568*4882a593Smuzhiyun<para> 4569*4882a593Smuzhiyun<blockquote><programlisting> 4570*4882a593Smuzhiyun 4571*4882a593Smuzhiyun void pGC->ops->ImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase) 4572*4882a593Smuzhiyun DrawablePtr pDrawable; 4573*4882a593Smuzhiyun GCPtr pGC; 4574*4882a593Smuzhiyun int x , y; 4575*4882a593Smuzhiyun unsigned int nglyph; 4576*4882a593Smuzhiyun CharInfoRec **ppci; /* array of character info */ 4577*4882a593Smuzhiyun pointer unused; /* unused since R5 */ 4578*4882a593Smuzhiyun 4579*4882a593Smuzhiyun</programlisting></blockquote> 4580*4882a593SmuzhiyunGC components: clipOrg, clientClip, font, fgPixel, bgPixel</para> 4581*4882a593Smuzhiyun<para> 4582*4882a593SmuzhiyunThese routines must copy the glyphs defined by the bitmaps in 4583*4882a593SmuzhiyunpglyphBase and the font metrics in ppci to the DrawablePtr, pDrawable. 4584*4882a593SmuzhiyunThe poly routine follows all fill, stipple, and tile rules. The image 4585*4882a593Smuzhiyunroutine simply blasts the glyph onto the glyph's rectangle, in 4586*4882a593Smuzhiyunforeground and background colors.</para> 4587*4882a593Smuzhiyun<para> 4588*4882a593SmuzhiyunMore precisely, the Image routine fills the character rectangle with 4589*4882a593Smuzhiyunthe background color, and then the glyph is applied in the foreground 4590*4882a593Smuzhiyuncolor. The glyph can extend outside of the character rectangle. 4591*4882a593SmuzhiyunImageGlyph() is used for terminal emulators and informal text purposes 4592*4882a593Smuzhiyunsuch as button labels.</para> 4593*4882a593Smuzhiyun<para> 4594*4882a593SmuzhiyunThe exact specification for the Poly routine is that the glyph is 4595*4882a593Smuzhiyunpainted with the current fill style. The character rectangle is 4596*4882a593Smuzhiyunirrelevant for this operation. PolyText, at a higher level, includes 4597*4882a593Smuzhiyunfacilities for font changes within strings and such; it is to be used 4598*4882a593Smuzhiyunfor WYSIWYG word processing and similar systems.</para> 4599*4882a593Smuzhiyun<para> 4600*4882a593SmuzhiyunBoth of these routines must clip themselves to the overall clipping region.</para> 4601*4882a593Smuzhiyun<para> 4602*4882a593SmuzhiyunExample implementations in mi are miPolyGlyphBlt() and 4603*4882a593SmuzhiyunmiImageGlyphBlt() in Xserver/mi/miglblt.c.</para> 4604*4882a593Smuzhiyun</section> 4605*4882a593Smuzhiyun<section> 4606*4882a593Smuzhiyun<title>PushPixels routine</title> 4607*4882a593Smuzhiyun<para> 4608*4882a593SmuzhiyunThe PushPixels routine writes the current fill style onto the drawable 4609*4882a593Smuzhiyunin a certain shape defined by a bitmap. PushPixels is equivalent to 4610*4882a593Smuzhiyunusing a second stipple. You can thing of it as pushing the fillStyle 4611*4882a593Smuzhiyunthrough a stencil. PushPixels is not used by any of the mi rendering code, 4612*4882a593Smuzhiyunbut is used by the mi software cursor code. 4613*4882a593Smuzhiyun<blockquote><para> 4614*4882a593Smuzhiyun Suppose the stencil is: 00111100 4615*4882a593Smuzhiyun and the stipple is: 10101010 4616*4882a593Smuzhiyun PushPixels result: 00101000 4617*4882a593Smuzhiyun</para></blockquote> 4618*4882a593Smuzhiyun</para> 4619*4882a593Smuzhiyun<para> 4620*4882a593SmuzhiyunYou have a choice in implementing this routine. 4621*4882a593SmuzhiyunYou can use the mi version which depends ultimately upon FillSpans(). 4622*4882a593SmuzhiyunAlthough it will work, it will be slow.</para> 4623*4882a593Smuzhiyun<para> 4624*4882a593Smuzhiyun<blockquote><programlisting> 4625*4882a593Smuzhiyun 4626*4882a593Smuzhiyun void pGC->ops->PushPixels(pGC, pBitMap, pDrawable, dx, dy, xOrg, yOrg) 4627*4882a593Smuzhiyun GCPtr pGC; 4628*4882a593Smuzhiyun PixmapPtr pBitMap; 4629*4882a593Smuzhiyun DrawablePtr pDrawable; 4630*4882a593Smuzhiyun int dx, dy, xOrg, yOrg; 4631*4882a593Smuzhiyun 4632*4882a593Smuzhiyun</programlisting></blockquote> 4633*4882a593SmuzhiyunGC components: alu, clipOrg, clientClip, and fillStyle.</para> 4634*4882a593Smuzhiyun<para> 4635*4882a593SmuzhiyunGC mode-dependent components: fgPixel (for fillStyle Solid); tile, patOrg 4636*4882a593Smuzhiyun(for fillStyle Tile); stipple, patOrg, fgPixel (for fillStyle Stipple); 4637*4882a593Smuzhiyunand stipple, patOrg, fgPixel and bgPixel (for fillStyle OpaqueStipple).</para> 4638*4882a593Smuzhiyun<para> 4639*4882a593SmuzhiyunPushPixels applys the foreground color, tile, or stipple from the pGC 4640*4882a593Smuzhiyunthrough a stencil onto pDrawable. pBitMap points to a stencil (of 4641*4882a593Smuzhiyunwhich we use an area dx wide by dy high), which is oriented over the 4642*4882a593Smuzhiyundrawable at xOrg, yOrg. Where there is a 1 bit in the bitmap, the 4643*4882a593Smuzhiyundestination is set according to the current fill style. Where there 4644*4882a593Smuzhiyunis a 0 bit in the bitmap, the destination is left the way it is.</para> 4645*4882a593Smuzhiyun<para> 4646*4882a593SmuzhiyunThis routine must clip to the overall clipping region.</para> 4647*4882a593Smuzhiyun<para> 4648*4882a593SmuzhiyunAn Example implementation is miPushPixels() in Xserver/mi/mipushpxl.c.</para> 4649*4882a593Smuzhiyun</section> 4650*4882a593Smuzhiyun</section> 4651*4882a593Smuzhiyun</section> 4652*4882a593Smuzhiyun<section> 4653*4882a593Smuzhiyun <title>Shutdown Procedures</title> 4654*4882a593Smuzhiyun<para> 4655*4882a593Smuzhiyun<blockquote><programlisting> 4656*4882a593Smuzhiyun void AbortDDX(enum ExitCode error) 4657*4882a593Smuzhiyun void ddxGiveUp(enum ExitCode error) 4658*4882a593Smuzhiyun</programlisting></blockquote> 4659*4882a593SmuzhiyunSome hardware may require special work to be done before the server 4660*4882a593Smuzhiyunexits so that it is not left in an intermediate state. As explained 4661*4882a593Smuzhiyunin the OS layer, FatalError() will call AbortDDX() just before 4662*4882a593Smuzhiyunterminating the server. In addition, ddxGiveUp() will be called just 4663*4882a593Smuzhiyunbefore terminating the server on a "clean" death. What AbortDDX() and 4664*4882a593SmuzhiyunddxGiveUP do is left unspecified, only that stubs must exist in the 4665*4882a593Smuzhiyunddx layer. It is up to local implementors as to what they should 4666*4882a593Smuzhiyunaccomplish before termination.</para> 4667*4882a593Smuzhiyun<section> 4668*4882a593Smuzhiyun <title>Command Line Procedures</title> 4669*4882a593Smuzhiyun<para> 4670*4882a593Smuzhiyun<blockquote><programlisting> 4671*4882a593Smuzhiyun int ddxProcessArgument(argc, argv, i) 4672*4882a593Smuzhiyun int argc; 4673*4882a593Smuzhiyun char *argv[]; 4674*4882a593Smuzhiyun int i; 4675*4882a593Smuzhiyun 4676*4882a593Smuzhiyun void 4677*4882a593Smuzhiyun ddxUseMsg() 4678*4882a593Smuzhiyun 4679*4882a593Smuzhiyun</programlisting></blockquote> 4680*4882a593SmuzhiyunYou should write these routines to deal with device-dependent command line 4681*4882a593Smuzhiyunarguments. The routine ddxProcessArgument() is called with the command line, 4682*4882a593Smuzhiyunand the current index into argv; you should return zero if the argument 4683*4882a593Smuzhiyunis not a device-dependent one, and otherwise return a count of the number 4684*4882a593Smuzhiyunof elements of argv that are part of this one argument. For a typical 4685*4882a593Smuzhiyunoption (e.g., "-realtime"), you should return the value one. This 4686*4882a593Smuzhiyunroutine gets called before checks are made against device-independent 4687*4882a593Smuzhiyunarguments, so it is possible to peek at all arguments or to override 4688*4882a593Smuzhiyundevice-independent argument processing. You can document the 4689*4882a593Smuzhiyundevice-dependent arguments in ddxUseMsg(), which will be 4690*4882a593Smuzhiyuncalled from UseMsg() after printing out the device-independent arguments.</para> 4691*4882a593Smuzhiyun</section> 4692*4882a593Smuzhiyun</section> 4693*4882a593Smuzhiyun<section id="wrappers_and_privates"> 4694*4882a593Smuzhiyun <title>Wrappers and Privates</title> 4695*4882a593Smuzhiyun<para> 4696*4882a593SmuzhiyunTwo new extensibility concepts have been developed for release 4, Wrappers 4697*4882a593Smuzhiyunand devPrivates. These replace the R3 GCInterest queues, which were not a 4698*4882a593Smuzhiyungeneral enough mechanism for many extensions and only provided hooks into a 4699*4882a593Smuzhiyunsingle data structure. devPrivates have been revised substantially for 4700*4882a593SmuzhiyunX.Org X server release 1.5, updated again for the 1.9 release and extended 4701*4882a593Smuzhiyunagain for the 1.13 relealse.</para> 4702*4882a593Smuzhiyun<section> 4703*4882a593Smuzhiyun <title>devPrivates</title> 4704*4882a593Smuzhiyun<para> 4705*4882a593SmuzhiyundevPrivates provides a way to attach arbitrary private data to various server structures. 4706*4882a593SmuzhiyunAny structure which contains a <structfield>devPrivates</structfield> field of 4707*4882a593Smuzhiyuntype <type>PrivateRec</type> supports this mechanism. Some structures allow 4708*4882a593Smuzhiyunallocating space for private data after some objects have been created, others 4709*4882a593Smuzhiyunrequire all space allocations be registered before any objects of that type 4710*4882a593Smuzhiyunare created. <filename class="headerfile">Xserver/include/privates.h</filename> 4711*4882a593Smuzhiyunlists which of these cases applies to each structure containing 4712*4882a593Smuzhiyun<structfield>devPrivates</structfield>.</para> 4713*4882a593Smuzhiyun 4714*4882a593Smuzhiyun<para> 4715*4882a593SmuzhiyunTo request private space, use 4716*4882a593Smuzhiyun<blockquote><programlisting> 4717*4882a593Smuzhiyun Bool dixRegisterPrivateKey(DevPrivateKey key, DevPrivateType type, unsigned size); 4718*4882a593Smuzhiyun</programlisting></blockquote> 4719*4882a593SmuzhiyunThe first argument is a pointer to a <type>DevPrivateKeyRec</type> which 4720*4882a593Smuzhiyunwill serve as the unique identifier for the private data. Typically this is 4721*4882a593Smuzhiyunthe address of a static <type>DevPrivateKeyRec</type> in your code. 4722*4882a593SmuzhiyunThe second argument is the class of objects for which this key will apply. 4723*4882a593SmuzhiyunThe third argument is the size of the space being requested, or 4724*4882a593Smuzhiyun<constant>0</constant> to only allocate a pointer that the caller will manage. 4725*4882a593SmuzhiyunIf space is requested, this space will be automatically freed when the object 4726*4882a593Smuzhiyunis destroyed. Note that a call to <function>dixSetPrivate</function> 4727*4882a593Smuzhiyunthat changes the pointer value may cause the space to be unreachable by the caller, however it will still be automatically freed. 4728*4882a593SmuzhiyunThe function returns <literal>TRUE</literal> unless memory allocation fails. 4729*4882a593SmuzhiyunIf the function is called more than once on the same key, all calls must use 4730*4882a593Smuzhiyunthe same value for <type>size</type> or the server will abort.</para> 4731*4882a593Smuzhiyun 4732*4882a593Smuzhiyun<para> 4733*4882a593SmuzhiyunTo request per-screen private space in an object, use 4734*4882a593Smuzhiyun<blockquote><programlisting> 4735*4882a593Smuzhiyun Bool dixRegisterScreenPrivateKey(DevScreenPrivateKey key, ScreenPtr pScreen, DevPrivateType type, unsigned size); 4736*4882a593Smuzhiyun</programlisting></blockquote> 4737*4882a593SmuzhiyunThe <parameter>type</parameter> and <parameter>size</parameter> arguments are 4738*4882a593Smuzhiyunthe same as those to <function>dixRegisterPrivateKey</function> but this 4739*4882a593Smuzhiyunfunction ensures the given <parameter>key</parameter> exists on objects of 4740*4882a593Smuzhiyunthe specified type with distinct storage for the given 4741*4882a593Smuzhiyun<parameter>pScreen</parameter>. The key is usable on ScreenPrivate variants 4742*4882a593Smuzhiyunthat are otherwise equivalent to the following Private functions.</para> 4743*4882a593Smuzhiyun 4744*4882a593Smuzhiyun<para> 4745*4882a593Smuzhiyun To request private space in objects created for a specific screen, use 4746*4882a593Smuzhiyun <blockquote><programlisting> 4747*4882a593Smuzhiyun Bool dixRegisterScreenSpecificPrivateKey(ScreenPtr pScreen, DevPrivateKey key, DevPrivateType type, unsigned size); 4748*4882a593Smuzhiyun </programlisting></blockquote> 4749*4882a593Smuzhiyun The <parameter>type</parameter> and <parameter>size</parameter> arguments are 4750*4882a593Smuzhiyun the same as those to <function>dixRegisterPrivateKey</function> but this 4751*4882a593Smuzhiyun function ensures only that the given <parameter>key</parameter> exists on objects of 4752*4882a593Smuzhiyun the specified type that are allocated with reference to the specified 4753*4882a593Smuzhiyun <parameter>pScreen</parameter>. Using the key on objects allocated for 4754*4882a593Smuzhiyun other screens will result in incorrect results; there is no check made to 4755*4882a593Smuzhiyun ensure that the caller's screen matches the private's screen. The key is 4756*4882a593Smuzhiyun usable in any of the following functions. Screen-specific private storage is available 4757*4882a593Smuzhiyun only for Windows, GCs, Pixmaps and Pictures. Attempts to allocate screen-specific 4758*4882a593Smuzhiyun privates on other objects will result in a call to FatalError. 4759*4882a593Smuzhiyun</para> 4760*4882a593Smuzhiyun 4761*4882a593Smuzhiyun<para> 4762*4882a593SmuzhiyunTo attach a piece of private data to an object, use: 4763*4882a593Smuzhiyun<blockquote><programlisting> 4764*4882a593Smuzhiyun void dixSetPrivate(PrivateRec **privates, const DevPrivateKey key, pointer val) 4765*4882a593Smuzhiyun</programlisting></blockquote> 4766*4882a593SmuzhiyunThe first argument is the address of the <structfield>devPrivates</structfield> 4767*4882a593Smuzhiyunfield in the target structure. This field is managed privately by the DIX 4768*4882a593Smuzhiyunlayer and should not be directly modified. The second argument is a pointer 4769*4882a593Smuzhiyunto the <type>DevPrivateKeyRec</type> which you registered with 4770*4882a593Smuzhiyun<function>dixRegisterPrivateKey</function> or allocated with 4771*4882a593Smuzhiyun<function>dixCreatePrivateKey</function>. Only one 4772*4882a593Smuzhiyunpiece of data with a given key can be attached to an object, and in most cases 4773*4882a593Smuzhiyuneach key is specific to the type of object it was registered for. (An 4774*4882a593Smuzhiyunexception is the PRIVATE_XSELINUX class which applies to multiple object types.) 4775*4882a593SmuzhiyunThe third argument is the value to store.</para> 4776*4882a593Smuzhiyun<para> 4777*4882a593SmuzhiyunIf private data with the given key is already associated with the object, 4778*4882a593Smuzhiyun<function>dixSetPrivate</function> will overwrite the old value with the 4779*4882a593Smuzhiyunnew one.</para> 4780*4882a593Smuzhiyun 4781*4882a593Smuzhiyun<para> 4782*4882a593SmuzhiyunTo look up a piece of private data, use one of: 4783*4882a593Smuzhiyun<blockquote><programlisting> 4784*4882a593Smuzhiyun pointer dixLookupPrivate(PrivateRec **privates, const DevPrivateKey key) 4785*4882a593Smuzhiyun pointer *dixLookupPrivateAddr(PrivateRec **privates, const DevPrivateKey key) 4786*4882a593Smuzhiyun</programlisting></blockquote> 4787*4882a593SmuzhiyunThe first argument is the address of the <structfield>devPrivates</structfield> field 4788*4882a593Smuzhiyunin the target structure. The second argument is the key to look up. 4789*4882a593SmuzhiyunIf a non-zero size was given when the key was registered, or if private data 4790*4882a593Smuzhiyunwith the given key is already associated with the object, then 4791*4882a593Smuzhiyun<function>dixLookupPrivate</function> will return the pointer value 4792*4882a593Smuzhiyunwhile <function>dixLookupPrivateAddr</function> 4793*4882a593Smuzhiyunwill return the address of the pointer.</para> 4794*4882a593Smuzhiyun 4795*4882a593Smuzhiyun<para> 4796*4882a593SmuzhiyunWhen implementing new server resource objects that support devPrivates, there 4797*4882a593Smuzhiyunare four steps to perform: 4798*4882a593SmuzhiyunAdd a type value to the <type>DevPrivateType</type> enum in 4799*4882a593Smuzhiyun<filename class="headerfile">Xserver/include/privates.h</filename>, 4800*4882a593Smuzhiyundeclare a field of type <type>PrivateRec *</type> in your structure; 4801*4882a593Smuzhiyuninitialize this field to <literal>NULL</literal> when creating any objects; and 4802*4882a593Smuzhiyunwhen freeing any objects call the <function>dixFreePrivates</function> or 4803*4882a593Smuzhiyun<function>dixFreeObjectWithPrivates</function> function.</para> 4804*4882a593Smuzhiyun</section> 4805*4882a593Smuzhiyun<section> 4806*4882a593Smuzhiyun <title>Wrappers</title> 4807*4882a593Smuzhiyun<para> 4808*4882a593SmuzhiyunWrappers are not a body of code, nor an interface spec. They are, instead, 4809*4882a593Smuzhiyuna technique for hooking a new module into an existing calling sequence. 4810*4882a593SmuzhiyunThere are limitations on other portions of the server implementation which 4811*4882a593Smuzhiyunmake using wrappers possible; limits on when specific fields of data 4812*4882a593Smuzhiyunstructures may be modified. They are intended as a replacement for 4813*4882a593SmuzhiyunGCInterest queues, which were not general enough to support existing 4814*4882a593Smuzhiyunmodules; in particular software cursors needed more 4815*4882a593Smuzhiyuncontrol over the activity. The general mechanism for using wrappers is: 4816*4882a593Smuzhiyun<blockquote><programlisting> 4817*4882a593SmuzhiyunprivateWrapperFunction (object, ...) 4818*4882a593Smuzhiyun ObjectPtr object; 4819*4882a593Smuzhiyun{ 4820*4882a593Smuzhiyun pre-wrapped-function-stuff ... 4821*4882a593Smuzhiyun 4822*4882a593Smuzhiyun object->functionVector = dixLookupPrivate(&object->devPrivates, privateKey); 4823*4882a593Smuzhiyun (*object->functionVector) (object, ...); 4824*4882a593Smuzhiyun /* 4825*4882a593Smuzhiyun * this next line is occasionally required by the rules governing 4826*4882a593Smuzhiyun * wrapper functions. Always using it will not cause problems. 4827*4882a593Smuzhiyun * Not using it when necessary can cause severe troubles. 4828*4882a593Smuzhiyun */ 4829*4882a593Smuzhiyun dixSetPrivate(&object->devPrivates, privateKey, object->functionVector); 4830*4882a593Smuzhiyun object->functionVector = privateWrapperFunction; 4831*4882a593Smuzhiyun 4832*4882a593Smuzhiyun post-wrapped-function-stuff ... 4833*4882a593Smuzhiyun} 4834*4882a593Smuzhiyun 4835*4882a593SmuzhiyunprivateInitialize (object) 4836*4882a593Smuzhiyun ObjectPtr object; 4837*4882a593Smuzhiyun{ 4838*4882a593Smuzhiyun dixSetPrivate(&object->devPrivates, privateKey, object->functionVector); 4839*4882a593Smuzhiyun object->functionVector = privateWrapperFunction; 4840*4882a593Smuzhiyun} 4841*4882a593Smuzhiyun</programlisting></blockquote> 4842*4882a593Smuzhiyun</para> 4843*4882a593Smuzhiyun<para> 4844*4882a593SmuzhiyunThus the privateWrapperFunction provides hooks for performing work both 4845*4882a593Smuzhiyunbefore and after the wrapped function has been called; the process of 4846*4882a593Smuzhiyunresetting the functionVector is called "unwrapping" while the process of 4847*4882a593Smuzhiyunfetching the wrapped function and replacing it with the wrapping function 4848*4882a593Smuzhiyunis called "wrapping". It should be clear that GCInterest queues could 4849*4882a593Smuzhiyunbe emulated using wrappers. In general, any function vectors contained in 4850*4882a593Smuzhiyunobjects can be wrapped, but only vectors in GCs and Screens have been tested.</para> 4851*4882a593Smuzhiyun<para> 4852*4882a593SmuzhiyunWrapping screen functions is quite easy; each vector is individually 4853*4882a593Smuzhiyunwrapped. Screen functions are not supposed to change after initialization, 4854*4882a593Smuzhiyunso rewrapping is technically not necessary, but causes no problems.</para> 4855*4882a593Smuzhiyun<para> 4856*4882a593SmuzhiyunWrapping GC functions is a bit more complicated. GC's have two tables of 4857*4882a593Smuzhiyunfunction vectors, one hanging from gc->ops and the other from gc->funcs, which 4858*4882a593Smuzhiyunshould be initially wrapped from a CreateGC wrapper. Wrappers should modify 4859*4882a593Smuzhiyunonly table pointers, not the contents of the tables, as they 4860*4882a593Smuzhiyunmay be shared by more than one GC (and, in the case of funcs, are probably 4861*4882a593Smuzhiyunshared by all gcs). Your func wrappers may change the GC funcs or ops 4862*4882a593Smuzhiyunpointers, and op wrappers may change the GC op pointers but not the funcs.</para> 4863*4882a593Smuzhiyun<para> 4864*4882a593SmuzhiyunThus, the rule for GC wrappings is: wrap the funcs from CreateGC and, in each 4865*4882a593Smuzhiyunfunc wrapper, unwrap the ops and funcs, call down, and re-wrap. In each op 4866*4882a593Smuzhiyunwrapper, unwrap the ops, call down, and rewrap afterwards. Note that in 4867*4882a593Smuzhiyunre-wrapping you must save out the pointer you're replacing again. This way the 4868*4882a593Smuzhiyunchain will be maintained when wrappers adjust the funcs/ops tables they use.</para> 4869*4882a593Smuzhiyun</section> 4870*4882a593Smuzhiyun</section> 4871*4882a593Smuzhiyun<section> 4872*4882a593Smuzhiyun <title>Work Queue</title> 4873*4882a593Smuzhiyun<para> 4874*4882a593SmuzhiyunTo queue work for execution when all clients are in a stable state (i.e. 4875*4882a593Smuzhiyunjust before calling select() in WaitForSomething), call: 4876*4882a593Smuzhiyun<blockquote><programlisting> 4877*4882a593Smuzhiyun Bool QueueWorkProc(function,client,closure) 4878*4882a593Smuzhiyun Bool (*function)(); 4879*4882a593Smuzhiyun ClientPtr client; 4880*4882a593Smuzhiyun pointer closure; 4881*4882a593Smuzhiyun</programlisting></blockquote> 4882*4882a593Smuzhiyun</para> 4883*4882a593Smuzhiyun<para> 4884*4882a593SmuzhiyunWhen the server is about to suspend itself, the given function will be 4885*4882a593Smuzhiyunexecuted: 4886*4882a593Smuzhiyun<blockquote><programlisting> 4887*4882a593Smuzhiyun (*function) (client, closure) 4888*4882a593Smuzhiyun</programlisting></blockquote> 4889*4882a593Smuzhiyun</para> 4890*4882a593Smuzhiyun<para> 4891*4882a593SmuzhiyunNeither client nor closure are actually used inside the work queue routines.</para> 4892*4882a593Smuzhiyun</section> 4893*4882a593Smuzhiyun</section> 4894*4882a593Smuzhiyun<section> 4895*4882a593Smuzhiyun <title>Summary of Routines</title> 4896*4882a593Smuzhiyun<para> 4897*4882a593SmuzhiyunThis is a summary of the routines discussed in this document. 4898*4882a593SmuzhiyunThe procedure names are in alphabetical order. 4899*4882a593SmuzhiyunThe Struct is the structure it is attached to; if blank, this 4900*4882a593Smuzhiyunprocedure is not attached to a struct and must be named as shown. 4901*4882a593SmuzhiyunThe sample server provides implementations in the following 4902*4882a593Smuzhiyuncategories. Notice that many of the graphics routines have both 4903*4882a593Smuzhiyunmi and fb implementations.</para> 4904*4882a593Smuzhiyun<para> 4905*4882a593Smuzhiyun<itemizedlist> 4906*4882a593Smuzhiyun<listitem><para>dix portable to all systems; do not attempt to rewrite (Xserver/dix)</para></listitem> 4907*4882a593Smuzhiyun<listitem><para>os routine provided in Xserver/os or Xserver/include/os.h</para></listitem> 4908*4882a593Smuzhiyun<listitem><para>ddx frame buffer dependent (examples in Xserver/fb)</para></listitem> 4909*4882a593Smuzhiyun<listitem><para>mi routine provided in Xserver/mi</para></listitem> 4910*4882a593Smuzhiyun<listitem><para>hd hardware dependent (examples in many Xserver/hw directories)</para></listitem> 4911*4882a593Smuzhiyun<listitem><para>none not implemented in sample implementation</para></listitem> 4912*4882a593Smuzhiyun</itemizedlist> 4913*4882a593Smuzhiyun</para> 4914*4882a593Smuzhiyun <table frame="all" id="routines-1"> 4915*4882a593Smuzhiyun <title>Server Routines (Page 1)</title> 4916*4882a593Smuzhiyun <tgroup cols='3' align='left' colsep='1' rowsep='1'> 4917*4882a593Smuzhiyun <thead> 4918*4882a593Smuzhiyun <row> 4919*4882a593Smuzhiyun <entry>Procedure</entry> 4920*4882a593Smuzhiyun <entry>Port</entry> 4921*4882a593Smuzhiyun <entry>Struct</entry> 4922*4882a593Smuzhiyun </row> 4923*4882a593Smuzhiyun </thead> 4924*4882a593Smuzhiyun <tbody> 4925*4882a593Smuzhiyun<row><entry><function>ALLOCATE_LOCAL</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 4926*4882a593Smuzhiyun<row><entry><function>AbortDDX</function></entry><entry><literal>hd</literal></entry><entry><para></para></entry></row> 4927*4882a593Smuzhiyun<row><entry><function>AddCallback</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 4928*4882a593Smuzhiyun<row><entry><function>AddEnabledDevice</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 4929*4882a593Smuzhiyun<row><entry><function>AddInputDevice</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 4930*4882a593Smuzhiyun<row><entry><function>AddScreen</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 4931*4882a593Smuzhiyun<row><entry><function>AdjustWaitForDelay</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 4932*4882a593Smuzhiyun<row><entry><function>Bell</function></entry><entry><literal>hd</literal></entry><entry><para>Device</para></entry></row> 4933*4882a593Smuzhiyun<row><entry><function>ChangeClip</function></entry><entry><literal>mi</literal></entry><entry><para>GC func</para></entry></row> 4934*4882a593Smuzhiyun<row><entry><function>ChangeGC</function></entry><entry><literal></literal></entry><entry><para>GC func</para></entry></row> 4935*4882a593Smuzhiyun<row><entry><function>ChangeWindowAttributes</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 4936*4882a593Smuzhiyun<row><entry><function>ClearToBackground</function></entry><entry><literal>ddx</literal></entry><entry><para>Window</para></entry></row> 4937*4882a593Smuzhiyun<row><entry><function>ClientAuthorized</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 4938*4882a593Smuzhiyun<row><entry><function>ClientSignal</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 4939*4882a593Smuzhiyun<row><entry><function>ClientSleep</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 4940*4882a593Smuzhiyun<row><entry><function>ClientWakeup</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 4941*4882a593Smuzhiyun<row><entry><function>ClipNotify</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 4942*4882a593Smuzhiyun<row><entry><function>CloseScreen</function></entry><entry><literal>hd</literal></entry><entry><para></para></entry></row> 4943*4882a593Smuzhiyun<row><entry><function>ConstrainCursor</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row> 4944*4882a593Smuzhiyun<row><entry><function>CopyArea</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 4945*4882a593Smuzhiyun<row><entry><function>CopyGCDest</function></entry><entry><literal>ddx</literal></entry><entry><para>GC func</para></entry></row> 4946*4882a593Smuzhiyun<row><entry><function>CopyGCSource</function></entry><entry><literal>none</literal></entry><entry><para>GC func</para></entry></row> 4947*4882a593Smuzhiyun<row><entry><function>CopyPlane</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 4948*4882a593Smuzhiyun<row><entry><function>CopyWindow</function></entry><entry><literal>ddx</literal></entry><entry><para>Window</para></entry></row> 4949*4882a593Smuzhiyun<row><entry><function>CreateGC</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 4950*4882a593Smuzhiyun<row><entry><function>CreateCallbackList</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 4951*4882a593Smuzhiyun<row><entry><function>CreatePixmap</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 4952*4882a593Smuzhiyun<row><entry><function>CreateScreenResources</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 4953*4882a593Smuzhiyun<row><entry><function>CreateWellKnowSockets</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 4954*4882a593Smuzhiyun<row><entry><function>CreateWindow</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 4955*4882a593Smuzhiyun<row><entry><function>CursorLimits</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row> 4956*4882a593Smuzhiyun<row><entry><function>DEALLOCATE_LOCAL</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 4957*4882a593Smuzhiyun<row><entry><function>DeleteCallback</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 4958*4882a593Smuzhiyun<row><entry><function>DeleteCallbackList</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 4959*4882a593Smuzhiyun<row><entry><function>DestroyClip</function></entry><entry><literal>ddx</literal></entry><entry><para>GC func</para></entry></row> 4960*4882a593Smuzhiyun<row><entry><function>DestroyGC</function></entry><entry><literal>ddx</literal></entry><entry><para>GC func</para></entry></row> 4961*4882a593Smuzhiyun<row><entry><function>DestroyPixmap</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 4962*4882a593Smuzhiyun<row><entry><function>DestroyWindow</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 4963*4882a593Smuzhiyun<row><entry><function>DisplayCursor</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row> 4964*4882a593Smuzhiyun<row><entry><function>Error</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 4965*4882a593Smuzhiyun<row><entry><function>ErrorF</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 4966*4882a593Smuzhiyun<row><entry><function>FatalError</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 4967*4882a593Smuzhiyun<row><entry><function>FillPolygon</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 4968*4882a593Smuzhiyun<row><entry><function>FillSpans</function></entry><entry><literal>ddx</literal></entry><entry><para>GC op</para></entry></row> 4969*4882a593Smuzhiyun<row><entry><function>FlushAllOutput</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 4970*4882a593Smuzhiyun<row><entry><function>FlushIfCriticalOutputPending</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 4971*4882a593Smuzhiyun<row><entry><function>FreeScratchPixmapHeader</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 4972*4882a593Smuzhiyun<row><entry><function>GetImage</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 4973*4882a593Smuzhiyun<row><entry><function>GetMotionEvents</function></entry><entry><literal>hd</literal></entry><entry><para>Device</para></entry></row> 4974*4882a593Smuzhiyun<row><entry><function>GetScratchPixmapHeader</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 4975*4882a593Smuzhiyun<row><entry><function>GetSpans</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 4976*4882a593Smuzhiyun<row><entry><function>GetStaticColormap</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 4977*4882a593Smuzhiyun </tbody> 4978*4882a593Smuzhiyun </tgroup> 4979*4882a593Smuzhiyun </table> 4980*4882a593Smuzhiyun 4981*4882a593Smuzhiyun <table frame="all" id="routines-2"> 4982*4882a593Smuzhiyun <title>Server Routines (Page 2)</title> 4983*4882a593Smuzhiyun <tgroup cols='3' align='left' colsep='1' rowsep='1'> 4984*4882a593Smuzhiyun <thead> 4985*4882a593Smuzhiyun <row> 4986*4882a593Smuzhiyun <entry>Procedure</entry> 4987*4882a593Smuzhiyun <entry>Port</entry> 4988*4882a593Smuzhiyun <entry>Struct</entry> 4989*4882a593Smuzhiyun </row> 4990*4882a593Smuzhiyun </thead> 4991*4882a593Smuzhiyun <tbody> 4992*4882a593Smuzhiyun<row><entry><function>ImageGlyphBlt</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 4993*4882a593Smuzhiyun<row><entry><function>ImageText16</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 4994*4882a593Smuzhiyun<row><entry><function>ImageText8</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 4995*4882a593Smuzhiyun<row><entry><function>InitInput</function></entry><entry><literal>hd</literal></entry><entry><para></para></entry></row> 4996*4882a593Smuzhiyun<row><entry><function>InitKeyboardDeviceStruct</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 4997*4882a593Smuzhiyun<row><entry><function>InitOutput</function></entry><entry><literal>hd</literal></entry><entry><para></para></entry></row> 4998*4882a593Smuzhiyun<row><entry><function>InitPointerDeviceStruct</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 4999*4882a593Smuzhiyun<row><entry><function>InsertFakeRequest</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 5000*4882a593Smuzhiyun<row><entry><function>InstallColormap</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 5001*4882a593Smuzhiyun<row><entry><function>Intersect</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5002*4882a593Smuzhiyun<row><entry><function>Inverse</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5003*4882a593Smuzhiyun<row><entry><function>LegalModifier</function></entry><entry><literal>hd</literal></entry><entry><para></para></entry></row> 5004*4882a593Smuzhiyun<row><entry><function>LineHelper</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 5005*4882a593Smuzhiyun<row><entry><function>ListInstalledColormaps</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 5006*4882a593Smuzhiyun<row><entry><function>LookupKeyboardDevice</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 5007*4882a593Smuzhiyun<row><entry><function>LookupPointerDevice</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 5008*4882a593Smuzhiyun<row><entry><function>ModifyPixmapHeader</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5009*4882a593Smuzhiyun<row><entry><function>NextAvailableClient</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 5010*4882a593Smuzhiyun<row><entry><function>OsInit</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 5011*4882a593Smuzhiyun<row><entry><function>PaintWindowBackground</function></entry><entry><literal>mi</literal></entry><entry><para>Window</para></entry></row> 5012*4882a593Smuzhiyun<row><entry><function>PaintWindowBorder</function></entry><entry><literal>mi</literal></entry><entry><para>Window</para></entry></row> 5013*4882a593Smuzhiyun<row><entry><function>PointerNonInterestBox</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row> 5014*4882a593Smuzhiyun<row><entry><function>PointInRegion</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5015*4882a593Smuzhiyun<row><entry><function>PolyArc</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 5016*4882a593Smuzhiyun<row><entry><function>PolyFillArc</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 5017*4882a593Smuzhiyun<row><entry><function>PolyFillRect</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 5018*4882a593Smuzhiyun<row><entry><function>PolyGlyphBlt</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 5019*4882a593Smuzhiyun<row><entry><function>Polylines</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 5020*4882a593Smuzhiyun<row><entry><function>PolyPoint</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 5021*4882a593Smuzhiyun<row><entry><function>PolyRectangle</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 5022*4882a593Smuzhiyun<row><entry><function>PolySegment</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 5023*4882a593Smuzhiyun<row><entry><function>PolyText16</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 5024*4882a593Smuzhiyun<row><entry><function>PolyText8</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 5025*4882a593Smuzhiyun<row><entry><function>PositionWindow</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 5026*4882a593Smuzhiyun<row><entry><function>ProcessInputEvents</function></entry><entry><literal>hd</literal></entry><entry><para></para></entry></row> 5027*4882a593Smuzhiyun<row><entry><function>PushPixels</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 5028*4882a593Smuzhiyun<row><entry><function>PutImage</function></entry><entry><literal>mi</literal></entry><entry><para>GC op</para></entry></row> 5029*4882a593Smuzhiyun<row><entry><function>QueryBestSize</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row> 5030*4882a593Smuzhiyun<row><entry><function>ReadRequestFromClient</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 5031*4882a593Smuzhiyun<row><entry><function>RealizeCursor</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row> 5032*4882a593Smuzhiyun<row><entry><function>RealizeFont</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 5033*4882a593Smuzhiyun<row><entry><function>RealizeWindow</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 5034*4882a593Smuzhiyun<row><entry><function>RecolorCursor</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row> 5035*4882a593Smuzhiyun<row><entry><function>RectIn</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5036*4882a593Smuzhiyun<row><entry><function>RegionCopy</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5037*4882a593Smuzhiyun<row><entry><function>RegionCreate</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5038*4882a593Smuzhiyun<row><entry><function>RegionDestroy</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5039*4882a593Smuzhiyun<row><entry><function>RegionEmpty</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5040*4882a593Smuzhiyun<row><entry><function>RegionExtents</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5041*4882a593Smuzhiyun<row><entry><function>RegionNotEmpty</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5042*4882a593Smuzhiyun<row><entry><function>RegionReset</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5043*4882a593Smuzhiyun<row><entry><function>ResolveColor</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 5044*4882a593Smuzhiyun </tbody> 5045*4882a593Smuzhiyun </tgroup> 5046*4882a593Smuzhiyun </table> 5047*4882a593Smuzhiyun 5048*4882a593Smuzhiyun <table frame="all" id="routines-3"> 5049*4882a593Smuzhiyun <title>Server Routines (Page 3)</title> 5050*4882a593Smuzhiyun <tgroup cols='3' align='left' colsep='1' rowsep='1'> 5051*4882a593Smuzhiyun <thead> 5052*4882a593Smuzhiyun <row> 5053*4882a593Smuzhiyun <entry>Procedure</entry> 5054*4882a593Smuzhiyun <entry>Port</entry> 5055*4882a593Smuzhiyun <entry>Struct</entry> 5056*4882a593Smuzhiyun </row> 5057*4882a593Smuzhiyun </thead> 5058*4882a593Smuzhiyun <tbody> 5059*4882a593Smuzhiyun<row><entry><function>RemoveEnabledDevice</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 5060*4882a593Smuzhiyun<row><entry><function>ResetCurrentRequest</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 5061*4882a593Smuzhiyun<row><entry><function>SaveScreen</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 5062*4882a593Smuzhiyun<row><entry><function>SetCriticalOutputPending</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 5063*4882a593Smuzhiyun<row><entry><function>SetCursorPosition</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row> 5064*4882a593Smuzhiyun<row><entry><function>SetInputCheck</function></entry><entry><literal>dix</literal></entry><entry><para></para></entry></row> 5065*4882a593Smuzhiyun<row><entry><function>SetSpans</function></entry><entry><literal>ddx</literal></entry><entry><para>GC op</para></entry></row> 5066*4882a593Smuzhiyun<row><entry><function>StoreColors</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 5067*4882a593Smuzhiyun<row><entry><function>Subtract</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5068*4882a593Smuzhiyun<row><entry><function>TimerCancel</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 5069*4882a593Smuzhiyun<row><entry><function>TimerCheck</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 5070*4882a593Smuzhiyun<row><entry><function>TimerForce</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 5071*4882a593Smuzhiyun<row><entry><function>TimerFree</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 5072*4882a593Smuzhiyun<row><entry><function>TimerInit</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 5073*4882a593Smuzhiyun<row><entry><function>TimerSet</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 5074*4882a593Smuzhiyun<row><entry><function>TimeSinceLastInputEvent</function></entry><entry><literal>hd</literal></entry><entry><para></para></entry></row> 5075*4882a593Smuzhiyun<row><entry><function>TranslateRegion</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5076*4882a593Smuzhiyun<row><entry><function>UninstallColormap</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 5077*4882a593Smuzhiyun<row><entry><function>Union</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5078*4882a593Smuzhiyun<row><entry><function>UnrealizeCursor</function></entry><entry><literal>hd</literal></entry><entry><para>Screen</para></entry></row> 5079*4882a593Smuzhiyun<row><entry><function>UnrealizeFont</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 5080*4882a593Smuzhiyun<row><entry><function>UnrealizeWindow</function></entry><entry><literal>ddx</literal></entry><entry><para>Screen</para></entry></row> 5081*4882a593Smuzhiyun<row><entry><function>ValidateGC</function></entry><entry><literal>ddx</literal></entry><entry><para>GC func</para></entry></row> 5082*4882a593Smuzhiyun<row><entry><function>ValidateTree</function></entry><entry><literal>mi</literal></entry><entry><para>Screen</para></entry></row> 5083*4882a593Smuzhiyun<row><entry><function>WaitForSomething</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 5084*4882a593Smuzhiyun<row><entry><function>WindowExposures</function></entry><entry><literal>mi</literal></entry><entry><para>Window</para></entry></row> 5085*4882a593Smuzhiyun<row><entry><function>WriteToClient</function></entry><entry><literal>os</literal></entry><entry><para></para></entry></row> 5086*4882a593Smuzhiyun </tbody> 5087*4882a593Smuzhiyun </tgroup> 5088*4882a593Smuzhiyun </table> 5089*4882a593Smuzhiyun</section> 5090*4882a593Smuzhiyun</article> 5091