by Marko Riedel, from a suggestion by Stefan Urbanek
This recipe is very simple. We build an application with a single window that contains a color well. There are two entries on the application’s menu: one to quit the application, and another to pick a color. The cursor changes to a red target cursor when the user clicks the latter, and she may then copy the color of any pixel on the screen to the color well by clicking on the pixel. The color picker code is isolated in a function that is called GSReadPixelFromScreen. There is a controller class that acts as a delegate to the application and responds to the action pick:.
Start with the usual include directives. We need the cursor font for the target cursor.
The function GSReadPixelFromScreen picks a color in several steps:
The first step is to obtain the current display and its root window.
We prepare the cursor from the font cursor with a target cross shape by setting the color components of its foreground and background colors. The foreground is red (RGB is (max,0,0)) and the background white (RGB (max,max,max).) The color components are unsigned, so we get the maximum value by using -1 without having to know the actual size of the components.
The next step is to grab the pointer. No other application will receive button clicks until we explicitly release the pointer. We must wait until the user chooses a pixel, i.e. until XNextEvent returns a button release, in which case we release the pointer. We receive no other events because the event mask argument to XGrabPointer only includes button release events.
The location of the button press in root window coordinates tells us what pixel to fetch. We ask the server for a one pixel image at that location and read the pixel once we have the image. We may then free the image since it is no longer needed.
We require the color components rather than the pixel value, so we query the server for the color components of the selected pixel in the default colormap. (We could have extracted the components from the pixel value ourselves e.g. for TrueColor visuals, but we choose to keep it simple.)
This concludes the definition of the color picker function. We have the color components and use them to obtain the appropriate NSColor object, taking care to scale the values; -1 provides the maximum value for each component when converted to an unsigned short integer.
It remains to implement the controller. It must assemble the window with the color well after the application finishes launching and pick colors when the user clicks the corresponding menu item.
First define the dimensions of the window’s content view, allocate the window and initialize it with the title and the minimum size.
The well has the same size as the window’s content frame and starts out containing the color “blue.”
We place the well in the view hierarchy by making it the window’s content view. We are done with the window, so we center it and place it on screen.
The action pick is very simple: it invokes GSReadPixelFromScreen and sets the well’s color to the color that it returns.
The main function allocates an autorelease pool, the controller and the application object.
The menu contains an entry that quits the application and another one that invokes the color picker.
It remains to connect the controller to the application and start the event loop.