vid_x.c 25 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // vid_x.c -- general x video driver
  16. #define _BSD
  17. typedef unsigned short PIXEL;
  18. #include <ctype.h>
  19. #include <sys/time.h>
  20. #include <sys/types.h>
  21. #include <unistd.h>
  22. #include <signal.h>
  23. #include <stdlib.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <sys/ipc.h>
  27. #include <sys/shm.h>
  28. #include <X11/Xlib.h>
  29. #include <X11/Xutil.h>
  30. #include <X11/Xatom.h>
  31. #include <X11/keysym.h>
  32. #include <X11/extensions/XShm.h>
  33. #include "quakedef.h"
  34. #include "d_local.h"
  35. cvar_t _windowed_mouse = {"_windowed_mouse","0", true};
  36. cvar_t m_filter = {"m_filter","0", true};
  37. float old_windowed_mouse;
  38. // not used
  39. int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
  40. byte *VGA_pagebase;
  41. qboolean mouse_avail;
  42. int mouse_buttons=3;
  43. int mouse_oldbuttonstate;
  44. int mouse_buttonstate;
  45. float mouse_x, mouse_y;
  46. float old_mouse_x, old_mouse_y;
  47. int p_mouse_x;
  48. int p_mouse_y;
  49. int ignorenext;
  50. int bits_per_pixel;
  51. typedef struct
  52. {
  53. int input;
  54. int output;
  55. } keymap_t;
  56. viddef_t vid; // global video state
  57. unsigned short d_8to16table[256];
  58. int num_shades=32;
  59. int d_con_indirect = 0;
  60. int vid_buffersize;
  61. static qboolean doShm;
  62. static Display *x_disp;
  63. static Colormap x_cmap;
  64. static Window x_win;
  65. static GC x_gc;
  66. static Visual *x_vis;
  67. static XVisualInfo *x_visinfo;
  68. //static XImage *x_image;
  69. static int x_shmeventtype;
  70. //static XShmSegmentInfo x_shminfo;
  71. static qboolean oktodraw = false;
  72. int XShmQueryExtension(Display *);
  73. int XShmGetEventBase(Display *);
  74. int current_framebuffer;
  75. static XImage *x_framebuffer[2] = { 0, 0 };
  76. static XShmSegmentInfo x_shminfo[2];
  77. static int verbose=0;
  78. static byte current_palette[768];
  79. static long X11_highhunkmark;
  80. static long X11_buffersize;
  81. int vid_surfcachesize;
  82. void *vid_surfcache;
  83. void (*vid_menudrawfn)(void);
  84. void (*vid_menukeyfn)(int key);
  85. void VID_MenuKey (int key);
  86. static PIXEL st2d_8to16table[256];
  87. static int shiftmask_fl=0;
  88. static long r_shift,g_shift,b_shift;
  89. static unsigned long r_mask,g_mask,b_mask;
  90. void shiftmask_init()
  91. {
  92. unsigned int x;
  93. r_mask=x_vis->red_mask;
  94. g_mask=x_vis->green_mask;
  95. b_mask=x_vis->blue_mask;
  96. for(r_shift=-8,x=1;x<r_mask;x=x<<1)r_shift++;
  97. for(g_shift=-8,x=1;x<g_mask;x=x<<1)g_shift++;
  98. for(b_shift=-8,x=1;x<b_mask;x=x<<1)b_shift++;
  99. shiftmask_fl=1;
  100. }
  101. PIXEL xlib_rgb(int r,int g,int b)
  102. {
  103. PIXEL p;
  104. if(shiftmask_fl==0) shiftmask_init();
  105. p=0;
  106. if(r_shift>0) {
  107. p=(r<<(r_shift))&r_mask;
  108. } else if(r_shift<0) {
  109. p=(r>>(-r_shift))&r_mask;
  110. } else p|=(r&r_mask);
  111. if(g_shift>0) {
  112. p|=(g<<(g_shift))&g_mask;
  113. } else if(g_shift<0) {
  114. p|=(g>>(-g_shift))&g_mask;
  115. } else p|=(g&g_mask);
  116. if(b_shift>0) {
  117. p|=(b<<(b_shift))&b_mask;
  118. } else if(b_shift<0) {
  119. p|=(b>>(-b_shift))&b_mask;
  120. } else p|=(b&b_mask);
  121. return p;
  122. }
  123. void st2_fixup( XImage *framebuf, int x, int y, int width, int height)
  124. {
  125. int xi,yi;
  126. unsigned char *src;
  127. PIXEL *dest;
  128. if( (x<0)||(y<0) )return;
  129. for (yi = y; yi < (y+height); yi++) {
  130. src = &framebuf->data [yi * framebuf->bytes_per_line];
  131. dest = (PIXEL*)src;
  132. for(xi = (x+width-1); xi >= x; xi--) {
  133. dest[xi] = st2d_8to16table[src[xi]];
  134. }
  135. }
  136. }
  137. // ========================================================================
  138. // Tragic death handler
  139. // ========================================================================
  140. void TragicDeath(int signal_num)
  141. {
  142. XAutoRepeatOn(x_disp);
  143. XCloseDisplay(x_disp);
  144. Sys_Error("This death brought to you by the number %d\n", signal_num);
  145. }
  146. // ========================================================================
  147. // makes a null cursor
  148. // ========================================================================
  149. static Cursor CreateNullCursor(Display *display, Window root)
  150. {
  151. Pixmap cursormask;
  152. XGCValues xgc;
  153. GC gc;
  154. XColor dummycolour;
  155. Cursor cursor;
  156. cursormask = XCreatePixmap(display, root, 1, 1, 1/*depth*/);
  157. xgc.function = GXclear;
  158. gc = XCreateGC(display, cursormask, GCFunction, &xgc);
  159. XFillRectangle(display, cursormask, gc, 0, 0, 1, 1);
  160. dummycolour.pixel = 0;
  161. dummycolour.red = 0;
  162. dummycolour.flags = 04;
  163. cursor = XCreatePixmapCursor(display, cursormask, cursormask,
  164. &dummycolour,&dummycolour, 0,0);
  165. XFreePixmap(display,cursormask);
  166. XFreeGC(display,gc);
  167. return cursor;
  168. }
  169. void ResetFrameBuffer(void)
  170. {
  171. int mem;
  172. int pwidth;
  173. if (x_framebuffer[0])
  174. {
  175. free(x_framebuffer[0]->data);
  176. free(x_framebuffer[0]);
  177. }
  178. if (d_pzbuffer)
  179. {
  180. D_FlushCaches ();
  181. Hunk_FreeToHighMark (X11_highhunkmark);
  182. d_pzbuffer = NULL;
  183. }
  184. X11_highhunkmark = Hunk_HighMark ();
  185. // alloc an extra line in case we want to wrap, and allocate the z-buffer
  186. X11_buffersize = vid.width * vid.height * sizeof (*d_pzbuffer);
  187. vid_surfcachesize = D_SurfaceCacheForRes (vid.width, vid.height);
  188. X11_buffersize += vid_surfcachesize;
  189. d_pzbuffer = Hunk_HighAllocName (X11_buffersize, "video");
  190. if (d_pzbuffer == NULL)
  191. Sys_Error ("Not enough memory for video mode\n");
  192. vid_surfcache = (byte *) d_pzbuffer
  193. + vid.width * vid.height * sizeof (*d_pzbuffer);
  194. D_InitCaches(vid_surfcache, vid_surfcachesize);
  195. pwidth = x_visinfo->depth / 8;
  196. if (pwidth == 3) pwidth = 4;
  197. mem = ((vid.width*pwidth+7)&~7) * vid.height;
  198. x_framebuffer[0] = XCreateImage( x_disp,
  199. x_vis,
  200. x_visinfo->depth,
  201. ZPixmap,
  202. 0,
  203. malloc(mem),
  204. vid.width, vid.height,
  205. 32,
  206. 0);
  207. if (!x_framebuffer[0])
  208. Sys_Error("VID: XCreateImage failed\n");
  209. vid.buffer = (byte*) (x_framebuffer[0]);
  210. vid.conbuffer = vid.buffer;
  211. }
  212. void ResetSharedFrameBuffers(void)
  213. {
  214. int size;
  215. int key;
  216. int minsize = getpagesize();
  217. int frm;
  218. if (d_pzbuffer)
  219. {
  220. D_FlushCaches ();
  221. Hunk_FreeToHighMark (X11_highhunkmark);
  222. d_pzbuffer = NULL;
  223. }
  224. X11_highhunkmark = Hunk_HighMark ();
  225. // alloc an extra line in case we want to wrap, and allocate the z-buffer
  226. X11_buffersize = vid.width * vid.height * sizeof (*d_pzbuffer);
  227. vid_surfcachesize = D_SurfaceCacheForRes (vid.width, vid.height);
  228. X11_buffersize += vid_surfcachesize;
  229. d_pzbuffer = Hunk_HighAllocName (X11_buffersize, "video");
  230. if (d_pzbuffer == NULL)
  231. Sys_Error ("Not enough memory for video mode\n");
  232. vid_surfcache = (byte *) d_pzbuffer
  233. + vid.width * vid.height * sizeof (*d_pzbuffer);
  234. D_InitCaches(vid_surfcache, vid_surfcachesize);
  235. for (frm=0 ; frm<2 ; frm++)
  236. {
  237. // free up old frame buffer memory
  238. if (x_framebuffer[frm])
  239. {
  240. XShmDetach(x_disp, &x_shminfo[frm]);
  241. free(x_framebuffer[frm]);
  242. shmdt(x_shminfo[frm].shmaddr);
  243. }
  244. // create the image
  245. x_framebuffer[frm] = XShmCreateImage( x_disp,
  246. x_vis,
  247. x_visinfo->depth,
  248. ZPixmap,
  249. 0,
  250. &x_shminfo[frm],
  251. vid.width,
  252. vid.height );
  253. // grab shared memory
  254. size = x_framebuffer[frm]->bytes_per_line
  255. * x_framebuffer[frm]->height;
  256. if (size < minsize)
  257. Sys_Error("VID: Window must use at least %d bytes\n", minsize);
  258. key = random();
  259. x_shminfo[frm].shmid = shmget((key_t)key, size, IPC_CREAT|0777);
  260. if (x_shminfo[frm].shmid==-1)
  261. Sys_Error("VID: Could not get any shared memory\n");
  262. // attach to the shared memory segment
  263. x_shminfo[frm].shmaddr =
  264. (void *) shmat(x_shminfo[frm].shmid, 0, 0);
  265. printf("VID: shared memory id=%d, addr=0x%lx\n", x_shminfo[frm].shmid,
  266. (long) x_shminfo[frm].shmaddr);
  267. x_framebuffer[frm]->data = x_shminfo[frm].shmaddr;
  268. // get the X server to attach to it
  269. if (!XShmAttach(x_disp, &x_shminfo[frm]))
  270. Sys_Error("VID: XShmAttach() failed\n");
  271. XSync(x_disp, 0);
  272. shmctl(x_shminfo[frm].shmid, IPC_RMID, 0);
  273. }
  274. }
  275. // Called at startup to set up translation tables, takes 256 8 bit RGB values
  276. // the palette data will go away after the call, so it must be copied off if
  277. // the video driver will need it again
  278. void VID_Init (unsigned char *palette)
  279. {
  280. int pnum, i;
  281. XVisualInfo template;
  282. int num_visuals;
  283. int template_mask;
  284. S_Init();
  285. ignorenext=0;
  286. vid.width = 320;
  287. vid.height = 200;
  288. vid.maxwarpwidth = WARP_WIDTH;
  289. vid.maxwarpheight = WARP_HEIGHT;
  290. vid.numpages = 2;
  291. vid.colormap = host_colormap;
  292. // vid.cbits = VID_CBITS;
  293. // vid.grades = VID_GRADES;
  294. vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048));
  295. srandom(getpid());
  296. verbose=COM_CheckParm("-verbose");
  297. // open the display
  298. x_disp = XOpenDisplay(0);
  299. if (!x_disp)
  300. {
  301. if (getenv("DISPLAY"))
  302. Sys_Error("VID: Could not open display [%s]\n",
  303. getenv("DISPLAY"));
  304. else
  305. Sys_Error("VID: Could not open local display\n");
  306. }
  307. // catch signals so i can turn on auto-repeat
  308. {
  309. struct sigaction sa;
  310. sigaction(SIGINT, 0, &sa);
  311. sa.sa_handler = TragicDeath;
  312. sigaction(SIGINT, &sa, 0);
  313. sigaction(SIGTERM, &sa, 0);
  314. }
  315. XAutoRepeatOff(x_disp);
  316. // for debugging only
  317. XSynchronize(x_disp, True);
  318. // check for command-line window size
  319. if ((pnum=COM_CheckParm("-winsize")))
  320. {
  321. if (pnum >= com_argc-2)
  322. Sys_Error("VID: -winsize <width> <height>\n");
  323. vid.width = Q_atoi(com_argv[pnum+1]);
  324. vid.height = Q_atoi(com_argv[pnum+2]);
  325. if (!vid.width || !vid.height)
  326. Sys_Error("VID: Bad window width/height\n");
  327. }
  328. if ((pnum=COM_CheckParm("-width"))) {
  329. if (pnum >= com_argc-1)
  330. Sys_Error("VID: -width <width>\n");
  331. vid.width = Q_atoi(com_argv[pnum+1]);
  332. if (!vid.width)
  333. Sys_Error("VID: Bad window width\n");
  334. }
  335. if ((pnum=COM_CheckParm("-height"))) {
  336. if (pnum >= com_argc-1)
  337. Sys_Error("VID: -height <height>\n");
  338. vid.height = Q_atoi(com_argv[pnum+1]);
  339. if (!vid.height)
  340. Sys_Error("VID: Bad window height\n");
  341. }
  342. template_mask = 0;
  343. // specify a visual id
  344. if ((pnum=COM_CheckParm("-visualid")))
  345. {
  346. if (pnum >= com_argc-1)
  347. Sys_Error("VID: -visualid <id#>\n");
  348. template.visualid = Q_atoi(com_argv[pnum+1]);
  349. template_mask = VisualIDMask;
  350. }
  351. // If not specified, use default visual
  352. else
  353. {
  354. int screen;
  355. screen = XDefaultScreen(x_disp);
  356. template.visualid =
  357. XVisualIDFromVisual(XDefaultVisual(x_disp, screen));
  358. template_mask = VisualIDMask;
  359. }
  360. // pick a visual- warn if more than one was available
  361. x_visinfo = XGetVisualInfo(x_disp, template_mask, &template, &num_visuals);
  362. if (num_visuals > 1)
  363. {
  364. printf("Found more than one visual id at depth %d:\n", template.depth);
  365. for (i=0 ; i<num_visuals ; i++)
  366. printf(" -visualid %d\n", (int)(x_visinfo[i].visualid));
  367. }
  368. else if (num_visuals == 0)
  369. {
  370. if (template_mask == VisualIDMask)
  371. Sys_Error("VID: Bad visual id %d\n", template.visualid);
  372. else
  373. Sys_Error("VID: No visuals at depth %d\n", template.depth);
  374. }
  375. if (verbose)
  376. {
  377. printf("Using visualid %d:\n", (int)(x_visinfo->visualid));
  378. printf(" screen %d\n", x_visinfo->screen);
  379. printf(" red_mask 0x%x\n", (int)(x_visinfo->red_mask));
  380. printf(" green_mask 0x%x\n", (int)(x_visinfo->green_mask));
  381. printf(" blue_mask 0x%x\n", (int)(x_visinfo->blue_mask));
  382. printf(" colormap_size %d\n", x_visinfo->colormap_size);
  383. printf(" bits_per_rgb %d\n", x_visinfo->bits_per_rgb);
  384. }
  385. x_vis = x_visinfo->visual;
  386. // setup attributes for main window
  387. {
  388. int attribmask = CWEventMask | CWColormap | CWBorderPixel;
  389. XSetWindowAttributes attribs;
  390. Colormap tmpcmap;
  391. tmpcmap = XCreateColormap(x_disp, XRootWindow(x_disp,
  392. x_visinfo->screen), x_vis, AllocNone);
  393. attribs.event_mask = StructureNotifyMask | KeyPressMask
  394. | KeyReleaseMask | ExposureMask | PointerMotionMask |
  395. ButtonPressMask | ButtonReleaseMask;
  396. attribs.border_pixel = 0;
  397. attribs.colormap = tmpcmap;
  398. // create the main window
  399. x_win = XCreateWindow( x_disp,
  400. XRootWindow(x_disp, x_visinfo->screen),
  401. 0, 0, // x, y
  402. vid.width, vid.height,
  403. 0, // borderwidth
  404. x_visinfo->depth,
  405. InputOutput,
  406. x_vis,
  407. attribmask,
  408. &attribs );
  409. XStoreName( x_disp,x_win,"xquake");
  410. if (x_visinfo->class != TrueColor)
  411. XFreeColormap(x_disp, tmpcmap);
  412. }
  413. if (x_visinfo->depth == 8)
  414. {
  415. // create and upload the palette
  416. if (x_visinfo->class == PseudoColor)
  417. {
  418. x_cmap = XCreateColormap(x_disp, x_win, x_vis, AllocAll);
  419. VID_SetPalette(palette);
  420. XSetWindowColormap(x_disp, x_win, x_cmap);
  421. }
  422. }
  423. // inviso cursor
  424. XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win));
  425. // create the GC
  426. {
  427. XGCValues xgcvalues;
  428. int valuemask = GCGraphicsExposures;
  429. xgcvalues.graphics_exposures = False;
  430. x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues );
  431. }
  432. // map the window
  433. XMapWindow(x_disp, x_win);
  434. // wait for first exposure event
  435. {
  436. XEvent event;
  437. do
  438. {
  439. XNextEvent(x_disp, &event);
  440. if (event.type == Expose && !event.xexpose.count)
  441. oktodraw = true;
  442. } while (!oktodraw);
  443. }
  444. // now safe to draw
  445. // even if MITSHM is available, make sure it's a local connection
  446. if (XShmQueryExtension(x_disp))
  447. {
  448. char *displayname;
  449. doShm = true;
  450. displayname = (char *) getenv("DISPLAY");
  451. if (displayname)
  452. {
  453. char *d = displayname;
  454. while (*d && (*d != ':')) d++;
  455. if (*d) *d = 0;
  456. if (!(!strcasecmp(displayname, "unix") || !*displayname))
  457. doShm = false;
  458. }
  459. }
  460. if (doShm)
  461. {
  462. x_shmeventtype = XShmGetEventBase(x_disp) + ShmCompletion;
  463. ResetSharedFrameBuffers();
  464. }
  465. else
  466. ResetFrameBuffer();
  467. current_framebuffer = 0;
  468. vid.rowbytes = x_framebuffer[0]->bytes_per_line;
  469. vid.buffer = x_framebuffer[0]->data;
  470. vid.direct = 0;
  471. vid.conbuffer = x_framebuffer[0]->data;
  472. vid.conrowbytes = vid.rowbytes;
  473. vid.conwidth = vid.width;
  474. vid.conheight = vid.height;
  475. vid.aspect = ((float)vid.height / (float)vid.width) * (320.0 / 240.0);
  476. // XSynchronize(x_disp, False);
  477. }
  478. void VID_ShiftPalette(unsigned char *p)
  479. {
  480. VID_SetPalette(p);
  481. }
  482. void VID_SetPalette(unsigned char *palette)
  483. {
  484. int i;
  485. XColor colors[256];
  486. for(i=0;i<256;i++)
  487. st2d_8to16table[i]= xlib_rgb(palette[i*3],
  488. palette[i*3+1],palette[i*3+2]);
  489. if (x_visinfo->class == PseudoColor && x_visinfo->depth == 8)
  490. {
  491. if (palette != current_palette)
  492. memcpy(current_palette, palette, 768);
  493. for (i=0 ; i<256 ; i++)
  494. {
  495. colors[i].pixel = i;
  496. colors[i].flags = DoRed|DoGreen|DoBlue;
  497. colors[i].red = palette[i*3] * 257;
  498. colors[i].green = palette[i*3+1] * 257;
  499. colors[i].blue = palette[i*3+2] * 257;
  500. }
  501. XStoreColors(x_disp, x_cmap, colors, 256);
  502. }
  503. }
  504. // Called at shutdown
  505. void VID_Shutdown (void)
  506. {
  507. Con_Printf("VID_Shutdown\n");
  508. XAutoRepeatOn(x_disp);
  509. XCloseDisplay(x_disp);
  510. }
  511. int XLateKey(XKeyEvent *ev)
  512. {
  513. int key;
  514. char buf[64];
  515. KeySym keysym;
  516. key = 0;
  517. XLookupString(ev, buf, sizeof buf, &keysym, 0);
  518. switch(keysym)
  519. {
  520. case XK_KP_Page_Up:
  521. case XK_Page_Up: key = K_PGUP; break;
  522. case XK_KP_Page_Down:
  523. case XK_Page_Down: key = K_PGDN; break;
  524. case XK_KP_Home:
  525. case XK_Home: key = K_HOME; break;
  526. case XK_KP_End:
  527. case XK_End: key = K_END; break;
  528. case XK_KP_Left:
  529. case XK_Left: key = K_LEFTARROW; break;
  530. case XK_KP_Right:
  531. case XK_Right: key = K_RIGHTARROW; break;
  532. case XK_KP_Down:
  533. case XK_Down: key = K_DOWNARROW; break;
  534. case XK_KP_Up:
  535. case XK_Up: key = K_UPARROW; break;
  536. case XK_Escape: key = K_ESCAPE; break;
  537. case XK_KP_Enter:
  538. case XK_Return: key = K_ENTER; break;
  539. case XK_Tab: key = K_TAB; break;
  540. case XK_F1: key = K_F1; break;
  541. case XK_F2: key = K_F2; break;
  542. case XK_F3: key = K_F3; break;
  543. case XK_F4: key = K_F4; break;
  544. case XK_F5: key = K_F5; break;
  545. case XK_F6: key = K_F6; break;
  546. case XK_F7: key = K_F7; break;
  547. case XK_F8: key = K_F8; break;
  548. case XK_F9: key = K_F9; break;
  549. case XK_F10: key = K_F10; break;
  550. case XK_F11: key = K_F11; break;
  551. case XK_F12: key = K_F12; break;
  552. case XK_BackSpace: key = K_BACKSPACE; break;
  553. case XK_KP_Delete:
  554. case XK_Delete: key = K_DEL; break;
  555. case XK_Pause: key = K_PAUSE; break;
  556. case XK_Shift_L:
  557. case XK_Shift_R: key = K_SHIFT; break;
  558. case XK_Execute:
  559. case XK_Control_L:
  560. case XK_Control_R: key = K_CTRL; break;
  561. case XK_Alt_L:
  562. case XK_Meta_L:
  563. case XK_Alt_R:
  564. case XK_Meta_R: key = K_ALT; break;
  565. case XK_KP_Begin: key = K_AUX30; break;
  566. case XK_Insert:
  567. case XK_KP_Insert: key = K_INS; break;
  568. case XK_KP_Multiply: key = '*'; break;
  569. case XK_KP_Add: key = '+'; break;
  570. case XK_KP_Subtract: key = '-'; break;
  571. case XK_KP_Divide: key = '/'; break;
  572. #if 0
  573. case 0x021: key = '1';break;/* [!] */
  574. case 0x040: key = '2';break;/* [@] */
  575. case 0x023: key = '3';break;/* [#] */
  576. case 0x024: key = '4';break;/* [$] */
  577. case 0x025: key = '5';break;/* [%] */
  578. case 0x05e: key = '6';break;/* [^] */
  579. case 0x026: key = '7';break;/* [&] */
  580. case 0x02a: key = '8';break;/* [*] */
  581. case 0x028: key = '9';;break;/* [(] */
  582. case 0x029: key = '0';break;/* [)] */
  583. case 0x05f: key = '-';break;/* [_] */
  584. case 0x02b: key = '=';break;/* [+] */
  585. case 0x07c: key = '\'';break;/* [|] */
  586. case 0x07d: key = '[';break;/* [}] */
  587. case 0x07b: key = ']';break;/* [{] */
  588. case 0x022: key = '\'';break;/* ["] */
  589. case 0x03a: key = ';';break;/* [:] */
  590. case 0x03f: key = '/';break;/* [?] */
  591. case 0x03e: key = '.';break;/* [>] */
  592. case 0x03c: key = ',';break;/* [<] */
  593. #endif
  594. default:
  595. key = *(unsigned char*)buf;
  596. if (key >= 'A' && key <= 'Z')
  597. key = key - 'A' + 'a';
  598. // fprintf(stdout, "case 0x0%x: key = ___;break;/* [%c] */\n", keysym);
  599. break;
  600. }
  601. return key;
  602. }
  603. struct
  604. {
  605. int key;
  606. int down;
  607. } keyq[64];
  608. int keyq_head=0;
  609. int keyq_tail=0;
  610. int config_notify=0;
  611. int config_notify_width;
  612. int config_notify_height;
  613. void GetEvent(void)
  614. {
  615. XEvent x_event;
  616. int b;
  617. XNextEvent(x_disp, &x_event);
  618. switch(x_event.type) {
  619. case KeyPress:
  620. keyq[keyq_head].key = XLateKey(&x_event.xkey);
  621. keyq[keyq_head].down = true;
  622. keyq_head = (keyq_head + 1) & 63;
  623. break;
  624. case KeyRelease:
  625. keyq[keyq_head].key = XLateKey(&x_event.xkey);
  626. keyq[keyq_head].down = false;
  627. keyq_head = (keyq_head + 1) & 63;
  628. break;
  629. case MotionNotify:
  630. if (_windowed_mouse.value) {
  631. mouse_x = (float) ((int)x_event.xmotion.x - (int)(vid.width/2));
  632. mouse_y = (float) ((int)x_event.xmotion.y - (int)(vid.height/2));
  633. //printf("m: x=%d,y=%d, mx=%3.2f,my=%3.2f\n",
  634. // x_event.xmotion.x, x_event.xmotion.y, mouse_x, mouse_y);
  635. /* move the mouse to the window center again */
  636. XSelectInput(x_disp,x_win,StructureNotifyMask|KeyPressMask
  637. |KeyReleaseMask|ExposureMask
  638. |ButtonPressMask
  639. |ButtonReleaseMask);
  640. XWarpPointer(x_disp,None,x_win,0,0,0,0,
  641. (vid.width/2),(vid.height/2));
  642. XSelectInput(x_disp,x_win,StructureNotifyMask|KeyPressMask
  643. |KeyReleaseMask|ExposureMask
  644. |PointerMotionMask|ButtonPressMask
  645. |ButtonReleaseMask);
  646. } else {
  647. mouse_x = (float) (x_event.xmotion.x-p_mouse_x);
  648. mouse_y = (float) (x_event.xmotion.y-p_mouse_y);
  649. p_mouse_x=x_event.xmotion.x;
  650. p_mouse_y=x_event.xmotion.y;
  651. }
  652. break;
  653. case ButtonPress:
  654. b=-1;
  655. if (x_event.xbutton.button == 1)
  656. b = 0;
  657. else if (x_event.xbutton.button == 2)
  658. b = 2;
  659. else if (x_event.xbutton.button == 3)
  660. b = 1;
  661. if (b>=0)
  662. mouse_buttonstate |= 1<<b;
  663. break;
  664. case ButtonRelease:
  665. b=-1;
  666. if (x_event.xbutton.button == 1)
  667. b = 0;
  668. else if (x_event.xbutton.button == 2)
  669. b = 2;
  670. else if (x_event.xbutton.button == 3)
  671. b = 1;
  672. if (b>=0)
  673. mouse_buttonstate &= ~(1<<b);
  674. break;
  675. case ConfigureNotify:
  676. //printf("config notify\n");
  677. config_notify_width = x_event.xconfigure.width;
  678. config_notify_height = x_event.xconfigure.height;
  679. config_notify = 1;
  680. break;
  681. default:
  682. if (doShm && x_event.type == x_shmeventtype)
  683. oktodraw = true;
  684. }
  685. if (old_windowed_mouse != _windowed_mouse.value) {
  686. old_windowed_mouse = _windowed_mouse.value;
  687. if (!_windowed_mouse.value) {
  688. /* ungrab the pointer */
  689. XUngrabPointer(x_disp,CurrentTime);
  690. } else {
  691. /* grab the pointer */
  692. XGrabPointer(x_disp,x_win,True,0,GrabModeAsync,
  693. GrabModeAsync,x_win,None,CurrentTime);
  694. }
  695. }
  696. }
  697. // flushes the given rectangles from the view buffer to the screen
  698. void VID_Update (vrect_t *rects)
  699. {
  700. // if the window changes dimension, skip this frame
  701. if (config_notify)
  702. {
  703. fprintf(stderr, "config notify\n");
  704. config_notify = 0;
  705. vid.width = config_notify_width & ~7;
  706. vid.height = config_notify_height;
  707. if (doShm)
  708. ResetSharedFrameBuffers();
  709. else
  710. ResetFrameBuffer();
  711. vid.rowbytes = x_framebuffer[0]->bytes_per_line;
  712. vid.buffer = x_framebuffer[current_framebuffer]->data;
  713. vid.conbuffer = vid.buffer;
  714. vid.conwidth = vid.width;
  715. vid.conheight = vid.height;
  716. vid.conrowbytes = vid.rowbytes;
  717. vid.recalc_refdef = 1; // force a surface cache flush
  718. Con_CheckResize();
  719. Con_Clear_f();
  720. return;
  721. }
  722. if (doShm)
  723. {
  724. while (rects)
  725. {
  726. if (x_visinfo->depth != 8)
  727. st2_fixup( x_framebuffer[current_framebuffer],
  728. rects->x, rects->y, rects->width,
  729. rects->height);
  730. if (!XShmPutImage(x_disp, x_win, x_gc,
  731. x_framebuffer[current_framebuffer], rects->x, rects->y,
  732. rects->x, rects->y, rects->width, rects->height, True))
  733. Sys_Error("VID_Update: XShmPutImage failed\n");
  734. oktodraw = false;
  735. while (!oktodraw) GetEvent();
  736. rects = rects->pnext;
  737. }
  738. current_framebuffer = !current_framebuffer;
  739. vid.buffer = x_framebuffer[current_framebuffer]->data;
  740. vid.conbuffer = vid.buffer;
  741. XSync(x_disp, False);
  742. }
  743. else
  744. {
  745. while (rects)
  746. {
  747. if (x_visinfo->depth != 8)
  748. st2_fixup( x_framebuffer[current_framebuffer],
  749. rects->x, rects->y, rects->width,
  750. rects->height);
  751. XPutImage(x_disp, x_win, x_gc, x_framebuffer[0], rects->x,
  752. rects->y, rects->x, rects->y, rects->width, rects->height);
  753. rects = rects->pnext;
  754. }
  755. XSync(x_disp, False);
  756. }
  757. }
  758. static int dither;
  759. void VID_DitherOn(void)
  760. {
  761. if (dither == 0)
  762. {
  763. vid.recalc_refdef = 1;
  764. dither = 1;
  765. }
  766. }
  767. void VID_DitherOff(void)
  768. {
  769. if (dither)
  770. {
  771. vid.recalc_refdef = 1;
  772. dither = 0;
  773. }
  774. }
  775. int Sys_OpenWindow(void)
  776. {
  777. return 0;
  778. }
  779. void Sys_EraseWindow(int window)
  780. {
  781. }
  782. void Sys_DrawCircle(int window, int x, int y, int r)
  783. {
  784. }
  785. void Sys_DisplayWindow(int window)
  786. {
  787. }
  788. void Sys_SendKeyEvents(void)
  789. {
  790. // get events from x server
  791. if (x_disp)
  792. {
  793. while (XPending(x_disp)) GetEvent();
  794. while (keyq_head != keyq_tail)
  795. {
  796. Key_Event(keyq[keyq_tail].key, keyq[keyq_tail].down);
  797. keyq_tail = (keyq_tail + 1) & 63;
  798. }
  799. }
  800. }
  801. #if 0
  802. char *Sys_ConsoleInput (void)
  803. {
  804. static char text[256];
  805. int len;
  806. fd_set readfds;
  807. int ready;
  808. struct timeval timeout;
  809. timeout.tv_sec = 0;
  810. timeout.tv_usec = 0;
  811. FD_ZERO(&readfds);
  812. FD_SET(0, &readfds);
  813. ready = select(1, &readfds, 0, 0, &timeout);
  814. if (ready>0)
  815. {
  816. len = read (0, text, sizeof(text));
  817. if (len >= 1)
  818. {
  819. text[len-1] = 0; // rip off the /n and terminate
  820. return text;
  821. }
  822. }
  823. return 0;
  824. }
  825. #endif
  826. void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
  827. {
  828. // direct drawing of the "accessing disk" icon isn't supported under Linux
  829. }
  830. void D_EndDirectRect (int x, int y, int width, int height)
  831. {
  832. // direct drawing of the "accessing disk" icon isn't supported under Linux
  833. }
  834. void IN_Init (void)
  835. {
  836. Cvar_RegisterVariable (&_windowed_mouse);
  837. Cvar_RegisterVariable (&m_filter);
  838. if ( COM_CheckParm ("-nomouse") )
  839. return;
  840. mouse_x = mouse_y = 0.0;
  841. mouse_avail = 1;
  842. }
  843. void IN_Shutdown (void)
  844. {
  845. mouse_avail = 0;
  846. }
  847. void IN_Commands (void)
  848. {
  849. int i;
  850. if (!mouse_avail) return;
  851. for (i=0 ; i<mouse_buttons ; i++) {
  852. if ( (mouse_buttonstate & (1<<i)) && !(mouse_oldbuttonstate & (1<<i)) )
  853. Key_Event (K_MOUSE1 + i, true);
  854. if ( !(mouse_buttonstate & (1<<i)) && (mouse_oldbuttonstate & (1<<i)) )
  855. Key_Event (K_MOUSE1 + i, false);
  856. }
  857. mouse_oldbuttonstate = mouse_buttonstate;
  858. }
  859. void IN_Move (usercmd_t *cmd)
  860. {
  861. if (!mouse_avail)
  862. return;
  863. if (m_filter.value) {
  864. mouse_x = (mouse_x + old_mouse_x) * 0.5;
  865. mouse_y = (mouse_y + old_mouse_y) * 0.5;
  866. }
  867. old_mouse_x = mouse_x;
  868. old_mouse_y = mouse_y;
  869. mouse_x *= sensitivity.value;
  870. mouse_y *= sensitivity.value;
  871. if ( (in_strafe.state & 1) || (lookstrafe.value && (in_mlook.state & 1) ))
  872. cmd->sidemove += m_side.value * mouse_x;
  873. else
  874. cl.viewangles[YAW] -= m_yaw.value * mouse_x;
  875. if (in_mlook.state & 1)
  876. V_StopPitchDrift ();
  877. if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) {
  878. cl.viewangles[PITCH] += m_pitch.value * mouse_y;
  879. if (cl.viewangles[PITCH] > 80)
  880. cl.viewangles[PITCH] = 80;
  881. if (cl.viewangles[PITCH] < -70)
  882. cl.viewangles[PITCH] = -70;
  883. } else {
  884. if ((in_strafe.state & 1) && noclip_anglehack)
  885. cmd->upmove -= m_forward.value * mouse_y;
  886. else
  887. cmd->forwardmove -= m_forward.value * mouse_y;
  888. }
  889. mouse_x = mouse_y = 0.0;
  890. }
  891. void VID_LockBuffer (void)
  892. {
  893. }
  894. void VID_UnlockBuffer (void)
  895. {
  896. }