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 90 if (container.FindString(kBackgroundImageInfoPath, index, &path) != B_OK) 91 break; 92 93 BBitmap *bitmap = BTranslationUtils::GetBitmap(path); 94 if (!bitmap) { 95 // PRINT(("failed to load background bitmap from path\n")); 96 continue; 97 } 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 BackgroundImage::~BackgroundImage() 144 { 145 } 146 147 148 void 149 BackgroundImage::Add(BackgroundImageInfo *info) 150 { 151 fBitmapForWorkspaceList.AddItem(info); 152 } 153 154 void 155 BackgroundImage::Show(BView *view, int32 workspace) 156 { 157 fView = view; 158 159 BackgroundImageInfo *info = ImageInfoForWorkspace(workspace); 160 if (info) { 161 BPoseView *poseView = dynamic_cast<BPoseView *>(fView); 162 if (poseView) 163 poseView->SetWidgetTextOutline(info->fTextWidgetOutline); 164 Show(info, fView); 165 } 166 } 167 168 void 169 BackgroundImage::Show(BackgroundImageInfo *info, BView *view) 170 { 171 BRect viewBounds(view->Bounds()); 172 BRect bitmapBounds(info->fBitmap->Bounds()); 173 BRect destinationBitmapBounds(bitmapBounds); 174 175 uint32 tile = 0; 176 uint32 followFlags = B_FOLLOW_TOP | B_FOLLOW_LEFT; 177 178 // figure out the display mode and the destination bounds for the bitmap 179 switch (info->fMode) { 180 case kCentered: 181 if (fIsDesktop) { 182 destinationBitmapBounds.OffsetBy( 183 (viewBounds.Width() - bitmapBounds.Width()) / 2, 184 (viewBounds.Height() - bitmapBounds.Height()) / 2); 185 break; 186 } 187 // else fall thru 188 case kScaledToFit: 189 if (fIsDesktop) { 190 destinationBitmapBounds = viewBounds; 191 followFlags = B_FOLLOW_ALL; 192 break; 193 } 194 // else fall thru 195 case kAtOffset: 196 destinationBitmapBounds.OffsetTo(info->fOffset); 197 break; 198 case kTiled: 199 if (fIsDesktop) { 200 destinationBitmapBounds.OffsetBy( 201 (viewBounds.Width() - bitmapBounds.Width()) / 2, 202 (viewBounds.Height() - bitmapBounds.Height()) / 2); 203 } 204 tile = B_TILE_BITMAP; 205 break; 206 } 207 208 BPoseView *poseView = dynamic_cast<BPoseView *>(view); 209 if (poseView) 210 poseView->SetWidgetTextOutline(info->fTextWidgetOutline); 211 212 // switch to the bitmap and force a redraw 213 view->SetViewBitmap(info->fBitmap, bitmapBounds, destinationBitmapBounds, 214 followFlags, tile); 215 view->Invalidate(); 216 217 fShowingBitmap = info; 218 } 219 220 void 221 BackgroundImage::Remove() 222 { 223 if (fShowingBitmap) { 224 fView->ClearViewBitmap(); 225 fView->Invalidate(); 226 BPoseView *poseView = dynamic_cast<BPoseView *>(fView); 227 // make sure text widgets draw the default way, erasing their background 228 if (poseView) 229 poseView->SetWidgetTextOutline(true); 230 } 231 fShowingBitmap = NULL; 232 } 233 234 BackgroundImage::BackgroundImageInfo * 235 BackgroundImage::ImageInfoForWorkspace(int32 workspace) const 236 { 237 uint32 workspaceMask = 1; 238 239 for ( ; workspace; workspace--) 240 workspaceMask *= 2; 241 242 int32 count = fBitmapForWorkspaceList.CountItems(); 243 244 // do a simple lookup for the most likely candidate bitmap - 245 // pick the imageInfo that is only defined for this workspace over one 246 // that supports multiple workspaces 247 BackgroundImageInfo *result = NULL; 248 for (int32 index = 0; index < count; index++) { 249 BackgroundImageInfo *info = fBitmapForWorkspaceList.ItemAt(index); 250 if (info->fWorkspace == workspaceMask) 251 return info; 252 if (info->fWorkspace & workspaceMask) 253 result = info; 254 } 255 256 return result; 257 } 258 259 void 260 BackgroundImage::WorkspaceActivated(BView *view, int32 workspace, bool state) 261 { 262 if (!fIsDesktop) 263 // we only care for desktop bitmaps 264 return; 265 266 if (!state) 267 // we only care comming into a new workspace, not leaving one 268 return; 269 270 BackgroundImageInfo *info = ImageInfoForWorkspace(workspace); 271 if (info != fShowingBitmap) { 272 if (info) 273 Show(info, view); 274 else { 275 if (BPoseView *poseView = dynamic_cast<BPoseView *>(view)) 276 poseView->SetWidgetTextOutline(true); 277 view->ClearViewBitmap(); 278 view->Invalidate(); 279 } 280 fShowingBitmap = info; 281 } 282 } 283 284 void 285 BackgroundImage::ScreenChanged(BRect, color_space) 286 { 287 if (!fIsDesktop || !fShowingBitmap) 288 return; 289 290 if (fShowingBitmap->fMode == kCentered) { 291 BRect viewBounds(fView->Bounds()); 292 BRect bitmapBounds(fShowingBitmap->fBitmap->Bounds()); 293 BRect destinationBitmapBounds(bitmapBounds); 294 destinationBitmapBounds.OffsetBy( 295 (viewBounds.Width() - bitmapBounds.Width()) / 2, 296 (viewBounds.Height() - bitmapBounds.Height()) / 2); 297 298 fView->SetViewBitmap(fShowingBitmap->fBitmap, bitmapBounds, destinationBitmapBounds, 299 B_FOLLOW_NONE, 0); 300 fView->Invalidate(); 301 } 302 } 303 304 BackgroundImage * 305 BackgroundImage::Refresh(BackgroundImage *oldBackgroundImage, 306 const BNode *fromNode, bool desktop, BPoseView *poseView) 307 { 308 if (oldBackgroundImage) { 309 oldBackgroundImage->Remove(); 310 delete oldBackgroundImage; 311 } 312 313 BackgroundImage *result = GetBackgroundImage(fromNode, desktop); 314 if (result && poseView->ViewMode() != kListMode) 315 result->Show(poseView, current_workspace()); 316 317 return result; 318 } 319 320