summaryrefslogtreecommitdiff
path: root/Documentation/CoreStructures
blob: 736c887eecd46a581f1546b8b6a5c704a1256a80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
Beryl's core structures - version this-is-not-complete-yet
=======================
1. Scope of this document
2. CompDisplay vs CompScreen
3. CompDisplay
4. CompScreen
5. CompWindow
6. Regions

1. Scope of this document
=========================
With this document I will attempt to clear up some confusion about the most
important data structures in Beryl. I will not describe every part of the
structures, but rather clear up some trickier parts.

A good way to get to know these structures is to use the debug plugin. It
allows you to easily view the CompScreen and CompWindow structure(s) with
some of the sub-structures.

2. CompDisplay vs CompScreen
============================
If you've seen the DISPLAY variable, it'll look something like this for most 
people: DISPLAY=:0.0 . The first 0 here is the display, and the second 0
is the screen. Each X server has ONE display, but can have multiple screens.

Do not confuse a screen with a monitor, though. In a xinerama-hinted 
environment (the most common multihead setup), the X server presents just one
screen to the programs, but gives us hints about where the head/monitor
stops and starts. 

Usually, there isn't any real work needed in a plugin to support multiscreen.
All you need to do is make sure you deal with CompScreen and never assume
that you can get the right CompScreen from display->screens. There are 
functions in core that let you find a screen based on the root window. Use
these, even if display->screens is very tempting.

Generally, we keep bindings in Display-scope. This can add some complications,
but make sure you find the right screen if you want your binding to only
affect one screen. Take a look at rotate.c to see how this is done as an
example. 


3. CompDisplay
==============
CompDisplay is mostly dealt with by core. It is the DataStructure that glues
all the possible screens together. Chances are, you will mostly just work with
d->activeWindow which defines the currently active (focused) window, and the
d->pointerX/Y which tells you where the pointer is. Also, it stores the atoms
fetched by core. 

4. CompScreen
=============
CompScreen is _the_ structure. You will get to know this whether you want to
or not if you intend to do development on Beryl.

First of all, it is a linked list item, so it contains a link to the next
CompScreen. It also has a link to the CompDisplay structure it belongs to.
Because of that fact, you never need to pass both CompDisplay and 
CompScreen to a function, and you are better off passing CompScreen than
CompDisplay, because the latter can have several CompScreens.

Each screen has a unique root window, which is often used in identifying the
screen when you get events. This is process is usually handled by core when
you call findScreenAtDisplay().

'height' and 'width' is the height and width of the entire screen. It is
very tempting to use these a lot, but they are dangerous. The reason they
are dangerous is that they span across all heads associated with that screen.
Therefore, you want to familiarise yourself with the CompOutput structure.
The CompScreen has an array of nOutputDev CompOutput structures; in other
words, one per monitor. It also has a convenient currentOutputDev which core
tries to set, but is not always accurate. 

Luckily, the CompOutput struct is very simple. It has a width, height, region
and workRegion variable that we care about. The region helps us establish
where an outputDev starts in the screen. region.x1 defines where the X-coordinate
of that specific window starts, and region.x2 describes where it ends. The same
with region.y1/y2 respectively for the Y coordinate.
For a single monitor with 1024x768, the outputdev will look like this:
x1: 0 
x2: 1023
y1: 0
y2: 767

Keep in mind that x + width puts you 1 pixel beyond the device. (0-1023 is 1024
numbers. A classic programming error is to forget that 0 is a valid number).
Currently, we don't really use the rects of the regions, so for nowe we can
ignore those. 

workRegion is identical to region, but is supposed to take struts into 
consideration. This code has undergone some changes, and is likely to change
in the future. The problem is that we never used the region nature of the 
workRegion so it was still just a rect. That discussion is beyond the scope
of this text, however. Just keep it in mind if you want a simple but imperfect
way of avoiding panels.

So when do you use s->width and when do you use 
s->outpudDev[s->currentOutputDev].region.x1/x2 ? There is no universal answer
to this, but the simple answer is to use s->width when you are concerned with
the entire screen, and the outputDev when you want to constrain yourself to the
monitor. Examples are maximization, which deals with outputDev, and edge-
detection, which wants to find the edge of the screen, not the monitor.

More obvious variables are hsize and vsize, which define the horisontal
and vertical size, x and y, which define which of these you are currently on,
screenNum, which defines which screen you are on (usually 0), and the WorkArea
rectangle, which defines the work area for the screen (avoid using this, as
it will be quite strange on xinerama-hinted multihead.)

Each CompScreen also has a list of windows (s->windows) and the reversed
version. Windows are stored in a bottom-up fashion, so the first window in
s->windows will be the bottommost window. 

The projectionStyle sets how the projection matrix should be set up. This
is mostly just relevant for xinerama multihead at the moment. See the multihead
documentation for details. In the future, this might be used to set orthographic
projection instead of perspective.

5. CompWindow
=============
Each window has a CompWindow structure. However, you should not store this link
unless you also make sure you listen for events which would destroy it and 
update your version accordingly. If you want your plugin to remember a window,
it is often wise to use the w->id instead, and locate the CompWindow when you
need it, but this depends on how you use the CompWindow. Storing the CompWindow
pointer is faster, but slightly more complex. 



6. Regions