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 #include <Message.h> 44 #include <Entry.h> 45 #include <Path.h> 46 #include <Screen.h> 47 #include <String.h> 48 49 #include <fs_attr.h> 50 #include <stdlib.h> 51 52 #include "BGView.h" 53 #include "BackgroundImage.h" 54 55 const char *kBackgroundImageInfo = "be:bgndimginfo"; 56 const char *kBackgroundImageInfoOffset = "be:bgndimginfooffset"; 57 const char *kBackgroundImageInfoEraseText = "be:bgndimginfoerasetext"; 58 const char *kBackgroundImageInfoMode = "be:bgndimginfomode"; 59 const char *kBackgroundImageInfoWorkspaces = "be:bgndimginfoworkspaces"; 60 const char *kBackgroundImageInfoPath = "be:bgndimginfopath"; 61 const char *kBackgroundImageInfoSet = "be:bgndimginfoset"; 62 const char *kBackgroundImageInfoCacheMode = "be:bgndimginfocachemode"; 63 const char *kBackgroundImageSetPeriod = "be:bgndimgsetperiod"; 64 const char *kBackgroundImageRandomChange = "be:bgndimgrandomchange"; 65 const char *kBackgroundImageCacheMode = "be:bgndimgcachemode"; 66 67 BackgroundImage * 68 BackgroundImage::GetBackgroundImage(const BNode *node, bool isDesktop, 69 BGView* view) 70 { 71 BackgroundImage *result = new BackgroundImage(node, isDesktop); 72 result->bgView = view; 73 attr_info info; 74 if (node->GetAttrInfo(kBackgroundImageInfo, &info) != B_OK) 75 return result; 76 77 BMessage container; 78 char *buffer = new char [info.size]; 79 80 status_t error = node->ReadAttr(kBackgroundImageInfo, info.type, 0, buffer, 81 (size_t)info.size); 82 if (error == info.size) 83 error = container.Unflatten(buffer); 84 85 delete [] buffer; 86 87 if (error != B_OK) 88 return NULL; 89 90 PRINT_OBJECT(container); 91 92 uint32 imageSetPeriod = 0; 93 uint32 globalCacheMode = 0; 94 bool randomChange = false; 95 uint32 maxImageSet = 0; 96 97 if(isDesktop) { 98 container.FindInt32(kBackgroundImageSetPeriod, (int32 *)&imageSetPeriod); 99 container.FindInt32(kBackgroundImageCacheMode, (int32 *)&globalCacheMode); 100 container.FindBool(kBackgroundImageRandomChange, &randomChange); 101 } 102 103 for (int32 index = 0; ; index++) { 104 const char *path; 105 uint32 workspaces = B_ALL_WORKSPACES; 106 Mode mode = kTiled; 107 bool eraseTextWidgetBackground = true; 108 BPoint offset; 109 uint32 imageSet = 0; 110 uint32 cacheMode = 0; 111 if (container.FindString(kBackgroundImageInfoPath, index, &path) != B_OK) 112 break; 113 114 BPath bpath(path); 115 int32 imageIndex = view->AddImage(bpath); 116 if(imageIndex < 0) 117 imageIndex = -imageIndex - 1; 118 119 container.FindInt32(kBackgroundImageInfoWorkspaces, index, 120 (int32 *)&workspaces); 121 container.FindInt32(kBackgroundImageInfoMode, index, (int32 *)&mode); 122 container.FindBool(kBackgroundImageInfoEraseText, index, 123 &eraseTextWidgetBackground); 124 container.FindPoint(kBackgroundImageInfoOffset, index, &offset); 125 if(isDesktop) 126 { 127 container.FindInt32(kBackgroundImageInfoSet, index, 128 (int32 *)&imageSet); 129 container.FindInt32(kBackgroundImageInfoCacheMode, index, 130 (int32 *)&cacheMode); 131 } 132 133 BackgroundImage::BackgroundImageInfo *imageInfo = new 134 BackgroundImage::BackgroundImageInfo(workspaces, imageIndex, 135 mode, offset, eraseTextWidgetBackground, imageSet, cacheMode); 136 137 //imageInfo->UnloadBitmap(globalCacheMode); 138 139 if(imageSet > maxImageSet) 140 maxImageSet = imageSet; 141 142 143 144 result->Add(imageInfo); 145 } 146 147 if(result) { 148 result->fImageSetCount = maxImageSet + 1; 149 result->fRandomChange = randomChange; 150 result->fImageSetPeriod = imageSetPeriod; 151 result->fCacheMode = globalCacheMode; 152 if(result->fImageSetCount > 1) 153 result->fShowingImageSet = random()%result->fImageSetCount; 154 } 155 156 return result; 157 } 158 159 160 BackgroundImage::BackgroundImageInfo::BackgroundImageInfo(uint32 workspaces, 161 int32 imageIndex, Mode mode, BPoint offset, bool eraseTextWidget, 162 uint32 imageSet, uint32 cacheMode) 163 : fWorkspace(workspaces), 164 fImageIndex(imageIndex), 165 fMode(mode), 166 fOffset(offset), 167 fEraseTextWidgetBackground(eraseTextWidget), 168 fImageSet(imageSet), 169 fCacheMode(cacheMode) 170 { 171 } 172 173 174 BackgroundImage::BackgroundImageInfo::~BackgroundImageInfo() 175 { 176 } 177 178 179 BackgroundImage::BackgroundImage(const BNode *node, bool desktop) 180 : fIsDesktop(desktop), 181 fDefinedByNode(*node), 182 fView(NULL), 183 fShowingBitmap(NULL), 184 fBitmapForWorkspaceList(1, true), 185 fImageSetPeriod(0), 186 fShowingImageSet(0), 187 fImageSetCount(0), 188 fCacheMode(0), 189 fRandomChange(false) 190 { 191 192 } 193 194 195 BackgroundImage::~BackgroundImage() 196 { 197 } 198 199 200 void 201 BackgroundImage::Add(BackgroundImageInfo *info) 202 { 203 fBitmapForWorkspaceList.AddItem(info); 204 } 205 206 207 void 208 BackgroundImage::RemoveAll() 209 { 210 for (int32 index = 0; index < fBitmapForWorkspaceList.CountItems();) { 211 BackgroundImageInfo *info = fBitmapForWorkspaceList.ItemAt(index); 212 if(info->fImageSet != fShowingImageSet) 213 index++; 214 else 215 fBitmapForWorkspaceList.RemoveItemAt(index); 216 } 217 } 218 219 220 void 221 BackgroundImage::Show(BView *view, int32 workspace) 222 { 223 fView = view; 224 225 BackgroundImageInfo *info = ImageInfoForWorkspace(workspace); 226 if (info) { 227 /*BPoseView *poseView = dynamic_cast<BPoseView *>(fView); 228 if (poseView) 229 poseView->SetEraseWidgetTextBackground(info->fEraseTextWidgetBackground);*/ 230 Show(info, fView); 231 232 } 233 } 234 235 236 void 237 BackgroundImage::Show(BackgroundImageInfo *info, BView *view) 238 { 239 BBitmap *bitmap = bgView->GetImage(info->fImageIndex)->GetBitmap(); 240 241 if(!bitmap) 242 return; 243 244 BRect viewBounds(view->Bounds()); 245 246 display_mode mode; 247 BScreen().GetMode(&mode); 248 float x_ratio = viewBounds.Width() / mode.virtual_width; 249 float y_ratio = viewBounds.Height() / mode.virtual_height; 250 251 BRect bitmapBounds(bitmap->Bounds()); 252 BRect destinationBitmapBounds(bitmapBounds); 253 destinationBitmapBounds.right *= x_ratio; 254 destinationBitmapBounds.bottom *= y_ratio; 255 BPoint offset(info->fOffset); 256 offset.x *= x_ratio; 257 offset.y *= y_ratio; 258 259 uint32 tile = 0; 260 uint32 followFlags = B_FOLLOW_TOP | B_FOLLOW_LEFT; 261 262 // figure out the display mode and the destination bounds for the bitmap 263 switch (info->fMode) { 264 case kCentered: 265 if (fIsDesktop) { 266 destinationBitmapBounds.OffsetBy( 267 (viewBounds.Width() - destinationBitmapBounds.Width()) / 2, 268 (viewBounds.Height() - destinationBitmapBounds.Height()) / 2); 269 break; 270 } 271 // else fall thru 272 case kScaledToFit: 273 if (fIsDesktop) { 274 destinationBitmapBounds = viewBounds; 275 followFlags = B_FOLLOW_ALL; 276 break; 277 } 278 // else fall thru 279 case kAtOffset: 280 { 281 destinationBitmapBounds.OffsetTo(offset); 282 break; 283 } 284 case kTiled: 285 // Original Backgrounds Preferences center the tiled paper but the Tracker don't do that 286 //if (fIsDesktop) { 287 destinationBitmapBounds.OffsetBy( 288 (viewBounds.Width() - destinationBitmapBounds.Width()) / 2, 289 (viewBounds.Height() - destinationBitmapBounds.Height()) / 2); 290 //} 291 tile = B_TILE_BITMAP; 292 break; 293 } 294 295 // switch to the bitmap and force a redraw 296 view->SetViewBitmap(bitmap, bitmapBounds, destinationBitmapBounds, 297 followFlags, tile); 298 view->Invalidate(); 299 300 /*if(fShowingBitmap != info) { 301 if(fShowingBitmap) 302 fShowingBitmap->UnloadBitmap(fCacheMode); 303 fShowingBitmap = info; 304 }*/ 305 } 306 307 308 void 309 BackgroundImage::Remove() 310 { 311 if (fShowingBitmap) { 312 fView->ClearViewBitmap(); 313 fView->Invalidate(); 314 /*BPoseView *poseView = dynamic_cast<BPoseView *>(fView); 315 // make sure text widgets draw the default way, erasing their background 316 if (poseView) 317 poseView->SetEraseWidgetTextBackground(true);*/ 318 } 319 fShowingBitmap = NULL; 320 } 321 322 323 BackgroundImage::BackgroundImageInfo * 324 BackgroundImage::ImageInfoForWorkspace(int32 workspace) const 325 { 326 uint32 workspaceMask = 1; 327 328 for ( ; workspace; workspace--) 329 workspaceMask *= 2; 330 331 int32 count = fBitmapForWorkspaceList.CountItems(); 332 333 // do a simple lookup for the most likely candidate bitmap - 334 // pick the imageInfo that is only defined for this workspace over one 335 // that supports multiple workspaces 336 BackgroundImageInfo *result = NULL; 337 for (int32 index = 0; index < count; index++) { 338 BackgroundImageInfo *info = fBitmapForWorkspaceList.ItemAt(index); 339 if(info->fImageSet != fShowingImageSet) 340 continue; 341 if(fIsDesktop) { 342 if (info->fWorkspace == workspaceMask) 343 return info; 344 if (info->fWorkspace & workspaceMask) 345 result = info; 346 } else 347 return info; 348 } 349 350 return result; 351 } 352 353 354 void 355 BackgroundImage::WorkspaceActivated(BView *view, int32 workspace, bool state) 356 { 357 if (!fIsDesktop) 358 // we only care for desktop bitmaps 359 return; 360 361 if (!state) 362 // we only care comming into a new workspace, not leaving one 363 return; 364 365 BackgroundImageInfo *info = ImageInfoForWorkspace(workspace); 366 if (info != fShowingBitmap) { 367 if (info) 368 Show(info, view); 369 else { 370 /*if (BPoseView *poseView = dynamic_cast<BPoseView *>(view)) 371 poseView->SetEraseWidgetTextBackground(true);*/ 372 view->ClearViewBitmap(); 373 view->Invalidate(); 374 } 375 fShowingBitmap = info; 376 } 377 } 378 379 380 void 381 BackgroundImage::ScreenChanged(BRect, color_space) 382 { 383 if (!fIsDesktop || !fShowingBitmap) 384 return; 385 386 /*if (fShowingBitmap->fMode == kCentered) { 387 BRect viewBounds(fView->Bounds()); 388 BRect bitmapBounds(fShowingBitmap->fBitmap->Bounds()); 389 BRect destinationBitmapBounds(bitmapBounds); 390 destinationBitmapBounds.OffsetBy( 391 (viewBounds.Width() - bitmapBounds.Width()) / 2, 392 (viewBounds.Height() - bitmapBounds.Height()) / 2); 393 394 fView->SetViewBitmap(fShowingBitmap->fBitmap, bitmapBounds, destinationBitmapBounds, 395 B_FOLLOW_NONE, 0); 396 fView->Invalidate(); 397 }*/ 398 } 399 400 401 status_t 402 BackgroundImage::SetBackgroundImage(BNode *node) 403 { 404 status_t err; 405 BMessage container; 406 int32 count = fBitmapForWorkspaceList.CountItems(); 407 408 for (int32 index = 0; index < count; index++) { 409 BackgroundImageInfo *info = fBitmapForWorkspaceList.ItemAt(index); 410 if(bgView->GetImage(info->fImageIndex)==NULL) 411 continue; 412 413 container.AddBool(kBackgroundImageInfoEraseText, info->fEraseTextWidgetBackground); 414 container.AddString( kBackgroundImageInfoPath, bgView->GetImage(info->fImageIndex)->GetPath().Path()); 415 container.AddInt32( kBackgroundImageInfoWorkspaces, info->fWorkspace); 416 container.AddPoint( kBackgroundImageInfoOffset, info->fOffset); 417 container.AddInt32( kBackgroundImageInfoMode, info->fMode); 418 if(fIsDesktop) { 419 container.AddInt32( kBackgroundImageInfoSet, info->fImageSet); 420 } 421 } 422 423 PRINT_OBJECT(container); 424 425 char buffer[container.FlattenedSize()]; 426 if((err = container.Flatten(buffer, container.FlattenedSize())) != B_OK) 427 return err; 428 ssize_t size = node->WriteAttr(kBackgroundImageInfo, 0, 0, buffer, container.FlattenedSize()); 429 if(size <= 0) 430 return B_ERROR; 431 return B_OK; 432 } 433 434 435 /*BackgroundImage * 436 BackgroundImage::Refresh(BackgroundImage *oldBackgroundImage, 437 const BNode *fromNode, bool desktop, BPoseView *poseView) 438 { 439 if (oldBackgroundImage) { 440 oldBackgroundImage->Remove(); 441 delete oldBackgroundImage; 442 } 443 444 BackgroundImage *result = GetBackgroundImage(fromNode, desktop); 445 if (result && poseView->ViewMode() != kListMode) 446 result->Show(poseView, current_workspace()); 447 return result; 448 } 449 450 451 void 452 BackgroundImage::ChangeImageSet(BPoseView *poseView) 453 { 454 if(fRandomChange) { 455 if(fImageSetCount > 1) { 456 uint32 oldShowingImageSet = fShowingImageSet; 457 while(oldShowingImageSet == fShowingImageSet) 458 fShowingImageSet = random()%fImageSetCount; 459 } else 460 fShowingImageSet = 0; 461 } else { 462 fShowingImageSet++; 463 if(fShowingImageSet > fImageSetCount - 1) 464 fShowingImageSet = 0; 465 } 466 467 this->Show(poseView, current_workspace()); 468 }*/ 469 470 471 Image::Image(BPath path) 472 : fBitmap(NULL), 473 fPath(path) 474 { 475 name = path.Leaf(); 476 } 477 478 479 Image::~Image() 480 { 481 if(fBitmap!=NULL) { 482 delete fBitmap; 483 fBitmap = NULL; 484 } 485 } 486 487 488 BBitmap* 489 Image::GetBitmap() 490 { 491 if(!fBitmap) 492 fBitmap = BTranslationUtils::GetBitmap(fPath.Path()); 493 return fBitmap; 494 } 495