screen.c

Window management of a simple window manager.

/*
* $QNXLicenseC:
* Copyright 2012, QNX Software Systems Limited. All Rights Reserved.
*
* This software is QNX Confidential Information subject to
* confidentiality restrictions. DISCLOSURE OF THIS SOFTWARE
* IS PROHIBITED UNLESS AUTHORIZED BY QNX SOFTWARE SYSTEMS IN
* WRITING.
*
* You must obtain a written license from and pay applicable license
* fees to QNX Software Systems Limited before you may reproduce, modify
* or distribute this software, or any work that includes all or part
* of this software. For more information visit
* http://licensing.qnx.com or email licensing@qnx.com.
*
* This file may contain contributions from others.  Please review
* this entire file for other proprietary rights or license notices,
* as well as the QNX Development Suite License Guide at
* http://licensing.qnx.com/license-guide/ for other information.
* $
*/

#include "struct.h"

static void set_window_properties(screen_window_t win){
    static int size[2] = {400, 240};
    static int pos[2] = {0, 0};
    static int order = 100;

    // if it is the video clip, set it to a fixed position
    static int i = 0;
    int r = i%4;

    if (r == 0 ){
        pos[0] = 0;
        pos[1] = 0;
    } else if (r == 1){
        pos[0] = 400;
        pos[1] = 0;
    } else if (r == 2){
        pos[0] = 0;
        pos[1] = 240;
    } else if (r == 3){
        pos[0] = 400;
        pos[1] = 240;
    }

    screen_set_window_property_iv(win, SCREEN_PROPERTY_SIZE, size);
    screen_set_window_property_iv(win, SCREEN_PROPERTY_POSITION, pos);
    screen_set_window_property_iv(win, SCREEN_PROPERTY_ZORDER, &order);

//    printf("application index: %d\tpos: %d,%d\n", r, pos[0], pos[1]);
    i++;
}

int screen_init(window_manager_t *winmgr, int argc, char **argv){

    /**
     ** This is the size for an invisible exit button. We choose a value that's
     ** big enough to be useable with touchscreens and pointer devices.
     **/


    screen_context_t screen_ctx;   /* connection to screen windowing system */
    screen_window_t screen_win;    /* native handle for our window */
    screen_buffer_t screen_buf;    /* renderable buffers for the window */
    screen_event_t screen_ev;      /* handle used to pop events from our queue */
    int size[2] = { 64, 64 };      /* size of the window on screen */
    int pos[2] = { 0, 0 };         /* position of the window on screen */
    int val;                       /* used for simple property queries */
    const char *tok;               /* used to process command line arguments */
    int rval = EXIT_FAILURE;       /* application exits with value stored here */
    int rc;                        /* store return value from functions */
    int i;                         /* loop/frame counter */
    int stride;                    /* size of each window line in bytes */
    void *pointer;                 /* virtual address of the window buffer */
    int zorder = 0;
    char *group_name = strdup("default-group");

    /**
     ** We start by processing the command line arguments. The first argument
     ** is skipped because it contains the name of the program. Arguments
     ** follow the syntax -(option)=(value).
     **/

    for (i = 1; i < argc; i++) {
        if (strncmp(argv[i], "-size=", strlen("-size=")) == 0) {
            /**
             ** The syntax of the size option is -size=(width)x(height).
             **/

            tok = argv[i] + strlen("-size=");
            size[0] = atoi(tok);
            while (*tok >= '0' && *tok <= '9') {
                tok++;
            }
            size[1] = atoi(tok+1);
        } else if (strncmp(argv[i], "-pos=", strlen("-pos=")) == 0) {
            /**
             ** The syntax of the pos option is -pos=(x),(y).
             **/

            tok = argv[i] + strlen("-pos=");
            pos[0] = atoi(tok);
            while (*tok >= '0' && *tok <= '9') {
                tok++;
            }
            pos[1] = atoi(tok+1);
        } else if (strncmp(argv[i], "-order=", strlen("-order=")) == 0){
            tok = argv[i] + strlen("-order=");
            zorder = atoi(tok);
        } else if (strncmp(argv[i], "-name=", strlen("-name=")) == 0){
            tok = argv[i] + strlen("-name=");
            if (group_name){
                free(group_name);
            }
            group_name = strdup(tok);
        } else {
            /**
             ** Make sure we say something instead of silently ignoring a
             ** command line option.
             **/

            fprintf(stderr, "invalid command line option: %s\n", argv[i]);
        }
    }

    /**
     ** The first step is to connect to the windowing system. A standard
     ** application would pass a 0 or SCREEN_APPLICATION_CONTEXT for the
     ** second argument. We are demonstration some of the features the
     ** screen windowing system provides to window managers, so in our case
     ** we want to pass SCREEN_WINDOW_MANAGER_CONTEXT. For security reasons,
     ** this can only succeed if the application is started as root.
     **/

    rc = screen_create_context(&screen_ctx, SCREEN_WINDOW_MANAGER_CONTEXT);

    if (rc) {
        perror("screen_context_create");
        goto fail1;
    }



    /**
     ** Now we create a window. Note that it is not necessary to have a window
     ** to get window manager events like window creation and destruction
     ** notifications. We create a window so we can get input events like
     ** pointer and keyboard events.
     **/

    rc = screen_create_window(&screen_win, screen_ctx);
    if (rc) {
        perror("screen_create_window");
        goto fail2;
    }



    /**
     ** We are going to use a plain memset to fill our window with a solid
     ** color. In order to guarantee that we will get a pointer to the buffer,
     ** we must set the usage to SCREEN_USAGE_WRITE. The SCREEN_PROPERTY_USAGE
     ** requires an array of a single integer. We will use val as a generic
     ** variable to hold our usage temporarily.
     **/

    val = SCREEN_USAGE_WRITE;
    rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &val);
    if (rc) {
        perror("screen_set_window_property_iv(SCREEN_PROPERTY_USAGE)");
        goto fail3;
    }

