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)
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
***********************************************************************/
22
#include <X11/Xutil.h>
24
#include <X11/Xatom.h>
25
#include <X11/StringDefs.h>
26
#include <X11/keysym.h>
27
#include <X11/Shell.h>
30
#include "be_common_24.h"
31
#include "be_common_pixels.h"
42
static Display *display;
44
static int screen_number;
45
static int display_depth;
47
static int other_fd = -1;
48
static XImage *root_image;
51
/*************************************************************************
52
Initialize video mode and window.
53
*************************************************************************/
54
void be_init(const struct ct_size *screen_size, bool fullscreen)
59
display = XOpenDisplay(NULL);
62
screen_number = DefaultScreen(display);
63
display_depth = DefaultDepth(display, screen_number);
64
x11fd = ConnectionNumber(display);
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);
75
Pixmap dummy_mask = XCreatePixmap(display, window, 1, 1, 1);
77
values.graphics_exposures = False;
78
values.foreground = BlackPixel(display, screen_number);
80
values.graphics_exposures = False;
81
gc_plain = XCreateGC(display, window, GCGraphicsExposures, &values);
83
XFreePixmap(display, dummy_mask);
86
/* pop this window up on the screen */
87
XMapRaised(display, window);
90
XCreateImage(display, DefaultVisual(display, screen_number),
91
display_depth, ZPixmap, 0, NULL, screen_size->width,
92
screen_size->height, 32, 0);
94
fc_malloc(root_image->bytes_per_line * root_image->height);
97
/*************************************************************************
99
*************************************************************************/
100
static bool copy_event(struct be_event *event, XEvent * xevent)
102
switch (xevent->type) {
108
XExposeEvent *xev = &xevent->xexpose;
110
if (xev->count > 0) {
113
event->type = BE_EXPOSE;
118
XMotionEvent *xev = &xevent->xmotion;
120
event->type = BE_MOUSE_MOTION;
121
event->position.x = xev->x;
122
event->position.y = xev->y;
128
XButtonEvent *xev = &xevent->xbutton;
131
printf("pos=(%d,%d) button=0x%x state=0x%x\n", xev->x, xev->y,
132
xev->button, xev->state);
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) {
140
event->button = BE_MB_LEFT;
143
event->button = BE_MB_MIDDLE;
146
event->button = BE_MB_RIGHT;
155
XKeyEvent *xev = &xevent->xkey;
156
XKeyEvent copy_xev = *xev;
159
struct be_key *k = &event->key;
162
/* Mod2Mask is NumLock */
163
copy_xev.state = copy_xev.state & (ShiftMask | Mod2Mask);
164
chars = XLookupString(©_xev, string, sizeof(string), &key, NULL);
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);
174
} else if (key == x) { \
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);
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;
205
("WARNING: BE-X11: unconverted KeyPress: chars=%d string='%s' key=0x%lx\n",
209
event->type = BE_KEY_PRESSED;
210
event->position.x = xev->x;
211
event->position.y = xev->y;
215
printf("got event %d\n", xevent->type);
221
/*************************************************************************
223
*************************************************************************/
224
void be_next_non_blocking_event(struct be_event *event)
229
event->type = BE_NO_EVENT;
231
if (XCheckMaskEvent(display, -1 /*all events */ , &xevent)) {
232
if (copy_event(event, &xevent)) {
241
/*************************************************************************
243
*************************************************************************/
244
void be_next_blocking_event(struct be_event *event, struct timeval *timeout)
246
fd_set readfds, exceptfds;
247
int ret, highest = x11fd;
250
event->type = BE_NO_EVENT;
252
/* No event available: block on input socket until one is */
254
FD_SET(x11fd, &readfds);
258
if (other_fd != -1) {
259
FD_SET(other_fd, &readfds);
260
FD_SET(other_fd, &exceptfds);
261
if (other_fd > highest) {
266
ret = my_select(highest + 1, &readfds, NULL, &exceptfds, timeout);
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;
277
* New data on the x11 fd. return with BE_NO_EVENT and let the
280
} else if (errno == EINTR) {
287
/*************************************************************************
289
*************************************************************************/
290
void be_add_net_input(int sock)
295
/*************************************************************************
297
*************************************************************************/
298
void be_remove_net_input(void)
303
/*************************************************************************
305
*************************************************************************/
306
void be_screen_get_size(struct ct_size *size)
308
XWindowAttributes window_attributes;
310
XGetWindowAttributes(display, window, &window_attributes);
312
size->width = window_attributes.width;
313
size->height = window_attributes.height;
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)
320
/*************************************************************************
322
*************************************************************************/
323
static void fill_ximage_from_image_565(XImage * ximage,
324
const struct image *image)
327
unsigned short *pdest = (unsigned short *) ximage->data;
328
int extra_per_line = ximage->bytes_per_line / 2 - ximage->width;
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]));
339
pdest += extra_per_line;
343
/*************************************************************************
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)
353
unsigned short *pdest = (unsigned short *) ximage->data;
354
int extra_per_line = ximage->bytes_per_line / 2 - ximage->width;
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]));
365
pdest += extra_per_line;
369
/*************************************************************************
371
*************************************************************************/
372
static void fill_ximage_from_image_8888(XImage * ximage,
373
const struct image *image)
376
unsigned char *pdest = (unsigned char *) ximage->data;
377
int extra_per_line = ximage->bytes_per_line - ximage->width*4;
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);
388
pdest += extra_per_line;
392
/*************************************************************************
394
*************************************************************************/
395
void be_copy_osda_to_screen(struct osda *src)
397
assert(root_image->width == src->image->width &&
398
root_image->height == src->image->height);
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);
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,
427
XPutImage(display, window, gc_plain, root_image, 0, 0, 0, 0,
428
root_image->width, root_image->height);
432
/*************************************************************************
434
*************************************************************************/
435
bool be_supports_fullscreen(void)