1 /* 2 * Copyright Karsten Heimrich, host.haiku@gmx.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 #include "ScreenshotWindow.h" 7 8 #include "PNGDump.h" 9 10 11 #include <Application.h> 12 #include <Bitmap.h> 13 #include <Box.h> 14 #include <BitmapStream.h> 15 #include <Button.h> 16 #include <CardLayout.h> 17 #include <CheckBox.h> 18 #include <Directory.h> 19 #include <Entry.h> 20 #include <File.h> 21 #include <FindDirectory.h> 22 #include <FilePanel.h> 23 #include <GridLayoutBuilder.h> 24 #include <GroupLayoutBuilder.h> 25 #include <LayoutItem.h> 26 #include <Menu.h> 27 #include <MenuField.h> 28 #include <MenuItem.h> 29 #include <Message.h> 30 #include <NodeInfo.h> 31 #include <Path.h> 32 #include <RadioButton.h> 33 #include <Screen.h> 34 #include <String.h> 35 #include <StringView.h> 36 #include <SpaceLayoutItem.h> 37 #include <TextControl.h> 38 #include <TranslatorFormats.h> 39 #include <TranslationUtils.h> 40 #include <TranslatorRoster.h> 41 #include <View.h> 42 #include <WindowInfo.h> 43 44 45 #include <stdio.h> 46 #include <stdlib.h> 47 48 49 enum { 50 kScreenshotType, 51 kIncludeBorder, 52 kShowCursor, 53 kBackToSave, 54 kTakeScreenshot, 55 kImageOutputFormat, 56 kLocationChanged, 57 kChooseLocation, 58 kFinishScreenshot, 59 kShowOptions 60 }; 61 62 63 // #pragma mark - DirectoryRefFilter 64 65 66 class DirectoryRefFilter : public BRefFilter { 67 public: 68 virtual ~DirectoryRefFilter() {} 69 bool Filter(const entry_ref* ref, BNode* node, struct stat* stat, 70 const char* filetype) 71 { 72 return node->IsDirectory(); 73 } 74 }; 75 76 77 // #pragma mark - ScreenshotWindow 78 79 80 ScreenshotWindow::ScreenshotWindow(bigtime_t delay, bool includeBorder, 81 bool includeCursor, bool grabActiveWindow, bool showConfigWindow, 82 bool saveScreenshotSilent) 83 : BWindow(BRect(0, 0, 200.0, 100.0), "Take Screenshot", B_TITLED_WINDOW, 84 B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_QUIT_ON_WINDOW_CLOSE | 85 B_AVOID_FRONT | B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE), 86 fDelayControl(NULL), 87 fScreenshot(NULL), 88 fOutputPathPanel(NULL), 89 fLastSelectedPath(NULL), 90 fDelay(delay), 91 fIncludeBorder(includeBorder), 92 fIncludeCursor(includeCursor), 93 fGrabActiveWindow(grabActiveWindow), 94 fShowConfigWindow(showConfigWindow) 95 { 96 if (saveScreenshotSilent) { 97 _TakeScreenshot(); 98 _SaveScreenshotSilent(); 99 be_app_messenger.SendMessage(B_QUIT_REQUESTED); 100 } else { 101 _InitWindow(); 102 _CenterAndShow(); 103 } 104 } 105 106 107 ScreenshotWindow::~ScreenshotWindow() 108 { 109 if (fOutputPathPanel) 110 delete fOutputPathPanel->RefFilter(); 111 112 delete fScreenshot; 113 delete fOutputPathPanel; 114 } 115 116 117 void 118 ScreenshotWindow::MessageReceived(BMessage* message) 119 { 120 switch (message->what) { 121 case kScreenshotType: { 122 fGrabActiveWindow = false; 123 if (fActiveWindow->Value() == B_CONTROL_ON) 124 fGrabActiveWindow = true; 125 fWindowBorder->SetEnabled(fGrabActiveWindow); 126 } break; 127 128 case kIncludeBorder: { 129 fIncludeBorder = (fWindowBorder->Value() == B_CONTROL_ON); 130 } break; 131 132 case kShowCursor: { 133 fIncludeCursor = (fShowCursor->Value() == B_CONTROL_ON); 134 } break; 135 136 case kBackToSave: { 137 BCardLayout* layout = dynamic_cast<BCardLayout*> (GetLayout()); 138 if (layout) 139 layout->SetVisibleItem(1L); 140 SetTitle("Save Screenshot"); 141 } break; 142 143 case kTakeScreenshot: { 144 Hide(); 145 _TakeScreenshot(); 146 _UpdatePreviewPanel(); 147 Show(); 148 } break; 149 150 case kImageOutputFormat: { 151 message->FindInt32("be:type", &fImageFileType); 152 message->FindInt32("be:translator", &fTranslator); 153 } break; 154 155 case kLocationChanged: { 156 void* source = NULL; 157 if (message->FindPointer("source", &source) == B_OK) 158 fLastSelectedPath = static_cast<BMenuItem*> (source); 159 160 const char* text = fNameControl->Text(); 161 fNameControl->SetText(_FindValidFileName(text).String()); 162 } break; 163 164 case kChooseLocation: { 165 if (!fOutputPathPanel) { 166 BMessenger target(this); 167 fOutputPathPanel = new BFilePanel(B_OPEN_PANEL, &target, 168 NULL, B_DIRECTORY_NODE, false, NULL, new DirectoryRefFilter()); 169 fOutputPathPanel->Window()->SetTitle("Choose directory"); 170 fOutputPathPanel->SetButtonLabel(B_DEFAULT_BUTTON, "Select"); 171 } 172 fOutputPathPanel->Show(); 173 } break; 174 175 case B_CANCEL: { 176 fLastSelectedPath->SetMarked(true); 177 } break; 178 179 case B_REFS_RECEIVED: { 180 entry_ref ref; 181 if (message->FindRef("refs", &ref) == B_OK) { 182 BString path(BPath(&ref).Path()); 183 int32 index = _PathIndexInMenu(path); 184 if (index < 0) { 185 _AddItemToPathMenu(path.String(), 186 path, fOutputPathMenu->CountItems() - 2, true); 187 } else { 188 fOutputPathMenu->ItemAt(index)->SetMarked(true); 189 } 190 } 191 } break; 192 193 case kFinishScreenshot: 194 _WriteSettings(); 195 _SaveScreenshot(); 196 197 // fall through 198 case B_QUIT_REQUESTED: 199 be_app_messenger.SendMessage(B_QUIT_REQUESTED); 200 break; 201 202 case kShowOptions: { 203 BCardLayout* layout = dynamic_cast<BCardLayout*> (GetLayout()); 204 if (layout) 205 layout->SetVisibleItem(0L); 206 SetTitle("Take Screenshot"); 207 fBackToSave->SetEnabled(true); 208 } break; 209 210 default: { 211 BWindow::MessageReceived(message); 212 } break; 213 }; 214 215 } 216 217 218 void 219 ScreenshotWindow::_InitWindow() 220 { 221 BCardLayout* layout = new BCardLayout(); 222 SetLayout(layout); 223 224 _SetupFirstLayoutItem(layout); 225 _SetupSecondLayoutItem(layout); 226 227 if (!fShowConfigWindow) { 228 _TakeScreenshot(); 229 _UpdatePreviewPanel(); 230 layout->SetVisibleItem(1L); 231 } else { 232 layout->SetVisibleItem(0L); 233 } 234 } 235 236 237 void 238 ScreenshotWindow::_SetupFirstLayoutItem(BCardLayout* layout) 239 { 240 BStringView* stringView = new BStringView("", "Options"); 241 stringView->SetFont(be_bold_font); 242 stringView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 243 244 fActiveWindow = new BRadioButton("Take active window", 245 new BMessage(kScreenshotType)); 246 fWholeDesktop = new BRadioButton("Take whole Desktop", 247 new BMessage(kScreenshotType)); 248 fWholeDesktop->SetValue(B_CONTROL_ON); 249 250 BString delay; 251 delay << fDelay / 1000000; 252 fDelayControl = new BTextControl("", "Take screenshot after a delay of", 253 delay.String(), NULL); 254 _DisallowChar(fDelayControl->TextView()); 255 fDelayControl->TextView()->SetAlignment(B_ALIGN_RIGHT); 256 257 BStringView* stringView2 = new BStringView("", "seconds"); 258 stringView2->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); 259 260 fWindowBorder = new BCheckBox("Include window border", 261 new BMessage(kIncludeBorder)); 262 fWindowBorder->SetEnabled(false); 263 264 fShowCursor = new BCheckBox("Include cursor in screenshot", 265 new BMessage(kShowCursor)); 266 fShowCursor->SetValue(fIncludeCursor); 267 268 BBox* divider = new BBox(B_FANCY_BORDER, NULL); 269 divider->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1)); 270 271 fBackToSave = new BButton("", "Back to save", new BMessage(kBackToSave)); 272 fBackToSave->SetEnabled(false); 273 274 fTakeScreenshot = new BButton("", "Take Screenshot", 275 new BMessage(kTakeScreenshot)); 276 277 layout->AddView(0, BGroupLayoutBuilder(B_VERTICAL) 278 .Add(stringView) 279 .Add(BGridLayoutBuilder() 280 .Add(BSpaceLayoutItem::CreateHorizontalStrut(15.0), 0, 0) 281 .Add(fWholeDesktop, 1, 0) 282 .Add(BSpaceLayoutItem::CreateHorizontalStrut(15.0), 0, 1) 283 .Add(fActiveWindow, 1, 1) 284 .SetInsets(0.0, 5.0, 0.0, 0.0)) 285 .AddGroup(B_HORIZONTAL) 286 .AddStrut(30.0) 287 .Add(fWindowBorder) 288 .End() 289 .AddStrut(10.0) 290 .AddGroup(B_HORIZONTAL) 291 .AddStrut(15.0) 292 .Add(fShowCursor) 293 .End() 294 .AddStrut(5.0) 295 .AddGroup(B_HORIZONTAL, 5.0) 296 .AddStrut(10.0) 297 .Add(fDelayControl->CreateLabelLayoutItem()) 298 .Add(fDelayControl->CreateTextViewLayoutItem()) 299 .Add(stringView2) 300 .End() 301 .AddStrut(10.0) 302 .AddGlue() 303 .Add(divider) 304 .AddStrut(10) 305 .AddGroup(B_HORIZONTAL, 10.0) 306 .Add(fBackToSave) 307 .AddGlue() 308 .Add(new BButton("", "Cancel", new BMessage(B_QUIT_REQUESTED))) 309 .Add(fTakeScreenshot) 310 .End() 311 .SetInsets(10.0, 10.0, 10.0, 10.0) 312 ); 313 314 if (fGrabActiveWindow) { 315 fWindowBorder->SetEnabled(true); 316 fActiveWindow->SetValue(B_CONTROL_ON); 317 fWindowBorder->SetValue(fIncludeBorder); 318 } 319 } 320 321 322 void 323 ScreenshotWindow::_SetupSecondLayoutItem(BCardLayout* layout) 324 { 325 fPreviewBox = new BBox(BRect(0.0, 0.0, 200.0, 150.0)); 326 fPreviewBox->SetExplicitMinSize(BSize(200.0, B_SIZE_UNSET)); 327 fPreviewBox->SetFlags(fPreviewBox->Flags() | B_FULL_UPDATE_ON_RESIZE); 328 329 fNameControl = new BTextControl("", "Name:", "screenshot1", NULL); 330 331 BMessage settings(_ReadSettings()); 332 333 _SetupTranslatorMenu(new BMenu("Please select"), settings); 334 BMenuField* menuField = new BMenuField("Save as:", fTranslatorMenu); 335 336 _SetupOutputPathMenu(new BMenu("Please select"), settings); 337 BMenuField* menuField2 = new BMenuField("Save in:", fOutputPathMenu); 338 339 fNameControl->SetText(_FindValidFileName("screenshot1").String()); 340 341 BBox* divider = new BBox(B_FANCY_BORDER, NULL); 342 divider->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1)); 343 344 BGridLayout* gridLayout = BGridLayoutBuilder(0.0, 5.0) 345 .Add(fNameControl->CreateLabelLayoutItem(), 0, 0) 346 .Add(fNameControl->CreateTextViewLayoutItem(), 1, 0) 347 .Add(menuField->CreateLabelLayoutItem(), 0, 1) 348 .Add(menuField->CreateMenuBarLayoutItem(), 1, 1) 349 .Add(menuField2->CreateLabelLayoutItem(), 0, 2) 350 .Add(menuField2->CreateMenuBarLayoutItem(), 1, 2); 351 gridLayout->SetMinColumnWidth(1, menuField->StringWidth("SomethingLongHere")); 352 353 layout->AddView(1, BGroupLayoutBuilder(B_VERTICAL) 354 .Add(BGroupLayoutBuilder(B_HORIZONTAL, 10.0) 355 .Add(fPreviewBox) 356 .AddGroup(B_VERTICAL) 357 .Add(gridLayout->View()) 358 .AddGlue() 359 .End()) 360 .AddStrut(10) 361 .Add(divider) 362 .AddStrut(10) 363 .AddGroup(B_HORIZONTAL, 10.0) 364 .Add(new BButton("", "Options", new BMessage(kShowOptions))) 365 .AddGlue() 366 .Add(new BButton("", "Cancel", new BMessage(B_QUIT_REQUESTED))) 367 .Add(new BButton("", "Save", new BMessage(kFinishScreenshot))) 368 .End() 369 .SetInsets(10.0, 10.0, 10.0, 10.0) 370 ); 371 } 372 373 374 void 375 ScreenshotWindow::_DisallowChar(BTextView* textView) 376 { 377 for (uint32 i = 0; i < '0'; ++i) 378 textView->DisallowChar(i); 379 380 for (uint32 i = '9' + 1; i < 255; ++i) 381 textView->DisallowChar(i); 382 } 383 384 385 void 386 ScreenshotWindow::_SetupTranslatorMenu(BMenu* translatorMenu, 387 const BMessage& settings) 388 { 389 fTranslatorMenu = translatorMenu; 390 391 BMessage message(kImageOutputFormat); 392 fTranslatorMenu = new BMenu("Please select"); 393 BTranslationUtils::AddTranslationItems(fTranslatorMenu, B_TRANSLATOR_BITMAP, 394 &message, NULL, NULL, NULL); 395 396 fTranslatorMenu->SetLabelFromMarked(true); 397 398 if (fTranslatorMenu->ItemAt(0)) 399 fTranslatorMenu->ItemAt(0)->SetMarked(true); 400 401 if (settings.FindInt32("be:type", &fImageFileType) != B_OK) 402 fImageFileType = B_PNG_FORMAT; 403 404 int32 imageFileType; 405 for (int32 i = 0; i < fTranslatorMenu->CountItems(); ++i) { 406 BMenuItem* item = fTranslatorMenu->ItemAt(i); 407 if (item && item->Message()) { 408 item->Message()->FindInt32("be:type", &imageFileType); 409 if (fImageFileType == imageFileType) { 410 item->SetMarked(true); 411 break; 412 } 413 } 414 } 415 } 416 417 418 void 419 ScreenshotWindow::_SetupOutputPathMenu(BMenu* outputPathMenu, 420 const BMessage& settings) 421 { 422 fOutputPathMenu = outputPathMenu; 423 fOutputPathMenu->SetLabelFromMarked(true); 424 425 BString lastSelectedPath; 426 settings.FindString("lastSelectedPath", &lastSelectedPath); 427 428 BPath path; 429 find_directory(B_USER_DIRECTORY, &path); 430 431 BString label("Home directory"); 432 _AddItemToPathMenu(path.Path(), label, 0, (path.Path() == lastSelectedPath)); 433 434 path.Append("Desktop"); 435 label.SetTo("Desktop"); 436 _AddItemToPathMenu(path.Path(), label, 0, (path.Path() == lastSelectedPath)); 437 438 find_directory(B_BEOS_ETC_DIRECTORY, &path); 439 path.Append("artwork"); 440 441 label.SetTo("Artwork directory"); 442 _AddItemToPathMenu(path.Path(), label, 2, (path.Path() == lastSelectedPath)); 443 444 int32 i = 0; 445 BString userPath; 446 while (settings.FindString("path", i++, &userPath) == B_OK) { 447 _AddItemToPathMenu(userPath.String(), userPath, 3, 448 (userPath == lastSelectedPath)); 449 } 450 451 if (!fLastSelectedPath) { 452 if (settings.IsEmpty() || lastSelectedPath.Length() == 0) { 453 fOutputPathMenu->ItemAt(1)->SetMarked(true); 454 fLastSelectedPath = fOutputPathMenu->ItemAt(1); 455 } else { 456 _AddItemToPathMenu(lastSelectedPath.String(), lastSelectedPath, 3, 457 true); 458 } 459 } 460 461 fOutputPathMenu->AddItem(new BSeparatorItem()); 462 fOutputPathMenu->AddItem(new BMenuItem("Choose directory...", 463 new BMessage(kChooseLocation))); 464 } 465 466 467 void 468 ScreenshotWindow::_AddItemToPathMenu(const char* path, BString& label, 469 int32 index, bool markItem) 470 { 471 BMessage* message = new BMessage(kLocationChanged); 472 message->AddString("path", path); 473 474 fOutputPathMenu->TruncateString(&label, B_TRUNCATE_MIDDLE, 475 fOutputPathMenu->StringWidth("SomethingLongHere")); 476 477 fOutputPathMenu->AddItem(new BMenuItem(label.String(), message), index); 478 479 if (markItem) { 480 fOutputPathMenu->ItemAt(index)->SetMarked(true); 481 fLastSelectedPath = fOutputPathMenu->ItemAt(index); 482 } 483 } 484 485 486 void 487 ScreenshotWindow::_CenterAndShow() 488 { 489 BSize size = GetLayout()->PreferredSize(); 490 ResizeTo(size.Width(), size.Height()); 491 492 BRect frame(BScreen(this).Frame()); 493 MoveTo((frame.Width() - size.Width()) / 2.0, 494 (frame.Height() - size.Height()) / 2.0); 495 496 Show(); 497 } 498 499 500 void 501 ScreenshotWindow::_UpdatePreviewPanel() 502 { 503 fPreviewBox->ClearViewBitmap(); 504 fPreviewBox->SetViewBitmap(fScreenshot, fScreenshot->Bounds(), 505 fPreviewBox->Bounds(), B_FOLLOW_ALL, 0); 506 507 BCardLayout* layout = dynamic_cast<BCardLayout*> (GetLayout()); 508 if (layout) 509 layout->SetVisibleItem(1L); 510 511 SetTitle("Save Screenshot"); 512 } 513 514 515 BString 516 ScreenshotWindow::_FindValidFileName(const char* name) const 517 { 518 BString fileName(name); 519 if (!fLastSelectedPath) 520 return fileName; 521 522 const char* path; 523 BMessage* message = fLastSelectedPath->Message(); 524 if (!message || message->FindString("path", &path) != B_OK) 525 return fileName; 526 527 BPath outputPath(path); 528 outputPath.Append(name); 529 if (!BEntry(outputPath.Path()).Exists()) 530 return fileName; 531 532 if (strncmp(name, "screenshot", strlen("screenshot")) == 0) 533 fileName.SetTo("screenshot"); 534 535 BEntry entry; 536 int32 index = 1; 537 char filename[32]; 538 do { 539 sprintf(filename, "%s%ld", fileName.String(), index++); 540 outputPath.SetTo(path); 541 outputPath.Append(filename); 542 entry.SetTo(outputPath.Path()); 543 } while (entry.Exists()); 544 545 return BString(filename); 546 } 547 548 549 int32 550 ScreenshotWindow::_PathIndexInMenu(const BString& path) const 551 { 552 BString userPath; 553 for (int32 i = 0; i < fOutputPathMenu->CountItems(); ++i) { 554 BMenuItem* item = fOutputPathMenu->ItemAt(i); 555 if (item && item->Message() 556 && item->Message()->FindString("path", &userPath) == B_OK) { 557 if (userPath == path) 558 return i; 559 } 560 } 561 return -1; 562 } 563 564 565 BMessage 566 ScreenshotWindow::_ReadSettings() const 567 { 568 BPath settingsPath; 569 find_directory(B_USER_SETTINGS_DIRECTORY, &settingsPath); 570 settingsPath.Append("screenshot"); 571 572 BMessage settings; 573 574 BFile file(settingsPath.Path(), B_READ_ONLY); 575 if (file.InitCheck() == B_OK) 576 settings.Unflatten(&file); 577 578 return settings; 579 } 580 581 582 void 583 ScreenshotWindow::_WriteSettings() const 584 { 585 BMessage settings; 586 settings.AddInt32("be:type", fImageFileType); 587 588 BString path; 589 int32 count = fOutputPathMenu->CountItems(); 590 if (count > 5) { 591 for (int32 i = count - 3; i > count - 8 && i > 2; --i) { 592 BMenuItem* item = fOutputPathMenu->ItemAt(i); 593 if (item) { 594 BMessage* msg = item->Message(); 595 if (msg && msg->FindString("path", &path) == B_OK) 596 settings.AddString("path", path.String()); 597 } 598 } 599 } 600 601 if (fLastSelectedPath) { 602 BMessage* msg = fLastSelectedPath->Message(); 603 if (msg && msg->FindString("path", &path) == B_OK) 604 settings.AddString("lastSelectedPath", path.String()); 605 } 606 607 BPath settingsPath; 608 find_directory(B_USER_SETTINGS_DIRECTORY, &settingsPath); 609 settingsPath.Append("screenshot"); 610 611 BFile file(settingsPath.Path(), B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY); 612 if (file.InitCheck() == B_OK) { 613 ssize_t size; 614 settings.Flatten(&file, &size); 615 } 616 } 617 618 619 void 620 ScreenshotWindow::_TakeScreenshot() 621 { 622 if (fDelayControl) 623 snooze((atoi(fDelayControl->Text()) * 1000000) + 50000); 624 625 BRect frame; 626 delete fScreenshot; 627 if (_GetActiveWindowFrame(&frame) == B_OK) { 628 fScreenshot = new BBitmap(frame.OffsetToCopy(B_ORIGIN), B_RGBA32); 629 BScreen(this).ReadBitmap(fScreenshot, fIncludeCursor, &frame); 630 } else { 631 BScreen(this).GetBitmap(&fScreenshot, fIncludeCursor); 632 } 633 } 634 635 636 status_t 637 ScreenshotWindow::_GetActiveWindowFrame(BRect* frame) 638 { 639 if (!fGrabActiveWindow || !frame) 640 return B_ERROR; 641 642 int32* tokens; 643 int32 tokenCount; 644 status_t status = BPrivate::get_window_order(current_workspace(), &tokens, 645 &tokenCount); 646 if (status != B_OK || !tokens || tokenCount < 1) 647 return B_ERROR; 648 649 status = B_ERROR; 650 for (int32 i = 0; i < tokenCount; ++i) { 651 client_window_info* windowInfo = get_window_info(tokens[i]); 652 if (!windowInfo->is_mini && !windowInfo->show_hide_level > 0) { 653 frame->left = windowInfo->window_left; 654 frame->top = windowInfo->window_top; 655 frame->right = windowInfo->window_right; 656 frame->bottom = windowInfo->window_bottom; 657 658 status = B_OK; 659 if (fIncludeBorder) { 660 float border = (windowInfo->border_size); 661 frame->InsetBy(-(border), -(border)); 662 frame->top -= windowInfo->tab_height; 663 } 664 free(windowInfo); 665 666 BRect screenFrame(BScreen(this).Frame()); 667 if (frame->left < screenFrame.left) 668 frame->left = screenFrame.left; 669 if (frame->top < screenFrame.top) 670 frame->top = screenFrame.top; 671 if (frame->right > screenFrame.right) 672 frame->right = screenFrame.right; 673 if (frame->bottom > screenFrame.bottom) 674 frame->bottom = screenFrame.bottom; 675 676 break; 677 } 678 free(windowInfo); 679 } 680 free(tokens); 681 return status; 682 } 683 684 685 void 686 ScreenshotWindow::_SaveScreenshot() 687 { 688 if (!fScreenshot || !fLastSelectedPath) 689 return; 690 691 const char* path; 692 BMessage* message = fLastSelectedPath->Message(); 693 if (!message || message->FindString("path", &path) != B_OK) 694 return; 695 696 BDirectory dir(path); 697 BFile file(&dir, fNameControl->Text(), B_CREATE_FILE | 698 B_ERASE_FILE | B_WRITE_ONLY); 699 if (file.InitCheck() != B_OK) 700 return; 701 702 BBitmapStream bitmapStream(fScreenshot); 703 BTranslatorRoster* roster = BTranslatorRoster::Default(); 704 roster->Translate(&bitmapStream, NULL, NULL, &file, fImageFileType, 705 B_TRANSLATOR_BITMAP); 706 fScreenshot = NULL; 707 708 BNodeInfo nodeInfo(&file); 709 if (nodeInfo.InitCheck() != B_OK) 710 return; 711 712 int32 numFormats; 713 const translation_format* formats = NULL; 714 if (roster->GetOutputFormats(fTranslator, &formats, &numFormats) != B_OK) 715 return; 716 717 for (int32 i = 0; i < numFormats; ++i) { 718 if (formats[i].type == uint32(fImageFileType)) { 719 nodeInfo.SetType(formats[i].MIME); 720 break; 721 } 722 } 723 } 724 725 726 void 727 ScreenshotWindow::_SaveScreenshotSilent() const 728 { 729 if (!fScreenshot) 730 return; 731 732 BPath homePath; 733 if (find_directory(B_USER_DIRECTORY, &homePath) != B_OK) { 734 fprintf(stderr, "failed to find user home directory\n"); 735 return; 736 } 737 738 BPath path; 739 BEntry entry; 740 int32 index = 1; 741 do { 742 char filename[32]; 743 sprintf(filename, "screenshot%ld", index++); 744 path = homePath; 745 path.Append(filename); 746 entry.SetTo(path.Path()); 747 } while (entry.Exists()); 748 749 // Dump to PNG 750 SaveToPNG(path.Path(), fScreenshot->Bounds(), fScreenshot->ColorSpace(), 751 fScreenshot->Bits(), fScreenshot->BitsLength(), 752 fScreenshot->BytesPerRow()); 753 } 754