~ubuntu-branches/debian/squeeze/freeciv/squeeze

« back to all changes in this revision

Viewing changes to utility/ftwl/be_x11_ximage.c

  • Committer: Bazaar Package Importer
  • Author(s): Jordi Mallach
  • Date: 2008-07-08 18:34:23 UTC
  • mfrom: (5.1.9 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080708183423-c80u1h25xmj6h9s0
Tags: 2.1.5-2
Export datarootdir=/usr/share in debian/rules, so make calls can
have a correct value for LOCALEDIR (closes: #489455). Thanks Loïc Minier
for the help to solve this.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**********************************************************************
2
 
 Freeciv - Copyright (C) 2004 - The Freeciv Project
3
 
   This program is free software; you can redistribute it and/or modify
4
 
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; either version 2, or (at your option)
6
 
   any later version.
7
 
 
8
 
   This program is distributed in the hope that it will be useful,
9
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
   GNU General Public License for more details.
12
 
***********************************************************************/
13
 
 
14
 
#ifdef HAVE_CONFIG_H
15
 
#include <config.h>
16
 
#endif
17
 
 
18
 
#include <assert.h>
19
 
#include <errno.h>
20
 
#include <stdio.h>
21
 
 
22
 
#include <X11/Xutil.h>
23
 
#include <X11/Xos.h>
24
 
#include <X11/Xatom.h>
25
 
#include <X11/StringDefs.h>
26
 
#include <X11/keysym.h>
27
 
#include <X11/Shell.h>
28
 
 
29
 
#include "back_end.h"
30
 
#include "be_common_24.h"
31
 
 
32
 
#include "shared.h"
33
 
 
34
 
#include "mem.h"
35
 
 
36
 
// fixme
37
 
#include "timing.h"
38
 
#include "widget.h"
39
 
 
40
 
static Display *display;
41
 
static Window window;
42
 
static int screen_number;
43
 
static int display_depth;
44
 
static int x11fd;
45
 
static int other_fd = -1;
46
 
static XImage *root_image;
47
 
static GC gc_plain;
48
 
 
49
 
/*************************************************************************
50
 
  ...
51
 
*************************************************************************/
52
 
void be_init(const struct ct_size *screen_size, bool fullscreen)
53
 
{
54
 
  XGCValues values;
55
 
 
56
 
  _Xdebug = 0;
57
 
  display = XOpenDisplay(NULL);
58
 
  assert(display);
59
 
 
60
 
  screen_number = DefaultScreen(display);
61
 
  display_depth = DefaultDepth(display, screen_number);
62
 
  x11fd = ConnectionNumber(display);
63
 
 
64
 
  window =
65
 
      XCreateSimpleWindow(display, XDefaultRootWindow(display), 200, 200,
66
 
                          screen_size->width, screen_size->height, 0, 0,
67
 
                          WhitePixel(display, screen_number));
68
 
  XSelectInput(display, window,
69
 
               ExposureMask | PointerMotionMask | ButtonPressMask |
70
 
               ButtonReleaseMask | KeyPressMask);
71
 
 
72
 
  {
73
 
    Pixmap dummy_mask = XCreatePixmap(display, window, 1, 1, 1);
74
 
 
75
 
    values.graphics_exposures = False;
76
 
    values.foreground = BlackPixel(display, screen_number);
77
 
 
78
 
    values.graphics_exposures = False;
79
 
    gc_plain = XCreateGC(display, window, GCGraphicsExposures, &values);
80
 
 
81
 
    XFreePixmap(display, dummy_mask);
82
 
  }
83
 
 
84
 
  /* pop this window up on the screen */
85
 
  XMapRaised(display, window);
86
 
 
87
 
  root_image =
88
 
      XCreateImage(display, DefaultVisual(display, screen_number),
89
 
                   display_depth, ZPixmap, 0, NULL, screen_size->width,
90
 
                   screen_size->height, 32, 0);
91
 
  root_image->data =
92
 
      fc_malloc(root_image->bytes_per_line * root_image->height);
93
 
}
94
 
 
95
 
/*************************************************************************
96
 
  ...
97
 
*************************************************************************/
98
 
static bool copy_event(struct be_event *event, XEvent * xevent)
99
 
{
100
 
  switch (xevent->type) {
101
 
  case NoExpose:
102
 
  case GraphicsExpose:
103
 
    return FALSE;
104
 
  case Expose:
105
 
    {
106
 
      XExposeEvent *xev = &xevent->xexpose;
107
 
 
108
 
      if (xev->count > 0) {
109
 
        return FALSE;
110
 
      }
111
 
      event->type = BE_EXPOSE;
112
 
    }
113
 
    break;
114
 
  case MotionNotify:
115
 
    {
116
 
      XMotionEvent *xev = &xevent->xmotion;
117
 
 
118
 
      event->type = BE_MOUSE_MOTION;
119
 
      event->position.x = xev->x;
120
 
      event->position.y = xev->y;
121
 
    }
122
 
    break;
123
 
  case ButtonPress:
124
 
  case ButtonRelease:
125
 
    {
126
 
      XButtonEvent *xev = &xevent->xbutton;
127
 
 
128
 
#if 0
129
 
      printf("pos=(%d,%d) button=0x%x state=0x%x\n", xev->x, xev->y,
130
 
             xev->button, xev->state);
131
 
#endif
132
 
      event->type =
133
 
          xevent->type == ButtonPress ? BE_MOUSE_PRESSED : BE_MOUSE_RELEASED;
134
 
      event->position.x = xev->x;
135
 
      event->position.y = xev->y;
136
 
      switch (xev->button) {
137
 
      case 1:
138
 
        event->button = BE_MB_LEFT;
139
 
        break;
140
 
      case 2:
141
 
        event->button = BE_MB_MIDDLE;
142
 
        break;
143
 
      case 3:
144
 
        event->button = BE_MB_RIGHT;
145
 
        break;
146
 
      default:
147
 
        assert(0);
148
 
      }
149
 
    }
150
 
    break;
151
 
  case KeyPress:
152
 
    {
153
 
      XKeyEvent *xev = &xevent->xkey;
154
 
      XKeyEvent copy_xev = *xev;
155
 
      char string[10];
156
 
      KeySym key;
157
 
      struct be_key *k = &event->key;
158
 
      int chars;
159
 
 
160
 
      /* Mod2Mask is NumLock */
161
 
      copy_xev.state = copy_xev.state & (ShiftMask | Mod2Mask);
162
 
      chars = XLookupString(&copy_xev, string, sizeof(string), &key, NULL);
163
 
 
164
 
      if (0)
165
 
        printf("chars=%d string='%s' key=%ld cursor=%d\n", chars, string,
166
 
               key, IsCursorKey(key));
167
 
      k->shift = (xev->state & ShiftMask);
168
 
      k->control = (xev->state & ControlMask);
169
 
      k->alt = (xev->state & Mod1Mask);
170
 
 
171
 
#define T(x,b)                  \
172
 
    } else if (key == x) {      \
173
 
      k->type = b
174
 
          
175
 
      if (FALSE) {
176
 
        T(XK_BackSpace, BE_KEY_BACKSPACE);
177
 
        T(XK_Return, BE_KEY_RETURN);
178
 
        T(XK_KP_Enter, BE_KEY_ENTER);
179
 
        T(XK_Delete, BE_KEY_DELETE);
180
 
        T(XK_Left, BE_KEY_LEFT);
181
 
        T(XK_Right, BE_KEY_RIGHT);
182
 
        T(XK_Up, BE_KEY_UP);
183
 
        T(XK_Down, BE_KEY_DOWN);
184
 
        T(XK_Escape, BE_KEY_ESCAPE);
185
 
        T(XK_Print, BE_KEY_PRINT);
186
 
        T(XK_space, BE_KEY_SPACE);
187
 
        T(XK_KP_0,BE_KEY_KP_0);
188
 
        T(XK_KP_1,BE_KEY_KP_1);
189
 
        T(XK_KP_2,BE_KEY_KP_2);
190
 
        T(XK_KP_3,BE_KEY_KP_3);
191
 
        T(XK_KP_4,BE_KEY_KP_4);
192
 
        T(XK_KP_5,BE_KEY_KP_5);
193
 
        T(XK_KP_6,BE_KEY_KP_6);
194
 
        T(XK_KP_7,BE_KEY_KP_7);
195
 
        T(XK_KP_8,BE_KEY_KP_8);
196
 
        T(XK_KP_9,BE_KEY_KP_9);
197
 
      } else if (chars == 1 && string[0] > ' ' && string[0] <= '~') {
198
 
        k->type = BE_KEY_NORMAL;
199
 
        k->key = string[0];
200
 
        k->shift = FALSE;
201
 
      } else {
202
 
        printf
203
 
            ("WARNING: BE-X11: unconverted KeyPress: chars=%d string='%s' key=0x%lx\n",
204
 
             chars, string, key);
205
 
        return FALSE;
206
 
      }
207
 
      event->type = BE_KEY_PRESSED;
208
 
      event->position.x = xev->x;
209
 
      event->position.y = xev->y;
210
 
    }
211
 
    break;
212
 
  default:
213
 
    printf("got event %d\n", xevent->type);
214
 
    assert(0);
215
 
  }
216
 
  return TRUE;
217
 
}
218
 
 
219
 
/*************************************************************************
220
 
  ...
221
 
*************************************************************************/
222
 
void be_next_event(struct be_event *event, struct timeval *timeout)
223
 
{
224
 
  XEvent xevent;
225
 
 
226
 
restart:
227
 
  event->type = BE_NO_EVENT;
228
 
 
229
 
  if (XCheckMaskEvent(display, -1 /*all events */ , &xevent)) {
230
 
    //printf("got event %d\n", xevent.type);
231
 
    if (copy_event(event, &xevent)) {
232
 
      return;
233
 
    } else {
234
 
      /* discard event */
235
 
      goto restart;
236
 
    }
237
 
  }
238
 
 
239
 
  sw_paint_all();
240
 
 
241
 
  {
242
 
    fd_set readfds, exceptfds;
243
 
    int ret, highest = x11fd;
244
 
 
245
 
    /* No event available: block on input socket until one is */
246
 
    FD_ZERO(&readfds);
247
 
    FD_SET(x11fd, &readfds);
248
 
 
249
 
    FD_ZERO(&exceptfds);
250
 
 
251
 
    if (other_fd != -1) {
252
 
      FD_SET(other_fd, &readfds);
253
 
      FD_SET(other_fd, &exceptfds);
254
 
      if (other_fd > highest) {
255
 
        highest = other_fd;
256
 
      }
257
 
    }
258
 
 
259
 
    ret = select(highest + 1, &readfds, NULL, &exceptfds, timeout);
260
 
    if (ret == 0) {
261
 
      // timed out
262
 
      event->type = BE_TIMEOUT;
263
 
    } else if (ret > 0) {
264
 
      if (other_fd != -1 && (FD_ISSET(other_fd, &readfds) ||
265
 
                             FD_ISSET(other_fd, &exceptfds))) {
266
 
        event->type = BE_DATA_OTHER_FD;
267
 
        event->socket = other_fd;
268
 
        return;
269
 
      }
270
 
      /* new data on the x11 fd */
271
 
      goto restart;
272
 
    } else if (errno == EINTR) {
273
 
      goto restart;
274
 
    } else {
275
 
      assert(0);
276
 
    }
277
 
  }
278
 
}
279
 
 
280
 
/*************************************************************************
281
 
  ...
282
 
*************************************************************************/
283
 
void be_add_net_input(int sock)
284
 
{
285
 
  other_fd = sock;
286
 
}
287
 
 
288
 
/*************************************************************************
289
 
  ...
290
 
*************************************************************************/
291
 
void be_remove_net_input(void)
292
 
{
293
 
  other_fd = -1;
294
 
}
295
 
 
296
 
/*************************************************************************
297
 
  ...
298
 
*************************************************************************/
299
 
void be_screen_get_size(struct ct_size *size)
300
 
{
301
 
  XWindowAttributes window_attributes;
302
 
 
303
 
  XGetWindowAttributes(display, window, &window_attributes);
304
 
 
305
 
  size->width = window_attributes.width;
306
 
  size->height = window_attributes.height;
307
 
}
308
 
 
309
 
#define COMP_565_RED(x)         ((((x)>>3)&0x1f)<<11)
310
 
#define COMP_565_GREEN(x)       ((((x)>>2)&0x3f)<< 5)
311
 
#define COMP_565_BLUE(x)        ((((x)>>3)&0x1f)<< 0)
312
 
 
313
 
/*************************************************************************
314
 
  ...
315
 
*************************************************************************/
316
 
static void fill_ximage_from_image_565(XImage * ximage,
317
 
                                       const struct image *image)
318
 
{
319
 
  int x, y;
320
 
  unsigned short *pdest = (unsigned short *) ximage->data;
321
 
  int extra_per_line = ximage->bytes_per_line / 2 - ximage->width;
322
 
 
323
 
  for (y = 0; y < ximage->height; y++) {
324
 
    for (x = 0; x < ximage->width; x++) {
325
 
      unsigned char *psrc = IMAGE_GET_ADDRESS(image, x, y);
326
 
      unsigned short new_value =
327
 
          (COMP_565_RED(psrc[0]) | COMP_565_GREEN(psrc[1]) |
328
 
           COMP_565_BLUE(psrc[2]));
329
 
      *pdest = new_value;
330
 
      pdest++;
331
 
    }
332
 
    pdest += extra_per_line;
333
 
  }
334
 
}
335
 
 
336
 
/*************************************************************************
337
 
  ...
338
 
*************************************************************************/
339
 
#define COMP_555_RED(x)         ((((x)>>3)&0x1f)<<10)
340
 
#define COMP_555_GREEN(x)       ((((x)>>3)&0x1f)<< 5)
341
 
#define COMP_555_BLUE(x)        ((((x)>>3)&0x1f)<< 0)
342
 
static void fill_ximage_from_image_555(XImage * ximage,
343
 
                                       const struct image *image)
344
 
{
345
 
  int x, y;
346
 
  unsigned short *pdest = (unsigned short *) ximage->data;
347
 
  int extra_per_line = ximage->bytes_per_line / 2 - ximage->width;
348
 
 
349
 
  for (y = 0; y < ximage->height; y++) {
350
 
    for (x = 0; x < ximage->width; x++) {
351
 
      unsigned char *psrc = IMAGE_GET_ADDRESS(image, x, y);
352
 
      unsigned short new_value =
353
 
          (COMP_555_RED(psrc[0]) | COMP_555_GREEN(psrc[1]) |
354
 
           COMP_555_BLUE(psrc[2]));
355
 
      *pdest = new_value;
356
 
      pdest++;
357
 
    }
358
 
    pdest += extra_per_line;
359
 
  }
360
 
}
361
 
 
362
 
/*************************************************************************
363
 
  ...
364
 
*************************************************************************/
365
 
static void fill_ximage_from_image_8888(XImage * ximage,
366
 
                                        const struct image *image)
367
 
{
368
 
  int x, y;
369
 
  unsigned char *pdest = (unsigned char *) ximage->data;
370
 
  int extra_per_line = ximage->bytes_per_line - ximage->width*4;
371
 
 
372
 
  for (y = 0; y < ximage->height; y++) {
373
 
    for (x = 0; x < ximage->width; x++) {
374
 
      unsigned char *psrc = IMAGE_GET_ADDRESS(image, x, y);
375
 
 
376
 
      pdest[0] = psrc[2];
377
 
      pdest[1] = psrc[1];
378
 
      pdest[2] = psrc[0];
379
 
      pdest += 4;
380
 
    }
381
 
    pdest += extra_per_line;
382
 
  }
383
 
}
384
 
 
385
 
/*************************************************************************
386
 
  ...
387
 
*************************************************************************/
388
 
void be_copy_osda_to_screen(struct osda *src)
389
 
{
390
 
  assert(root_image->width == src->image->width &&
391
 
         root_image->height == src->image->height);
392
 
 
393
 
  if (root_image->red_mask == 0xf800 &&
394
 
      root_image->green_mask == 0x7e0 && root_image->blue_mask == 0x1f &&
395
 
      root_image->depth == 16 && root_image->bits_per_pixel == 16
396
 
      && root_image->byte_order == LSBFirst) {
397
 
    fill_ximage_from_image_565(root_image, src->image);
398
 
  } else if (root_image->red_mask == 0x7c00 &&
399
 
             root_image->green_mask == 0x3e0 && root_image->blue_mask == 0x1f
400
 
             && root_image->depth == 15 && root_image->bits_per_pixel == 16
401
 
             && root_image->byte_order == LSBFirst) {
402
 
    fill_ximage_from_image_555(root_image, src->image);
403
 
  } else if (root_image->red_mask == 0xff0000 &&
404
 
             root_image->green_mask == 0xff00
405
 
             && root_image->blue_mask == 0xff && root_image->depth == 24
406
 
             && root_image->bits_per_pixel == 32
407
 
             && root_image->byte_order == LSBFirst) {
408
 
    fill_ximage_from_image_8888(root_image, src->image);
409
 
  } else {
410
 
    fprintf(stderr, "ERROR: unknown screen format: red=0x%lx, "
411
 
            "green=0x%lx, blue=0x%lx depth=%d bpp=%d "
412
 
            "byte_order=%d (LSB=%d MSB=%d)\n",
413
 
            root_image->red_mask, root_image->green_mask,
414
 
            root_image->blue_mask, root_image->depth,
415
 
            root_image->bits_per_pixel, root_image->byte_order, LSBFirst,
416
 
            MSBFirst);
417
 
    assert(0);
418
 
  }
419
 
 
420
 
  XPutImage(display, window, gc_plain, root_image, 0, 0, 0, 0,
421
 
            root_image->width, root_image->height);
422
 
  XFlush(display);
423
 
}
424
 
 
425
 
/*************************************************************************
426
 
  ...
427
 
*************************************************************************/
428
 
bool be_supports_fullscreen(void)
429
 
{
430
 
    return FALSE;
431
 
}