Implement "take a screenshot" feature
* Like in android - press power+volume down, screenshots are saved in /sdcard/Pictures/Screenshots (if /sdcard is mounted) or /tmp Change-Id: Iaefa15b11a1d5fdfac57d77388db1621f378a8d4 Signed-off-by: Vojtech Bocek <vbocek@gmail.com>
This commit is contained in:
committed by
Gerrit Code Review
parent
67351dca66
commit
03fd6c56fe
@@ -32,6 +32,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <sys/wait.h>
|
||||
#include <dirent.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
@@ -775,6 +776,54 @@ int GUIAction::doAction(Action action, int isThreaded /* = 0 */)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (function == "screenshot")
|
||||
{
|
||||
time_t tm;
|
||||
char path[256];
|
||||
int path_len;
|
||||
uid_t uid = -1;
|
||||
gid_t gid = -1;
|
||||
|
||||
struct passwd *pwd = getpwnam("media_rw");
|
||||
if(pwd) {
|
||||
uid = pwd->pw_uid;
|
||||
gid = pwd->pw_gid;
|
||||
}
|
||||
|
||||
const std::string storage = DataManager::GetCurrentStoragePath();
|
||||
if(PartitionManager.Is_Mounted_By_Path(storage)) {
|
||||
snprintf(path, sizeof(path), "%s/Pictures/Screenshots/", storage.c_str());
|
||||
} else {
|
||||
strcpy(path, "/tmp/");
|
||||
}
|
||||
|
||||
if(!TWFunc::Create_Dir_Recursive(path, 0666, uid, gid))
|
||||
return 0;
|
||||
|
||||
tm = time(NULL);
|
||||
path_len = strlen(path);
|
||||
|
||||
// Screenshot_2014-01-01-18-21-38.png
|
||||
strftime(path+path_len, sizeof(path)-path_len, "Screenshot_%Y-%m-%d-%H-%M-%S.png", localtime(&tm));
|
||||
|
||||
int res = gr_save_screenshot(path);
|
||||
if(res == 0) {
|
||||
chmod(path, 0666);
|
||||
chown(path, uid, gid);
|
||||
|
||||
gui_print("Screenshot was saved to %s\n", path);
|
||||
|
||||
// blink to notify that the screenshow was taken
|
||||
gr_color(255, 255, 255, 255);
|
||||
gr_fill(0, 0, gr_fb_width(), gr_fb_height());
|
||||
gr_flip();
|
||||
gui_forceRender();
|
||||
} else {
|
||||
LOGERR("Failed to take a screenshot!\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (isThreaded)
|
||||
{
|
||||
if (function == "fileexists")
|
||||
|
||||
Executable → Regular
+10
@@ -277,6 +277,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
@@ -4159,6 +4164,11 @@
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
|
||||
<object type="template" name="keyboardtemplate" />
|
||||
|
||||
<object type="action">
|
||||
|
||||
@@ -277,6 +277,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
@@ -4159,6 +4164,11 @@
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
|
||||
<object type="template" name="keyboardtemplate" />
|
||||
|
||||
<object type="action">
|
||||
|
||||
@@ -266,6 +266,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
|
||||
@@ -269,6 +269,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
|
||||
@@ -277,6 +277,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
@@ -4159,6 +4164,11 @@
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
|
||||
<object type="template" name="keyboardtemplate" />
|
||||
|
||||
<object type="action">
|
||||
|
||||
@@ -277,6 +277,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
@@ -4159,6 +4164,11 @@
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
|
||||
<object type="template" name="keyboardtemplate" />
|
||||
|
||||
<object type="action">
|
||||
|
||||
@@ -253,6 +253,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
|
||||
@@ -277,6 +277,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
@@ -4159,6 +4164,11 @@
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
|
||||
<object type="template" name="keyboardtemplate" />
|
||||
|
||||
<object type="action">
|
||||
|
||||
@@ -259,6 +259,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
|
||||
@@ -259,6 +259,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
|
||||
@@ -258,6 +258,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
|
||||
@@ -259,6 +259,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
|
||||
@@ -266,6 +266,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
|
||||
Executable → Regular
+5
@@ -260,6 +260,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
|
||||
Executable → Regular
+10
@@ -279,6 +279,11 @@
|
||||
<touch key="power" />
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
</template>
|
||||
|
||||
<template name="progress_bar">
|
||||
@@ -4167,6 +4172,11 @@
|
||||
<action function="overlay">lock</action>
|
||||
</object>
|
||||
|
||||
<object type="action">
|
||||
<touch key="power+voldown" />
|
||||
<action function="screenshot" />
|
||||
</object>
|
||||
|
||||
<object type="template" name="keyboardtemplate" />
|
||||
|
||||
<object type="action">
|
||||
|
||||
@@ -2,7 +2,7 @@ LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES := events.c resources.c graphics_overlay.c
|
||||
LOCAL_SRC_FILES := events.c resources.c graphics_overlay.c graphics_utils.c
|
||||
|
||||
ifneq ($(TW_BOARD_CUSTOM_GRAPHICS),)
|
||||
LOCAL_SRC_FILES += $(TW_BOARD_CUSTOM_GRAPHICS)
|
||||
|
||||
@@ -68,7 +68,7 @@ static GRFont *gr_font = 0;
|
||||
static GGLContext *gr_context = 0;
|
||||
static GGLSurface gr_font_texture;
|
||||
static GGLSurface gr_framebuffer[NUM_BUFFERS];
|
||||
static GGLSurface gr_mem_surface;
|
||||
GGLSurface gr_mem_surface;
|
||||
static unsigned gr_active_fb = 0;
|
||||
static unsigned double_buffering = 0;
|
||||
static int gr_is_curr_clr_opaque = 0;
|
||||
@@ -76,7 +76,7 @@ static int gr_is_curr_clr_opaque = 0;
|
||||
static int gr_fb_fd = -1;
|
||||
static int gr_vt_fd = -1;
|
||||
|
||||
static struct fb_var_screeninfo vi;
|
||||
struct fb_var_screeninfo vi;
|
||||
static struct fb_fix_screeninfo fi;
|
||||
|
||||
static bool has_overlay = false;
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (C) 2007 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <png.h>
|
||||
#include <pixelflinger/pixelflinger.h>
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include "minui.h"
|
||||
|
||||
struct fb_var_screeninfo vi;
|
||||
GGLSurface gr_mem_surface;
|
||||
|
||||
int gr_save_screenshot(const char *dest)
|
||||
{
|
||||
uint32_t y, stride_bytes;
|
||||
int res = -1;
|
||||
GGLContext *gl = NULL;
|
||||
GGLSurface surface;
|
||||
uint8_t * volatile img_data = NULL;
|
||||
uint8_t *ptr;
|
||||
FILE *fp = NULL;
|
||||
png_structp png_ptr = NULL;
|
||||
png_infop info_ptr = NULL;
|
||||
|
||||
fp = fopen(dest, "wb");
|
||||
if(!fp)
|
||||
goto exit;
|
||||
|
||||
img_data = malloc(vi.xres * vi.yres * 3);
|
||||
surface.version = sizeof(surface);
|
||||
surface.width = gr_mem_surface.width;
|
||||
surface.height = gr_mem_surface.height;
|
||||
surface.stride = gr_mem_surface.width;
|
||||
surface.data = img_data;
|
||||
surface.format = GGL_PIXEL_FORMAT_RGB_888;
|
||||
|
||||
gglInit(&gl);
|
||||
gl->colorBuffer(gl, &surface);
|
||||
gl->activeTexture(gl, 0);
|
||||
|
||||
gl->bindTexture(gl, &gr_mem_surface);
|
||||
gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
|
||||
gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
|
||||
gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
|
||||
gl->enable(gl, GGL_TEXTURE_2D);
|
||||
gl->texCoord2i(gl, 0, 0);
|
||||
gl->recti(gl, 0, 0, gr_mem_surface.width, gr_mem_surface.height);
|
||||
|
||||
gglUninit(gl);
|
||||
gl = NULL;
|
||||
|
||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png_ptr)
|
||||
goto exit;
|
||||
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == NULL)
|
||||
goto exit;
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr)))
|
||||
goto exit;
|
||||
|
||||
png_init_io(png_ptr, fp);
|
||||
png_set_IHDR(png_ptr, info_ptr, surface.width, surface.height,
|
||||
8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
ptr = img_data;
|
||||
stride_bytes = surface.width*3;
|
||||
for(y = 0; y < surface.height; ++y)
|
||||
{
|
||||
png_write_row(png_ptr, ptr);
|
||||
ptr += stride_bytes;
|
||||
}
|
||||
|
||||
png_write_end(png_ptr, NULL);
|
||||
|
||||
res = 0;
|
||||
exit:
|
||||
if(info_ptr)
|
||||
png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
|
||||
if(png_ptr)
|
||||
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
|
||||
if(gl)
|
||||
gglUninit(gl);
|
||||
if(img_data)
|
||||
free(img_data);
|
||||
if(fp)
|
||||
fclose(fp);
|
||||
return res;
|
||||
}
|
||||
@@ -52,6 +52,8 @@ unsigned int gr_get_height(gr_surface surface);
|
||||
int gr_get_surface(gr_surface* surface);
|
||||
int gr_free_surface(gr_surface surface);
|
||||
|
||||
int gr_save_screenshot(const char *dest);
|
||||
|
||||
// input event structure, include <linux/input.h> for the definition.
|
||||
// see http://www.mjmwired.net/kernel/Documentation/input/ for info.
|
||||
struct input_event;
|
||||
|
||||
@@ -1176,4 +1176,22 @@ std::vector<std::string> TWFunc::Split_String(const std::string& str, const std:
|
||||
return res;
|
||||
}
|
||||
|
||||
bool TWFunc::Create_Dir_Recursive(const std::string& path, mode_t mode, uid_t uid, gid_t gid)
|
||||
{
|
||||
std::vector<std::string> parts = Split_String(path, "/");
|
||||
std::string cur_path;
|
||||
struct stat info;
|
||||
for(size_t i = 0; i < parts.size(); ++i)
|
||||
{
|
||||
cur_path += "/" + parts[i];
|
||||
if(stat(cur_path.c_str(), &info) < 0 || !S_ISDIR(info.st_mode))
|
||||
{
|
||||
if(mkdir(cur_path.c_str(), mode) < 0)
|
||||
return false;
|
||||
chown(cur_path.c_str(), uid, gid);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // ndef BUILD_TWRPTAR_MAIN
|
||||
|
||||
@@ -82,6 +82,7 @@ public:
|
||||
static void Auto_Generate_Backup_Name(); // Populates TW_BACKUP_NAME with a backup name based on current date and ro.build.display.id from /system/build.prop
|
||||
static void Fixup_Time_On_Boot(); // Fixes time on devices which need it
|
||||
static std::vector<std::string> Split_String(const std::string& str, const std::string& delimiter, bool removeEmpty = true); // Splits string by delimiter
|
||||
static bool Create_Dir_Recursive(const std::string& path, mode_t mode = 0755, uid_t uid = -1, gid_t gid = -1); // Create directory and it's parents, if they don't exist. mode, uid and gid are set to all _newly_ created folders. If whole path exists, do nothing.
|
||||
|
||||
private:
|
||||
static void Copy_Log(string Source, string Destination);
|
||||
|
||||
Reference in New Issue
Block a user