This appendix provides a technical overview of Photon's architecture.
The essential characteristic of Photon is the way in which graphical applications are represented. All Photon applications consist of one or more rectangles called regions. These regions reside in an abstract, three-dimensional event space; the user is outside this space looking in.
Regions can emit and collect objects called events. These events can travel in either direction through the event space (i.e. either toward or away from the user). As events move through the event space, they interact with other regions — this is how applications interact with each other. The process maintaining this simple architecture is the Photon Manager.
All the services required for a windowing system — window managers, drivers, and applications — can easily be created using regions and events. And because processes whose regions are managed by the Photon Manager needn't reside on the same computer as the Photon Manager, it's also easy to implement network-distributed applications.
Photon programs use two basic objects: regions and events. Regions are stationary, while events move through the event space.
A region is a single, fixed rectangular area that a program places in the event space. A region possesses attributes that define how it interacts with events.
An event is a set of nonoverlapping rectangles that can be emitted and collected by regions in either direction in the event space. All events have an associated type. Some event types also possess corresponding data.
As an event flows through the event space, its rectangle set intersects with regions placed in the event space by other applications. As this occurs, the Photon Manager adjusts the event's rectangle set according to the attributes of the regions with which the event intersected.
An emitted event's default initial rectangle set contains a single rectangle whose dimensions are usually the size of the emitting region. As the event moves through the event space, its interactions with other regions may cause some portions of this rectangle to be removed. If this happens, the rectangle will be divided into a set of smaller rectangles that represent the remaining portions:
Certain event types (e.g. button presses) have no need for their initial rectangle set to have the dimensions of the emitting region. For such events, the rectangle set consists of a single rectangle whose size is a single point. A single-point rectangle set is called a point source.
The rectangle set of a “collected” event contains the rectangles resulting from the event's interaction with prior regions in the event space. If an event is completely occluded by other regions such that it results in a set containing no rectangles, then that event ceases to exist.
|For a list of the event types, see the “Event types” section.|
A process may create or use any number of regions and may place them anywhere in the event space. Furthermore, by controlling the dimensions, location, and attributes of a region (relative to the other regions in the event space), a process can use, modify, add, or remove services provided by other regions.
Photon uses a series of regions, ranging from the Root region at the back of the Photon event space to the Graphics region at the front. Draw events start at an application's region and move forward to the Graphics region. Input events start at the Pointer/Keyboard region and travel towards the Root region.
The following constants are defined in <photon/PhT.h>:
A region's owner and the Photon Manager can reside on different computers.
A region has two attributes that control how events are to be treated when they intersect with a region:
You can set these independently for each different type of event.
If a region is sensitive to a particular type of event, then the region's owner collects a copy of any event of that type that intersects with the region. If other regions are sensitive to this same event type and the event intersects with them, they'll also collect a copy of the event — but with a potentially different rectangle set.
Although many regions can collect a copy of the same event, the rectangle set for the event may be adjusted and will therefore be unique for each region that collects the event. The rectangle set reflects the event's interaction with other regions in the event space before arriving at the collecting region.
If a region isn't sensitive to an event type, the region's owner never collects that type of event.
The sensitivity attribute doesn't modify the rectangle set of an event, nor does it affect the event's ability to continue flowing through the event space.
Opaque regions block portions of an event's rectangle set from traveling further in the event space. The opacity attribute controls whether or not an event's rectangle set is adjusted as a result of intersecting with a region.
If a region is opaque to an event type, any event of that type that intersects with the region has its rectangle set adjusted in order to “clip out” the intersecting area. This changes the rectangle set such that it includes smaller rectangles. These new rectangles describe the portions of the event that remain visible to regions beyond this region in the event space.
If a region isn't opaque to an event type, then events of that type never have their rectangle set adjusted as a result of intersecting with that region.
The following table summarizes how a region's attributes affect events that intersect with that region:
|If the region is:||Then the event is:||And the rectangle set is:|
|Not sensitive, not opaque||Ignored||Unaffected|
|Not sensitive, opaque||Ignored||Adjusted|
|Sensitive, not opaque||Collected||Unaffected|
By placing a region across the entire event space, a process can intercept and modify any event passing through that region. If a region is sensitive to all events, but not opaque, it can transparently log all events.
If a region is sensitive and opaque, it can choose to reemit a modified version of the event. For example, a region could collect pointer events, perform handwriting recognition on those events, and then generate the equivalent keyboard events.
All regions have parent/child relationships. A child region is always placed in front of the parent region (i.e. closer to the user), and its coordinates are relative to the parent's region.
All regions reside within the Photon coordinate space, whose dimensions are as follows:
A special region called the root region is always the region furthest away from the user. All other regions descend in some way from the root region. Once an event traveling away from the user reaches the root region, it ceases to exist.
The root region's dimensions are the width of the entire Photon coordinate space. As a result of the parent/child relationship of all regions, any region's location is ultimately related to the root region's dimensions.
|A region can be located anywhere in the event space and still have the root region as its parent.|
Events are emitted for the following reasons:
For more information on event types, see PhEvent_t in the Photon Library Reference.
Region owners can be notified of events by the Photon Manager in three different ways:
To poll, the application calls a function that asks the Photon Manager to reply immediately with either an event or a status indicating no event is available.
|Normally you should avoid polling, but you may find it beneficial on occasion. For example, an application rapidly animating a screen can poll for events as part of its stream of draw events. An application can also use polling to retrieve an event after asynchronous notification.|
For synchronous notification, the application calls a function that asks the Photon Manager to reply immediately if an event is pending, or to wait until one becomes available before replying.
With synchronous notification, an application can't block on other sources while it's waiting for the Photon Manager to reply. You should find this behavior acceptable in most cases since it causes the application to execute only when the desired events become available. But if for some reason the possibility of blocking on the Photon Manager isn't acceptable, you may consider asynchronous notification.
For asynchronous notification, the application calls a function that sets up a notification method (e.g. a signal or a pulse) that the Photon Manager activates when an event of the desired type is available. The application can then retrieve the event by polling.
With asynchronous notification, an application can block on multiple sources, including processes that aren't Photon applications.
The device region is owned by the Photon Manager, which divides the event space into two sections:
The Photon Manager uses the device region to focus pointer and keyboard events as well as to manage drag events.
As with other windowing systems, Photon has the concept of a pointer (i.e. screen cursor). This pointer is graphically represented on the screen and tracks the movements of the pointing device (e.g. a mouse or touchscreen). Drivers for pointing devices emit pointer events toward the root region.
A pointer event emitted from a driver is unfocused, or raw, until it arrives at the device region, where the Photon Manager intercepts it and then assigns it a location in the Photon coordinate space.
Assigning this location — which is known as focusing the event — controls which regions will collect the event. The Photon Manager then reemits the event with the focused location.
Because Photon emits focused, or cooked, pointer motion events in both directions from the device region, application programs as well as driver programs can be informed of pointer actions. For example, when the graphics driver collects focused pointer events, it updates the location of the pointer's graphical image on the screen.
The keyboard driver is similar to pointing device drivers, except it emits keyboard events. As with pointer events, keyboard events are unfocused until they arrive at the device region, where the Photon Manager assigns them a location (i.e. focuses them) in the Photon coordinate space.
By default, the device region sets the same focus location for both keyboard events and pointer events. Therefore, regions directly behind the screen pointer will collect focused keyboard events.
The window manager supplements the keyboard focus methods. For more information, see the section on the Photon window manager.
An application initiates dragging by emitting a drag event to the device region. Once this event is collected at the device region, the Photon Manager takes care of the interaction with the pointer (i.e. drag rectangle) until the drag operation is complete. Once completed, the device region emits a drag event to the application.
During a drag-and-drop operation, a series of events is emitted to advise the widgets involved of the operation's status. Some of these events are emitted to the source of the operation, and others to the destination. For more information, see the Drag and Drop chapter.
In Photon, drivers aren't inherently different from other applications. They're simply programs that use regions and events in a particular way to provide their services. Depending on its function, a driver is either an input driver or an output driver.
For example, the mouse and keyboard drivers are input drivers because they emit, and are the source of, hardware actions. Graphics drivers, on the other hand, are output drivers because they collect events that cause them to take action with hardware devices.
The mouse driver places a region on the user's side of the device region. It gets information from the mouse hardware and builds Photon raw pointer events that it then emits toward the root region.
When the device region collects a raw pointer event, the Photon Manager focuses it and then emits cooked events in both directions in the event space.
The keyboard driver also places a region on the user's side of the device region. The driver gets information from the keyboard hardware and builds Photon keyboard events that it then emits toward the root region.
When the device region collects keyboard events, the Photon Manager focuses those events and then reemits them toward the root region.
|The window manager supplements the default focus method provided by the device region.|
Since Photon makes no assumptions as to what type of keyboard is being used, the keyboard driver could acquire its event data on any hardware or even from another process.
Photon allows multiple input drivers and multiple output drivers to be associated with each other as an input group. This group of devices will be treated distinctly from other input groups by Photon.
To determine the current input group, call PhInputGroup(), passing to it the current event, if any.
A graphics driver places a region sensitive to draw events onto the user's side of the device region. As the driver collects draw events, it renders the graphical information on the screen. Because the collected event's rectangle set contains only those areas that need to be updated, the driver can optimize its update. (This is especially efficient if the graphics hardware can handle clipping lists directly.)
|The Photon drawing API accumulates draw requests into batches that are emitted as single draw events.|
The region a graphics driver uses can have dimensions that represent an area smaller than the entire Photon coordinate space. As a result, multiple graphics drivers can share the coordinate space by each handling different portions of it and displaying their events on different screens. And since region owners don't have to be on the same node as the Photon Manager, those graphics drivers can display their portion of the coordinate space on screens located on other computers in the network.
From an application's perspective, the Photon coordinate space always looks like a single, unified graphical space, yet it allows users to drag windows from one physical screen to another.
For example, let's say an operator in a factory control environment has a small handheld computer. If this computer were connected to network via a wireless link, the operator could walk up to a computer with a large-screen control application and drag a window from that screen onto the screen of the handheld unit. Taking the handheld computer, the operator could then walk out onto the plant floor and continue to interact with the control application to monitor and adjust equipment.
In another type of example, instead of having driver regions with exclusive portions of the coordinate space, you could have drivers using overlapping regions. This approach would let you replicate the same draw events on multiple screens, which would be ideal for support or training environments.
Since graphics drivers for Photon are really just applications, they can display the graphical output of Photon inside another windowing system (for example, the X Window System). A Photon driver could also take the keyboard and mouse events it collects from the X system and regenerate them within Photon, allowing the Photon window in the X system to be fully functional, both for graphical display and for keyboard/mouse input.
The window manager is an optional Photon application that manages the appearance and operation of menus, buttons, scrollbars, and so on. It provides the windowing system with a certain “look and feel” (e.g. Motif).
The window manager also manages the workspace, supplements the methods for focusing keyboard events, and lets you display a backdrop. To provide all these services, the window manager places several regions in the event space:
Most applications rely on the windowing system to provide the user with the means to manipulate their size, position, and state (i.e. open/iconified). In order for the user to perform these actions, the window manager puts a frame around the application's region and then places controls in that frame (e.g. resize corners, title bars, buttons). We refer to these controls as window services.
To indicate it can provide window services, the window manager registers with the Photon Manager. When an application opens a window, the window manager sets up two regions on its behalf: a window frame region and an application region (or window region). The window frame region is slightly larger than the application region and is placed just behind it.
The window manager uses the window frame region for its controls, while the application uses its own region. But the application isn't aware of the controls. If the user uses the controls to move the application, the application notices only that its location has changed. The same goes for resizing, iconifying, and so on.
As mentioned earlier, the device region focuses keyboard events to regions directly behind the screen pointer. But by placing a region of its own (i.e. the focus region) just behind the device region, the window manager intercepts these keyboard events as they're emitted from the device region and implements an alternate focus method.
The window manager can redirect keyboard events to regions not directly beneath the screen pointer. For example, it can focus events toward the last window the user “clicked” on (i.e. the active window). The window manager can direct keyboard events to that active region even if the region gets covered by another region.
From the user's perspective, the workspace is the empty space surrounding the windows on the screen. The window manager places a workspace region just in front of the root region to capture pointer events before they get to the root region and thus disappear. When the user presses a pointer button and no region collects the event, the window manager brings up a workspace menu that lets the user select a program to run.
Users often like to have an ornamental backdrop image displayed behind the windows on the screen. To display such a bitmap, the window manager places a backdrop region in the event space.