~ubuntu-branches/ubuntu/warty/matchbox/warty

« back to all changes in this revision

Viewing changes to tests/winspew.c

  • Committer: Bazaar Package Importer
  • Author(s): Steinar H. Gunderson
  • Date: 2004-02-16 01:27:37 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040216012737-fakbjc1vs72vcz2w
Tags: 1:0.6.2-1.1
* Non-Maintainer Upload.
* Add -fPIC to libmb.so linker flags. (Closes: #227920)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  winspew - a EWMH testing tool.
 
3
 
 
4
  Copyright 2003 Matthew Allum
 
5
 
 
6
  This program is free software; you can redistribute it and/or modify
 
7
  it under the terms of the GNU General Public License as published by
 
8
  the Free Software Foundation; either version 2, or (at your option)
 
9
  any later version.
 
10
  
 
11
  This program is distributed in the hope that it will be useful,
 
12
  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
  GNU General Public License for more details.
 
15
  
 
16
*/
 
17
 
 
18
 
 
19
#include <X11/Xlib.h>
 
20
#include <X11/Xutil.h>
 
21
#include <X11/Xatom.h>
 
22
 
 
23
#include <stdio.h>
 
24
#include <stdlib.h>
 
25
#include <string.h>
 
26
#include <unistd.h>
 
27
 
 
28
#define MAX_WINS 32
 
29
 
 
30
#define WIN_OPTS_NO_TITLE           (1<<1)
 
31
#define WIN_OPTS_STATE_FULLSCREEN   (1<<2)
 
32
#define WIN_OPTS_STATE_MODAL        (1<<3)
 
33
#define WIN_OPTS_WM_PROTO_ACCEPT    (1<<5)
 
34
#define WIN_OPTS_WM_PROTO_HELP      (1<<6)
 
35
/* XXX possibles */
 
36
#define WIN_OPTS_UTF8_TITLE         (1<<7)
 
37
#define WIN_OPTS_NO_DECOR           (1<<8)
 
38
 
 
39
enum {                          /* Window Atoms */
 
40
 
 
41
  WINDOW_TYPE_TOOLBAR = 1,
 
42
  WINDOW_TYPE_DOCK,
 
43
  WINDOW_TYPE_DIALOG,
 
44
  WINDOW_TYPE_SPLASH,
 
45
  WINDOW_TYPE_DESKTOP,
 
46
  WINDOW_TYPE,    
 
47
 
 
48
  WINDOW_STATE,
 
49
  WINDOW_STATE_FULLSCREEN,
 
50
  WINDOW_STATE_MODAL,
 
51
  
 
52
  _NET_CLOSE_WINDOW,
 
53
  
 
54
  _NET_WM_NAME,
 
55
  UTF8_STRING,
 
56
 
 
57
  _NET_SHOW_DESKTOP,
 
58
  _NET_WM_ICON,
 
59
 
 
60
  _MOTIF_WM_HINTS,
 
61
 
 
62
  WM_PROTOCOLS,
 
63
  WM_DELETE_WINDOW,
 
64
  _NET_WM_CONTEXT_HELP,
 
65
  _NET_WM_CONTEXT_ACCEPT,
 
66
 
 
67
  WINDOW_TYPE_MESSAGE,
 
68
  WINDOW_TYPE_MESSAGE_TIMEOUT,
 
69
  
 
70
  _NET_SUPPORTED,
 
71
 
 
72
  ATOM_COUNT
 
73
};
 
74
 
 
75
 
 
76
 
 
77
static void paint(Window win, int width, int height);
 
78
 
 
79
static Display* dpy;    
 
80
static Window win_top_level[MAX_WINS], win_child[MAX_WINS], 
 
81
  win_current_top_level, win_root;
 
82
int win_top_level_idx = 0, win_child_idx = 0;
 
83
static int screen;
 
84
static Atom atoms[ATOM_COUNT];
 
85
static Bool WinIsFullscreen = False;
 
86
 
 
87
static struct { 
 
88
  char *key; int  flag; char *desc;
 
89
} Options_lookup[] = {
 
90
  { "no_title",       WIN_OPTS_NO_TITLE,
 
91
    "Request no titlebar / border only\n"},
 
92
  { "no_decor",       WIN_OPTS_NO_DECOR,
 
93
    "Request no window decorations\n"},
 
94
  { "fullscreen",     WIN_OPTS_STATE_FULLSCREEN ,
 
95
    "Request Fullscreen\n"},
 
96
  { "modal",          WIN_OPTS_STATE_MODAL,
 
97
    "Request dialog be modal\n"},    
 
98
  { "help_button",    WIN_OPTS_WM_PROTO_HELP,
 
99
  "Request help button in window title bar\n"},
 
100
  { "accept_button",  WIN_OPTS_WM_PROTO_ACCEPT,
 
101
  "Request 'OK' button in window title bar\n"},  
 
102
  { NULL, 0, NULL }
 
103
};
 
104
 
 
105
static struct { 
 
106
  char *key; unsigned char *data; int len;
 
107
} UTF8_Names_lookup[] = {
 
108
  { "utf8-zn_CH", "\344\275\240\345\245\275\344\270\255\345\233\275!", 13 },
 
109
  { NULL, 0, NULL }
 
110
};
 
111
 
 
112
void 
 
113
wm_check_supported_features(void)
 
114
{
 
115
  /* 
 
116
     XXX This functioniality here could be greatly enhances, though
 
117
         Im not sure how useful it would be. 
 
118
  */
 
119
  Atom type, *atoms_supported = NULL;
 
120
  int format;
 
121
  long bytes_after;
 
122
  long n_items;
 
123
  int result;
 
124
  unsigned char *atom_str_name;
 
125
  int i;
 
126
  Bool have_help_support = False, have_accept_support = False;
 
127
 
 
128
  result =  XGetWindowProperty (dpy, win_root, atoms[_NET_SUPPORTED],
 
129
                                0, 1024L,
 
130
                                False, XA_ATOM,
 
131
                                &type, &format, &n_items,
 
132
                                &bytes_after, 
 
133
                                (unsigned char **)&atoms_supported);
 
134
 
 
135
  printf("winspew log: Checking wm features..\n");
 
136
 
 
137
  if (result != Success || atoms_supported == NULL)
 
138
    {
 
139
      if (atoms_supported) XFree (atoms_supported);
 
140
      printf("winspew log: *WARNING* looks like wm is not EWMH compliant\n"
 
141
             "             Many features _will_not_ work!");
 
142
      return;
 
143
    }
 
144
 
 
145
  for (i=0; i<n_items; i++)
 
146
    {
 
147
      atom_str_name = XGetAtomName(dpy, atoms_supported[i]);
 
148
      printf("\t %s supported\n", atom_str_name); 
 
149
      if (atoms_supported[i] == atoms[_NET_WM_CONTEXT_HELP])
 
150
        have_help_support = True;
 
151
      if (atoms_supported[i] == atoms[_NET_WM_CONTEXT_ACCEPT])
 
152
        have_accept_support = True;
 
153
      if (atom_str_name) XFree(atom_str_name);
 
154
    }
 
155
 
 
156
  if (!have_help_support)
 
157
    printf("winspew log: *WARNING* This wm _does_not_ support help buttons\n"); 
 
158
 
 
159
  if (!have_accept_support)
 
160
    printf("winspew log: *WARNING* This wm _does_not_ support accpet buttons\n"); 
 
161
 
 
162
  XFree (atoms_supported);
 
163
}
 
164
 
 
165
void
 
166
create_atoms(void)
 
167
{
 
168
  
 
169
  atoms[WINDOW_TYPE_TOOLBAR] 
 
170
    = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_TOOLBAR",False);
 
171
  atoms[WINDOW_TYPE_DOCK]
 
172
    = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DOCK",False);
 
173
  atoms[WINDOW_TYPE_DIALOG]
 
174
    = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG",False);
 
175
  atoms[WINDOW_TYPE_SPLASH]
 
176
    = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_SPLASH",False);
 
177
  atoms[WINDOW_TYPE_DESKTOP]
 
178
    = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DESKTOP",False);
 
179
  atoms[WINDOW_TYPE]
 
180
    = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False);
 
181
 
 
182
 
 
183
  atoms[WINDOW_STATE]
 
184
    = XInternAtom(dpy, "_NET_WM_STATE",False);
 
185
  atoms[WINDOW_STATE_FULLSCREEN]
 
186
    = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN",False);
 
187
  atoms[WINDOW_STATE_MODAL]
 
188
    = XInternAtom(dpy, "_NET_WM_STATE_MODAL",False);
 
189
 
 
190
 
 
191
  atoms[_NET_WM_NAME]
 
192
    = XInternAtom(dpy, "_NET_WM_NAME",False);
 
193
  atoms[UTF8_STRING]
 
194
    = XInternAtom(dpy, "UTF8_STRING",False);
 
195
 
 
196
  atoms[_NET_CLOSE_WINDOW]
 
197
    = XInternAtom(dpy, "_NET_CLOSE_WINDOW",False);
 
198
  atoms[_NET_SHOW_DESKTOP]
 
199
    = XInternAtom(dpy, "_NET_SHOWING_DESKTOP",False);
 
200
  atoms[_NET_WM_ICON]
 
201
    = XInternAtom(dpy, "_NET_WM_ICON", False);
 
202
 
 
203
 
 
204
   atoms[_MOTIF_WM_HINTS]
 
205
      = XInternAtom(dpy, "_MOTIF_WM_HINTS", False);
 
206
 
 
207
   atoms[WM_PROTOCOLS]
 
208
      = XInternAtom(dpy, "WM_PROTOCOLS", False);
 
209
   atoms[WM_DELETE_WINDOW]
 
210
      = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
 
211
   atoms[_NET_WM_CONTEXT_HELP]
 
212
      = XInternAtom(dpy, "_NET_WM_CONTEXT_HELP", False);
 
213
   atoms[_NET_WM_CONTEXT_ACCEPT]
 
214
      = XInternAtom(dpy, "_NET_WM_CONTEXT_ACCEPT", False);
 
215
 
 
216
   atoms[_NET_SUPPORTED]
 
217
      = XInternAtom(dpy, "_NET_SUPPORTED", False);
 
218
 
 
219
   atoms[WINDOW_TYPE_MESSAGE]
 
220
     = XInternAtom(dpy, "_MB_WM_WINDOW_TYPE_MESSAGE", False);
 
221
 
 
222
   atoms[WINDOW_TYPE_MESSAGE_TIMEOUT]
 
223
     = XInternAtom(dpy, "_MB_WM_WINDOW_TYPE_MESSAGE_TIMEOUT", False);
 
224
 
 
225
}
 
