Second part of walking through the WanderingPolygon screen saver to understand how to make screensavers work across multiple monitors in a cooperative manner.
The WanderingPloygon.[h,m] source represents the state of the drawing, composed of the current color, the vertices of the polygon, and the current velocity vector of each vertices expressed as an x and y delta to apply for each frame of the animation.
This class is more difficult than it needs to be, because of the decision to detect the edge of each monitor individually instead of as one large rectangular space. Each monitor can be represented as a rectangle, and generally these rectangles have at least one edge adjecent to the the edge of another monitor. For example, here would be a representation of 2 monitors, a 30″ 2560×1600 and 23″ 1920×1200 rotated to portrait mode.

Each monitor would get a separate instance of the WanderingPolygonView, and if the state was in that class they would draw independently. By removing the state to this class we can share the state across the views. When each vertex hits an edge it needs to bounce off in a new direction. So there needs to be a way to track the actual complete drawing area, and when a vertex cross off an “outside” edge. A vertex moving between monitors would be completely acceptable and should not have a chance in direction.
A first pass is to simply use NSUnionRect to get the “maximum possible rectangle. In this case it would be the striped view in back.

But this striped view actually has some dead area above and below the red monitor because the monitors aren’t the same height. This is going to be the case whenever the user has two monitors that aren’t identical in size or do not have perfectly aligned edges.
The vertices should not bounce of the edges of monitors, but instead the edges of the monitors as a whole:

As examples, the location prior and after the velocity delta is applied are shows as a white and black dot in these four examples. In the first pair, neither of these movements should cause a bounce because they stay within the screens as a whole, even though the second one crosses the boundary between two monitors.

In this second pair of examples the vertex should bounce because they have left the edges of the monitors. If the monitors were treated as a simple single large rectangle as described above in the striped example, the first would not bounce until it continued for a while.

To simply the tracking of the vertices, the WanderingPolygon state always assumes that there are multiple monitors. The single monitor or preview rectangle is just the simplest case of multiple monitors.
+(WanderingPolygon *)polygonInRects:(NSRect*)baseRects count:(NSUInteger)count; +(WanderingPolygon *)polygonInScreens;
Nothing really special here, just two separate initializers depending on whether the polygon is going to be used in a preview mode or in screen saver mode. For good appearance, the goal is to have vertices start inside the “drawing area”.
- (void)makeCurrentColor;
This method creates a smooth endless gradient that passes through the rainbow of colors. The gradient repeats after about 3 days of continuous drawing. It does this by having the three components of RGB running through 3 sine waves at different rates. I’m not sure where I picked this up from but IIRC it was from the Mandelbrot app that shipped with the first color NeXTStations.

- (void)makeCurrentPath;
Like makeCurrentColor, this method just builds the path used for drawing in the draw method. It is build here instead of in the draw method so that it doesn’t need to be created for each monitor. Not a huge performance savings, but good practice all the same.
- (void)draw;
This method is pretty straight forward. It draws the polygon. The magic to making it appear linked between both monitors is in performing a CGContextTranslateCTM() when auxiliary monitors draw the polygon. This translates the drawing origin so the image is shifted by an amount equal to the distance of the monitor from the main monitor.
- (void)oneFrameInRectList:(NSRect *)rect count:(NSUInteger)count;
This method walks through each vertex and figures out the new location, determines whether that new location is outside the edges of the monitors, and if so changes a component of the velocity for that vertex.
Like the initializer it is designed to work with multiple monitors in mind, with one monitor being the simplest case of multiple monitors.
