The complete code sample is listed below.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <screen/screen.h>
const int barwidth = 32;
int ndisplays = 0;
struct {
pthread_mutex_t mutex;
pthread_cond_t cond;
enum { detached, attached, focused } state;
} *displays;
screen_pixmap_t screen_pix = NULL;
screen_buffer_t screen_pbuf = NULL;
void pixmap(screen_context_t screen_ctx)
{
int i, j;
screen_create_pixmap(&screen_pix, screen_ctx);
int format = SCREEN_FORMAT_RGBA8888;
screen_set_pixmap_property_iv(screen_pix, SCREEN_PROPERTY_FORMAT, &format);
int usage = SCREEN_USAGE_WRITE | SCREEN_USAGE_NATIVE;
screen_set_pixmap_property_iv(screen_pix, SCREEN_PROPERTY_USAGE, &usage);
int size[2] = { 100, 100 };
screen_set_pixmap_property_iv(screen_pix, SCREEN_PROPERTY_BUFFER_SIZE, size);
screen_create_pixmap_buffer(screen_pix);
screen_get_pixmap_property_pv(screen_pix, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)&screen_pbuf);
unsigned char *ptr = NULL;
screen_get_buffer_property_pv(screen_pbuf, SCREEN_PROPERTY_POINTER, (void **)&ptr);
int stride = 0;
screen_get_buffer_property_iv(screen_pbuf, SCREEN_PROPERTY_STRIDE, &stride);
for (i = 0; i < size[1]; i++, ptr += stride) {
for (j = 0; j < size[0]; j++) {
ptr[j*4] = 0xa0;
ptr[j*4+1] = 0xa0;
ptr[j*4+2] = 0xa0;
ptr[j*4+3] = ((j >= i && j <= size[1]-i) || (j <= i && j >= size[1]-i)) ? 0xff : 0;
}
}
}
void *display(void *arg)
{
const int idx = (int)arg;
int rect[4] = { 0, 0 };
int realized = 0;
int pos = 0;
int attached;
int focus;
int i;
screen_context_t screen_ctx;
screen_create_context(&screen_ctx, SCREEN_APPLICATION_CONTEXT);
screen_display_t *screen_dpy = calloc(ndisplays, sizeof(screen_display_t));
screen_get_context_property_pv(screen_ctx, SCREEN_PROPERTY_DISPLAYS, (void **)screen_dpy);
screen_window_t screen_win;
screen_create_window(&screen_win, screen_ctx);
screen_set_window_property_pv(screen_win, SCREEN_PROPERTY_DISPLAY, (void **)&screen_dpy[idx]);
int usage = SCREEN_USAGE_NATIVE;
screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_USAGE, &usage);
pthread_mutex_lock(&displays[idx].mutex);
attached = displays[idx].state != detached ? 1 : 0;
focus = displays[idx].state == focused ? 1 : 0;
pthread_mutex_unlock(&displays[idx].mutex);
screen_event_t screen_ev;
screen_create_event(&screen_ev);
while (1) {
if (attached) {
if (!realized) {
screen_get_display_property_iv(screen_dpy[idx], SCREEN_PROPERTY_SIZE, rect+2);
screen_set_window_property_iv(screen_win, SCREEN_PROPERTY_BUFFER_SIZE, rect+2);
screen_create_window_buffers(screen_win, 2);
realized = 1;
}
screen_buffer_t screen_buf[2];
screen_get_window_property_pv(screen_win, SCREEN_PROPERTY_RENDER_BUFFERS, (void **)screen_buf);
int bg[] = { SCREEN_BLIT_COLOR, 0xffffff00, SCREEN_BLIT_END };
screen_fill(screen_ctx, screen_buf[0], bg);
if (focus > 0) {
int bar[] = {
SCREEN_BLIT_COLOR, 0xff0000ff,
SCREEN_BLIT_DESTINATION_X, pos,
SCREEN_BLIT_DESTINATION_WIDTH, barwidth,
SCREEN_BLIT_END };
screen_fill(screen_ctx, screen_buf[0], bar);
if (++pos > rect[2] - barwidth) {
for (i = (idx+1) % ndisplays; i != idx; i = (i+1) % ndisplays) {
pthread_mutex_lock(&displays[i].mutex);
if (displays[i].state == attached) {
displays[i].state = focused;
pthread_cond_signal(&displays[i].cond);
pthread_mutex_unlock(&displays[i].mutex);
break;
}
pthread_mutex_unlock(&displays[i].mutex);
}
if (i != idx) {
pthread_mutex_lock(&displays[idx].mutex);
displays[idx].state = attached;
pthread_mutex_unlock(&displays[idx].mutex);
focus = -1;
}
pos = 0;
}
} else {
focus = 0;
}
int hg[] = {
SCREEN_BLIT_SOURCE_WIDTH, 100,
SCREEN_BLIT_SOURCE_HEIGHT, 100,
SCREEN_BLIT_DESTINATION_X, 10,
SCREEN_BLIT_DESTINATION_Y, 10,
SCREEN_BLIT_DESTINATION_WIDTH, 100,
SCREEN_BLIT_DESTINATION_HEIGHT, 100,
SCREEN_BLIT_TRANSPARENCY, SCREEN_TRANSPARENCY_SOURCE_OVER,
SCREEN_BLIT_END
};
screen_blit(screen_ctx, screen_buf[0], screen_pbuf, hg);
screen_post_window(screen_win, screen_buf[0], 1, rect, 0);
}
if (!attached && realized) {
screen_destroy_window_buffers(screen_win);
screen_flush_context(screen_ctx, 0);
realized = 0;
}
if (focus != -1) {
pthread_mutex_lock(&displays[idx].mutex);
if (!focus) {
printf("%s[%d]: idx=%d\n", __FUNCTION__, __LINE__, idx);
pthread_cond_wait(&displays[idx].cond, &displays[idx].mutex);
pos = 0;
}
attached = displays[idx].state != detached ? 1 : 0;
focus = displays[idx].state == focused ? 1 : 0;
pthread_mutex_unlock(&displays[idx].mutex);
}
}
free(screen_dpy);
return NULL;
}
int main(int argc, char **argv)
{
int i, j, idx = -1;
screen_context_t screen_ctx;
screen_create_context(&screen_ctx, SCREEN_APPLICATION_CONTEXT);
screen_get_context_property_iv(screen_ctx, SCREEN_PROPERTY_DISPLAY_COUNT, &ndisplays);
pixmap(screen_ctx);
screen_display_t *screen_dpy = calloc(ndisplays, sizeof(screen_display_t));
screen_get_context_property_pv(screen_ctx, SCREEN_PROPERTY_DISPLAYS, (void **)screen_dpy);
displays = calloc(ndisplays, sizeof(*displays));
for (i = 0; i < ndisplays; i++) {
int active = 0;
screen_get_display_property_iv(screen_dpy[i], SCREEN_PROPERTY_ATTACHED, &active);
if (active) {
if (idx == -1) {
displays[i].state = focused;
idx = i;
} else {
displays[i].state = attached;
}
} else {
displays[i].state = detached;
}
pthread_mutex_init(&displays[i].mutex, NULL);
pthread_cond_init(&displays[i].cond, NULL);
pthread_t thread;
pthread_create(&thread, NULL, display, (void *)i);
}
screen_event_t screen_ev;
screen_create_event(&screen_ev);
while (1) {
int type = SCREEN_EVENT_NONE;
screen_get_event(screen_ctx, screen_ev, ~0);
screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_TYPE, &type);
if (type == SCREEN_EVENT_DISPLAY) {
screen_display_t tmp = NULL;
screen_get_event_property_pv(screen_ev, SCREEN_PROPERTY_DISPLAY, (void **)&tmp);
for (i = 0; i < ndisplays; i++) {
if (tmp == screen_dpy[i]) {
int active = 0;
screen_get_event_property_iv(screen_ev, SCREEN_PROPERTY_ATTACHED, &active);
if (active) {
int size[2];
screen_get_display_property_iv(tmp, SCREEN_PROPERTY_SIZE, size);
if (size[0] == 0 || size[1] == 0) {
active = 0;
}
}
pthread_mutex_lock(&displays[i].mutex);
if ((active && displays[i].state == detached) ||
(!active && displays[i].state != detached)) {
if (active) {
for (j = 0; j < ndisplays; j++) {
printf("%s[%d]: j=%d\n", __FUNCTION__, __LINE__, j);
if (i != j) {
pthread_mutex_lock(&displays[j].mutex);
if (displays[j].state == focused) {
displays[i].state = attached;
pthread_mutex_unlock(&displays[j].mutex);
break;
}
pthread_mutex_unlock(&displays[j].mutex);
}
}
if (displays[i].state == detached) {
displays[i].state = focused;
}
} else {
if (displays[i].state == focused) {
for (j = (i+1) % ndisplays; j != i; j = (j+1) % ndisplays) {
printf("%s[%d]: j=%d\n", __FUNCTION__, __LINE__, j);
pthread_mutex_lock(&displays[j].mutex);
if (displays[j].state == attached) {
displays[j].state = focused;
pthread_cond_signal(&displays[j].cond);
pthread_mutex_unlock(&displays[j].mutex);
break;
}
pthread_mutex_unlock(&displays[j].mutex);
}
}
displays[i].state = detached;
}
pthread_cond_signal(&displays[i].cond);
}
pthread_mutex_unlock(&displays[i].mutex);
break;
}
}
}
}
screen_destroy_pixmap(screen_pix);
screen_destroy_event(screen_ev);
screen_destroy_context(screen_ctx);
free(displays);
return EXIT_SUCCESS;
}