//    val = SCREEN_FORMAT_RGB565;
//    rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_FORMAT, &val);
//    if (rc) {
//        perror("screen_set_window_property_iv(SCREEN_PROPERTY_FORMAT)");
//        goto fail3;
//    }


    /**
     ** By default, windows are full screen unless the application specifically
     ** sets the window size. We don't necessarily want to be full screen,
     ** since we'll want to run a couple of other applications to show that we
     ** are getting window manager events. The SCREEN_PROPERTY_SIZE requires
     ** two integers (the width and height), so we use the iv variant and pass
     ** size, which is an array of two.
     **/

    rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_SIZE, size);
    if (rc) {
        perror("screen_set_window_property_iv(SCREEN_PROPERTY_SIZE)");
        goto fail3;
    }

    /**
     ** We also allow the position of our window to be controlled by the -pos
     ** command line argument. This might be useful if the default position
     ** obscured an area of interest of another window we want to see while
     ** running this tutorial. The SCREEN_PROPERTY_POSITION also requires two
     ** integers (the x and y offsets), so again we use the iv variant and pass
     ** pos, which is an array of two integers.
     **/

    rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_POSITION, pos);
    if (rc) {
        perror("screen_set_window_property_iv(SCREEN_PROPERTY_POSITION)");
        goto fail3;
    }

    rc = screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_ZORDER, &zorder);
    if (rc) {
        perror("screen_set_window_property_iv(SCREEN_PROPERTY_POSITION)");
        goto fail3;
    }

    /**
     ** A window will never be visible until at least one buffer was created
     ** to hold its contents and one frame was posted. Since we don't plan on
     ** changing the contents of this window at all, there is no need for more
     ** than a single buffer.
     **/

    rc = screen_create_window_buffers(screen_win, 1);
    if (rc) {
        perror("screen_create_window_buffers");
        goto fail3;
    }

    /**
     ** We want to fill our window with a solid color so we can see it. In
     ** order to do that we will need to get a pointer to the buffer. We get
     ** the buffer first, so we can later query the pointer and stride
     ** properties that we need. The SCREEN_PROPERTY_RENDER_BUFFERS returns
     ** up to n buffers, where n is the number of buffers created or attached
     ** to a window. We've created one, so we only need to pass in an array
     ** of one buffer handle.
     **/

    rc = screen_get_window_property_pv(screen_win,
                                       SCREEN_PROPERTY_RENDER_BUFFERS,
                                       (void **)&screen_buf);
    if (rc) {
        perror("screen_get_pixmap_property_pv(SCREEN_PROPERTY_RENDER_BUFFERS)");
        goto fail3;
    }

    /**
     ** Now we query the pointer from our buffer. Because we've set the usage
     ** to include write access, this should be a pointer to memory we can
     ** write to. The SCREEN_PROPERTY_POINTER returns a single pointer, so we
     ** pass the address of a void pointer variable, which is equivalent to
     ** passing an array of one pointer.
     **/

    rc = screen_get_buffer_property_pv(screen_buf, SCREEN_PROPERTY_POINTER, &pointer);
    if (rc) {
        perror("screen_get_buffer_property_pv(SCREEN_PROPERTY_POINTER)");
        goto fail3;
    }

    /**
     ** The last piece of information we need before we can fill our window
     ** with a solid color is the stride of the buffer. The stride is the size,
     ** in bytes, of each line of the buffer. This may or may not be the same
     ** as the width times the bit depth. The SCREEN_PROPERTY_STRIDE writes to
     ** an array of one integer, so we can pass in the address of our stride
     ** variable.
     **/

    rc = screen_get_buffer_property_iv(screen_buf, SCREEN_PROPERTY_STRIDE, &stride);
    if (rc) {
        perror("screen_get_buffer_property_iv(SCREEN_PROPERTY_STRIDE)");
        goto fail3;
    }

    /**
     ** The following line fills the window buffer with a solid color pattern.
     ** We don't really care about the color, as long as we see something on
     ** the screen, so we will simply use memset. The transparency will be off
     ** by default, and our format is RGBX8888, so we don't need to put a 255
     ** in the alpha channel.
     **/

    memset(pointer, 0x80, stride * size[1]);

    // to test window group
    rc = screen_create_window_group(screen_win, group_name);
    if (rc) {
        perror("screen_create_window_group");
        goto fail3;
    }

    /**
     ** Nothing is going to be visible on the screen until we post the changes.
     ** Posting will tell the windowing system that we're done drawing into our
     ** render buffer and that we want the changes to be made visible. When we
     ** post we must indicate which parts of the buffer have changed. This
     ** allows the composited windowing system to be smart and redraw only the
     ** parts of the frame buffer that need an update. Since this is our first
     ** frame we naturally put a full dirty rect.
     **/

    int rect[4] = { 0, 0, size[0], size[1] };
    rc = screen_post_window(screen_win, screen_buf, 1, rect, 0);
    if (rc) {
        perror("screen_post_window");
        goto fail3;
    }

    rc = screen_flush_context(screen_ctx, SCREEN_WAIT_IDLE);
    if (rc) {
            perror("screen_post_window");
            goto fail3;
        }


    rc = screen_create_event(&screen_ev);
    if (rc) {
        perror("screen_create_event");
        goto fail3;
    }

    screen_display_t *displays;
    int display_count = 0, port;

    printf("checking displays\n");
    screen_get_context_property_iv(screen_ctx, SCREEN_PROPERTY_DISPLAY_COUNT, &display_count);
    printf("%d displays\n", display_count);
    displays = malloc(display_count * sizeof(screen_display_t));
    screen_get_context_property_pv(screen_ctx, SCREEN_PROPERTY_DISPLAYS, (void *)displays);
    for(i = 0; i < display_count; i++ ) {
        screen_get_display_property_iv(displays[i], SCREEN_PROPERTY_ATTACHED, &val);
        screen_get_display_property_iv(displays[i], SCREEN_PROPERTY_ID, &port);
        printf("display %d (port %d) is %stached\n", i, port, val?"at":"de");
    }

    winmgr->screen_ctx = screen_ctx;
    winmgr->screen_win = screen_win;
    winmgr->screen_ev = screen_ev;

    return EOK;

    fail3:
        screen_destroy_window(screen_win);
    fail2:
        screen_destroy_context(screen_ctx);
    fail1:
        return rval;
}


