1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 35 // Classes used for setting up and managing background images 36 // 37 38 #include <Bitmap.h> 39 #include <Node.h> 40 #include <TranslationKit.h> 41 #include <View.h> 42 #include <Window.h> 43 44 #include <fs_attr.h> 45 46 #include "BackgroundImage.h" 47 48 #include "Background.h" 49 #include "Commands.h" 50 #include "PoseView.h" 51 52 namespace BPrivate { 53 54 const char *kBackgroundImageInfo = B_BACKGROUND_INFO; 55 const char *kBackgroundImageInfoOffset = B_BACKGROUND_ORIGIN; 56 const char *kBackgroundImageInfoTextOutline = B_BACKGROUND_TEXT_OUTLINE; 57 const char *kBackgroundImageInfoMode = B_BACKGROUND_MODE; 58 const char *kBackgroundImageInfoWorkspaces = B_BACKGROUND_WORKSPACES; 59 const char *kBackgroundImageInfoPath = B_BACKGROUND_IMAGE; 60 61 } 62 63 BackgroundImage * 64 BackgroundImage::GetBackgroundImage(const BNode *node, bool isDesktop) 65 { 66 attr_info info; 67 if (node->GetAttrInfo(kBackgroundImageInfo, &info) != B_OK) 68 return NULL; 69 70 BMessage container; 71 char *buffer = new char [info.size]; 72 73 status_t error = node->ReadAttr(kBackgroundImageInfo, info.type, 0, buffer, (size_t)info.size); 74 if (error == info.size) 75 error = container.Unflatten(buffer); 76 77 delete [] buffer; 78 79 if (error != B_OK) 80 return NULL; 81 82 BackgroundImage *result = NULL; 83 for (int32 index = 0; ; index++) { 84 const char *path; 85 uint32 workspaces = B_ALL_WORKSPACES; 86 Mode mode = kTiled; 87 bool textWidgetLabelOutline = false; 88 BPoint offset; 89 BBitmap *bitmap = NULL; 90 91 if (container.FindString(kBackgroundImageInfoPath, index, &path) == B_OK) { 92 bitmap = BTranslationUtils::GetBitmap(path); 93 if (!bitmap) { 94 PRINT(("failed to load background bitmap from path\n")); 95 } 96 } else 97 break; 98 99 container.FindInt32(kBackgroundImageInfoWorkspaces, index, (int32 *)&workspaces); 100 container.FindInt32(kBackgroundImageInfoMode, index, (int32 *)&mode); 101 container.FindBool(kBackgroundImageInfoTextOutline, index, &textWidgetLabelOutline); 102 container.FindPoint(kBackgroundImageInfoOffset, index, &offset); 103 104 BackgroundImage::BackgroundImageInfo *imageInfo = new 105 BackgroundImage::BackgroundImageInfo(workspaces, bitmap, mode, offset, 106 textWidgetLabelOutline); 107 108 if (!result) 109 result = new BackgroundImage(node, isDesktop); 110 111 result->Add(imageInfo); 112 } 113 return result; 114 } 115 116 117 BackgroundImage::BackgroundImageInfo::BackgroundImageInfo(uint32 workspaces, 118 BBitmap *bitmap, Mode mode, BPoint offset, bool textWidgetOutline) 119 : fWorkspace(workspaces), 120 fBitmap(bitmap), 121 fMode(mode), 122 fOffset(offset), 123 fTextWidgetOutline(textWidgetOutline) 124 { 125 } 126 127 128 BackgroundImage::BackgroundImageInfo::~BackgroundImageInfo() 129 { 130 delete fBitmap; 131 } 132 133 134 BackgroundImage::BackgroundImage(const BNode *node, bool desktop) 135 : fIsDesktop(desktop), 136 fDefinedByNode(*node), 137 fView(NULL), 138 fShowingBitmap(NULL), 139 fBitmapForWorkspaceList(1, true) 140 { 141 } 142 143 144 BackgroundImage::~BackgroundImage() 145 { 146 } 147 148 149 void 150 BackgroundImage::Add(BackgroundImageInfo *info) 151 { 152 fBitmapForWorkspaceList.AddItem(info); 153 } 154 155 156 void 157 BackgroundImage::Show(BView *view, int32 workspace) 158 { 159 fView = view; 160 161 BackgroundImageInfo *info = ImageInfoForWorkspace(workspace); 162 if (info) { 163 BPoseView *poseView = dynamic_cast<BPoseView *>(fView); 164 if (poseView) 165 poseView->SetWidgetTextOutline(info->fTextWidgetOutline); 166 Show(info, fView); 167 } 168 } 169 170 void 171 BackgroundImage::Show(BackgroundImageInfo *info, BView *view) 172 { 173 BPoseView *poseView = dynamic_cast<BPoseView *>(view); 174 if (poseView) 175 poseView->SetWidgetTextOutline(info->fTextWidgetOutline); 176 177 if (info->fBitmap == NULL) { 178 view->ClearViewBitmap(); 179 view->Invalidate(); 180 fShowingBitmap = info; 181 return; 182 } 183 BRect viewBounds(view->Bounds()); 184 BRect bitmapBounds(info->fBitmap->Bounds()); 185 BRect destinationBitmapBounds(bitmapBounds); 186 187 uint32 tile = 0; 188 uint32 followFlags = B_FOLLOW_TOP | B_FOLLOW_LEFT; 189 190 // figure out the display mode and the destination bounds for the bitmap 191 switch (info->fMode) { 192 case kCentered: 193 if (fIsDesktop) { 194 destinationBitmapBounds.OffsetBy( 195 (viewBounds.Width() - bitmapBounds.Width()) / 2, 196 (viewBounds.Height() - bitmapBounds.Height()) / 2); 197 break; 198 } 199 // else fall thru 200 case kScaledToFit: 201 if (fIsDesktop) { 202 destinationBitmapBounds = viewBounds; 203 followFlags = B_FOLLOW_ALL; 204 break; 205 } 206 // else fall thru 207 case kAtOffset: 208 destinationBitmapBounds.OffsetTo(info->fOffset); 209 break; 210 case kTiled: 211 if (fIsDesktop) { 212 destinationBitmapBounds.OffsetBy( 213 (viewBounds.Width() - bitmapBounds.Width()) / 2, 214 (viewBounds.Height() - bitmapBounds.Height()) / 2); 215 } 216 tile = B_TILE_BITMAP; 217 break; 218 } 219 220 // switch to the bitmap and force a redraw 221 view->SetViewBitmap(info->fBitmap, bitmapBounds, destinationBitmapBounds, 222 followFlags, tile); 223 view->Invalidate(); 224 fShowingBitmap = info; 225 } 226 227 void 228 BackgroundImage::Remove() 229 { 230 if (fShowingBitmap) { 231 fView->ClearViewBitmap(); 232 fView->Invalidate(); 233 BPoseView *poseView = dynamic_cast<BPoseView *>(fView); 234 // make sure text widgets draw the default way, erasing their background 235 if (poseView) 236 poseView->SetWidgetTextOutline(true); 237 } 238 fShowingBitmap = NULL; 239 } 240 241 BackgroundImage::BackgroundImageInfo * 242 BackgroundImage::ImageInfoForWorkspace(int32 workspace) const 243 { 244 uint32 workspaceMask = 1; 245 246 for ( ; workspace; workspace--) 247 workspaceMask *= 2; 248 249 int32 count = fBitmapForWorkspaceList.CountItems(); 250 251 // do a simple lookup for the most likely candidate bitmap - 252 // pick the imageInfo that is only defined for this workspace over one 253 // that supports multiple workspaces 254 BackgroundImageInfo *result = NULL; 255 for (int32 index = 0; index < count; index++) { 256 BackgroundImageInfo *info = fBitmapForWorkspaceList.ItemAt(index); 257 if (info->fWorkspace == workspaceMask) 258 return info; 259 if (info->fWorkspace & workspaceMask) 260 result = info; 261 } 262 263 return result; 264 } 265 266 void 267 BackgroundImage::WorkspaceActivated(BView *view, int32 workspace, bool state) 268 { 269 if (!fIsDesktop) 270 // we only care for desktop bitmaps 271 return; 272 273 if (!state) 274 // we only care comming into a new workspace, not leaving one 275 return; 276 277 BackgroundImageInfo *info = ImageInfoForWorkspace(workspace); 278 279 if (info != fShowingBitmap) { 280 if (info) 281 Show(info, view); 282 else { 283 if (BPoseView *poseView = dynamic_cast<BPoseView *>(view)) 284 poseView->SetWidgetTextOutline(true); 285 view->ClearViewBitmap(); 286 view->Invalidate(); 287 } 288 fShowingBitmap = info; 289 } 290 } 291 292 void 293 BackgroundImage::ScreenChanged(BRect, color_space) 294 { 295 if (!fIsDesktop || !fShowingBitmap) 296 return; 297 298 if (fShowingBitmap->fMode == kCentered) { 299 BRect viewBounds(fView->Bounds()); 300 BRect bitmapBounds(fShowingBitmap->fBitmap->Bounds()); 301 BRect destinationBitmapBounds(bitmapBounds); 302 destinationBitmapBounds.OffsetBy( 303 (viewBounds.Width() - bitmapBounds.Width()) / 2, 304 (viewBounds.Height() - bitmapBounds.Height()) / 2); 305 306 fView->SetViewBitmap(fShowingBitmap->fBitmap, bitmapBounds, destinationBitmapBounds, 307 B_FOLLOW_NONE, 0); 308 fView->Invalidate(); 309 } 310 } 311 312 BackgroundImage * 313 BackgroundImage::Refresh(BackgroundImage *oldBackgroundImage, 314 const BNode *fromNode, bool desktop, BPoseView *poseView) 315 { 316 if (oldBackgroundImage) { 317 oldBackgroundImage->Remove(); 318 delete oldBackgroundImage; 319 } 320 321 BackgroundImage *result = GetBackgroundImage(fromNode, desktop); 322 if (result && poseView->ViewMode() != kListMode) 323 result->Show(poseView, current_workspace()); 324 325 return result; 326 } 327 328