/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ // vid_x.c -- general x video driver, with hacks for Xv #define _BSD #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "quakedef.h" #include "d_local.h" cvar_t _windowed_mouse = {"_windowed_mouse","0", true}; cvar_t m_filter = {"m_filter","0", true}; float old_windowed_mouse; /* only needed for QW */ int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar; byte *VGA_pagebase; qboolean mouse_avail; int mouse_buttons=3; int mouse_oldbuttonstate; int mouse_buttonstate; float mouse_x, mouse_y; float old_mouse_x, old_mouse_y; int p_mouse_x; int p_mouse_y; int ignorenext; int bits_per_pixel; typedef struct { int input; int output; } keymap_t; viddef_t vid; // global video state unsigned short d_8to16table[256]; static Display *x_disp; static Colormap x_cmap; static Window x_win; static GC x_gc; static Visual *x_vis; static XVisualInfo *x_visinfo; //static XImage *x_image; static int verbose=0; statt_height_save; int fullscreen; XvImage *xvi; unsigned char *overlaybuf; unsigned char *y_start,*u_start,*v_start; /* yv12 planes */ void (*conv_fn)(); void rgb_yuy2() { static unsigned short x,y; static unsigned char left,right; static unsigned char * dest_start; static unsigned char * src_start; src_start=(unsigned char *)vid.buffer; dest_start=overlaybuf; for (y = 0;y=2) S_Init(); ignorenext=0; vid.width = BASEWIDTH; vid.height = BASEHEIGHT; vid.maxwarpwidth = WARP_WIDTH; vid.maxwarpheight = WARP_HEIGHT; vid.numpages = 1; vid.colormap = host_colormap; // vid.cbits = VID_CBITS; // vid.grades = VID_GRADES; vid.fullbright = 256 - LittleLong (*((int *)vid.colormap + 2048)); VID_SetPalette(palette); verbose=COM_CheckParm("-verbose"); // open the display x_disp = XOpenDisplay(0); if (!x_disp) { if (getenv("DISPLAY")) Sys_Error("VID: Could not open display [%s]\n", getenv("DISPLAY")); else Sys_Error("VID: Could not open local display\n"); } // catch signals so i can turn on auto-repeat { struct sigaction sa; sigaction(SIGINT, 0, &sa); sa.sa_handler = TragicDeath; sigaction(SI*)vid.buffer; for (y=0;y= com_argc-2) Sys_Error("VID: -winsize \n"); vid.width = Q_atoi(com_argv[pnum+1]); vid.height = Q_atoi(com_argv[pnum+2]); if (!vid.width || !vid.height) Sys_Error("VID: Bad window width/height\n"); } if ((pnum=COM_CheckParm("-width"))) { if (pnum >= com_argc-1) Sys_Error("VID: -width \n"); vid.width = Q_atoi(com_argv[pnum+1]); if (!vid.width) Sys_Error("VID: Bad window width\n"); } if ((pnum=COM_CheckParm("-height"))) { if (pnum >= com_argc-1) Sys_Error("VID: -height \n"); vid.height = Q_atoi(com_argv[pnum+1]); if (!vid.height) Sys_Error("VID: Bad window height\n"); } /* initial output size to match input size - no scaling */ dest_width=vid.width;dest_height=vid.height; template_mask = 0; // specify a visual id if ((pnum=COM_CheckParm("-visualid"))) { if (pnum >= com_argc-1) Sys_Error("VID: -visualid \n"); template.visualid = Q_atoi(com_argv[pnum+1]); template_mask = VisualIDMask; } // If not specified, use default visual else { screen = XDefaultScreen(x_disp); template.visualid = XVisualIDFromVisual(XDefaultVisual(x_disp, screen)); template_mask = VisualIDMask; } // pick a visual- warn if more than one was available x_visinfo = XGetVisualInfo(x_disp, template_mask, &template, &count); if (count > 1) { printf("Found more than one visual id at depth %d:\n", template.depth); for (i=0 ; ivisualid)); printf(" screen %d\n", x_visinfo->screen); printf(" red_mask 0x%x\n", (int)(x_visinfo->red_mask)); printf(" green_mask 0x%x\n", (int)(x_visinfo->green_mask)); printf(" blue_mask 0x%x\n", (int)(x_visinfo->blue_mask)); printf(" colormap_size %d\n", x_visinfo->colormap_size); printf(" bits_per_rgb %d\n", x_visinfo->bits_per_rgb); } x_vis = x_visinfo->visual; root = DefaultRootWindow(x_disp); { int attribmask = CWEventMask | CWBorderPixel; XSetWindowAttributes attribs; attribs.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask | ExposureMask | PointerMotionMask | ButtonPressMask | ButtonReleaseMask; attribs.border_pixel = 0; // create the main window x_win = XCreateWindow( x_disp, root, 0, 0, // x, y dest_width,dest_height, 0, // borderwidth x_visinfo->depth, InputOutput, x_vis, attribmask, &attribs ); XStoreName( x_disp,x_win,"xvquake"); } // inviso cursor XDefineCursor(x_disp, x_win, CreateNullCursor(x_disp, x_win)); // create the GC { XGCValues xgcvalues; int valuemask = GCGraphicsExposures; xgcvalues.graphics_exposures = False; x_gc = XCreateGC(x_disp, x_win, valuemask, &xgcvalues ); } // map the window XMapWindow(x_disp, x_win); // wait for first exposure event { XEvent event; do { XNextEvent(x_disp, &event); } while (event.type != Expose || event.xexpose.count); } /* find an xv adaptor */ XvQueryAdaptors(x_disp,root,&count,&adaptors); for (i=0;idata = malloc(xvi->data_size); overlaybuf = (unsigned char *)xvi->data; Cmd_AddCommand ("vid_fullscreen", Xv_Fullscreen); } /* set up plane positions if yv12 */ if (chosen_f == YV12) { y_start = (unsigned char*)overlaybuf; v_start = y_start + vid.width*vid.height; key = '8';break;/* [*] */ case 0x028: key = '9';;break;/* [(] */ case 0x029: key = '0';break;/* [)] */ case 0x05f: key = '-';break;/* [_] */ case 0x02b: key = '=';break;/* [+] */ case 0x07c: key = '\'';break;/* [|] */ case 0x07d: key = '[';break;/* [}] */ case 0x07b: key = ']';break;/* [{] */ case 0x022: key = '\'';break;/* ["] */ case 0x03a: key = ';';break;/* [:] */ case 0x03f: key = '/';break;/* [?] */ case 0x03e: key = '.';break;/* [>] */ case 0x03c: key = ',';break;/* [<] */ #endif default: key = *(unsigned char*)buf; if (key >= 'A' && key <= 'Z') key = key - 'A' + 'a'; // fprintf(stdout, "case 0x0%x: key = ___;break;/* [%c] */\n", keysym); break; } return key; } struct { int key; int down; } keyq[64]; int keyq_head=0; int keyq_tail=0; int config_notify=0; int config_notify_width; int config_notify_height; void GetEvent(void) { XEvent x_event; int b; XNextEvent(x_disp, &x_event); switch(x_event.type) { case KeyPress: keyq[keyq_head].key = XLateKey(&x_event.xkey); keyq[keyq_head].down = true; keyq_head = (keyq_head + 1) & 63; break; case KeyRelease: keyq[keyq_head].key = XLateKey(&x_event.xkey); keyq[keyq_head].down = false; keyq_head = (keyq_head + 1) & 63; break; case MotionNotify: if (_windowed_mouse.value) { mouse_x = (float) ((int)x_event.xmotion.x - (int)(vid.width/2)); mouse_y = (float) ((int)x_event.xmotion.y - (int)(vid.height/2)); //printf("m: x=%d,y=%d, mx=%3.2f,my=%3.2f\n", // x_event.xmotion.x, x_event.xmotion.y, mouse_x, mouse_y); /* move the mouse to the window center again */ XSelectInput(x_disp,x_win,StructureNotifyMask|KeyPressMask |KeyReleaseMask|ExposureMask |ButtonPressMask |ButtonReleaseMask); XWarpPointer(x_disp,None,x_win,0,0,0,0, (vid.width/2),(vid.height/2)); XSelectInput(x_disp,x_win,StructureNotifyMask|KeyPressMask |KeyReleaseMask|ExposureMask |PointerMotionMask|ButtonPressMask |ButtonReleaseMask); } else { mouse_x = (float) (x_event.xmotion.x-p_mouse_x); mouse_y = (float) (x_event.xmotion.y-p_mouse_y); p_mouse_x=x_event.xmotion.x; p_mouse_y=x_event.xmotion.y; } break; case ButtonPress: b=-1; if (x_event.xbutton.button == 1) b = 0; else if (x_event.xbutton.button == 2) b = 2; else if (x_event.xbutton.button == 3) b = 1; if (b>=0) mouse_buttonstate |= 1<=0) mouse_buttonstate &= ~(1<0) { len = read (0, text, sizeof(text)); if (len >= 1) { text[len-1] = 0; // rip off the /n and terminate return text; } } return 0; } #endif void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height) { // direct drawing of the "accessing disk" icon isn't supported under Linux } void D_EndDirectRect (int x, int y, int width, int height) { // direct drawing of the "accessing disk" icon isn't supported under Linux } void IN_Init (void) { Cvar_RegisterVariable (&_windowed_mouse); Cvar_RegisterVariable (&m_filter); if ( COM_CheckParm ("-nomouse") ) return; mouse_x = mouse_y = 0.0; mouse_avail = 1; } void IN_Shutdown (void) { mouse_avail = 0; } void IN_Commands (void) { int i; if (!mouse_avail) return; for (i=0 ; isidemove += m_side.value * mouse_x; else cl.viewangles[YAW] -= m_yaw.value * mouse_x; if (in_mlook.state & 1) V_StopPitchDrift (); if ( (in_mlook.state & 1) && !(in_strafe.state & 1)) { cl.viewangles[PITCH] += m_pitch.value * mouse_y; if (cl.viewangles[PITCH] > 80) cl.viewangles[PITCH] = 80; if (cl.viewangles[PITCH] < -70) cl.viewangles[PITCH] = -70; } else { if ((in_strafe.state & 1) && noclip_anglehack) cmd->upmove -= m_forward.value * mouse_y; else cmd->forwardmove -= m_forward.value * mouse_y; } mouse_x = mouse_y = 0.0; } /* only needed for QW */ #ifndef VID_LockBuffer void VID_LockBuffer () { } #endif #ifndef VID_LockBuffer void VID_UnlockBuffer () { } #endif