The complete code sample for a window screenshot is listed below.
In the following code sample, an hourglass is placed in the top left corner of an application window while a vertical bar sweeps from left to right across the screen. The background window is of type SCREEN_APPLICATION_WINDOW, while the hourglass and the bar are implemented as windows of type SCREEN_CHILD_WINDOW.
This code sample performs a screenshot of the hourglass window upon a MTOUCH touch event. The screenshot of the hourglass window is written to a designated bitmap on the system.
#include <ctype.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <screen/screen.h> const char *hg_id_string = "hourglass"; const char *bar_id_string = "bar"; const int barwidth = 32; screen_window_t screen_bg_win = NULL; screen_window_t screen_hg_win = NULL; screen_window_t screen_bar_win = NULL; /* Create the background window in this example */ screen_window_t create_bg_window(const char *group, int dims[2], screen_context_t screen_ctx) { /* Start by creating the context, application window and window group. */ screen_window_t screen_win; screen_create_window(&screen_win, screen_ctx); screen_create_window_group(screen_win, group); /* Set the visibility of this window to FALSE; we want to make all windows * invisible until all the windows have been created and are ready to be displayed.*/ int vis = 0; screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_VISIBLE, &vis); /* Set the color of the background window. */ int color = 0xffffff00; screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_COLOR, &color); /* Screen and Windowing API * requires all visible windows to have at least one buffer, so * here we will create the smallest possible buffer since you don't need to use this buffer * in this example.*/ int rect[4] = { 0, 0, 1, 1 }; screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, rect+2); screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_SOURCE_SIZE, dims); /* Move the source viewport to outside the bounds of the window buffer to allow the * windowing system to replace all areas outside of the buffer with the window color.*/ int pos[2] = { -dims[0], -dims[1] }; screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_SOURCE_POSITION, pos); /* Create and post the window buffer to make this window visible when we are ready. */ screen_buffer_t screen_buf; screen_create_window_buffers(screen_win, 1); screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&screen_buf); screen_post_window(screen_win, screen_buf, 1, rect, 0); return screen_win; } /* Create the bar window in this example.*/ void create_bar_window(const char *group, const char *id, int dims[2]) { /* Start by creating the another context. A separate context for each child window * emphasizes the steps required on how to deal with child windows created by other processes.*/ screen_context_t screen_ctx; screen_create_context(&screen_ctx, SCREEN_APPLICATION_CONTEXT); /* Create a child window. */ screen_window_t screen_win; screen_create_window_type(&screen_win, screen_ctx, SCREEN_CHILD_WINDOW); screen_join_window_group(screen_win, group); screen_set_window_property_cv(screen_win, SCREEN_PROPERTY_ID_STRING, strlen(id), id); /* Set the visibility to FALSE. */ int vis = 0; screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_VISIBLE, &vis); /* Set the color of the bar window. */ int color = 0xff0000ff; screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_COLOR, &color); /* Screen and Windowing * API requires all visible windows to have at least one buffer, so * here we will create the smallest possible buffer since you don't need to use this buffer * in this example.*/ int rect[4] = { 0, 0, 1, 1 }; screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, rect+2); /* Move the source viewport to outside the bounds of the window buffer to allow the windowing system to replace all areas outside of the buffer with the window color.*/ int pos[2] = { -rect[2], -rect[3] }; screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_SOURCE_POSITION, pos); /* Create and post the window buffer to make this window visible when we are ready. */ screen_buffer_t screen_buf; screen_create_window_buffers(screen_win, 1); screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&screen_buf); screen_post_window(screen_win, screen_buf, 1, rect, 0); } /* Create the hourglass window in this example. */ void create_hg_window(const char *group, const char *id, int dims[2]) { int i, j; /* Start by creating the another context. A separate context for each child window emphasizes the steps required on how to deal with child windows created by other processes.*/ screen_context_t screen_ctx; screen_create_context(&screen_ctx, SCREEN_APPLICATION_CONTEXT); /* Create a child window. */ screen_window_t screen_win; screen_create_window_type(&screen_win, screen_ctx, SCREEN_CHILD_WINDOW); screen_join_window_group(screen_win, group); screen_set_window_property_cv(screen_win, SCREEN_PROPERTY_ID_STRING, strlen(id), id); /* Set the static window property to indicate that the contents of this window buffer will not change and therefore posting will not be expected.*/ int flag = 1; screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_STATIC, &flag); /* Set the visibility to FALSE. */ int vis = 0; screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_VISIBLE, &vis); /* Set the pixel format. The hourglass shape will have transparency, so we need * a pixel format with an alpha channel; here we choose RGBA8888.*/ int format = SCREEN_FORMAT_RGBA8888; screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_FORMAT, &format); /* Set usage flag. Usage flag must be set to write in order for us to draw to the * window buffer. */ int usage = SCREEN_USAGE_WRITE; screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage); /* Set the transparency mode. * By default, RGBA8888 formats will have the transparency mode set to * source over. The windowing system assumes that if an application chooses * rgba over rgbx, it's because it wants to do some blending. However, * it is good practice to set the transparency mode. */ int transparency = SCREEN_TRANSPARENCY_SOURCE_OVER; screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_TRANSPARENCY, &transparency); /* Set the window buffer size for the hourglass. */ int rect[4] = { 0, 0, 100, 100 }; screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, rect+2); /* Create the window buffer and then get a handle to this buffer. */ screen_buffer_t screen_buf; screen_create_window_buffers(screen_win, 1); screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&screen_buf); /* Get the pointer to this buffer in order to fill the hourglass shape. */ char *ptr = NULL; screen_get_buffer_property_pv(screen_buf, SCREEN_PROPERTY_POINTER, (void **)&ptr); /* Get the stride (the number of bytes between pixels on different rows) so that we can * use it to draw the hourglass shape. */ int stride = 0; screen_get_buffer_property_iv(screen_buf, SCREEN_PROPERTY_STRIDE, &stride); /* Draw the hourglass shape. */ for (i = 0; i < rect[3]; i++, ptr += stride) { for (j = 0; j < rect[2]; j++) { ptr[j*4] = 0xa0; ptr[j*4+1] = 0xa0; ptr[j*4+2] = 0xa0; ptr[j*4+3] = ((j >= i && j <= rect[3]-i) || (j <= i && j >= rect[3]-i)) ? 0xff : 0; } } /* Post the window. */ screen_post_window(screen_win, screen_buf, 1, rect, 0); } void write_bitmap_header(int nbytes, int fd, const int size[]) { char header[54]; /* Set standard bitmap header */ header[0] = 'B'; header[1] = 'M'; header[2] = nbytes & 0xff; header[3] = (nbytes >> 8) & 0xff; header[4] = (nbytes >> 16) & 0xff; header[5] = (nbytes >> 24) & 0xff; header[6] = 0; header[7] = 0; header[8] = 0; header[9] = 0; header[10] = 54; header[11] = 0; header[12] = 0; header[13] = 0; header[14] = 40; header[15] = 0; header[16] = 0; header[17] = 0; header[18] = size[0] & 0xff; header[19] = (size[0] >> 8) & 0xff; header[20] = (size[0] >> 16) & 0xff; header[21] = (size[0] >> 24) & 0xff; header[22] = -size[1] & 0xff; header[23] = (-size[1] >> 8) & 0xff; header[24] = (-size[1] >> 16) & 0xff; header[25] = (-size[1] >> 24) & 0xff; header[26] = 1; header[27] = 0; header[28] = 32; header[29] = 0; header[30] = 0; header[31] = 0; header[32] = 0; header[33] = 0; header[34] = 0; /* image size*/ header[35] = 0; header[36] = 0; header[37] = 0; header[38] = 0x9; header[39] = 0x88; header[40] = 0; header[41] = 0; header[42] = 0x9l; header[43] = 0x88; header[44] = 0; header[45] = 0; header[46] = 0; header[47] = 0; header[48] = 0; header[49] = 0; header[50] = 0; header[51] = 0; header[52] = 0; header[53] = 0; /* Write bitmap header to file */ write(fd, header, sizeof(header)); } void write_bitmap_file(const int size[], const char* screenshot_ptr, const int screenshot_stride) { int nbytes; /* number of bytes of the bimap */ int fd /* file descriptor */ int i; /* iterator to iterate over the screenshot buffer */ char *fname = "/accounts/1000/appdata/com.example.Tutorial_WindowApp." "testDev_l_WindowApp85f8001_/data/hourglass_window_screenshot.bmp"; /* bitmap filename */ /* Calculate the size of the bitmap */ nbytes = size[0] * size[1] * 4; /* Open file*/ fd = creat(fname, S_IRUSR | S_IWUSR); /* Write the standard bitmap header */ write_bitmap_header(nbytes, fd, size); /* Write screenshot buffer contents to file */ for (i = 0; i < size[1]; i++) { write(fd, screenshot_ptr + i * screenshot_stride, size[0] * 4); } } /* Take window screenshot. */ void take_window_screenshot(screen_window_t screenshot_win, screen_context_t screenshot_ctx) { /* Variables for setting up taking a screenshot. */ screen_pixmap_t screen_pix; screen_buffer_t screenshot_buf; char *screenshot_ptr = NULL; int screenshot_stride = 0; int usage, format; int size[2]; /* Create pixmap. */ screen_create_pixmap(&screen_pix, screenshot_ctx); /* Set Usage Flags. */ usage = SCREEN_USAGE_READ | SCREEN_USAGE_NATIVE; screen_set_pixmap_property_iv(screen_pix, SCREEN_PROPERTY_USAGE, &usage); /* Set format. */ format = SCREEN_FORMAT_RGBA8888; screen_set_pixmap_property_iv(screen_pix, SCREEN_PROPERTY_FORMAT, &format); /* Set pixmap buffer size */ size[0] = 200; size[1] = 200; screen_set_pixmap_property_iv(screen_pix, SCREEN_PROPERTY_BUFFER_SIZE, size); /* Create pixmap buffer and get handle to the buffer. */ screen_create_pixmap_buffer(screen_pix); screen_get_pixmap_property_pv(screen_pix, SCREEN_PROPERTY_RENDER_BUFFERS, (void**)&screenshot_buf); /* Get a pointer to the buffer. */ screen_get_buffer_property_pv(screenshot_buf, SCREEN_PROPERTY_POINTER, (void**)&screenshot_ptr); /* Get the stride. */ screen_get_buffer_property_iv(screenshot_buf, SCREEN_PROPERTY_STRIDE, &screenshot_stride); /* Take the window screenshot. */ screen_read_window(screenshot_win, screenshot_buf, 0, NULL ,0); /* Write the screenshot buffer to a bitmap file*/ write_bitmap_file(size, screenshot_ptr, screenshot_stride); /* Perform necessary Screen and Windowing API clean-up. */ screen_destroy_pixmap(screen_pix); } int main(int argc, char **argv) { int pos[2], size[2]; int vis = 0; int type; /* Create the context to set up connection with the windowing system. */ screen_context_t screen_ctx; screen_create_context(&screen_ctx, SCREEN_APPLICATION_CONTEXT); /* Specify the dimensions when creating our child windows. */ /* Get all displays available for the context. */ int count = 0; screen_get_context_property_iv(screen_ctx, SCREEN_PROPERTY_DISPLAY_COUNT, &count); screen_display_t *screen_disps = calloc(count, sizeof(screen_display_t)); screen_get_context_property_pv(screen_ctx, SCREEN_PROPERTY_DISPLAYS, (void **)screen_disps); screen_display_t screen_disp = screen_disps[0]; free(screen_disps); /* Get the size of the display; we will use this as the dimensions for our windows. */ int dims[2] = { 0, 0 }; screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, dims); /* Construct a unique name for the window group. */ char str[16]; snprintf(str, sizeof(str), "%d", getpid()); /* Create the parent window; in this example the background window is the parent. */ screen_bg_win = create_bg_window(str, dims, screen_ctx); /* Create the child windows. */ create_bar_window(str, bar_id_string, dims); create_hg_window(str, hg_id_string, dims); /* Create a screen event handle to be used to receive events from the windowing system. */ screen_event_t screen_ev; screen_create_event(&screen_ev); while (1) { do { /* Wait for next event. */ screen_get_event(screen_ctx, screen_ev, vis ? 0 : ~0); screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_TYPE, &type); /* We are interested only in post, close and mtouch events in this example. */ if (type == SCREEN_EVENT_POST) { /* Get the handle for the window for this post event. */ screen_window_t screen_win; screen_get_event_property_pv(screen_ev, SCREEN_PROPERTY_WINDOW, (void **)&screen_win); screen_get_window_property_cv(screen_win, SCREEN_PROPERTY_ID_STRING, sizeof(str), str); /* Determine which window is posting. */ if (!screen_bar_win && !strcmp(str, bar_id_string)) { screen_bar_win = screen_win; } else if (!screen_hg_win && !strcmp(str, hg_id_string)) { screen_hg_win = screen_win; } /* Once the child windows have been created and posted, switch * all windows to be visible.*/ if (screen_bar_win && screen_hg_win) { vis = 1; /* Set the screen size to full screen, except for the hourglass which will be 100x100 * and positioned at 10, 10. */ screen_get_window_property_iv(screen_hg_win, SCREEN_PROPERTY_BUFFER_SIZE, size); screen_set_window_property_iv(screen_hg_win, SCREEN_PROPERTY_SIZE, size); pos[0] = pos[1] = 10; screen_set_window_property_iv(screen_hg_win, SCREEN_PROPERTY_POSITION, pos); pos[0] = pos[1] = 0; screen_set_window_property_iv(screen_bar_win, SCREEN_PROPERTY_POSITION, pos); screen_set_window_property_iv(screen_bg_win, SCREEN_PROPERTY_POSITION, pos); size[0] = barwidth; size[1] = dims[1]; screen_set_window_property_iv(screen_bar_win, SCREEN_PROPERTY_SIZE, size); size[0] = dims[0]; screen_set_window_property_iv(screen_bg_win, SCREEN_PROPERTY_SIZE, size); int zorder = 0; screen_set_window_property_iv(screen_bg_win, SCREEN_PROPERTY_ZORDER, &zorder); zorder++; screen_set_window_property_iv(screen_bar_win, SCREEN_PROPERTY_ZORDER, &zorder); zorder++; screen_set_window_property_iv(screen_hg_win, SCREEN_PROPERTY_ZORDER, &zorder); /* Set all windows visible. */ screen_set_window_property_iv(screen_bg_win, SCREEN_PROPERTY_VISIBLE, &vis); screen_set_window_property_iv(screen_hg_win, SCREEN_PROPERTY_VISIBLE, &vis); screen_set_window_property_iv(screen_bar_win, SCREEN_PROPERTY_VISIBLE, &vis); screen_flush_context(screen_ctx, SCREEN_WAIT_IDLE); } } else if (type == SCREEN_EVENT_CLOSE) { /* Handle the window that just posted the close event. */ screen_window_t screen_win; screen_get_event_property_pv(screen_ev, SCREEN_PROPERTY_WINDOW, (void **)&screen_win); /* Track the window that just closed. */ if (screen_win == screen_bar_win) { screen_bar_win = NULL; } else if (screen_win == screen_hg_win) { screen_hg_win = NULL; } /* Destroy the window that just closed, so that resources that * were allocated locally can be freed. */ screen_destroy_window(screen_win); /* Update visibility for that window. */ if (!screen_bar_win || !screen_hg_win) { vis = 0; } }else if (type == SCREEN_EVENT_MTOUCH_TOUCH){ /* Handle the mtouch event to take screenshot of hourglass window. */ take_window_screenshot(screen_hg_win, screen_ctx); } } while (type != SCREEN_EVENT_NONE); /* Wrap the position of the bar window back at the origin of the buffer before * the bar goes off the edge. Also, to prevent the animation from moving the * bar too fast, we will call screen_flush_context with the appropriate flags. * This will limit the animation to the refresh rate of the display. */ if (vis) { if (++pos[0] > dims[0] - barwidth) { pos[0] = 0; } screen_set_window_property_iv(screen_bar_win, SCREEN_PROPERTY_POSITION, pos); screen_flush_context(screen_ctx, SCREEN_WAIT_IDLE); } } /* Perform necessary cleanup. In this example we will rely on the windowing system * to release the resources for the bar and hourglass window contexts when the * process exits. */ screen_destroy_event(screen_ev); screen_destroy_context(screen_ctx); return EXIT_SUCCESS; }