From a75264d3f6fdda0f26b0d6b20357209d72c9660a Mon Sep 17 00:00:00 2001 From: Karsten Heimrich Date: Wed, 17 Sep 2008 22:59:09 +0000 Subject: [PATCH] * small screenshot app that was once discussed * misses a proper icon and does not save atm... git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27605 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/screenshot/Jamfile | 12 + src/apps/screenshot/Screenshot.cpp | 111 ++++++ src/apps/screenshot/Screenshot.h | 22 ++ src/apps/screenshot/Screenshot.rdef | 36 ++ src/apps/screenshot/ScreenshotWindow.cpp | 411 +++++++++++++++++++++++ src/apps/screenshot/ScreenshotWindow.h | 63 ++++ src/apps/screenshot/main.cpp | 14 + 7 files changed, 669 insertions(+) create mode 100644 src/apps/screenshot/Jamfile create mode 100644 src/apps/screenshot/Screenshot.cpp create mode 100644 src/apps/screenshot/Screenshot.h create mode 100644 src/apps/screenshot/Screenshot.rdef create mode 100644 src/apps/screenshot/ScreenshotWindow.cpp create mode 100644 src/apps/screenshot/ScreenshotWindow.h create mode 100644 src/apps/screenshot/main.cpp diff --git a/src/apps/screenshot/Jamfile b/src/apps/screenshot/Jamfile new file mode 100644 index 0000000000..1d2e3734ab --- /dev/null +++ b/src/apps/screenshot/Jamfile @@ -0,0 +1,12 @@ +SubDir HAIKU_TOP src apps screenshot ; + +UsePrivateHeaders interface ; + +Application Screenshot : + main.cpp + Screenshot.cpp + ScreenshotWindow.cpp + : be translation + : Screenshot.rdef +; + diff --git a/src/apps/screenshot/Screenshot.cpp b/src/apps/screenshot/Screenshot.cpp new file mode 100644 index 0000000000..43c28e4d3e --- /dev/null +++ b/src/apps/screenshot/Screenshot.cpp @@ -0,0 +1,111 @@ +/* + * Copyright Karsten Heimrich, host.haiku@gmx.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "Screenshot.h" +#include "ScreenshotWindow.h" + + +#include +#include +#include + + +Screenshot::Screenshot() + : BApplication("application/x-vnd.haiku-screenshot"), + fArgvReceived(false) +{ +} + + +Screenshot::~Screenshot() +{ +} + + +void +Screenshot::ReadyToRun() +{ + if(!fArgvReceived) + new ScreenshotWindow(); + + fArgvReceived = false; +} + + +void +Screenshot::RefsReceived(BMessage* message) +{ + int32 delay = 0; + message->FindInt32("delay", &delay); + + bool includeBorder = false; + message->FindBool("border", &includeBorder); + + bool includeCursor = false; + message->FindBool("border", &includeCursor); + + bool grabActiveWindow = false; + message->FindBool("window", &grabActiveWindow); + + bool showConfigureWindow = false; + message->FindBool("configure", &showConfigureWindow); + + new ScreenshotWindow(delay * 1000000, includeBorder, includeCursor, + grabActiveWindow, showConfigureWindow); +} + + +void +Screenshot::ArgvReceived(int32 argc, char** argv) +{ + bigtime_t delay = 0; + + bool includeBorder = false; + bool includeCursor = false; + bool grabActiveWindow = false; + bool showConfigureWindow = false; + + for (int32 i = 0; i < argc; i++) { + if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) + _ShowHelp(); + else if (strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "--border") == 0) + includeBorder = true; + else if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--cursor") == 0) + includeCursor = true; + else if (strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "--window") == 0) + grabActiveWindow = true; + else if (strcmp(argv[i], "-o") == 0 || strcmp(argv[i], "--options") == 0) + showConfigureWindow = true; + else if (strcmp(argv[i], "-d") == 0 + || strncmp(argv[i], "--delay", 7) == 0 + || strncmp(argv[i], "--delay=", 8) == 0) { + int32 seconds = atoi(argv[i + 1]); + if (seconds > 0) { + delay = seconds * 1000000; + i++; + } + } + } + fArgvReceived = true; + new ScreenshotWindow(delay, includeBorder, includeCursor, grabActiveWindow, + showConfigureWindow); +} + + +void +Screenshot::_ShowHelp() const +{ + printf("Screenshot [OPTION]... Creates a Bitmap of the current screen\n\n"); + printf("OPTION\n"); + printf("..-o, --options Show options window first\n"); + printf("..-c, --cursor Have the cursor inside the screenshot\n"); + printf("..-b, --border Include the window border with the screenshot\n"); + printf("..-w, --window Use active window instead of the entire screen\n"); + printf("..-d, --delay=seconds Take screenshot after specified delay [in seconds]\n"); + printf("\n"); + printf("Note: OPTION -b, --border takes only effect when used with -w, --window\n"); + + exit(0); +} diff --git a/src/apps/screenshot/Screenshot.h b/src/apps/screenshot/Screenshot.h new file mode 100644 index 0000000000..7087c3f360 --- /dev/null +++ b/src/apps/screenshot/Screenshot.h @@ -0,0 +1,22 @@ +/* + * Copyright Karsten Heimrich, host.haiku@gmx.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#include + + +class Screenshot : public BApplication { +public: + Screenshot(); + virtual ~Screenshot(); + + virtual void ReadyToRun(); + virtual void RefsReceived(BMessage* message); + virtual void ArgvReceived(int32 argc, char** argv); + +private: + void _ShowHelp() const; + +private: + bool fArgvReceived; +}; diff --git a/src/apps/screenshot/Screenshot.rdef b/src/apps/screenshot/Screenshot.rdef new file mode 100644 index 0000000000..e6c580810a --- /dev/null +++ b/src/apps/screenshot/Screenshot.rdef @@ -0,0 +1,36 @@ + +resource app_signature "application/x-vnd.haiku-screenshot"; + +resource app_flags B_MULTIPLE_LAUNCH; + +resource app_version { + major = 1, + middle = 0, + minor = 0, + + /* 0 = development 1 = alpha 2 = beta + 3 = gamma 4 = golden master 5 = final */ + variety = 2, + internal = 0, + + short_info = "Screenshot", + long_info = "Screenshot ©2008 Haiku" +}; + +resource vector_icon { + $"6E6369660B03010000020016023CC7EE389BC0BA16573E39B04977C842ADC700" + $"FFFFD3020006023C529D3753A2B8966F3D9D084B6044496AAF00474747FFA5A0" + $"A002001602BC4E76BC411B3C90DABCA00D47587D4ABA850090FFD40200160238" + $"313C3B5CF0BFCD963C7AAC4C13943FCAF901ECFFC3054B04017E020006033E2F" + $"99387F17BA42DB3FF5B94A0E32482C90001D1E2C3D454658FF01010102000602" + $"3879063B8224BE2CC83B10DB4A1F6F49B894FF9A9A9A00242222020006033C69" + $"A60000000000003E186148800049800058F3F3F300D4CECEFFD9D9D9038DFF06" + $"0D0A062228224A485E525252302C220A042228483852302C220A044838485E52" + $"5252300A042228224A485E48380A04453A45572446242C0A04B561C15A244624" + $"2CB569B8200A0445544557244626C1590A04453A45542644B569B8200A043826" + $"3D234E28492C080438263D234E284E2E0A03492C4E284E2E0802425843C9830A" + $"06486054606052CA1BC5B95C4D52480C0A06010C000A0001091001178400040A" + $"040108000A05010A000A0001001001178400040A010101000A020102000A0302" + $"0304000A070107000A080105000A090106000A0A010B1815FF0117822004" +}; + diff --git a/src/apps/screenshot/ScreenshotWindow.cpp b/src/apps/screenshot/ScreenshotWindow.cpp new file mode 100644 index 0000000000..db58422841 --- /dev/null +++ b/src/apps/screenshot/ScreenshotWindow.cpp @@ -0,0 +1,411 @@ +/* + * Copyright Karsten Heimrich, host.haiku@gmx.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "ScreenshotWindow.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include + + +enum { + kScreenshotType, + kIncludeBorder, + kShowCursor, + kBackToSave, + kTakeScreenshot, + kImageOutputFormat, + kChooseLocation, + kFinishScreenshot, + kShowOptions +}; + + +ScreenshotWindow::ScreenshotWindow() + : BWindow(BRect(0, 0, 200.0, 100.0), "Save Screenshot", B_TITLED_WINDOW, + B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_QUIT_ON_WINDOW_CLOSE | + B_AVOID_FRONT | B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE), + fScreenshot(NULL), + fDelay(0), + fIncludeBorder(false), + fIncludeCursor(false), + fGrabActiveWindow(false), + fShowConfigWindow(false) +{ + _InitWindow(); + _CenterAndShow(); +} + + +ScreenshotWindow::ScreenshotWindow(bigtime_t delay, bool includeBorder, + bool includeCursor, bool grabActiveWindow, bool showConfigWindow) + : BWindow(BRect(0, 0, 200.0, 100.0), "Take Screenshot", B_TITLED_WINDOW, + B_NOT_ZOOMABLE | B_NOT_RESIZABLE | B_QUIT_ON_WINDOW_CLOSE | + B_AVOID_FRONT | B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE), + fScreenshot(NULL), + fDelay(delay), + fIncludeBorder(includeBorder), + fIncludeCursor(includeCursor), + fGrabActiveWindow(grabActiveWindow), + fShowConfigWindow(showConfigWindow) +{ + _InitWindow(); + _CenterAndShow(); +} + + +ScreenshotWindow::~ScreenshotWindow() +{ + delete fScreenshot; +} + + +void +ScreenshotWindow::MessageReceived(BMessage* message) +{ + switch (message->what) { + case kScreenshotType: { + fGrabActiveWindow = false; + if (fActiveWindow->Value() == B_CONTROL_ON) + fGrabActiveWindow = true; + fWindowBorder->SetEnabled(fGrabActiveWindow); + } break; + + case kIncludeBorder: { + fIncludeBorder = (fWindowBorder->Value() == B_CONTROL_ON); + } break; + + case kShowCursor: { + fIncludeCursor = (fShowCursor->Value() == B_CONTROL_ON); + } break; + + case kBackToSave: { + BCardLayout* layout = dynamic_cast (GetLayout()); + if (layout) + layout->SetVisibleItem(1L); + SetTitle("Save Screenshot"); + } break; + + case kTakeScreenshot: { + Hide(); + _TakeScreenshot(); + Show(); + } break; + + case kImageOutputFormat: { + fFinishScreenshot->SetEnabled(true); + message->FindInt32("be:type", &fImageFileType); + message->FindInt32("be:translator", &fTranslator); + } break; + + case kChooseLocation: { + + } break; + + case kFinishScreenshot: { + + } break; + + case kShowOptions: { + BCardLayout* layout = dynamic_cast (GetLayout()); + if (layout) + layout->SetVisibleItem(0L); + SetTitle("Take Screenshot"); + fBackToSave->SetEnabled(true); + } break; + + default: { + BWindow::MessageReceived(message); + } break; + }; + +} + + +void +ScreenshotWindow::_InitWindow() +{ + BCardLayout* layout = new BCardLayout(); + SetLayout(layout); + + _SetupFirstLayoutItem(layout); + _SetupSecondLayoutItem(layout); + + if (!fShowConfigWindow) { + _TakeScreenshot(); + layout->SetVisibleItem(1L); + } else { + layout->SetVisibleItem(0L); + } +} + + +void +ScreenshotWindow::_SetupFirstLayoutItem(BCardLayout* layout) +{ + BStringView* stringView = new BStringView("", "Take Screenshot"); + stringView->SetFont(be_bold_font); + stringView->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); + + fActiveWindow = new BRadioButton("Take active window", + new BMessage(kScreenshotType)); + fWholeDesktop = new BRadioButton("Take whole Desktop", + new BMessage(kScreenshotType)); + fWholeDesktop->SetValue(B_CONTROL_ON); + + BString delay; + delay << fDelay / 1000000; + fDelayControl = new BTextControl("", "Take screenshot after a delay of", + delay.String(), NULL); + _DisallowChar(fDelayControl->TextView()); + fDelayControl->TextView()->SetAlignment(B_ALIGN_RIGHT); + + BStringView* stringView2 = new BStringView("", "seconds"); + stringView2->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); + + fWindowBorder = new BCheckBox("Include window border", + new BMessage(kIncludeBorder)); + fWindowBorder->SetEnabled(false); + + fShowCursor = new BCheckBox("Include cursor in screenshot", + new BMessage(kShowCursor)); + fShowCursor->SetValue(fIncludeCursor); + + BStringView* stringView3 = new BStringView("", "Options"); + stringView3->SetFont(be_bold_font); + stringView3->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, B_SIZE_UNSET)); + + BBox* divider = new BBox(B_FANCY_BORDER, NULL); + divider->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1)); + + fBackToSave = new BButton("", "Back to save", new BMessage(kBackToSave)); + fBackToSave->SetEnabled(false); + + fTakeScreenshot = new BButton("", "Take Screenshot", + new BMessage(kTakeScreenshot)); + + layout->AddView(0, BGroupLayoutBuilder(B_VERTICAL) + .Add(stringView) + .Add(BGridLayoutBuilder() + .Add(BSpaceLayoutItem::CreateHorizontalStrut(15.0), 0, 0) + .Add(fActiveWindow, 1, 0) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(15.0), 0, 1) + .Add(fWholeDesktop, 1, 1) + .SetInsets(0.0, 5.0, 0.0, 5.0)) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, 5.0) + .AddStrut(10.0) + .Add(fDelayControl->CreateLabelLayoutItem()) + .Add(fDelayControl->CreateTextViewLayoutItem()) + .Add(stringView2)) + .AddStrut(10.0) + .Add(stringView3) + .Add(BGridLayoutBuilder() + .Add(BSpaceLayoutItem::CreateHorizontalStrut(15.0), 0, 0) + .Add(fWindowBorder, 1, 0) + .Add(BSpaceLayoutItem::CreateHorizontalStrut(15.0), 0, 1) + .Add(fShowCursor, 1, 1) + .SetInsets(0.0, 5.0, 0.0, 5.0)) + .AddGlue() + .Add(divider) + .AddStrut(5) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, 10.0) + .Add(fBackToSave) + .AddGlue() + .Add(new BButton("", "Cancel", new BMessage(B_QUIT_REQUESTED))) + .Add(fTakeScreenshot)) + .SetInsets(10.0, 10.0, 10.0, 10.0) + ); + + if (fGrabActiveWindow) { + fWindowBorder->SetEnabled(true); + fActiveWindow->SetValue(B_CONTROL_ON); + fWindowBorder->SetValue(fIncludeBorder); + } +} + + +void +ScreenshotWindow::_SetupSecondLayoutItem(BCardLayout* layout) +{ + fPreviewBox = new BBox(BRect(0.0, 0.0, 200.0, 150.0)); + fPreviewBox->SetExplicitMinSize(BSize(200.0, B_SIZE_UNSET)); + fPreviewBox->SetFlags(fPreviewBox->Flags() | B_FULL_UPDATE_ON_RESIZE); + + fNameControl = new BTextControl("", "Name:", "Screenshot", NULL); + + BMessage message(kImageOutputFormat); + fTranslatorMenu = new BMenu("Please select"); + BTranslationUtils::AddTranslationItems(fTranslatorMenu, B_TRANSLATOR_BITMAP, + &message, NULL, NULL, NULL); + BMenuField* menuField = new BMenuField("Save as:", fTranslatorMenu); + fTranslatorMenu->SetLabelFromMarked(true); + + fOutputPathMenu = new BMenu("Please select"); + fOutputPathMenu->AddItem(new BMenuItem("Home directory", NULL)); + fOutputPathMenu->AddItem(new BMenuItem("Artwork directory", NULL)); + fOutputPathMenu->AddItem(new BSeparatorItem()); + fOutputPathMenu->AddItem(new BMenuItem("Choose location", + new BMessage(kChooseLocation))); + BMenuField* menuField2 = new BMenuField("Save in:", fOutputPathMenu); + fOutputPathMenu->SetLabelFromMarked(true); + fOutputPathMenu->ItemAt(0)->SetMarked(true); + + BBox* divider = new BBox(B_FANCY_BORDER, NULL); + divider->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1)); + + BGridLayout* gridLayout = BGridLayoutBuilder(0.0, 5.0) + .Add(fNameControl->CreateLabelLayoutItem(), 0, 0) + .Add(fNameControl->CreateTextViewLayoutItem(), 1, 0) + .Add(menuField->CreateLabelLayoutItem(), 0, 1) + .Add(menuField->CreateMenuBarLayoutItem(), 1, 1) + .Add(menuField2->CreateLabelLayoutItem(), 0, 2) + .Add(menuField2->CreateMenuBarLayoutItem(), 1, 2); + gridLayout->SetMinColumnWidth(1, menuField->StringWidth("SomethingLongHere")); + + fFinishScreenshot = new BButton("", "OK", new BMessage(kFinishScreenshot)); + fFinishScreenshot->SetEnabled(false); + + layout->AddView(1, BGroupLayoutBuilder(B_VERTICAL) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, 10.0) + .Add(fPreviewBox) + .AddGroup(B_VERTICAL) + .Add(gridLayout->View()) + .AddGlue() + .End()) + .AddStrut(5) + .Add(divider) + .AddStrut(5) + .Add(BGroupLayoutBuilder(B_HORIZONTAL, 10.0) + .Add(new BButton("", "Options", new BMessage(kShowOptions))) + .AddGlue() + .Add(new BButton("", "Cancel", new BMessage(B_QUIT_REQUESTED))) + .Add(fFinishScreenshot)) + .SetInsets(10.0, 10.0, 10.0, 10.0) + ); +} + + +void +ScreenshotWindow::_DisallowChar(BTextView* textView) +{ + for (uint32 i = 0; i < '0'; ++i) + textView->DisallowChar(i); + + for (uint32 i = '9' + 1; i < 255; ++i) + textView->DisallowChar(i); +} + + +void +ScreenshotWindow::_CenterAndShow() +{ + BSize size = GetLayout()->PreferredSize(); + ResizeTo(size.Width(), size.Height()); + + BRect frame(BScreen(this).Frame()); + MoveTo((frame.Width() - size.Width()) / 2.0, + (frame.Height() - size.Height()) / 2.0); + + Show(); +} + + +void +ScreenshotWindow::_TakeScreenshot() +{ + snooze((atoi(fDelayControl->Text()) * 1000000) + 50000); + + BRect frame; + delete fScreenshot; + if (_GetActiveWindowFrame(&frame) == B_OK) { + fScreenshot = new BBitmap(frame.OffsetToCopy(B_ORIGIN), B_RGBA32); + BScreen(this).ReadBitmap(fScreenshot, fIncludeCursor, &frame); + } else { + BScreen(this).GetBitmap(&fScreenshot, fIncludeCursor); + } + + fPreviewBox->ClearViewBitmap(); + fPreviewBox->SetViewBitmap(fScreenshot, fScreenshot->Bounds(), + fPreviewBox->Bounds(), B_FOLLOW_ALL, 0); + + BCardLayout* layout = dynamic_cast (GetLayout()); + if (layout) + layout->SetVisibleItem(1L); + + SetTitle("Save Screenshot"); +} + + +status_t +ScreenshotWindow::_GetActiveWindowFrame(BRect* frame) +{ + if (!fGrabActiveWindow || !frame) + return B_ERROR; + + int32* tokens; + int32 tokenCount; + status_t status = BPrivate::get_window_order(B_CURRENT_WORKSPACE, &tokens, + &tokenCount); + if (status != B_OK || !tokens || tokenCount < 1) + return B_ERROR; + + status = B_ERROR; + for (int32 i = 0; i < tokenCount; ++i) { + client_window_info* windowInfo = get_window_info(tokens[i]); + if (!windowInfo->is_mini && !windowInfo->show_hide_level > 0) { + frame->left = windowInfo->window_left; + frame->top = windowInfo->window_top; + frame->right = windowInfo->window_right; + frame->bottom = windowInfo->window_bottom; + + status = B_OK; + free(windowInfo); + + if (fIncludeBorder) { + // TODO: this is wrong for windows with titlebar, change once + // we can access the decorator or get it via window info + frame->InsetBy(-5.0, -5.0); + frame->top -= 17.0; + } + + BRect screenFrame(BScreen(this).Frame()); + if (frame->left < screenFrame.left) + frame->left = screenFrame.left; + if (frame->top < screenFrame.top) + frame->top = screenFrame.top; + if (frame->right > screenFrame.right) + frame->right = screenFrame.right; + if (frame->bottom > screenFrame.bottom) + frame->bottom = screenFrame.bottom; + + break; + } + free(windowInfo); + } + free(tokens); + return status; +} diff --git a/src/apps/screenshot/ScreenshotWindow.h b/src/apps/screenshot/ScreenshotWindow.h new file mode 100644 index 0000000000..872dcef2d2 --- /dev/null +++ b/src/apps/screenshot/ScreenshotWindow.h @@ -0,0 +1,63 @@ +/* + * Copyright Karsten Heimrich, host.haiku@gmx.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#include + + +class BBitmap; +class BBox; +class BButton; +class BCardLayout; +class BCheckBox; +class BMenu; +class BRadioButton; +class BTextControl; +class BTextView; + + +class ScreenshotWindow : public BWindow { +public: + ScreenshotWindow(); + ScreenshotWindow(bigtime_t delay, bool includeBorder, + bool includeCursor, bool grabActiveWindow, + bool showConfigWindow); + virtual ~ScreenshotWindow(); + + virtual void MessageReceived(BMessage* message); + +private: + void _InitWindow(); + void _SetupFirstLayoutItem(BCardLayout* layout); + void _SetupSecondLayoutItem(BCardLayout* layout); + void _DisallowChar(BTextView* textView); + void _CenterAndShow(); + + void _TakeScreenshot(); + status_t _GetActiveWindowFrame(BRect* frame); + +private: + BBox* fPreviewBox; + BRadioButton* fActiveWindow; + BRadioButton* fWholeDesktop; + BTextControl* fDelayControl; + BCheckBox* fWindowBorder; + BCheckBox* fShowCursor; + BButton* fBackToSave; + BButton* fTakeScreenshot; + BTextControl* fNameControl; + BMenu* fTranslatorMenu; + BMenu* fOutputPathMenu; + BButton* fFinishScreenshot; + BBitmap* fScreenshot; + + bigtime_t fDelay; + + bool fIncludeBorder; + bool fIncludeCursor; + bool fGrabActiveWindow; + bool fShowConfigWindow; + + int32 fTranslator; + int32 fImageFileType; +}; diff --git a/src/apps/screenshot/main.cpp b/src/apps/screenshot/main.cpp new file mode 100644 index 0000000000..6c5867e72d --- /dev/null +++ b/src/apps/screenshot/main.cpp @@ -0,0 +1,14 @@ +/* + * Copyright Karsten Heimrich, host.haiku@gmx.de. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#include "Screenshot.h" + + +int +main(int argc, char* argv[]) +{ + Screenshot screenshot; + return screenshot.Run(); +}