void *screen_thread(void *arg){
    window_manager_t *winmgr = (window_manager_t*)arg;

    const int exit_area_size = 20;

    screen_context_t screen_ctx = winmgr->screen_ctx;   /* connection to screen windowing system */
    screen_window_t screen_win = winmgr->screen_win;    /* native handle for our window */
    screen_event_t screen_ev = winmgr->screen_ev;      /* handle used to pop events from our queue */
    screen_window_t win;           /* stores a window contained in an event */
    int size[2] = { 64, 64 };      /* size of the window on screen */
    int val;                       /* used for simple property queries */
    int pair[2];                   /* used to query pos, size */
    void *ptr;                     /* used to query user handles */
    char str[128];                 /* used to query string properties */
    int i;                         /* loop/frame counter */
//    void *pointer;                 /* virtual address of the window buffer */
//    int zorder = 0;

    screen_display_t *displays, disp;
    int display_count = 0, port;

//    char *group_name = strdup("default-group");

    pthread_setname_np(winmgr->screen_tid = pthread_self(), "screen_monitor");

    while (winmgr->state & WINMGR_UPDATE) {
        while (!screen_get_event(screen_ctx, screen_ev, ~0L)) {
            screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_TYPE, &val);
            switch (val) {
                case SCREEN_EVENT_DISPLAY:
                    if ( screen_get_event_property_pv(screen_ev,
                                                      SCREEN_PROPERTY_DISPLAY,
                                                      (void *)&disp) == 0 ) {
                        printf("SCREEN_EVENT_DISPLAY(display=%p)\n", disp);
                    } else {
                        perror("SCREEN_PROPERTY_DISPLAY");
                        break;
                    }
                    screen_get_display_property_iv(disp, SCREEN_PROPERTY_TYPE, &val);
                    switch(val) {
                    case SCREEN_DISPLAY_TYPE_HDMI:
                        screen_get_display_property_iv(disp, SCREEN_PROPERTY_ATTACHED, &val);
                        port = 0;
                        screen_get_display_property_iv(disp, SCREEN_PROPERTY_ID, &port);
                        printf("HDMI display (port %d) is %stached\n", port, val?"at":"de");
                        break;
                    default:
                        printf("display %p is type %#x\n", disp, val );
                        break;
                    }
                    break;
                case SCREEN_EVENT_IDLE:
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_IDLE_STATE, &val);
                    printf("SCREEN_EVENT_IDLE_STATE(state=%d)\n", val);
                    screen_get_context_property_iv(screen_ctx, SCREEN_PROPERTY_IDLE_STATE, &val);
                    printf("context idle state is %d\n", val);
                    screen_get_context_property_iv(screen_ctx,
                                                   SCREEN_PROPERTY_DISPLAY_COUNT,
                                                   &display_count);
                    printf("%d displays\n", display_count);
                    displays = malloc(display_count * sizeof(screen_display_t));
                    screen_get_context_property_pv(screen_ctx,
                                                   SCREEN_PROPERTY_DISPLAYS,
                                                   (void *)displays);
                    for (i=0; i < display_count; i++) {
                        screen_get_display_property_iv(displays[i],
                                                       SCREEN_PROPERTY_KEEP_AWAKES,
                                                       &val);
                        printf("display %d has %d keep awake windows\n", i, val );
                    }
                    free(displays);
                    break;
                case SCREEN_EVENT_CREATE:
                    screen_get_event_property_pv(screen_ev, SCREEN_PROPERTY_WINDOW, (void **)&win);
                    screen_get_window_property_iv(win, SCREEN_PROPERTY_OWNER_PID, &val);
                    printf("SCREEN_EVENT_CREATE(window=0x%08x,
                                                pid=%d,
                                                handle=0x%08x)\n",
                                                (size_t)win,
                                                val,
                                                (size_t)ptr);
                    break;
                case SCREEN_EVENT_PROPERTY:
                    screen_get_event_property_pv(screen_ev, SCREEN_PROPERTY_WINDOW, (void **)&win);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_NAME, &val);
                    switch (val) {
                        case SCREEN_PROPERTY_ALPHA_MODE:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_ALPHA_MODE, &val);
                            if (val) {
                                printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                              pname=SCREEN_PROPERTY_ALPHA_MODE,
                                                              value=SCREEN_ALPHA_MODE_PREMULTIPLIED)\n",
                                                              (size_t)win);
                            } else {
                                printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                              pname=SCREEN_PROPERTY_ALPHA_MODE,
                                                              value=SCREEN_ALPHA_MODE_NONPREMULTIPLIED)\n",
                                                              (size_t)win);
                            }
                            break;
                        case SCREEN_PROPERTY_BRIGHTNESS:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_BRIGHTNESS, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_BRIGHTNESS,
                                                          value=%d)\n",
                                                          (size_t)win,
                                                          val);
                            break;
                        case SCREEN_PROPERTY_BUFFER_COUNT:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_BUFFER_COUNT, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_BUFFER_COUNT,
                                                          value=%d)\n",
                                                          (size_t)win,
                                                          val);
                            break;
                        case SCREEN_PROPERTY_BUFFER_SIZE:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_BUFFER_SIZE, pair);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_BUFFER_COUNT,
                                                          value=%dx%d)\n",
                                                          (size_t)win,
                                                          pair[0],
                                                          pair[1]);
                            break;
                        case SCREEN_PROPERTY_CLASS:
                            screen_get_window_property_cv(win, SCREEN_PROPERTY_CLASS, sizeof(str), str);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_CLASS,
                                                          value=%s)\n",
                                                          (size_t)win,
                                                          str);
                            break;
                        case SCREEN_PROPERTY_COLOR_SPACE:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_COLOR_SPACE, &val);
                            if (val) {
                                printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                              pname=SCREEN_PROPERTY_COLOR_SPACE,
                                                              value=SCREEN_COLOR_SPACE_LINEAR)\n",
                                                              (size_t)win);
                            } else {
                                printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                              pname=SCREEN_PROPERTY_COLOR_SPACE,
                                                              value=SCREEN_COLOR_SPACE_sRGB)\n",
                                                              (size_t)win);
                            }
                            break;
                        case SCREEN_PROPERTY_CONTRAST:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_CONTRAST, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_CONTRAST,
                                                          value=%d)\n",
                                                          (size_t)win,
                                                          val);
                            break;
                        case SCREEN_PROPERTY_FLIP:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_FLIP, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_FLIP,
                                                          value=%d)\n",
                                                          (size_t)win,
                                                          val);
                            break;
                        case SCREEN_PROPERTY_FORMAT:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_FORMAT, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_FORMAT,
                                                          value=",
                                                          (size_t)win);
                            switch (val) {
                                case SCREEN_FORMAT_BYTE:
                                    printf("SCREEN_FORMAT_BYTE)\n");
                                    break;
                                case SCREEN_FORMAT_RGBA4444:
                                    printf("SCREEN_FORMAT_RGBA4444)\n");
                                    break;
                                case SCREEN_FORMAT_RGBX4444:
                                    printf("SCREEN_FORMAT_RGBX4444)\n");
                                    break;
                                case SCREEN_FORMAT_RGBA5551:
                                    printf("SCREEN_FORMAT_RGBA5551)\n");
                                    break;
                                case SCREEN_FORMAT_RGBX5551:
                                    printf("SCREEN_FORMAT_RGBX5551)\n");
                                    break;
                                case SCREEN_FORMAT_RGB565:
                                    printf("SCREEN_FORMAT_RGB565)\n");
                                    break;
                                case SCREEN_FORMAT_RGB888:
                                    printf("SCREEN_FORMAT_RGB888)\n");
                                    break;
                                case SCREEN_FORMAT_RGBA8888:
                                    printf("SCREEN_FORMAT_RGBA8888)\n");
                                    break;
                                case SCREEN_FORMAT_RGBX8888:
                                    printf("SCREEN_FORMAT_RGBX8888)\n");
                                    break;
                                case SCREEN_FORMAT_YVU9:
                                    printf("SCREEN_FORMAT_YVU9)\n");
                                    break;
                                case SCREEN_FORMAT_YUV420:
                                    printf("SCREEN_FORMAT_YUV420)\n");
                                    break;
                                case SCREEN_FORMAT_NV12:
                                    printf("SCREEN_FORMAT_NV12)\n");
                                    break;
                                case SCREEN_FORMAT_YV12:
                                    printf("SCREEN_FORMAT_YV12)\n");
                                    break;
                                case SCREEN_FORMAT_UYVY:
                                    printf("SCREEN_FORMAT_UYVY)\n");
                                    break;
                                case SCREEN_FORMAT_YUY2:
                                    printf("SCREEN_FORMAT_YUY2)\n");
                                    break;
                                case SCREEN_FORMAT_YVYU:
                                    printf("SCREEN_FORMAT_YUY2)\n");
                                    break;
                                case SCREEN_FORMAT_V422:
                                    printf("SCREEN_FORMAT_V422)\n");
                                    break;
                                case SCREEN_FORMAT_AYUV:
                                    printf("SCREEN_FORMAT_AYUV)\n");
                                    break;
                                default:
                                    printf("%d)\n", val);
                                    break;
                            }
                            break;
                        case SCREEN_PROPERTY_GLOBAL_ALPHA:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_GLOBAL_ALPHA, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_GLOBAL_ALPHA, value=%d)\n",
                                                          (size_t)win,
                                                          val);
                            break;
                        case SCREEN_PROPERTY_HUE:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_HUE, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_HUE,
                                                          value=%d)\n",
                                                          (size_t)win,
                                                          val);
                            break;
                        case SCREEN_PROPERTY_ID_STRING:
                            screen_get_window_property_cv(win, SCREEN_PROPERTY_ID_STRING, sizeof(str), str);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_ID_STRING,
                                                          value=%s)\n",
                                                          (size_t)win,
                                                          str);
                            break;
                        case SCREEN_PROPERTY_MIRROR:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_MIRROR, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_MIRROR,
                                                          value=%d)\n",
                                                          (size_t)win,
                                                          val);
                            break;
                        case SCREEN_PROPERTY_POSITION:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_POSITION, pair);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_POSITION,
                                                          value=%d,%d)\n",
                                                          (size_t)win,
                                                          pair[0],
                                                          pair[1]);
                            break;
                        case SCREEN_PROPERTY_ROTATION:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_ROTATION, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_ROTATION,
                                                          value=%d)\n",
                                                          (size_t)win,
                                                          val);
                            break;
                        case SCREEN_PROPERTY_SATURATION:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_SATURATION, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_SATURATION,
                                                          value=%d)\n",
                                                          (size_t)win,
                                                          val);
                            break;
                        case SCREEN_PROPERTY_SIZE:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_SIZE, pair);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_SIZE,
                                                          value=%dx%d)\n",
                                                          (size_t)win,
                                                          pair[0],
                                                          pair[1]);
                            break;
                        case SCREEN_PROPERTY_SOURCE_POSITION:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_SOURCE_POSITION, pair);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_SOURCE_POSITION,
                                                          value=%d,%d)\n",
                                                          (size_t)win,
                                                          pair[0],
                                                          pair[1]);
                            break;
                        case SCREEN_PROPERTY_SOURCE_SIZE:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_SOURCE_SIZE, pair);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_SOURCE_SIZE,
                                                          value=%dx%d)\n",
                                                          (size_t)win,
                                                          pair[0],
                                                          pair[1]);
                            break;
                        case SCREEN_PROPERTY_STATIC:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_STATIC, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_STATIC,
                                                          value=%d)\n",
                                                          (size_t)win,
                                                          val);
                            break;
                        case SCREEN_PROPERTY_SWAP_INTERVAL:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_SWAP_INTERVAL, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_SWAP_INTERVAL,
                                                          value=%d)\n",
                                                          (size_t)win,
                                                          val);
                            break;
                        case SCREEN_PROPERTY_TRANSPARENCY:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_TRANSPARENCY, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_TRANSPARENCY,
                                                          value=",
                                                          (size_t)win);
                            switch (val) {
                                case SCREEN_TRANSPARENCY_NONE:
                                    printf("SCREEN_TRANSPARENCY_NONE)\n");
                                    break;
                                case SCREEN_TRANSPARENCY_TEST:
                                    printf("SCREEN_TRANSPARENCY_TEST)\n");
                                    break;
                                case SCREEN_TRANSPARENCY_SOURCE_COLOR:
                                    printf("SCREEN_TRANSPARENCY_SOURCE_COLOR)\n");
                                    break;
                                case SCREEN_TRANSPARENCY_SOURCE_OVER:
                                    printf("SCREEN_TRANSPARENCY_SOURCE_OVER)\n");
                                    break;
                                default:
                                    printf("%d)\n", val);
                                    break;
                            }
                            break;
                        case SCREEN_PROPERTY_USAGE:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_USAGE, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_USAGE,
                                                          value=0x%04x)\n",
                                                          (size_t)win, val);
                            break;
                        case SCREEN_PROPERTY_VISIBLE:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_VISIBLE, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_VISIBLE,
                                                          value=%d)\n",
                                                          (size_t)win,
                                                          val);
                            break;
                        case SCREEN_PROPERTY_ZORDER:
                            screen_get_window_property_iv(win, SCREEN_PROPERTY_ZORDER, &val);
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x,
                                                          pname=SCREEN_PROPERTY_ZORDER,
                                                          value=%d)\n",
                                                          (size_t)win,
                                                          val);
                            break;
                        default:
                            printf("SCREEN_EVENT_PROPERTY(window=0x%08x, pname=%d)\n", (size_t)win, val);
                            break;
                    }
                    break;
                case SCREEN_EVENT_CLOSE:
                    screen_get_event_property_pv(screen_ev, SCREEN_PROPERTY_WINDOW, (void **)&win);
                    screen_get_window_property_pv(win, SCREEN_PROPERTY_USER_HANDLE, &ptr);
                    printf("SCREEN_EVENT_CLOSE(window=0x%08x, handle=0x%08x)\n", (size_t)win, (size_t)ptr);
                    screen_destroy_window(win);
                    break;
                case SCREEN_EVENT_POST:
                    screen_get_event_property_pv(screen_ev, SCREEN_PROPERTY_WINDOW, (void **)&win);
                    screen_get_window_property_pv(win, SCREEN_PROPERTY_USER_HANDLE, &ptr);
                    printf("SCREEN_EVENT_POST(window=0x%08x, handle=0x%08x)\n", (size_t)win, (size_t)ptr);

                    set_window_properties(win);
                    screen_flush_context(screen_ctx, 0);
                    break;
                case SCREEN_EVENT_INPUT:
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_DEVICE_INDEX, &val);
                    printf("SCREEN_EVENT_INPUT(index=%d, ", val);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_INPUT_VALUE, &val);
                    printf("value=%d)\n", val);
                    break;
                case SCREEN_EVENT_JOG:
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_DEVICE_INDEX, &val);
                    printf("SCREEN_EVENT_JOG(index=%d, ", val);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_JOG_COUNT, &val);
                    printf("count=%d)\n", val);
                    break;
                case SCREEN_EVENT_POINTER:
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_DEVICE_INDEX, &val);
                    printf("SCREEN_EVENT_POINTER(index=%d, ", val);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_POSITION, pair);
                    printf("pos=[%d,%d], ", pair[0], pair[1]);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_BUTTONS, &val);
                    printf("buttons=0x%04x)\n", val);

                    if (val) {
                        if (pair[0] >= size[0] - exit_area_size &&
                            pair[0] < size[0] &&
                            pair[1] >= 0 &&
                            pair[1] < exit_area_size) {
                            goto end;
                        }
                    }
                    break;
                case SCREEN_EVENT_KEYBOARD:
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_DEVICE_INDEX, &val);
                    printf("SCREEN_EVENT_KEYBOARD(index=%d, ", val);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_KEY_CAP, &val);
                    printf("cap=%d, ", val);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_KEY_FLAGS, &val);
                    printf("flags=%d, ", val);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_KEY_MODIFIERS, &val);
                    printf("modifiers=%d, ", val);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_KEY_SCAN, &val);
                    printf("scan=%d, ", val);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_KEY_SYM, &val);
                    printf("sym=%d)\n", val);

                    switch (val) {
                        case KEYCODE_ESCAPE:
                            goto end;
                    }
                    break;
                case SCREEN_EVENT_MTOUCH_TOUCH:
                case SCREEN_EVENT_MTOUCH_MOVE:
                case SCREEN_EVENT_MTOUCH_RELEASE:
                    switch (val) {
                        case SCREEN_EVENT_MTOUCH_TOUCH:
                            printf("SCREEN_EVENT_MTOUCH_TOUCH(");
                            break;
                        case SCREEN_EVENT_MTOUCH_MOVE:
                            printf("SCREEN_EVENT_MTOUCH_MOVE(");
                            break;
                        case SCREEN_EVENT_MTOUCH_RELEASE:
                            printf("SCREEN_EVENT_MTOUCH_RELEASE(");
                            break;
                    }
                    screen_get_event_property_pv(screen_ev, SCREEN_PROPERTY_WINDOW, (void **)&win);
                    printf("window=0x%08x, ", (size_t)win);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_TOUCH_ID, &val);
                    printf("id=%d, ", val);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_SEQUENCE_ID, &val);
                    printf("sequence=%d, ", val);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_POSITION, pair);
                    printf("pos=[%d,%d], ", pair[0], pair[1]);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_SIZE, pair);
                    printf("size=[%d,%d], ", pair[0], pair[1]);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_SOURCE_POSITION, pair);
                    printf("source pos=[%d,%d], ", pair[0], pair[1]);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_SOURCE_SIZE, pair);
                    printf("source size=[%d,%d], ", pair[0], pair[1]);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_TOUCH_ORIENTATION, &val);
                    printf("orientation=%d, ", val);
                    screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_TOUCH_PRESSURE, &val);
                    printf("pressure=%d)\n", val);
                    break;
                case SCREEN_EVENT_USER:
                    break;
            }
        }
    }

end:

    screen_destroy_event(screen_ev);
    screen_destroy_window(screen_win);
    screen_destroy_context(screen_ctx);

    return 0;
}