Observations about pointers, coordinates, and halfstepping.
* Pointer placement by bisecting regions
* Placement and resizing of the pointer
* Placement of a midpoint in a pointer part
* Locations and regions
* Vectors
* Possibilities for storing coordinates
Pointer placement by bisecting regions
A pointer can be placed anywhere within the bounds of a
view by centering the pointer within one half at a time:
left, right, top, or bottom. Start in the center of a
view, then split it and recenter the pointer within one of
the halves.
The maximum number of steps for placing the pointer on any
dot of a line is also the number times of dividing the
length in half until the result is the value of 1 or less.
That is also the same as the magnitude of the value of 2
that results in a value equal or greater than the length of
that line.
For example, a length of 1200 dots is between 2^10 and 2^11
(t.i. 1024 and 2048), therefore the maximum number of steps
to a single dot is 11. For a view 1200 by 900, the maximum
is 11 for the xaxis and 10 for the yaxis, a total maximum
of 21 steps to any dot within the view.
Starting with the pointer in the center is the same as
dividing in half twice, once for each axis, thereby
potentially reducing the number of additional steps by two.
Thereafter, each step divides only one axis, but is
required only until the pointer is placed where needed.
Guidelines for humancomputer interfaces (HCI) have
recommended a minimum of 32 dots for width and height of
regions intended for selection with a pointer, such as
commands presented as regions on a "toolbar". Placing the
pointer within a region of 32 dots by 32 dots
(preferably slightly smaller) is potentially five steps
fewer (32 = 2^5) for each axis than for a single dot
in a view.
For example, a view of 1200 by 900 divided into regions
of 30 by 30 effectively reduces the view to 40 regions
by 30 regions. The magnitudes for the value of 2 for each
axis is then 6 (2^6 = 64 > 40) and 5 (2^5 = 32 > 30),
a total maximum of 11 steps to any 30 by 30 region.
As six steps accounts for 64 regions, a view with 64 regions
of 30 by 30 dots along each axis has a size of 1920 by 1920
and a total maximum of 12 steps. Similarly, seven steps
for regions of 30 by 30 covers a view of 3840 by 3840 dots
with a total maximum of 14 steps.
A line of text is typically at least 16 dots tall, such as
within a menu or a hypertext link. A single word averages
about five characters, and the width of each character is
about half the height of a line. Therefore, a word might
be at least 40 dots wide, though less with narrower
characters.
Menus are typically more than one word wide, and widen
further with left and right margins of empty space. The
maximum number of steps is potentially reduced when the
width of a menu (or a hypertext link) is greater than the
next magnitude of 2.
> 64 dots wide (1.5 words): max steps reduced by six
> 128 dots wide (3 words): max steps reduced by seven
> 256 dots wide (6 words): max steps reduced by eight
That is 1, 2, or 3 fewer steps for the maximum when compared
to a region 32 dots wide.
Vertically, a line height of 16 dots is half the 32 dots of
the HCI guidelines for regions requiring a pointer for
activation. That potentially increases the maximum steps
by one for the yaxis.
Overall, placing the pointer on text is potentially the same
or less maximum steps than for a subregion on toolbars.
Dividing in half is about proportions. A sequence of
halving remains relevant when scaling a region
(and its content), regardless of a change in aspect ratio,
f.e. a change of screen resolution. The ratio of the sizes
guides the translation of the coordinates. The exact same
number of steps suffices for a region scaled larger,
or even when squished or stretched.
Placement and resizing of the pointer
A step length is half of either the width or height
of the current region. Beginning with the whole Xwindow,
the first position is the center of the Xwindow,
a step in both directions. The number of steps
for each axis and the coordinates are both stored
per Xwindow, in its plist property 'nupointerstep'.
The pointer visually divides the current region in half
horizonatlly and vertically, wherewith it reveals the
potential result of the next step. A gap at the center
provides a view of the focal point, coordinated with
the actual cursor, thereby segmenting the pointer into
four parts. These four parts are stored per root Xwindow,
in its plist property 'nupointer'.
Each part of the pointer is a thin line masked (bordered)
by a contrasting color, the standard approach for ensuring
contrast with any content. Each line is isolated in
a separate Xwindow, all with greater priority than
any other managed Xwindow.
For an Xserver, the width and height of an Xwindow
is distinct from its border width, and the border
is the same width for the whole perimeter.
An Xwindow is placed at the origin of its border,
so its own origin is displaced by the border width.
The pointer gap width and height is 16 by 16, based on
the typical minimal line height for text.
The minimal length of the pointer dividing line is
the same as gap, and its thickness (line width) is 2.
The border is the mask and its width is 1.
The pointer breadth is the pointer thickness (line width)
plus the border on either side. Therefrom: 1 + 2 + 1.
The left and right parts are distanced by the gap width,
so the width of each part is the current horizontal step
minus half the gap width (and Xwindow border).
The length of the current horizontal step:
Xwindow width
/ 2 ^ number of horizontal steps
As it might be less than the minimal pointer line length,
the actual line length (width of pointer part)
is used for calculating the position of the line.
The width of the left and right pointer parts:
horizontal step length
 (2 * pointer border)
 half width of pointer gap