226
 
 
227
 
 
228
void
 
229
usage(char *bin_name, char *error)
 
230
{
 
231
  int i = 0;
 
232
  if (!bin_name) {
 
233
    bin_name = "winspew";
 
234
  }
 
235
  printf("\n %s usage:\n"
 
236
         "%s [ -display <X11 display> ] -top <options> [ -dialog <options> ] ...\n\n"
 
237
         "-top, ( -t ) creates a top level window, <options> should consist of;\n\n"
 
238
         "   <title>,<window type>[,[geom],[extra opts], [message window timeout]]\n\n"
 
239
         "-dialog, ( -c) creates a dialog for the previous top level, <options> are;\n\n"
 
240
         "   <title>[,[geom],[extra opts],]\n\n"
 
241
 
 
242
         "   'window type' is one of normal, dock, toolbar, dialog, splash, desktop, message\n"
 
243
 
 
244
         "   'geom' is a X11 window geometry definition, like 100x100+100+100\n"
 
245
         "   'message window timeout' is the time ( seconds ) a message win is active\n"
 
246
         "   'extra opts' is a ':' seperated list of the following flags;\n\n",
 
247
         bin_name, bin_name);
 
248
 
 
249
  while( Options_lookup[i].key != NULL )
 
250
    {
 
251
      printf("       %s - %s", Options_lookup[i].key, Options_lookup[i].desc);
 
252
      i++;
 
253
    }  
 
254
 
 
255
  printf("\nNote, you may use as many instances of -top and -dialog as you like.\n"); 
 
256
 
 
257
  if (error) {
 
258
    printf("\nError: %s\n", error);
 
259
  }
 
260
  exit(1);
 
261
}
 
