~ubuntu-branches/debian/sid/freeciv/sid

« back to all changes in this revision

Viewing changes to utility/ftwl/be_x11_ximage.c

  • Committer: Bazaar Package Importer
  • Author(s): Clint Adams, Karl Goetz, Clint Adams
  • Date: 2009-11-27 23:24:00 UTC
  • mfrom: (7.1.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091127232400-nmoil1yvvskugn1h
[ Karl Goetz ]
* New upstream release
* Bump standards-version to 3.8.3
* Update watch file
  - Now version 3
  - Switched to gna.org instead of sf.net
* Switch readline dev dependency to libreadline-dev instead of
libreadline5-dev. Closes: #553758
* Changed compat to 5
* Relaxed dependencies on freeciv-server for sdl and gtk clients,
freeciv-server is now a recommends
* Stop d/rules trying to gzip scenarios - upstream does this.
* Remove export of datarootdir in d/rules, upstream seems to handle
this correctly now.
* Deleted 01_configure_ac_localedir.diff from d/patches/ and from series.
* Create per-client .desktop files. Closes: #470978, LP: #190555
* Desktop files mention which client they are (sdl/gtk/xaw3d).
* Add myself to uploaders on Clint's suggestion.

[ Clint Adams ]
* Change watch file to grab bz2 tarballs.
* Switch to 3.0 (quilt) source format.
* Remove quilt code from debian/rules.

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