but at least the minimal pointer line length.
The height of the left and right pointer parts is
the thickness (width) of the pointer line.
The left and right coordinates, for point (x, y):
< Xwindow origin < Xwindow origin
 point 
 
b line b + b line b
1/2 gap1/2 gap
possible split length  possible split length
Left pointer part x coordinate.
x of point
 (width of left pointer part
+ (2 * pointer border)
+ half width of pointer gap)
Right pointer part x coordinate.
x of point
+ half width of pointer gap
Both left and right y coordinate.
y of point
 half breadth of pointer
The top and bottom parts are distanced by the gap height,
so the height of each part is the current vertical step
minus half the gap height (and Xwindow border).
The length of the current vertical step:
Xwindow height
/ 2 ^ number of vertical steps
As it might be less than the minimal pointer line length,
the actual line length (height of pointer part)
is used for calculating the position of the line.
The width of the top and bottom pointer parts is
the thickness (width) of the pointer line.
The height of the top and bottom pointer parts:
vertical step length
 (2 * pointer border)
 half height of pointer gap
but at least the minimal pointer line length.
The top and bottom coordinates,  Xwin origin
for point (x, y):  border

Both top and bottom x coordinate.  line (height)
x of point 
 half breadth of pointer  border

Top pointer part y coordinate.  1/2 gap
y of point + point
 (height of top pointer part  1/2 gap
+ (2 * pointer border)  Xwin origin
+ half height of pointer gap)  border

Bottom pointer part y coordinate.  line (height)
y of point 
+ half height of pointer gap  border

Placement of a midpoint in a pointer part
The split length spans from gap center
to the edge of the narrowed region.
A pointer part spans the split length
minus half the pointer gap.
The line of a pointer part is between
its border edges.
The origin of the line begins at
the inside edge of the border.
A midpoint is at half the distance
of the split length from gap center
(and as wide as the line thickness).
The midpoint is positioned from
the line origin.
The left part (xaxis) and top part (yaxis),
for a border width of 1,
and a midpoint width of 2:
< line origin

b line b gap 
1/2 gap
split length 
 1/2 split
mid
 2 
Remember, the split length might be less than
the minimum pointer line length, so depend on
the line length instead.
The midpoint from line origin is at:
line length
+ one border
+ 1/2 gap width
 1/2 split length
 1/2 midpoint width
and zero for the other axis.
The right part (xaxis) and bottom part (yaxis),
for a pointer gap width and height of 16,
(and the aforementioned measurements):
< line origin

 gap b line b
1/2 gap
 split length
1/2 split 
mid
 2 
The midpoint from line origin is at:
1/2 split length
 1/2 gap width
 one border
 1/2 midpoint width
