Background Images¶
Declared in: be_apps/Tracker/Background.h
Tracker lets you put background images on each workspace on your desktop and in the background of individual Tracker folder windows.
Warning
Currently, Tracker only paints the background of a folder window when the window is in icon (or mini-icon) view mode.
Background Attributes¶
Information about the background image for a folder is stored as a
flattened BMessage
in the folder’s
B_BACKGROUND_INFO
file attribute. The
B_DESKTOP_FOLDER
directory holds the background info for
the workspaces (one flattened message per workspace).
The B_BACKGROUND_INFO
attribute’s data is a flattened
BMessage
with these fields:
Name |
Type |
Description |
---|---|---|
|
|
The full path to the image. The image needs to be in a format understood by one of the translators (see the Translation Kit) installed on the system. |
|
|
Specifies how the background is placed (tiled, centered, etc). See the list of mode constants after this table. |
|
|
If |
|
|
If true the icon label will have its background erased to the window’s background color, otherwise the label will be drawn on top of the image (which could make it difficult to read). |
|
|
A bitmask indicating which workspaces the image should be drawn on. This only applies to Desktop images. |
The B_BACKGROUND_MODE
values are:
Constant |
Description |
---|---|
|
Draw the image once at the location specified by
|
|
Center the image (only works on Desktop.) |
|
Scale the image to fit (only works on Desktop.) |
|
Tile the image to cover the entire window/Desktop. |
You can write multiple sets of these message fields into the Desktop’s
B_BACKGROUND_INFO
attribute message in order to put
different images on different workspaces. The fields are correlated by
index. Don’t put different B_BACKGROUND_IMAGE
paths onto
the same workspace though, the behavior is undefined.
For example, this is OK:
...
/* ALMOST_ALL_WORKSPACES is every workspace except the first */
const int32 ALMOST_ALL_WORKSPACES = 0xffffffff - 0x00000001;
const int32 OTHER_WORKSPACE = 0x00000001;
...
BMessage backgrounds;
/* Add the first image to ALMOST_ALL_WORKSPACES */
backgrounds.AddString( B_BACKGROUND_IMAGE, "/boot/home/nice.jpg" );
backgrounds.AddInt32( B_BACKGROUND_WORKSPACES, ALMOST_ALL_WORKSPACES );
backgrounds.AddInt32( B_BACKGROUND_MODE, B_BACKGROUND_MODE_TILED );
backgrounds.AddPoint( B_BACKGROUND_ORIGIN, BPoint( 0.0, 0.0 ) );
backgrounds.AddBool( B_BACKGROUND_ERASE_TEXT, true );
/* Add the second image to the OTHER_WORKSPACE */
backgrounds.AddString( B_BACKGROUND_IMAGE, "/boot/home/nicer.jpg" );
backgrounds.AddInt32( B_BACKGROUND_WORKSPACES, OTHER_WORKSPACE );
backgrounds.AddInt32( B_BACKGROUND_MODE, B_BACKGROUND_MODE_SCALED );
backgrounds.AddPoint( B_BACKGROUND_ORIGIN, BPoint( 0.0, 0.0 ) );
backgrounds.AddBool( B_BACKGROUND_ERASE_TEXT, true );
...
This is not OK, and results in undefined behaviour:
...
const int32 ALL_WORKSPACES = 0xffffffff;
...
BMessage backgrounds;
backgrounds.AddString( B_BACKGROUND_IMAGE, "/boot/home/nice.jpg" );
backgrounds.AddInt32( B_BACKGROUND_WORKSPACES, ALL_WORKSPACES );
/* ... other B_BACKGROUND_* data here ... */
backgrounds.AddString( B_BACKGROUND_IMAGE, "/boot/home/nicer.jpg" );
backgrounds.AddInt32( B_BACKGROUND_WORKSPACES, ALL_WORKSPACES );
/* ... other B_BACKGROUND_* data here ... */
...
Note
The B_BACKGROUND_INFO
attribute’s contents might be
extended in the future (but will remain compatible with the existing
attribute data). Be prepared to preserve any data you don’t recognize by
reading in the existing B_BACKGROUND_INFO
attribute (if
one exists).
Special Folders¶
There are two special folders you can apply attributes to:
Constant |
Description |
---|---|
|
Applying the |
Tracker/DefaultFolderTemplate
inside |
Applying the |
Notifying Tracker¶
Once you’ve written an appropriate B_BACKGROUND_INFO
attribute, you’ll want to tell the Tracker to pick up the new background
image.
Send the Tracker’s main looper (remember, the Tracker’s signature is
“application/x-vnd.Be-TRAK”) a BMessage with a what of
B_RESTORE_BACKGROUND_IMAGE
to tell it to reload the
desktop background image.
Sending the same message to the looper for a specific Tracker window will tell that window to reload its background image. This is a little trickier because you need to find the right window.
Refreshing All Windows¶
Taking the shotgun approach, you can tell all of the open Tracker windows to repaint their backgrounds by using Tracker scripting (see Scripting in the Application Kit). You’ll need to do this if you change the default folder background image.
This code asks the Tracker for windows that have a “Poses” property and
sends them a B_RESTORE_BACKGROUND_IMAGE
. This updates
every Tracker window that’s displaying a folder’s contents.
BMessenger tracker( "application/x-vnd.Be-TRAK" );
int32 i = 0;
BMessage reply;
int32 err;
do {
/* scripting message */
BMessage msg( B_GET_PROPERTY );
/* look at the "Poses" in every Tracker window */
msg.AddSpecifier( "Poses" );
msg.AddSpecifier( "Window", i++ );
reply.MakeEmpty();
tracker.SendMessage( &msg, &reply );
/* break out of the loop when we're at the end of
* the windows
*/
if( reply.what == B_MESSAGE_NOT_UNDERSTOOD &&
reply.FindInt32( "error", &err ) == B_OK &&
err == B_BAD_INDEX )
break;
/* don't stop for windows that don't understand
* a request for "Poses"; they're not displaying
* folders
*/
if( reply.what == B_MESSAGE_NOT_UNDERSTOOD &&
reply.FindInt32( "error", &err ) == B_OK &&
err != B_BAD_SCRIPT_SYNTAX )
continue;
BMessenger m;
if( reply.FindMessenger( "result", &m ) == B_OK) {
/* m is the messenger of a Tracker window with
* a folder inside
*/
m.SendMessage( B_RESTORE_BACKGROUND_IMAGE );
}
} while( true );
Refreshing One Window¶
If want to refresh the background of the folder you’ve changed, you scan
through the open folders using code similar to the above, until you find
the folder with the “Path” you’re interested in. Once you’ve got the right
window, you send it a B_RESTORE_BACKGROUND_IMAGE
message.
Using this technique is nicer (from the user’s point of view) because only
one Tracker window gets updated.
Here’s the same code, modified to target a specific path. Assume you’ve
still got the path in question in the_path (you just used it as a
B_BACKGROUND_IMAGE
):
BMessenger tracker( "application/x-vnd.Be-TRAK" );
/* CHANGE: we'll increment "i" at the start of the loop
* now; this lets us use it later when we find
* a Window with a Poses
*/
int32 i = -1;
BMessage reply;
int32 err;
do {
/* CHANGE: */
i++;
/* scripting message */
BMessage msg( B_GET_PROPERTY );
/* look at the "Poses" in every Tracker window */
msg.AddSpecifier( "Poses" );
msg.AddSpecifier( "Window", i ); /* CHANGE */
reply.MakeEmpty();
tracker.SendMessage( &msg, &reply );
/* break out of the loop when we're at the end of
* the windows
*/
if( reply.what == B_MESSAGE_NOT_UNDERSTOOD &&
reply.FindInt32( "error", &err ) == B_OK &&
err == B_BAD_INDEX )
break;
/* don't stop for windows that don't understand
* a request for "Poses"; they're not displaying
* folders
*/
if( reply.what == B_MESSAGE_NOT_UNDERSTOOD &&
reply.FindInt32( "error", &err ) == B_OK &&
err != B_BAD_SCRIPT_SYNTAX )
continue;
/* CHANGE: everything from here down is new */
/* make a messenger to this window */
BMessenger m;
if( reply.FindMessenger( "result", &m ) != B_OK) continue;
/* found a Window with a Poses, ask for its Path */
msg.MakeEmpty();
msg.what = B_GET_PROPERTY;
msg.AddSpecifier( "Path" );
msg.AddSpecifier( "Poses" );
msg.AddSpecifier( "Window", i );
reply.MakeEmpty();
tracker.SendMessage( &msg, &reply );
/* go on with the next if this din't have a Path */
if( reply.what == B_MESSAGE_NOT_UNDERSTOOD ) continue;
/* dig out the Path */
entry_ref ref;
if( reply.FindRef( "result", &ref ) == B_OK ) {
BEntry ent( &ref );
BPath path( &ent );
/* these are not the Paths you're looking for */
if( strcmp( the_path, path.Path() ) ) continue;
}
/* if you got this far, you have a messenger to a valid Tracker
* window displaying a folder with the path you were after,
* so tell it to refresh its background
*/
m.SendMessage( B_RESTORE_BACKGROUND_IMAGE );
} while( true );