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"
40
static Display *display;
42
static int screen_number;
43
static int display_depth;
45
static int other_fd = -1;
46
static XImage *root_image;
49
/*************************************************************************
51
*************************************************************************/
52
void be_init(const struct ct_size *screen_size, bool fullscreen)
57
display = XOpenDisplay(NULL);
60
screen_number = DefaultScreen(display);
61
display_depth = DefaultDepth(display, screen_number);
62
x11fd = ConnectionNumber(display);
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);
73
Pixmap dummy_mask = XCreatePixmap(display, window, 1, 1, 1);
75
values.graphics_exposures = False;
76
values.foreground = BlackPixel(display, screen_number);
78
values.graphics_exposures = False;
79
gc_plain = XCreateGC(display, window, GCGraphicsExposures, &values);
81
XFreePixmap(display, dummy_mask);
84
/* pop this window up on the screen */
85
XMapRaised(display, window);
88
XCreateImage(display, DefaultVisual(display, screen_number),
89
display_depth, ZPixmap, 0, NULL, screen_size->width,
90
screen_size->height, 32, 0);
92
fc_malloc(root_image->bytes_per_line * root_image->height);
95
/*************************************************************************
97
*************************************************************************/
98
static bool copy_event(struct be_event *event, XEvent * xevent)
100
switch (xevent->type) {
106
XExposeEvent *xev = &xevent->xexpose;
108
if (xev->count > 0) {
111
event->type = BE_EXPOSE;
116
XMotionEvent *xev = &xevent->xmotion;
118
event->type = BE_MOUSE_MOTION;
119
event->position.x = xev->x;
120
event->position.y = xev->y;
126
XButtonEvent *xev = &xevent->xbutton;
129
printf("pos=(%d,%d) button=0x%x state=0x%x\n", xev->x, xev->y,
130
xev->button, xev->state);
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) {
138
event->button = BE_MB_LEFT;
141
event->button = BE_MB_MIDDLE;
144
event->button = BE_MB_RIGHT;
153
XKeyEvent *xev = &xevent->xkey;
154
XKeyEvent copy_xev = *xev;
157
struct be_key *k = &event->key;
160
/* Mod2Mask is NumLock */
161
copy_xev.state = copy_xev.state & (ShiftMask | Mod2Mask);
162
chars = XLookupString(©_xev, string, sizeof(string), &key, NULL);
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);
172
} else if (key == x) { \
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);
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;
203
("WARNING: BE-X11: unconverted KeyPress: chars=%d string='%s' key=0x%lx\n",
207
event->type = BE_KEY_PRESSED;
208
event->position.x = xev->x;
209
event->position.y = xev->y;
213
printf("got event %d\n", xevent->type);
219
/*************************************************************************
221
*************************************************************************/
222
void be_next_event(struct be_event *event, struct timeval *timeout)
227
event->type = BE_NO_EVENT;
229
if (XCheckMaskEvent(display, -1 /*all events */ , &xevent)) {
230
//printf("got event %d\n", xevent.type);
231
if (copy_event(event, &xevent)) {
242
fd_set readfds, exceptfds;
243
int ret, highest = x11fd;
245
/* No event available: block on input socket until one is */
247
FD_SET(x11fd, &readfds);
251
if (other_fd != -1) {
252
FD_SET(other_fd, &readfds);
253
FD_SET(other_fd, &exceptfds);
254
if (other_fd > highest) {
259
ret = select(highest + 1, &readfds, NULL, &exceptfds, timeout);
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;
270
/* new data on the x11 fd */
272
} else if (errno == EINTR) {
280
/*************************************************************************
282
*************************************************************************/
283
void be_add_net_input(int sock)
288
/*************************************************************************
290
*************************************************************************/
291
void be_remove_net_input(void)
296
/*************************************************************************
298
*************************************************************************/
299
void be_screen_get_size(struct ct_size *size)
301
XWindowAttributes window_attributes;
303
XGetWindowAttributes(display, window, &window_attributes);
305
size->width = window_attributes.width;
306
size->height = window_attributes.height;
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)
313
/*************************************************************************
315
*************************************************************************/
316
static void fill_ximage_from_image_565(XImage * ximage,
317
const struct image *image)
320
unsigned short *pdest = (unsigned short *) ximage->data;
321
int extra_per_line = ximage->bytes_per_line / 2 - ximage->width;
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]));
332
pdest += extra_per_line;
336
/*************************************************************************
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)
346
unsigned short *pdest = (unsigned short *) ximage->data;
347
int extra_per_line = ximage->bytes_per_line / 2 - ximage->width;
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]));
358
pdest += extra_per_line;
362
/*************************************************************************
364
*************************************************************************/
365
static void fill_ximage_from_image_8888(XImage * ximage,
366
const struct image *image)
369
unsigned char *pdest = (unsigned char *) ximage->data;
370
int extra_per_line = ximage->bytes_per_line - ximage->width*4;
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);
381
pdest += extra_per_line;
385
/*************************************************************************
387
*************************************************************************/
388
void be_copy_osda_to_screen(struct osda *src)
390
assert(root_image->width == src->image->width &&
391
root_image->height == src->image->height);
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);
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,
420
XPutImage(display, window, gc_plain, root_image, 0, 0, 0, 0,
421
root_image->width, root_image->height);
425
/*************************************************************************
427
*************************************************************************/
428
bool be_supports_fullscreen(void)