and zero for the other axis.
Locations and regions
The location of the pointer of an Xserver is a pair of
coordinates based on the lefttop corner of a view as the
origin. Relatedly, the width and height of that view is
equivalent to the kittycorner coordinate for the origin of
that view.
For example, a 1200 by 900 view is represented by a list of
kittycorner coordinates
'((xy 0 0)(xy 1200 900))
or by its location with its width and height
'((xy 0 0)(wh 1200 900))
Thereby, the topright region of a quarteredview is within
'((xy 600 0)(xy 1200 450))
or represented by its location and size within the view as
'((xy 600 0)(wh 600 450))
The location of the pointer centered within the view might
be represented as
'((xy 600 450)((xy 0 0)(wh 1200 900)))
or simplified as with any region with a presumed origin
'((xy 600 450)(wh 1200 900))
Clearly, coordinates can have different meanings,
even when associated with a width and height,
so the context must be documented for the data.
Vectors
A list of coordinates is like a vector for each
perpendicular axis, declaring direction with length.
For an origin in the lefttop corner, the directions are
summarized for a set of coordinates by pairing left and
right as negative and positive values for the horizontal,
and up and down as negative and positive values for the
vertical.
For example, the location from the origin at lefttop
'(xy 600 450)
is equivalent to
'((right 600)(down 450))
A path of vectors with most recent step first
'((up 225)(down 450)(right 600))
can be represented as
'((xy 0 225)(xy 600 450))
The initial placement of the pointer in the center of the
screen is the same as two steps from the origin, one for
each axis as half the length of an axis. The coordinates
represent the difference for both axes.
For example, a screen of 1200 by 900 has its center at
'(xy 600 450)
or represented as differences of vectors with each step
'((xy 0 450)(xy 600 0))
thereby each step has one axis with a difference of zero.
Possibilities for storing coordinates
Horizontal stepping is separate from vertical stepping.
The initial distances can be different, thereby the
halving would have different values.
The number of steps along an axis is the same as the
magnitude for the value of 2 that would divide the
axis length for the distance of a step on that axis,
f.e. plus or minus (/ axislength(expt 2 3)) for the
third step.
The final coordinate for an axis results from summing
the positive or negative distances of each step.
Establish the origin (0, 0) at lefttop. Horizontally,
left is negative and right is positive, and up is negative
and down is positive for the vertical. Push each step
into a list of steps, t.i. the first step becomes last
in the list of steps as each new step is prepended.
For example, gradually stepping "right, right, left" from
the origin along an xaxis of length 1200:
1st step: right from (0, 0)
=> 1200/2^1
=> 1200/2
=> 600
(0 + 600, 0) => (600, 0)
2nd step: right from (600, 0)
=> 1200/2^2
=> 1200/4
=> 300
(600 + 300, 0) => (900, 0)
3rd step: left from (900, 0)
=> 1200/2^3
=> 1200/8
=> 150
(900  150, 0) => (750, 0)
Or, the steps summarized into a list as
'(horizontal 1200 (left right right))
then restored:
=>  1200/2^3  1200/2^2 + 1200/2^1
=>  1200/8 + 1200/4 + 1200/2
=>  150 + 300 + 600
=> 750
The number of steps for halving reveals the next (and prior)
magnitude for either axis. For example,
'((xy 750 0)(steps 3 0))
The number of steps is the magnitude of the value of 2 for
dividing the length of an axis for the length of the next
vector. Thereby, the magnitude for each axis is enough
for progressing from the current coordinate by bitshifting
the length of an axis by the number of steps.
The list of coordinates of prior pointer placement is a
means of backtracking without recalculation. It can begin
with the coordinates of the pointer prior to centering for
returning to the location prior to stepping.
For example,
'((steps 2 1)
(xy 750 225)(xy 900 225)(xy 900 450)
(xy 600 450)
(xy 289 337))
or succinctly as
'((2 . 1)
(750 225 900 225 900 450
600 450
289 337))
Halving would be for only one view at a time, so the size
of the view is obtainable from the environment. When
desired for future reference, the size can be appended.
For example,
'((steps 2 1)
((xy 750 225)(xy 900 225)(xy 900 450)
(xy 600 450)
(xy 289 337))
(wh 1200 900))
or succinctly as
'((2 . 1)
(750 225 900 225 900 450
600 450
289 337)
(1200 . 900))
That might be helpful when focusing on a tiled view, or
eventually saving coordinates for a scaled region.
Fractional results are truncated, so either the actual value
added is stored or the number of steps so the value can be
reliably derived.
For example, track the number of steps with the vector
differences:
'((steps 2 1)
((150 0)(0 225)(300 0)(600 450)))