* 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
This commit is contained in:
Karsten Heimrich 2008-09-17 22:59:09 +00:00
parent cbc456de3b
commit a75264d3f6
7 changed files with 669 additions and 0 deletions

View File

@ -0,0 +1,12 @@
SubDir HAIKU_TOP src apps screenshot ;
UsePrivateHeaders interface ;
Application Screenshot :
main.cpp
Screenshot.cpp
ScreenshotWindow.cpp
: be translation
: Screenshot.rdef
;

View File

@ -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 <stdio.h>
#include <stdlib.h>
#include <string.h>
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);
}

View File

@ -0,0 +1,22 @@
/*
* Copyright Karsten Heimrich, host.haiku@gmx.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <Application.h>
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;
};

View File

@ -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"
};

View File

@ -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 <Bitmap.h>
#include <Box.h>
#include <Button.h>
#include <CardLayout.h>
#include <CheckBox.h>
#include <GridLayoutBuilder.h>
#include <GroupLayoutBuilder.h>
#include <LayoutItem.h>
#include <Menu.h>
#include <MenuField.h>
#include <MenuItem.h>
#include <Screen.h>
#include <RadioButton.h>
#include <String.h>
#include <StringView.h>
#include <SpaceLayoutItem.h>
#include <TextControl.h>
#include <TranslatorFormats.h>
#include <TranslationUtils.h>
#include <View.h>
#include <WindowInfo.h>
#include <stdio.h>
#include <stdlib.h>
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<BCardLayout*> (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<BCardLayout*> (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<BCardLayout*> (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;
}

View File

@ -0,0 +1,63 @@
/*
* Copyright Karsten Heimrich, host.haiku@gmx.de. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <Window.h>
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;
};

View File

@ -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();
}