summaryrefslogtreecommitdiff
path: root/Development/Documentation/DevPrivates.mdwn
diff options
context:
space:
mode:
authorJoe Rayhawk <jrayhawk@freedesktop.org>2013-07-08 07:19:38 +0000
committerJoe Rayhawk <jrayhawk@freedesktop.org>2013-07-08 07:19:38 +0000
commit350e2d1f959c63392659bd21f81a58e38b866cfd (patch)
tree08fb9d171806983a0834b8fa5e6e3d2060738a6b /Development/Documentation/DevPrivates.mdwn
parente4863cea63a88dc233704055011977b71f723732 (diff)
moin2mdwn: convert page Development/Documentation/DevPrivates
Diffstat (limited to 'Development/Documentation/DevPrivates.mdwn')
-rw-r--r--Development/Documentation/DevPrivates.mdwn100
1 files changed, 100 insertions, 0 deletions
diff --git a/Development/Documentation/DevPrivates.mdwn b/Development/Documentation/DevPrivates.mdwn
new file mode 100644
index 00000000..3235c070
--- /dev/null
+++ b/Development/Documentation/DevPrivates.mdwn
@@ -0,0 +1,100 @@
+
+devPrivates are a way to store information in a struct without modifying the header for the struct, thus keeping the ABI.
+
+Each major struct ([[ScreenRec|ScreenRec]], [[DeviceIntRec|DeviceIntRec]], [[WindowRec|WindowRec]], [[ClientRec|ClientRec]]) has a pointer to it's devPrivates as part of the struct. The usage of the devPrivates is as follows:
+
+
+[[!format txt """
+#include <privates.h>
+
+
+DevPrivatesKey myKey = &myKey;
+
+
+void store_private(ClientPtr client)
+{
+ MyStruct *a = xalloc(sizeof(MyStruct));
+
+ /* do stuff with a */
+
+ dixSetPrivate(&client->devPrivates, myKey, a);
+}
+
+void retrieve_private(ClientPtr client)
+{
+ MyStruct *a;
+
+ a = (MyStruct*)dixLookupPrivate(&client->devPrivates, myKey);
+
+ /* do stuff with a */
+}
+
+
+/* The following will free _ALL_ devPrivates on the given client. Not just yours! */
+void delete_private(ClientPtr client)
+{
+ dixFreePrivates(client->devPrivates);
+
+}
+
+"""]]
+devPrivates are more fully documented in the _Definition of the Porting Layer for the X v11 Sample Server_ document, sources of which are in [[xorg-docs/sgml/core/Xserver-spec.sgml|http://cgit.freedesktop.org/xorg/doc/xorg-docs/tree/sgml/core/Xserver-spec.sgml]]
+
+
+# Deprecated information
+
+The following is a description of the devPrivates system before the serious overhaul. It is now outdated.
+
+Client devPrivates are similar to those of the [[ScreenRec|ScreenRec]] and [[DeviceIntRec|DeviceIntRec]] structures, but those have their own API to initialize and access them. Please note that there a overhaul of the devPrivates system in progress and this information may be out of date soon [[http://lists.freedesktop.org/archives/xorg/2007-March/022212.html|http://lists.freedesktop.org/archives/xorg/2007-March/022212.html]].
+
+Need to be initialised at start time, as each time a client is allocated. The devPrivates are an array of [[DevUnions|DevUnions]] that are allocated when the client starts and released when the client finishes. Each client has the same size allocated for devPrivates and at the moment there are no methods to resize the array at a later point in time. Better make sure you allocate everything on server startup before the first client connects.
+
+_[[AllocateClientPrivatesIndex|AllocateClientPrivatesIndex]]()_ gives you an index into the array. Each time you need to access your data, access it with `client->devPrivates[MyIndex].ptr` and cast it to your specific data information. Immediately after retrieving your index, call _[[AllocateClientPrivate|AllocateClientPrivate]]([[MyIndex|MyIndex]], size)_, where size is the number of bytes you need for your private struct in bytes. You can now assume that every client that connects will have enough space for your data.
+
+Finally, you will probably want to add a callback to reset the data when a client starts up. Use _[[AddCallback|AddCallback]]()_ to register your function and then do stuff. The first argument is always the same (_[[ClientStateCallback|ClientStateCallback]]_), the second your callback proc and the third one some pointer data which will get passed into the callback function (argument {{closure]] in example below). Most extensions just pass in 0. You need to check the state of the client in the callback function. If client->state is [[ClientStateRunning|ClientStateRunning]] then the client has just started up, [[ClientStateGone|ClientStateGone]] or [[ClientStateRetained|ClientStateRetained]] means it has been shut down. There are a few other states. (comment by Eamon Walsh)
+
+I recommend looking at damageext/damageext.c, it has a low signal-to-noise ratio. The full code you need:
+
+
+[[!format txt """
+int myIndex = AllocateClientPrivateIndex(); /* check myIndex > 0 */
+AllocateClientPrivate(myIndex, sizeof(MyStruct)); /* has to return true */
+AddCallback(&ClientStateCallback, MyCallbackProc, 0);
+
+static void MyCallbackProc(CallbackListPtr *list, pointer closure, pointer data)
+{
+ NewClientInfoRec* clientinfo = (NewClientInfoRec*)data;
+ ClientPtr client = clientinfo->client;
+ MyStruct mystruct = (MyStruct*)client->devPrivates[myIndex].ptr;
+
+ /* do stuff */
+
+}
+"""]]
+Finally, you want to add a _[[DeleteCallback|DeleteCallback]]()_ call to remove your callback when the extension resets.
+
+
+## Notes
+
+The client that owns the root window is `serverClient` and will be created before extensions initialize. It will (most likely) not have devPrivates set to what you added, so make sure you cater for this.
+
+
+### Window DevPrivates
+
+The devPrivates of a [[WindowRec|WindowRec]] are stored after the struct's memory. Each screen keeps a totalWindowSize for the memory that is to be allocated per screen. The memory for a [[WindowRec|WindowRec]] with 4 devPrivates entries looks approximately like this:
+
+
+[[!format txt """
+ ___________________________________________________________________________
+| | | | | | | | | |
+| WindowRec | 1 | 2 | 3 | 4 | A | B | C | D |
+|___________dP__|___|___|___|___|__________|_____________|___|______________|
+ | ^ | | | | ^ ^ ^ ^
+ |__| | | | |__|__________|_____________|___|
+ | | |______|__________|_____________|
+ | |__________|__________|
+ |______________|
+"""]]
+With `1 = &A, 2 = &B, `etc. Before you allocate a window, you need to call _[[AllocateWindowPrivate|AllocateWindowPrivate]]()_ with the size you need for your entry. A, B, C, D have the sizes that were specified for _[[AllocateWindowPrivate|AllocateWindowPrivate]]_
+
+--- [[CategoryServerInternals|CategoryServerInternals]]