summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenning Sten <henning.sten@yahoo.com>2008-09-07 23:19:47 -0700
committerBart Massey <bart@cs.pdx.edu>2008-09-07 23:37:33 -0700
commitecd6579b647d6aa7e9d6525ae0e4854ddd1f863c (patch)
treef7e7945638935dac13fe3721b0d7461393a9d8ca
parentb5560bb7700a7faff1fb534b97fee054d8031f36 (diff)
made flames respond properly to EWMH delete window
Signed-off-by: Bart Massey <bart@cs.pdx.edu>
-rw-r--r--tests/flames.c76
1 files changed, 64 insertions, 12 deletions
diff --git a/tests/flames.c b/tests/flames.c
index ba594ac..ccf77a4 100644
--- a/tests/flames.c
+++ b/tests/flames.c
@@ -21,14 +21,20 @@
/* standard library */
#include <stdlib.h>
#include <stdio.h>
+#include <stdbool.h>
#include <time.h>
#include <assert.h>
#include <string.h>
+#include <unistd.h>
#include <xcb/xcb.h>
#include <xcb/shm.h>
#include <xcb/xcb_aux.h>
#include <xcb/xcb_image.h>
+
+/* Needed for xcb_set_wm_protocols() */
+#include <xcb/xcb_icccm.h>
+
#define XCB_ALL_PLANES ~0
#include <xcb/xcb_icccm.h>
@@ -69,6 +75,7 @@ typedef struct
}flame;
+static xcb_atom_t get_atom (xcb_connection_t *connection, const char *atomName);
static void title_set (flame *f, const char *title);
static int ilog2 (unsigned int n);
static void flame_set_palette (flame *f);
@@ -78,6 +85,22 @@ static void flame_modify_flame_base (flame *f);
static void flame_process_flame (flame *f);
static void flame_draw_flame (flame *f);
+xcb_atom_t
+get_atom (xcb_connection_t *connection, const char *atomName)
+{
+ if (atomName == NULL)
+ return XCB_NONE;
+ xcb_atom_t atom = XCB_NONE;
+ xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection,
+ xcb_intern_atom(connection, 0, strlen(atomName), atomName), NULL);
+ if (reply)
+ {
+ atom = reply->atom;
+ free(reply);
+ }
+ return atom;
+}
+
flame *
flame_init ()
{
@@ -207,21 +230,34 @@ main ()
flame_set_flame_zero (f);
flame_set_random_flame_base (f);
- while (1)
+ xcb_atom_t deleteWindowAtom = get_atom(f->xcb.c, "WM_DELETE_WINDOW");
+ /* Listen to X client messages in order to be able to pickup
+ the "delete window" message that is generated for example
+ when someone clicks the top-right X button within the window
+ manager decoration (or when user hits ALT-F4). */
+ xcb_set_wm_protocols (f->xcb.c, f->xcb.draw, 1, &deleteWindowAtom);
+
+ bool finished = false;
+ while (!finished)
{
if ((e = xcb_poll_for_event (f->xcb.c)))
{
- switch (e->response_type)
+ switch (e->response_type & 0x7f)
{
case XCB_EXPOSE:
xcb_copy_area(f->xcb.c, f->xcb.pixmap, f->xcb.draw, gc,
0, 0, 0, 0, BG_W, BG_H);
xcb_flush (f->xcb.c);
break;
- case XCB_BUTTON_PRESS:
- printf ("Exiting...\n");
- free (e);
- goto sortie;
+ case XCB_CLIENT_MESSAGE:
+ if (((xcb_client_message_event_t *)e)->data.data32[0] == deleteWindowAtom)
+ {
+ finished = true;
+ }
+ break;
+ case XCB_BUTTON_PRESS:
+ finished = true;
+ break;
}
free (e);
}
@@ -229,7 +265,6 @@ main ()
xcb_flush (f->xcb.c);
}
- sortie:
flame_shutdown (f);
return 0;
@@ -284,16 +319,33 @@ flame_draw_flame (flame *f)
int cl3;
int cl4;
- /* modify the base of the flame */
- flame_modify_flame_base (f);
- /* process the flame array, propagating the flames up the array */
- flame_process_flame (f);
-
image = xcb_image_get (f->xcb.c, f->xcb.draw,
0, 0, BG_W, BG_H,
XCB_ALL_PLANES, XCB_IMAGE_FORMAT_Z_PIXMAP);
+ /* If the top-level window is minimized (iconic) then the xcb_image_get()
+ will return NULL. In this case, we'll skip both updating and drawing
+ the flame, and we will also do a small sleep so that the program doesn't
+ hog as much CPU while minimized.
+
+ Another (non-polling == cleaner) way to not hog the CPU while minimized
+ would be to pass the XCB_EVENT_MASK_STRUCTURE_NOTIFY flag to
+ xcb_create_window(). This will give you XCB_UNMAP_NOTIFY and
+ XCB_MAP_NOTIFY events whenever the window is "minimized" (made iconic)
+ and "unminimized" (made normal again). This information would then be
+ used to make the main loop use the xcb_wait_for_event() instead of
+ xcb_poll_for_event() while the window is minimized (iconic). */
+ if (image == NULL)
+ {
+ usleep (100000);
+ return;
+ }
f->im = (unsigned int *)image->data;
+ /* modify the base of the flame */
+ flame_modify_flame_base (f);
+ /* process the flame array, propagating the flames up the array */
+ flame_process_flame (f);
+
for (y = 0 ; y < ((BG_H >> 1) - 1) ; y++)
{
for (x = 0 ; x < ((BG_W >> 1) - 1) ; x++)