262
 
 
263
void
 
264
set_motif_no_title_decoration_hint(Window win, Bool border_only)
 
265
{
 
266
 
 
267
#define PROP_MOTIF_WM_HINTS_ELEMENTS    5
 
268
#define MWM_HINTS_DECORATIONS          (1L << 1)
 
269
#define MWM_DECOR_BORDER               (1L << 1)
 
270
 
 
271
  typedef struct
 
272
  {
 
273
    unsigned long       flags;
 
274
    unsigned long       functions;
 
275
    unsigned long       decorations;
 
276
    long                inputMode;
 
277
    unsigned long       status;
 
278
  } PropMotifWmHints;
 
279
 
 
280
  PropMotifWmHints *hints;
 
281
 
 
282
  hints = malloc(sizeof(PropMotifWmHints));
 
283
  memset(hints, 0, sizeof(PropMotifWmHints));
 
284
 
 
285
  hints->flags = MWM_HINTS_DECORATIONS;
 
286
 
 
287
  if (border_only)
 
288
    hints->decorations = MWM_DECOR_BORDER;
 
289
  else
 
290
    hints->decorations = 0;
 
291
 
 
292
  XChangeProperty(dpy, win, atoms[_MOTIF_WM_HINTS], 
 
293
                  XA_ATOM, 32, PropModeReplace, 
 
294
                  (unsigned char *)hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
 
295
 
 
296
  free(hints);
 
297
 
 
298
  return;
 
299
 
 
300
}
 
301
 
 
302
 
 
303
int
 
304
parse_options(const char *options_spec)
 
305
{
 
306
 
 
307
  int i = 0, result_flags = 0;
 
308
 
 
309
  printf("parsing %s\n", options_spec);
 
310
 
 
311
  while( Options_lookup[i].key != NULL )
 
312
    {
 
313
      if (strstr(options_spec, Options_lookup[i].key) != NULL)
 
314
        {
 
315
          printf("parsed %s\n", Options_lookup[i].key);
 
316
          result_flags |= Options_lookup[i].flag;
 
317
        }
 
318
      i++;
 
319
    }
 
320
 
 
321
  return result_flags;
 
322
}
 
323
 
 
324
void
 
325
win_set_utf8_name(Window         win, 
 
326
                  unsigned char *data, 
 
327
                  int            data_len)
 
328
{
 
329
  XChangeProperty(dpy, win, atoms[_NET_WM_NAME], 
 
330
                  atoms[UTF8_STRING], 8, PropModeReplace, 
 
331
                  data, data_len);
 
332
}
 
333
 
 
334
void
 
335
win_set_standard_props(Window win, char *win_title, int x, int y, int h, int w)
 
336
{
 
337
  XSizeHints size_hints;
 
338
 
 
339
  size_hints.flags = PPosition | PSize | PMinSize;
 
340
  size_hints.x = x;
 
341
  size_hints.y = y;
 
342
  size_hints.width      =  h;
 
343
  size_hints.height     =  w;
 
344
  size_hints.min_width  =  w;
 
345
  size_hints.min_height =  h;
 
346
  
 
347
  XSetStandardProperties(dpy, win, 
 
348
                         win_title, win_title, None,
 
349
                         NULL, 0, &size_hints);
 
350
}
 
351
 
 
352
void
 
353
win_set_ewmh_type(Window win, Atom atom_type)
 
354
{
 
355
  printf("winspew log: Setting type\n");
 
356
  XChangeProperty(dpy, win, atoms[WINDOW_TYPE], XA_ATOM, 32, 
 
357
                  PropModeReplace, (unsigned char *) &atom_type, 1);
 
358
}
 
359
 
 
360
void
 
361
win_set_extened_options(Window win, int option_flags, int message_timeout)
 
362
{
 
363
  Atom wm_protocols[3];
 
364
  int wm_protocols_idx = 1;
 
365
 
 
366
  wm_protocols[0] = atoms[WM_DELETE_WINDOW];
 
367
 
 
368
  if (option_flags & WIN_OPTS_NO_TITLE)
 
369
    {
 
370
      printf("winspew log: Setting no decor hint\n"); 
 
371
      set_motif_no_title_decoration_hint(win, True);
 
372
    }
 
373
 
 
374
  if (option_flags & WIN_OPTS_NO_DECOR)
 
375
    {
 
376
      printf("winspew log: Setting no decor hint\n"); 
 
377
      set_motif_no_title_decoration_hint(win, False);
 
378
    }
 
379
 
 
380
  
 
381
  if (option_flags & WIN_OPTS_STATE_FULLSCREEN)
 
382
    {
 
383
      printf("winspew log: Setting fullscreen hint\n"); 
 
384
      XChangeProperty(dpy, win, 
 
385
                      atoms[WINDOW_STATE], XA_ATOM, 32, 
 
386
                      PropModeReplace, 
 
387
                      (unsigned char *) &atoms[WINDOW_STATE_FULLSCREEN], 1);
 
388
      WinIsFullscreen = True;
 
389
    }
 
390
 
 
391
  if (option_flags & WIN_OPTS_STATE_MODAL)
 
392
    {
 
393
      printf("winspew log: Setting modal hint\n"); 
 
394
      XChangeProperty(dpy, win, 
 
395
                      atoms[WINDOW_STATE], XA_ATOM, 32, 
 
396
                      PropModeReplace, 
 
397
                      (unsigned char *) &atoms[WINDOW_STATE_MODAL], 1);
 
398
    }
 
399
 
 
400
  if (message_timeout)
 
401
    {
 
402
      int data[1];
 
403
 
 
404
      printf("winspew log: Setting message timeout\n"); 
 
405
 
 
406
      data[0] = message_timeout;
 
407
      XChangeProperty(dpy, win, 
 
408
                      atoms[WINDOW_TYPE_MESSAGE_TIMEOUT], XA_CARDINAL, 32, 
 
409
                      PropModeReplace, 
 
410
                      (unsigned char *) &data[0], 1);
 
411
    }
 
412
  
 
413
  if (option_flags & WIN_OPTS_WM_PROTO_ACCEPT)
 
414
    {
 
415
      printf("winspew log: Setting accept protocol\n"); 
 
416
      wm_protocols[wm_protocols_idx] = atoms[_NET_WM_CONTEXT_ACCEPT];
 
417
      wm_protocols_idx++;
 
418
    }
 
419
  
 
420
  if (option_flags & WIN_OPTS_WM_PROTO_HELP)
 
421
    {
 
422
      printf("winspew log: Setting help protocol\n"); 
 
423
      wm_protocols[wm_protocols_idx] = atoms[_NET_WM_CONTEXT_HELP];
 
424
      wm_protocols_idx++;
 
425
    }
 
426
  
 
427
  if (wm_protocols_idx)
 
428
    XSetWMProtocols(dpy, win, wm_protocols, wm_protocols_idx );
 
429
 
 
430
}
 
431
 
 
432
void
 
433
win_realize(Window win)
 
434
{
 
435
  XSelectInput(dpy, win,
 
436
               KeyPressMask             
 
437
               |KeyReleaseMask          
 
438
               |ButtonPressMask
 
439
               |ButtonReleaseMask       
 
440
               |EnterWindowMask
 
441
               |LeaveWindowMask
 
442
               |PointerMotionMask       
 
443
               |PointerMotionHintMask   
 
444
               |Button1MotionMask       
 
445
               |Button2MotionMask       
 
446
               |Button3MotionMask       
 
447
               |Button4MotionMask       
 
448
               |Button5MotionMask       
 
449
               |ButtonMotionMask        
 
450
               |KeymapStateMask
 
451
               |ExposureMask            
 
452
               |VisibilityChangeMask    
 
453
               |StructureNotifyMask     
 
454
               |SubstructureNotifyMask  
 
455
               |FocusChangeMask 
 
456
               |PropertyChangeMask      
 
457
               |ColormapChangeMask      
 
458
               |OwnerGrabButtonMask     
 
459
               );               /* XXX really need all this ? */
 
460
     
 
461
  XMapWindow(dpy, win);
 
462
}
 
463
 
 
464
void
 
465
win_destroy(Window win)         
 
466
{
 
467
  Window win_tmp;
 
468
  int i;
 
469
 
 
470
  for (i=0; i<win_child_idx; i++) /* destroy any transient dialogs */
 
471
    {
 
472
      if (win_child[i] != None 
 
473
          && XGetTransientForHint(dpy, win_child[i], &win_tmp)
 
474
          && win_tmp == win)
 
475
        {
 
476
          XDestroyWindow(dpy, win_child[i]);
 
477
          win_child[i] = None;
 
478
        }
 
479
    }
 
480
 
 
481
  XDestroyWindow(dpy,win);
 
482
 
 
483
  /* Update window arrays */
 
484
 
 
485
  for (i=0; i<win_top_level_idx; i++)
 
486
    if (win_top_level[i] == win)
 
487
      {
 
488
        win_top_level[i] = None;
 
489
        return;
 
490
      }
 
491
 
 
492
  for (i=0; i<win_child_idx; i++)
 
493
    if (win_child[i] == win)
 
494
      win_child[i] = None;
 
495
 
 
496
}
 
497
 
 
498
void
 
499
create_top_level(int argc, char **argv, char *spec)
 
500
{
 
501
  char *str;
 
502
  const char delim[] = ",";
 
503
  char *tmp;
 
504
  int i;
 
505
 
 
506
  char *win_title;
 
507
  int win_type = 0, win_x = 0, win_y = 0, win_w = 100, win_h = 50;
 
508
 
 
509
  int option_flags    = 0;
 
510
  int message_timeout = 0;
 
511
  int geom_bitmask    = 0;
 
512
 
 
513
  struct {
 
514
    char *name;
 
515
    int id;
 
516
  } win_types[] = {
 
517
    {"normal",  0},
 
518
    {"dock",    WINDOW_TYPE_DOCK},
 
519
    {"dialog",  WINDOW_TYPE_DIALOG},
 
520
    {"splash",  WINDOW_TYPE_SPLASH},
 
521
    {"toolbar", WINDOW_TYPE_TOOLBAR},
 
522
    {"desktop", WINDOW_TYPE_DESKTOP},
 
523
    {"message", WINDOW_TYPE_MESSAGE},
 
524
    {NULL, 0}
 
525
  };
 
526
 
 
527
  if ((strchr(spec, delim[0]) != NULL))
 
528
  {
 
529
     str = strdup(spec);
 
530
 
 
531
     if ((win_title = strsep (&str, delim)) == NULL)
 
532
       usage(NULL, "top title missing");
 
533
 
 
534
     if ((tmp = strsep (&str, delim)) == NULL)
 
535
       usage(NULL, "top type missing");
 
536
     
 
537
     if (atoi(tmp) > 0)
 
538
       win_type = atoi(tmp);
 
539
     else
 
540
       {
 
541
         Bool found = False;
 
542
         i = 0;
 
543
         while(win_types[i].name != NULL)
 
544
           {
 
545
             if (!strcmp(tmp, win_types[i].name))
 
546
               {
 
547
                 win_type =  win_types[i].id;
 
548
                 found = True;
 
549
                 break;
 
550
               }
 
551
             i++;
 
552
           }
 
553
       }
 
554
     
 
555
     /* Rest are optional */
 
556
 
 
557
     if ((tmp = strsep (&str, delim)) != NULL)
 
558
       {
 
559
         geom_bitmask = XParseGeometry(tmp, &win_x, &win_y, &win_w, &win_h);
 
560
 
 
561
         if (!win_w) win_w = 100;
 
562
         if (!win_h) win_h = 100;
 
563
 
 
564
         /* XXX see code for dialogs
 
565
         if (!(geom_bitmask & XNegative))
 
566
           {
 
567
             win_x = (-1 * DisplayWidth(dpy, screen)) + win_x;
 
568
           }
 
569
 
 
570
         if (!(geom_bitmask & YNegative)) 
 
571
           {
 
572
             win_y = (-1 * DisplayHeight(dpy, screen)) + win_y;
 
573
           }
 
574
         */
 
575
       }
 
576
 
 
577
     if ((tmp = strsep (&str, delim)) != NULL)
 
578
       {
 
579
         option_flags = parse_options(tmp);
 
580
       }
 
581
 
 
582
     if ((tmp = strsep (&str, delim)) != NULL)
 
583
       {
 
584
         message_timeout = atoi(tmp);
 
585
       }
 
586
 
 
587
     free(str);
 
588
 
 
589
     /* Now create actual window */
 
590
 
 
591
     printf("winspew log: creating top level x:%i, y:%i, w:%i, h:%i\n",
 
592
            win_x, win_y, win_w, win_h);
 
593
 
 
594
     win_top_level[win_top_level_idx] 
 
595
       = XCreateSimpleWindow(dpy, win_root, win_x, win_y,
 
596
                             win_w, win_h, 0,
 
597
                             BlackPixel(dpy, screen),
 
598
                             WhitePixel(dpy, screen));
 
599
 
 
600
     printf("winspew log: window id is %li\n", 
 
601
            win_top_level[win_top_level_idx]);
 
602
 
 
603
     win_current_top_level = win_top_level[win_top_level_idx];
 
604
 
 
605
     win_set_standard_props(win_top_level[win_top_level_idx], win_title,
 
606
                            win_x, win_y, win_h, win_w);
 
607
 
 
608
     if (win_type)              /* something other than a normal window */
 
609
       win_set_ewmh_type(win_top_level[win_top_level_idx], atoms[win_type]);
 
610
 
 
611
     win_set_extened_options(win_top_level[win_top_level_idx], 
 
612
                             option_flags, message_timeout);
 
613
 
 
614
     /* Set utf8 name from lookup */
 
615
     i = 0;
 
616
     while( UTF8_Names_lookup[i].key != NULL )
 
617
       {
 
618
         if (!strcmp(win_title, UTF8_Names_lookup[i].key))
 
619
           {
 
620
             win_set_utf8_name(win_top_level[win_top_level_idx],
 
621
                               UTF8_Names_lookup[i].data, 
 
622
                               UTF8_Names_lookup[i].len);
 
623
           }
 
624
         i++;
 
625
       }
 
626
 
 
627
     win_realize(win_top_level[win_top_level_idx]);
 
628
 
 
629
 
 
630
      win_top_level_idx++;
 
631
     
 
632
  } else {
 
633
    /* Failed */
 
634
    usage("winspew", "top options missing");
 
635
  }
 
636
}
 
637
 
 
638
void                            /* XXX this should be merged into above */
 
639
create_child_dialog(int argc, char **argv, char *spec)
 
640
{
 
641
  char *str;
 
642
  const char delim[] = ",";
 
643
  char *tmp;
 
644
 
 
645
  char *win_title;
 
646
  int win_x = 0, win_y = 0, win_w = 100, win_h = 50;
 
647
  int option_flags = 0, geom_bitmask = 0;
 
648
 
 
649
  if (spec == NULL) usage("winspew", "child options missing");
 
650
 
 
651
  if ((strchr(spec, delim[0]) != NULL))
 
652
  {
 
653
     str = strdup(spec);
 
654
 
 
655
     if ((win_title = strsep (&str, delim)) == NULL)
 
656
       usage(NULL, "child title missing");
 
657
 
 
658
     /* Rest are optional */
 
659
 
 
660
     if ((tmp = strsep (&str, delim)) != NULL)
 
661
       {
 
662
         geom_bitmask = XParseGeometry(tmp, &win_x, &win_y, &win_w, &win_h);
 
663
 
 
664
         if (!win_w) win_w = 100;
 
665
         if (!win_h) win_h = 100;
 
666
 
 
667
         /* XXX we need to do gravitys for the below to work correctly. 
 
668
         if (!(geom_bitmask & XNegative))
 
669
           {
 
670
             win_x = (-1 * DisplayWidth(dpy, screen)) - win_x - win_w;
 
671
           }
 
672
 
 
673
         if (!(geom_bitmask & YNegative)) 
 
674
           {
 
675
             win_y = (-1 * DisplayHeight(dpy, screen)) - win_y - win_h;
 
676
           }
 
677
         */
 
678
       }
 
679
 
 
680
     if ((tmp = strsep (&str, delim)) != NULL)
 
681
       {
 
682
         option_flags = parse_options(tmp);
 
683
       }
 
684
 
 
685
     free(str);
 
686
  } 
 
687
  else win_title = spec;
 
688
 
 
689
  /* Now create actual window */
 
690
 
 
691
  printf("winspew log: creating dialog x:%i, y:%i, w:%i, h:%i\n",
 
692
         win_x, win_y, win_w, win_h);
 
693
 
 
694
  win_child[win_child_idx] 
 
695
    = XCreateSimpleWindow(dpy, win_root, win_x, win_y,
 
696
                          win_w, win_h, 0,
 
697
                          BlackPixel(dpy, screen),
 
698
                          WhitePixel(dpy, screen));
 
699
 
 
700
  printf("winspew log: window id is %li\n", 
 
701
         win_child[win_child_idx]);
 
702
 
 
703
  XSetTransientForHint(dpy, win_child[win_child_idx], 
 
704
                       win_current_top_level);
 
705
 
 
706
  win_set_standard_props(win_child[win_child_idx], win_title,
 
707
                         win_x, win_y, win_h, win_w);
 
708
 
 
709
  win_set_extened_options(win_child[win_child_idx], option_flags, 0);
 
710
  
 
711
  win_realize(win_child[win_child_idx]);
 
712
 
 
713
  win_child_idx++;
 
714
 
 
715
}
 
716
 
 
717
static void  /* Fill the window with a simple pattern  */
 
718
paint(Window win, int width, int height)
 
719
{
 
720
  XWindowAttributes win_attr;
 
721
  XGCValues gc_values;
 
722
  GC gc;
 
723
  int x, y;
 
724
  Pixmap pxm_backing;
 
725
 
 
726
  XGetWindowAttributes(dpy, win, &win_attr);
 
727
 
 
728
  gc_values.graphics_exposures = False;
 
729
  gc_values.function           = GXcopy;
 
730
  gc_values.background         = WhitePixel(dpy, DefaultScreen(dpy));
 
731
  gc = XCreateGC(dpy, win, GCGraphicsExposures|GCFunction|GCForeground, 
 
732
                 &gc_values);
 
733
 
 
734
  pxm_backing = XCreatePixmap(dpy, win, width, height, 
 
735
                              win_attr.depth);
 
736
 
 
737
  XSetForeground(dpy, gc, WhitePixel(dpy, DefaultScreen(dpy)));
 
738
  XFillRectangle(dpy, pxm_backing, gc, 0, 0, width, height);
 
739
 
 
740
  XSetForeground(dpy, gc, BlackPixel(dpy, DefaultScreen(dpy)));
 
741
                 
 
742
  /* Quick hack for a window pattern, using window ID  */
 
743
  if (win % 2)
 
744
    {
 
745
      for (y = 0; y < height; y += win % 12)
 
746
        XDrawLine(dpy, pxm_backing, gc, 0, y, width, y);
 
747
    } else {
 
748
      for (x = 0; x < width; x += win % 12)
 
749
        XDrawLine(dpy, pxm_backing, gc, x, 0, x, height);
 
750
    }
 
751
 
 
752
  XSetWindowBackgroundPixmap(dpy, win, pxm_backing);
 
753
  XClearWindow(dpy, win);
 
754
 
 
755
  XFreePixmap(dpy, pxm_backing);
 
756
  XFreeGC(dpy, gc);
 
757
 
758
 
 
759
void
 
760
toggle_ewmh_fullscreen (Window win_to_toggle)
 
761
{
 
762
 
 
763
#define _NET_WM_STATE_TOGGLE        2    /* toggle property  */
 
764
 
 
765
  XEvent ev;
 
766
  Atom atom_win_state, atom_win_state_fullscreen;
 
767
 
 
768
  atom_win_state = XInternAtom(dpy, "_NET_WM_STATE",False);
 
769
  atom_win_state_fullscreen = XInternAtom(dpy,
 
770
                                          "_NET_WM_STATE_FULLSCREEN",False);
 
771
 
 
772
  printf("winspew-log: attempting toggle on %li\n", win_to_toggle);
 
773
 
 
774
  memset(&ev, 0, sizeof(ev));
 
775
  ev.xclient.type = ClientMessage;
 
776
  ev.xclient.window = win_to_toggle;
 
777
  ev.xclient.message_type = atom_win_state;
 
778
  ev.xclient.format = 32;
 
779
  ev.xclient.data.l[1] = atom_win_state_fullscreen;
 
780
  ev.xclient.data.l[0] = _NET_WM_STATE_TOGGLE;
 
781
 
 
782
  XSendEvent(dpy, win_root, False, SubstructureRedirectMask , &ev);
 
783
 
 
784
  XSync(dpy, False);
 
785
}
 
786
 
 
787
 
 
788
int 
 
789
main(int argc, char **argv)
 
790
{
 
791
  int i;
 
792
  char *dpy_name = NULL;
 
793
  XEvent xevent;
 
794
 
 
795
  for (i = 1; i < argc; i++) {
 
796
    if (!strcmp ("-display", argv[i]) || !strcmp ("-d", argv[i])) {
 
797
      if (++i>=argc) usage (argv[0], "display missing");
 
798
      dpy_name = argv[i++];
 
799
      break;
 
800
    }
 
801
  }
 
802
  if (i >= argc) {
 
803
    if (argc == 1) {
 
804
      usage(argv[0], "no options");
 
805
    } else {
 
806
      /* no display option */
 
807
      i = 1;
 
808
    }
 
809
  }
 
810
 
 
811
  if ((dpy = XOpenDisplay(dpy_name)) == NULL) {
 
812
    fprintf(stderr, "Cannot connect to X server on display %s.",
 
813
            dpy_name);
 
814
    exit(1);
 
815
  }
 
816
  
 
817
  screen   = DefaultScreen(dpy);
 
818
  win_root = DefaultRootWindow(dpy);
 
819
 
 
820
  create_atoms();
 
821
 
 
822
  wm_check_supported_features();
 
823
 
 
824
  win_current_top_level = win_root;
 
825
 
 
826
  for (; i < argc; i++) {
 
827
    if (!strcmp ("-top", argv[i]) || !strcmp ("-t", argv[i])) {
 
828
      if (++i>=argc) usage (argv[0], "no -top options");
 
829
      create_top_level(argc, argv, argv[i]);
 
830
      continue;
 
831
    }
 
832
    if (!strcmp ("-dialog", argv[i]) || !strcmp ("-c", argv[i])) {
 
833
      if (++i>=argc) usage (argv[0], "no -child options");
 
834
      create_child_dialog(argc, argv, argv[i]);
 
835
      continue;
 
836
    }
 
837
    usage(argv[0], argv[i]);
 
838
  }
 
839
 
 
840
  while(1)
 
841
    {
 
842
      char *tmp;
 
843
      fflush(stdout);
 
844
      XNextEvent(dpy, &xevent);
 
845
      switch (xevent.type) 
 
846
        {
 
847
        case ButtonPress:
 
848
          printf("winspew log: %li, Button press event\n", 
 
849
                 xevent.xbutton.window);
 
850
          if (WinIsFullscreen) 
 
851
            toggle_ewmh_fullscreen (xevent.xbutton.window);
 
852
          break;
 
853
        case Expose:
 
854
          printf("winspew log: %li, Expose event\n", 
 
855
                 xevent.xexpose.window);
 
856
          /*
 
857
          paint(xevent.xexpose.window, xevent.xexpose.width, 
 
858
                xevent.xexpose.height);
 
859
          */
 
860
          break;
 
861
        case MapNotify:
 
862
          printf("winspew log: %li, MapNotfiy event\n", 
 
863
                 xevent.xmap.window);
 
864
          break;
 
865
        case UnmapNotify:
 
866
          printf("winspew log: %li, UnmapNotfiy event\n", 
 
867
                 xevent.xunmap.window);
 
868
          break;
 
869
        case ReparentNotify:
 
870
          printf("winspew log: %li, ReparentNotify\n", 
 
871
                 xevent.xreparent.window);
 
872
          break;
 
873
          
 
874
        case ConfigureNotify:
 
875
          printf("winspew log: %li, ConfigureNotify event\n", 
 
876
                 xevent.xconfigure.window);
 
877
          /* XXX compress configure notifys ? */
 
878
          paint(xevent.xconfigure.window, xevent.xconfigure.width, 
 
879
                xevent.xconfigure.height);
 
880
          break;
 
881
        case ClientMessage:
 
882
          printf("winspew log: %li, ClientMessage event\n", 
 
883
                 xevent.xclient.window);
 
884
          if ((xevent.xclient.message_type == atoms[WM_PROTOCOLS])
 
885
              && (xevent.xclient.data.l[0] == atoms[WM_DELETE_WINDOW])) 
 
886
            {
 
887
              printf("\tis WM_DELETE, deleteing...\n");
 
888
              win_destroy(xevent.xclient.window);
 
889
            }
 
890
          break;
 
891
        case KeyPress:
 
892
          break;
 
893
        case FocusIn:
 
894
          printf("winspew log: %li, FocusIn event\n", 
 
895
                 xevent.xfocus.window);
 
896
          break;
 
897
        case FocusOut:
 
898
          printf("winspew log: %li, FocusOut event\n", 
 
899
                 xevent.xfocus.window);
 
900
          break;
 
901
        case PropertyNotify:
 
902
          tmp = XGetAtomName(dpy, xevent.xproperty.atom);
 
903
          printf("winspew log: %li, PropertyNotify event. Atom '%s' ( ID: %li )\n", 
 
904
                 xevent.xproperty.window, tmp, xevent.xproperty.atom);
 
905
          if (tmp) XFree(tmp);
 
906
          break;
 
907
        default:
 
908
          break;
 
909
        }
 
910
    }
 
911
  
 
912
}