You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

389 lines
8.3 KiB

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <sys/types.h>
  4. #include <sys/stat.h>
  5. #include "x11.h"
  6. #include "util.h"
  7. #include "Game.h"
  8. #include "UI.h"
  9. static int in_popup;
  10. static const char *pictdir;
  11. static Display *display;
  12. static XtAppContext app;
  13. static Drawable window, rootwindow;
  14. static Colormap colormap;
  15. static int depth;
  16. static XColor white, black;
  17. static Pixmap offscreen;
  18. static XtIntervalId timer;
  19. static GC stdgc, whitegc;
  20. static int screensize;
  21. static Widget toplevel, field;
  22. /*
  23. * Callback functions
  24. */
  25. static void
  26. popdown(Widget w, XtPointer client_data, XtPointer call_data) {
  27. UNUSED(w);
  28. UNUSED(client_data);
  29. UNUSED(call_data);
  30. in_popup = 0;
  31. }
  32. void
  33. x11_popup(Widget dialog) {
  34. Window temp;
  35. int tx, ty;
  36. XWindowAttributes tattr, pattr;
  37. int px, py;
  38. XtRealizeWidget(XtParent(dialog));
  39. XtSetMappedWhenManaged(XtParent(dialog), FALSE);
  40. XtManageChild(dialog);
  41. in_popup = 1;
  42. XTranslateCoordinates(display, XtWindow(toplevel), rootwindow,
  43. 0, 0, &tx, &ty, &temp);
  44. XGetWindowAttributes(display, XtWindow(toplevel), &tattr);
  45. XGetWindowAttributes(display, XtWindow(dialog), &pattr);
  46. px = tx + (tattr.width - pattr.width) / 2;
  47. py = ty + (tattr.height - pattr.height) / 2;
  48. XtVaSetValues(XtParent(dialog), XtNx, px, XtNy, py, NULL);
  49. XtAddCallback(XtParent(dialog), XtNpopdownCallback,
  50. (XtCallbackProc) popdown, NULL);
  51. XtPopup(XtParent(dialog), XtGrabExclusive);
  52. while (in_popup || XtAppPending(app))
  53. XtAppProcessEvent(app, XtIMXEvent);
  54. }
  55. /*
  56. * Event handlers
  57. */
  58. static void
  59. leave_window(Widget w, XtPointer client_data, XEvent *event, Boolean *b) {
  60. UNUSED(w);
  61. UNUSED(client_data);
  62. UNUSED(event);
  63. UNUSED(b);
  64. UI_pause_game();
  65. }
  66. static void
  67. enter_window(Widget w, XtPointer client_data, XEvent *event, Boolean *b) {
  68. UNUSED(w);
  69. UNUSED(client_data);
  70. UNUSED(event);
  71. UNUSED(b);
  72. UI_resume_game();
  73. }
  74. static void
  75. redraw_window(Widget w, XtPointer client_data, XEvent *event, Boolean *b) {
  76. UNUSED(w);
  77. UNUSED(client_data);
  78. UNUSED(event);
  79. UNUSED(b);
  80. UI_refresh();
  81. }
  82. static void
  83. button_press(Widget w, XtPointer data, XEvent *event, Boolean *b) {
  84. XButtonEvent *buttonevent = (XButtonEvent *) event;
  85. UNUSED(w);
  86. UNUSED(data);
  87. UNUSED(b);
  88. Game_button_press(buttonevent->x, buttonevent->y);
  89. }
  90. static void
  91. button_release(Widget w, XtPointer data, XEvent *event, Boolean *b) {
  92. XButtonEvent *buttonevent = (XButtonEvent *) event;
  93. UNUSED(w);
  94. UNUSED(data);
  95. UNUSED(b);
  96. Game_button_release(buttonevent->x, buttonevent->y);
  97. }
  98. static void
  99. timer_tick(XtPointer client_data, XtIntervalId *timer_id) {
  100. UNUSED(client_data);
  101. UNUSED(timer_id);
  102. UI_restart_timer();
  103. Game_update();
  104. }
  105. /*
  106. * Cursor handling
  107. */
  108. void
  109. x11_set_cursor(MCursor *cursor) {
  110. XDefineCursor(display, window, cursor->cursor);
  111. }
  112. void
  113. x11_load_cursor(const char *name, int masked, MCursor **cursorp) {
  114. MCursor *cursor;
  115. Pixmap bitmap, mask;
  116. int i, xh, yh;
  117. unsigned width, height;
  118. char file[255];
  119. cursor = xalloc(sizeof *cursor);
  120. sprintf(file, "%s/bitmaps/%s.xbm", pictdir, name);
  121. i = XReadBitmapFile(display, rootwindow, file,
  122. &width, &height, &bitmap, &xh, &yh);
  123. if (i == BitmapOpenFailed)
  124. fatal("cannot open %s", file);
  125. if (masked == CURSOR_SEP_MASK) {
  126. sprintf(file, "%s/bitmaps/%s_mask.xbm", pictdir, name);
  127. i = XReadBitmapFile(display, rootwindow,
  128. file, &width, &height, &mask, &xh, &yh);
  129. if (i == BitmapOpenFailed)
  130. fatal("cannot open %s", file);
  131. }
  132. else
  133. mask = bitmap;
  134. cursor->cursor = XCreatePixmapCursor(display, bitmap, mask,
  135. &black, &white,
  136. width/2, height/2);
  137. *cursorp = cursor;
  138. }
  139. /*
  140. * Pixmap handling
  141. */
  142. void
  143. x11_load_picture(const char *name, int trans, Picture **pictp) {
  144. Picture *pict;
  145. int i;
  146. char file[255];
  147. XpmColorSymbol symbol;
  148. Pixmap mask;
  149. XpmAttributes attr;
  150. unsigned long gcmask;
  151. XGCValues gcval;
  152. pict = xalloc(sizeof *pict);
  153. gcmask = GCForeground | GCBackground | GCGraphicsExposures;
  154. gcval.graphics_exposures = False;
  155. attr.valuemask = XpmCloseness | XpmReturnPixels | XpmColormap |
  156. XpmDepth;
  157. attr.closeness = 65535;
  158. attr.colormap = colormap;
  159. attr.depth = depth;
  160. if (!trans) {
  161. symbol.name = NULL;
  162. symbol.value = "none";
  163. XtVaGetValues(field, XtNbackground, &symbol.pixel, NULL);
  164. attr.colorsymbols = &symbol;
  165. attr.numsymbols = 1;
  166. attr.valuemask |= XpmColorSymbols;
  167. }
  168. sprintf(file, "%s/pixmaps/%s.xpm", pictdir, name);
  169. i = XpmReadFileToPixmap(display, rootwindow, file, &pict->pix,
  170. &mask, &attr);
  171. if (i < 0)
  172. fatal("cannot open %s", file);
  173. pict->mask = mask;
  174. pict->gc = XCreateGC(display, offscreen, gcmask, &gcval);
  175. if (trans)
  176. XSetClipMask(display, pict->gc, mask);
  177. pict->width = attr.width;
  178. pict->height = attr.height;
  179. *pictp = pict;
  180. }
  181. void
  182. x11_set_icon(Picture *icon) {
  183. XtVaSetValues(toplevel, XtNiconPixmap, icon->pix,
  184. XtNiconMask, icon->mask, NULL);
  185. }
  186. int
  187. x11_picture_width(Picture *pict) {
  188. return (pict->width);
  189. }
  190. int
  191. x11_picture_height(Picture *pict) {
  192. return (pict->height);
  193. }
  194. /*
  195. * Graphics operations
  196. */
  197. void
  198. x11_graphics_init() {
  199. XGCValues gcval;
  200. unsigned long gcmask;
  201. gcmask = GCGraphicsExposures;
  202. gcval.graphics_exposures = False;
  203. stdgc = XCreateGC(display, window, gcmask, &gcval);
  204. XSetLineAttributes(display, stdgc, 2, LineSolid, CapRound, JoinMiter);
  205. XSetBackground(display, stdgc, white.pixel);
  206. XSetForeground(display, stdgc, black.pixel);
  207. whitegc = XCreateGC(display, window, gcmask, &gcval);
  208. XSetBackground(display, whitegc, white.pixel);
  209. XSetForeground(display, whitegc, white.pixel);
  210. offscreen = XCreatePixmap(display, rootwindow, screensize,
  211. screensize, depth);
  212. }
  213. void
  214. x11_clear_window() {
  215. XFillRectangle(display, offscreen, whitegc, 0, 0,
  216. screensize, screensize);
  217. }
  218. void
  219. x11_refresh_window() {
  220. XCopyArea(display, offscreen, window, stdgc, 0, 0,
  221. screensize, screensize, 0, 0);
  222. }
  223. void
  224. x11_draw_image(Picture *pict, int x, int y) {
  225. XSetClipOrigin(display, pict->gc, x, y);
  226. XCopyArea(display, pict->pix, offscreen, pict->gc, 0, 0,
  227. pict->width, pict->height, x, y);
  228. }
  229. void
  230. x11_draw_line(int x1, int y1, int x2, int y2) {
  231. XDrawLine(display, offscreen, stdgc, x1, y1, x2, y2);
  232. }
  233. void
  234. x11_draw_string(const char *str, int x, int y) {
  235. XDrawString(display, offscreen, stdgc, x, y, str, strlen(str));
  236. }
  237. /*
  238. * Timer operations
  239. */
  240. void
  241. x11_start_timer(int ms) {
  242. timer = XtAppAddTimeOut(app, ms, timer_tick, NULL);
  243. }
  244. void
  245. x11_stop_timer() {
  246. if (!timer)
  247. return;
  248. XtRemoveTimeOut(timer);
  249. timer = (XtIntervalId) 0;
  250. }
  251. int
  252. x11_timer_active() {
  253. return (!!timer);
  254. }
  255. /*
  256. * Main Loop
  257. */
  258. void
  259. x11_main_loop() {
  260. XtAppMainLoop(app);
  261. }
  262. /*
  263. * Initialization
  264. */
  265. void
  266. x11_initialize(int *argc, char **argv) {
  267. struct stat stats;
  268. timer = (XtIntervalId) 0;
  269. toplevel = XtAppInitialize(&app, "XBill", NULL, 0, argc, argv,
  270. NULL, NULL, 0);
  271. display = XtDisplay(toplevel);
  272. if (stat(IMAGES, &stats) == 0)
  273. pictdir = IMAGES;
  274. else
  275. pictdir = ".";
  276. }
  277. void
  278. x11_setup_resources() {
  279. XrmDatabase database;
  280. database = XrmGetDatabase(display);
  281. XrmPutStringResource(&database, "*background", "#c4c4c4");
  282. XrmPutStringResource(&database, "*foreground", "#000000");
  283. XrmSetDatabase(display, database);
  284. }
  285. void
  286. x11_setup() {
  287. Screen *screen;
  288. XSizeHints h;
  289. Dimension winwidth, winheight;
  290. XtRealizeWidget(toplevel);
  291. screen = XtScreen(toplevel);
  292. depth = DefaultDepthOfScreen(screen);
  293. rootwindow = RootWindowOfScreen(screen);
  294. colormap = DefaultColormapOfScreen(screen);
  295. white.pixel = WhitePixelOfScreen(screen);
  296. XQueryColor(display, colormap, &white);
  297. black.pixel = BlackPixelOfScreen(screen);
  298. XQueryColor(display, colormap, &black);
  299. XtVaGetValues(toplevel, XtNwidth, &winwidth, XtNheight, &winheight,
  300. NULL);
  301. h.width = h.base_width = h.min_width = h.max_width = winwidth;
  302. h.height = h.base_height = h.min_height = h.max_height = winheight;
  303. h.width_inc = h.height_inc = 0;
  304. h.flags = PSize|PMaxSize|PMinSize|PBaseSize|PResizeInc;
  305. XSetWMNormalHints(display, XtWindow(toplevel), &h);
  306. }
  307. void
  308. x11_add_event_handlers(Widget w) {
  309. XtAddEventHandler(w, ButtonPressMask, FALSE, button_press, NULL);
  310. XtAddEventHandler(w, ButtonReleaseMask, FALSE, button_release, NULL);
  311. XtAddEventHandler(w, LeaveWindowMask, FALSE, leave_window, NULL);
  312. XtAddEventHandler(w, EnterWindowMask, FALSE, enter_window, NULL);
  313. XtAddEventHandler(w, ExposureMask, FALSE, redraw_window, NULL);
  314. }
  315. Widget
  316. x11_toplevel() {
  317. return toplevel;
  318. }
  319. void
  320. x11_set_drawingarea(Widget w, int size) {
  321. field = w;
  322. window = XtWindow(w);
  323. screensize = size;
  324. }