5. 修复鼠标抓取

修复鼠标隐藏问题。

Quake 代码在当前状态下,当你使用鼠标时,并不会隐藏鼠标。指针会保持可见并在屏幕中间的一个固定点附近抖动 - 非常烦人。我在一个关于 glx 开发的邮件存档中找到了以下简单的修复方法,链接地址为: http://lists.openprojects.net/pipermail/glx-dev/1999-October/000994.html

请查看下面的补丁列表和下载链接,或者您可以自己进行更改。
	cd q1src/QW/client
	edit the file: gl_vidlinuxglx.c
        

在名为 install_grabs(void) 的函数顶部(第 234 行),添加以下代码
	static void install_grabs(void)
	{
		/* vars to make blank cursor */
		Pixmap blank;
		XColor dummy;
		char data[1] = {0};
		Cursor cursor;

		/* make a blank cursor */
		blank = XCreateBitmapFromData (dpy, win, data, 1, 1);
		if(blank == None) fprintf(stderr, "error: out of memory.\n");
		cursor = XCreatePixmapCursor(dpy, blank, blank, &dummy, &dummy, 0, 0);
		XFreePixmap (dpy, blank);
		Con_Printf("Cursor blanked.\n");
        

XGrabPointer 的第 8 个参数应该从 "None" 更改为 "cursor" 以使用空白光标
	XGrabPointer(dpy, win,
			 True,
			 0,
			 GrabModeAsync, GrabModeAsync,
			 win,
			 cursor,
			 CurrentTime);
        
(参见:man XGrabPointer)

如果你在相应的 *vid*.c 文件中进行类似的更改,此修复程序可能适用于其他客户端构建。目前,这会造成内存泄漏,因为它每次都分配另一个 Cursor 对象,并且不调用 XFreeCursor(),但这可能不是问题,因为我认为 1x1 光标不会占用太多内存。 如果您愿意,可以针对以下文件应用以下补丁:q1src/QW/client/gl_vidlinuxglx.c(patch gl_vidlinuxglx.c patchfile)。只需将 begin/end patchfile 行之间的内容剪切并粘贴到一个名为 gl_vidlinuxglx.c.patch 的文件中(或者任何您想命名的文件)。将补丁文件保存在q1src/QW/client目录,gl_vidlinuxglx.c 所在的目录。然后运行命令
	patch gl_vidlinuxglx.c gl_vidlinuxglx.c.patch
        

此补丁文件将使 gl_vidlinuxglx.c 不再有任何内存泄漏。您可以从以下链接下载此补丁文件: http://www.comptechnews.com/~reaster/mini-HOWTO/LinuxGL-QuakeWorld-mini-HOWTO/gl_vidlinuxglx.c.patch
*************************** begin patchfile ************************************
*** q1src-p/QW/client/gl_vidlinuxglx.c	Tue Dec 21 18:45:54 1999
--- gl_vidlinuxglx.c	Sat Aug 19 20:47:42 2000
***************
*** 1,22 ****
! /*
! 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.
!
! */
  #include <termios.h>
  #include <sys/ioctl.h>
  #include <sys/stat.h>
--- 1,22 ----
! /*
! 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.
!
! */
  #include <termios.h>
  #include <sys/ioctl.h>
  #include <sys/stat.h>
***************
*** 66,71 ****
--- 66,74 ----

  static int scr_width, scr_height;

+ /* blank cursor - gets initialized in VID_Init, freed in VID_Shutdown */
+ Cursor cursor;
+
  /*-----------------------------------------------------------------------*/

  //int		texture_mode = GL_NEAREST;
***************
*** 236,243 ****
  				 0,
  				 GrabModeAsync, GrabModeAsync,
  				 win,
! 				 None,
  				 CurrentTime);

  #ifdef USE_DGA
  	XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse);
--- 239,247 ----
  				 0,
  				 GrabModeAsync, GrabModeAsync,
  				 win,
! 				 cursor,
  				 CurrentTime);
+ 	Con_Printf("Cursor blanked.\n");

  #ifdef USE_DGA
  	XF86DGADirectVideo(dpy, DefaultScreen(dpy), XF86DGADirectMouse);
***************
*** 350,355 ****
--- 354,360 ----
  	if (!ctx)
  		return;

+ 	XFreeCursor(dpy, cursor);
  	glXDestroyContext(dpy, ctx);
  }

***************
*** 602,608 ****
  	unsigned long mask;
  	Window root;
  	XVisualInfo *visinfo;
!
  	S_Init();

  	Cvar_RegisterVariable (&vid_mode);
--- 607,617 ----
  	unsigned long mask;
  	Window root;
  	XVisualInfo *visinfo;
! 	/* vars to make blank cursor */
! 	Pixmap blank;
! 	XColor dummy;
! 	char data[1] = {0};
!
  	S_Init();

  	Cvar_RegisterVariable (&vid_mode);
***************
*** 701,706 ****
--- 710,720 ----
  	Con_SafePrintf ("Video mode %dx%d initialized.\n", width, height);

  	vid.recalc_refdef = 1;				// force a surface cache flush
+
+ 	blank = XCreateBitmapFromData(dpy, win, data, 1, 1);
+ 	if(blank == None) fprintf(stderr, "error: out of memory.\n");
+ 	cursor = XCreatePixmapCursor(dpy, blank, blank, &dummy, &dummy, 0, 0);
+ 	XFreePixmap(dpy, blank);
  }

  void Sys_SendKeyEvents(void)

*************************** end patchfile   ************************************
        

在 Quake 控制台中绑定一些按键来切换鼠标抓取会很方便
	bind q "_windowed_mouse 0"
	bind w "_windowed_mouse 1"