RemoteDrawingEngine: Reduce RP_READ_BITMAP result timeout.
[haiku.git] / src / kits / tracker / BackgroundImage.cpp
blobd0dbd43ab3c02c4f1f50693a099cfc7d6e1c08ba
1 /*
2 Open Tracker License
4 Terms and Conditions
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
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:
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.
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.
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.
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.
35 // Classes used for setting up and managing background images
38 #include <Bitmap.h>
39 #include <ControlLook.h>
40 #include <Node.h>
41 #include <TranslationKit.h>
42 #include <View.h>
43 #include <Window.h>
45 #include <fs_attr.h>
47 #include "BackgroundImage.h"
49 #include "Background.h"
50 #include "Commands.h"
51 #include "PoseView.h"
54 namespace BPrivate {
56 const char* kBackgroundImageInfo = B_BACKGROUND_INFO;
57 const char* kBackgroundImageInfoOffset = B_BACKGROUND_ORIGIN;
58 const char* kBackgroundImageInfoTextOutline = B_BACKGROUND_TEXT_OUTLINE;
59 const char* kBackgroundImageInfoMode = B_BACKGROUND_MODE;
60 const char* kBackgroundImageInfoWorkspaces = B_BACKGROUND_WORKSPACES;
61 const char* kBackgroundImageInfoPath = B_BACKGROUND_IMAGE;
63 } // namespace BPrivate
66 // #pragma mark - BackgroundImage
69 BackgroundImage*
70 BackgroundImage::GetBackgroundImage(const BNode* node, bool isDesktop)
72 attr_info info;
73 if (node->GetAttrInfo(kBackgroundImageInfo, &info) != B_OK)
74 return NULL;
76 BMessage container;
77 char* buffer = new char[info.size];
79 status_t error = node->ReadAttr(kBackgroundImageInfo, info.type, 0,
80 buffer, (size_t)info.size);
81 if (error == info.size)
82 error = container.Unflatten(buffer);
84 delete[] buffer;
86 if (error != B_OK)
87 return NULL;
89 BackgroundImage* backgroundImage = NULL;
90 for (int32 index = 0; ; index++) {
91 const char* path;
92 uint32 workspaces = B_ALL_WORKSPACES;
93 Mode mode = kTiled;
94 bool textWidgetLabelOutline = false;
95 BPoint offset;
96 BBitmap* bitmap = NULL;
98 if (container.FindString(kBackgroundImageInfoPath, index, &path)
99 == B_OK) {
100 bitmap = BTranslationUtils::GetBitmap(path);
101 if (!bitmap)
102 PRINT(("failed to load background bitmap from path\n"));
103 } else
104 break;
106 if (isDesktop)
107 be_control_look->SetBackgroundInfo(container);
109 container.FindInt32(kBackgroundImageInfoWorkspaces, index,
110 (int32*)&workspaces);
111 container.FindInt32(kBackgroundImageInfoMode, index, (int32*)&mode);
112 container.FindBool(kBackgroundImageInfoTextOutline, index,
113 &textWidgetLabelOutline);
114 container.FindPoint(kBackgroundImageInfoOffset, index, &offset);
116 BackgroundImage::BackgroundImageInfo* imageInfo = new
117 BackgroundImage::BackgroundImageInfo(workspaces, bitmap, mode,
118 offset, textWidgetLabelOutline);
120 if (backgroundImage == NULL)
121 backgroundImage = new BackgroundImage(node, isDesktop);
123 backgroundImage->Add(imageInfo);
126 return backgroundImage;
130 BackgroundImage::BackgroundImageInfo::BackgroundImageInfo(uint32 workspaces,
131 BBitmap* bitmap, Mode mode, BPoint offset, bool textWidgetOutline)
133 fWorkspace(workspaces),
134 fBitmap(bitmap),
135 fMode(mode),
136 fOffset(offset),
137 fTextWidgetOutline(textWidgetOutline)
142 BackgroundImage::BackgroundImageInfo::~BackgroundImageInfo()
144 delete fBitmap;
148 BackgroundImage::BackgroundImage(const BNode* node, bool desktop)
150 fIsDesktop(desktop),
151 fDefinedByNode(*node),
152 fView(NULL),
153 fShowingBitmap(NULL),
154 fBitmapForWorkspaceList(1, true)
159 BackgroundImage::~BackgroundImage()
164 void
165 BackgroundImage::Add(BackgroundImageInfo* info)
167 fBitmapForWorkspaceList.AddItem(info);
171 void
172 BackgroundImage::Show(BView* view, int32 workspace)
174 fView = view;
176 BackgroundImageInfo* info = ImageInfoForWorkspace(workspace);
177 if (info) {
178 BPoseView* poseView = dynamic_cast<BPoseView*>(fView);
179 if (poseView != NULL)
180 poseView->SetWidgetTextOutline(info->fTextWidgetOutline);
182 Show(info, fView);
187 void
188 BackgroundImage::Show(BackgroundImageInfo* info, BView* view)
190 BPoseView* poseView = dynamic_cast<BPoseView*>(view);
191 if (poseView != NULL)
192 poseView->SetWidgetTextOutline(info->fTextWidgetOutline);
194 if (info->fBitmap == NULL) {
195 view->ClearViewBitmap();
196 view->Invalidate();
197 fShowingBitmap = info;
198 return;
200 BRect viewBounds(view->Bounds());
201 BRect bitmapBounds(info->fBitmap->Bounds());
202 BRect destinationBitmapBounds(bitmapBounds);
204 uint32 options = 0;
205 uint32 followFlags = B_FOLLOW_TOP | B_FOLLOW_LEFT;
207 // figure out the display mode and the destination bounds for the bitmap
208 switch (info->fMode) {
209 case kCentered:
210 if (fIsDesktop) {
211 destinationBitmapBounds.OffsetBy(
212 (viewBounds.Width() - bitmapBounds.Width()) / 2,
213 (viewBounds.Height() - bitmapBounds.Height()) / 2);
214 break;
216 // else fall thru
217 case kScaledToFit:
218 if (fIsDesktop) {
219 if (BRectRatio(destinationBitmapBounds)
220 >= BRectRatio(viewBounds)) {
221 float overlap = BRectHorizontalOverlap(viewBounds,
222 destinationBitmapBounds);
223 destinationBitmapBounds.Set(-overlap, 0,
224 viewBounds.Width() + overlap, viewBounds.Height());
225 } else {
226 float overlap = BRectVerticalOverlap(viewBounds,
227 destinationBitmapBounds);
228 destinationBitmapBounds.Set(0, -overlap,
229 viewBounds.Width(), viewBounds.Height() + overlap);
231 followFlags = B_FOLLOW_ALL;
232 options |= B_FILTER_BITMAP_BILINEAR;
233 break;
235 // else fall thru
236 case kAtOffset:
237 destinationBitmapBounds.OffsetTo(info->fOffset);
238 break;
240 case kTiled:
241 if (fIsDesktop) {
242 destinationBitmapBounds.OffsetBy(
243 (viewBounds.Width() - bitmapBounds.Width()) / 2,
244 (viewBounds.Height() - bitmapBounds.Height()) / 2);
246 options |= B_TILE_BITMAP;
247 break;
250 // switch to the bitmap and force a redraw
251 view->SetViewBitmap(info->fBitmap, bitmapBounds, destinationBitmapBounds,
252 followFlags, options);
253 view->Invalidate();
254 fShowingBitmap = info;
258 float
259 BackgroundImage::BRectRatio(BRect rect)
261 return rect.Width() / rect.Height();
265 float
266 BackgroundImage::BRectHorizontalOverlap(BRect hostRect, BRect resizedRect)
268 return ((hostRect.Height() / resizedRect.Height() * resizedRect.Width())
269 - hostRect.Width()) / 2;
273 float
274 BackgroundImage::BRectVerticalOverlap(BRect hostRect, BRect resizedRect)
276 return ((hostRect.Width() / resizedRect.Width() * resizedRect.Height())
277 - hostRect.Height()) / 2;
281 void
282 BackgroundImage::Remove()
284 if (fShowingBitmap != NULL) {
285 fView->ClearViewBitmap();
286 fView->Invalidate();
287 BPoseView* poseView = dynamic_cast<BPoseView*>(fView);
288 // make sure text widgets draw the default way, erasing
289 // their background
290 if (poseView != NULL)
291 poseView->SetWidgetTextOutline(true);
294 fShowingBitmap = NULL;
298 BackgroundImage::BackgroundImageInfo*
299 BackgroundImage::ImageInfoForWorkspace(int32 workspace) const
301 uint32 workspaceMask = 1;
303 for ( ; workspace; workspace--)
304 workspaceMask *= 2;
306 int32 count = fBitmapForWorkspaceList.CountItems();
308 // do a simple lookup for the most likely candidate bitmap -
309 // pick the imageInfo that is only defined for this workspace over one
310 // that supports multiple workspaces
311 BackgroundImageInfo* result = NULL;
312 for (int32 index = 0; index < count; index++) {
313 BackgroundImageInfo* info = fBitmapForWorkspaceList.ItemAt(index);
314 if (info->fWorkspace == workspaceMask)
315 return info;
317 if (info->fWorkspace & workspaceMask)
318 result = info;
321 return result;
325 void
326 BackgroundImage::WorkspaceActivated(BView* view, int32 workspace, bool state)
328 if (!fIsDesktop) {
329 // we only care for desktop bitmaps
330 return;
333 if (!state) {
334 // we only care comming into a new workspace, not leaving one
335 return;
338 BackgroundImageInfo* info = ImageInfoForWorkspace(workspace);
339 if (info != fShowingBitmap) {
340 if (info != NULL)
341 Show(info, view);
342 else {
343 BPoseView* poseView = dynamic_cast<BPoseView*>(view);
344 if (poseView != NULL)
345 poseView->SetWidgetTextOutline(true);
347 view->ClearViewBitmap();
348 view->Invalidate();
351 fShowingBitmap = info;
356 void
357 BackgroundImage::ScreenChanged(BRect, color_space)
359 if (!fIsDesktop || fShowingBitmap == NULL)
360 return;
362 if (fShowingBitmap->fMode == kCentered) {
363 BRect viewBounds(fView->Bounds());
364 BRect bitmapBounds(fShowingBitmap->fBitmap->Bounds());
365 BRect destinationBitmapBounds(bitmapBounds);
366 destinationBitmapBounds.OffsetBy(
367 (viewBounds.Width() - bitmapBounds.Width()) / 2,
368 (viewBounds.Height() - bitmapBounds.Height()) / 2);
370 fView->SetViewBitmap(fShowingBitmap->fBitmap, bitmapBounds,
371 destinationBitmapBounds, B_FOLLOW_NONE, 0);
372 fView->Invalidate();
377 BackgroundImage*
378 BackgroundImage::Refresh(BackgroundImage* oldBackgroundImage,
379 const BNode* fromNode, bool desktop, BPoseView* poseView)
381 if (oldBackgroundImage != NULL) {
382 oldBackgroundImage->Remove();
383 delete oldBackgroundImage;
386 BackgroundImage* backgroundImage = GetBackgroundImage(fromNode, desktop);
387 if (backgroundImage != NULL && poseView->ViewMode() != kListMode)
388 backgroundImage->Show(poseView, current_workspace());
390 return backgroundImage;