[AD] Yet another hardware mouse

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


I've spend the past two days hacking about in Windows, which was a rather 
painful process filled with lockups and reboots. I''ll spare you teh 
details. Anyway, it was worthwhile: the attached patch adds a hardware 
cursor to the windowed mode DirectX driver. I leave the extension to 
fullscreen mode as an excersise for now ;) (meaning, this code doesn't 
work out of the box).

Tested on Windows 98 in the grabber, test and exmouse programs. It probably 
doesn't have as many side-effects as the X11 cursor does, so I hope that 
is sufficent testing. On the other hand, Windows seems to be a lot more 
demanding about what it gets as input (cursors have to be 32x32 pixels, 
for instance - which I didn't find out until I'd already smashed my 
keyboard several times over).

I'm going to commit the X hardware mouse patch I posted earlier (sans 
documentation), and work on the implicit/explicit pointer warping after 
that, followed by some documentation. I'll also add a function to the API 
that allows Allegro to use the default system cursor, which can make sense 
for window-mode programs. This should be a simple addition now.

Evert
diff -ur src/win/wddraw.c /windows/d/Program/allegro-hw-mouse/src/win/wddraw.c
--- src/win/wddraw.c	2004-03-22 14:25:22.000000000 +0100
+++ /windows/d/Program/allegro-hw-mouse/src/win/wddraw.c	2004-09-22 23:34:36.000000000 +0200
@@ -360,3 +360,135 @@
    _exit_critical();
 }
 
+
+
+static HCURSOR hcursor = NULL;
+static HBITMAP and_mask = NULL;
+static HBITMAP xor_mask = NULL;
+
+/* gfx_directx_set_mouse_sprite:
+ *  Create a Windows system cursor from the specified bitmap
+ */
+int gfx_directx_set_mouse_sprite(struct BITMAP *sprite, int xfocus, int yfocus)
+{
+	HBITMAP hbmpcursor;
+   int mask_color;
+   int x, y, col, n;
+	int sys_sm_cx, sys_sm_cy;
+   HDC h_dc;
+   HDC h_main_dc;
+   HDC h_and_dc;
+   HDC h_xor_dc;
+   ICONINFO iconinfo;
+   HBITMAP hOldAndMaskBitmap;
+   HBITMAP hOldXorMaskBitmap;
+
+   if (hcursor) {
+      DestroyIcon(hcursor);
+      hcursor = NULL;
+   }
+
+   if (and_mask) {
+      DeleteObject(and_mask);
+      and_mask = NULL;
+   }
+
+   if (xor_mask) {
+      DeleteObject(xor_mask);
+      xor_mask = NULL;
+   }
+
+	/* Get allowed cursor size - Windows can't make cursors of arbitrary size */
+	sys_sm_cx = GetSystemMetrics(SM_CXCURSOR);
+	sys_sm_cy = GetSystemMetrics(SM_CYCURSOR);
+
+	/* Test if we can make a cursor compatible with the one requested */
+   if (sprite && (sprite->w <= sys_sm_cx) && (sprite->h <= sys_sm_cy)) {
+		/* Create bitmap */
+      h_dc = GetDC(allegro_wnd);
+      h_xor_dc = CreateCompatibleDC(h_dc);
+      h_and_dc = CreateCompatibleDC(h_dc);
+
+      /* Prepare AND (monochrome) and XOR (colour) mask */
+      and_mask = CreateBitmap(sys_sm_cx, sys_sm_cy, 1, 1, NULL);
+      xor_mask = CreateCompatibleBitmap(h_dc, sys_sm_cx, sys_sm_cy);
+      hOldAndMaskBitmap = SelectObject(h_and_dc, and_mask);
+		hOldXorMaskBitmap = SelectObject(h_xor_dc, xor_mask);
+
+		/* Create transparent cursor */
+      for(y=0; y<sys_sm_cy; y++) {
+         for(x=0; x<sys_sm_cx; x++) {
+				SetPixel(h_and_dc, x, y, WINDOWS_RGB(255, 255, 255));
+				SetPixel(h_xor_dc, x, y, WINDOWS_RGB(0, 0, 0));
+			}
+		}
+		draw_to_hdc(h_xor_dc, sprite, 0, 0);
+		mask_color = bitmap_mask_color(sprite);
+
+		/* Make cursor background transparent */
+		for(y=0; y<sprite->h; y++) {
+         for(x=0; x<sprite->w; x++) {
+				if (getpixel(sprite, x, y) != mask_color) {
+					/* Don't touch XOR value */
+					SetPixel(h_and_dc, x, y, 0);
+				} else {
+					/* No need to touch AND value */
+					SetPixel(h_xor_dc, x, y, WINDOWS_RGB(0, 0, 0));
+				}
+			}
+		}
+
+      SelectObject(h_and_dc, hOldAndMaskBitmap);
+      SelectObject(h_xor_dc, hOldXorMaskBitmap);
+      DeleteDC(h_and_dc);
+      DeleteDC(h_xor_dc);
+      ReleaseDC(allegro_wnd, h_dc);
+
+      iconinfo.fIcon = FALSE;
+      iconinfo.xHotspot = xfocus;
+      iconinfo.yHotspot = yfocus;
+      iconinfo.hbmMask = and_mask;
+      iconinfo.hbmColor = xor_mask;
+
+      hcursor = CreateIconIndirect(&iconinfo);
+      return 0;
+   }
+
+   return -1;
+}
+
+
+
+/* gfx_directx_show_mouse:
+ *  Switch the Windows cursor to a hardware cursor
+ */
+int gfx_directx_show_mouse(struct BITMAP *bmp, int x, int y)
+{
+   if (hcursor) {
+      _win_hcursor = hcursor;
+      SetCursor(hcursor);
+      return 0;
+   }
+
+   return -1;
+}
+
+
+/* gfx_directx_hide_mouse:
+ *  Hide the hardware cursor
+ */
+void gfx_directx_hide_mouse(void)
+{
+   _win_hcursor = NULL;
+   SetCursor(NULL);
+}
+
+
+
+/* gfx_directx_move_mouse:
+ *  Move the hardware cursor (not needed)
+ */
+void gfx_directx_move_mouse(int x, int y)
+{
+}
+
diff -ur src/win/wddraw.h /windows/d/Program/allegro-hw-mouse/src/win/wddraw.h
--- src/win/wddraw.h	2003-06-11 20:13:21.000000000 +0200
+++ /windows/d/Program/allegro-hw-mouse/src/win/wddraw.h	2004-09-22 23:24:56.000000000 +0200
@@ -85,6 +85,10 @@
 AL_FUNC(BITMAP *, gfx_directx_create_system_bitmap, (int width, int height));
 AL_FUNC(void, gfx_directx_destroy_system_bitmap, (BITMAP *bmp));
 AL_FUNC(GFX_MODE_LIST *, gfx_directx_fetch_mode_list, (void));
+AL_FUNC(int, gfx_directx_set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus));
+AL_FUNC(int, gfx_directx_show_mouse, (struct BITMAP *bmp, int x, int y));
+AL_FUNC(void, gfx_directx_hide_mouse, (void));
+AL_FUNC(void, gfx_directx_move_mouse, (int x, int y));
 
 
 /* driver initialisation and shutdown (from wddraw.c) */
diff -ur src/win/wddwin.c /windows/d/Program/allegro-hw-mouse/src/win/wddwin.c
--- src/win/wddwin.c	2004-03-22 14:25:23.000000000 +0100
+++ /windows/d/Program/allegro-hw-mouse/src/win/wddwin.c	2004-09-22 23:25:34.000000000 +0200
@@ -54,10 +68,10 @@
    NULL,
    gfx_directx_create_system_bitmap,
    gfx_directx_destroy_system_bitmap,
-   NULL,                        // AL_METHOD(int, set_mouse_sprite, (struct BITMAP *sprite, int xfocus, int yfocus));
-   NULL,                        // AL_METHOD(int, show_mouse, (struct BITMAP *bmp, int x, int y));
-   NULL,                        // AL_METHOD(void, hide_mouse, (void));
-   NULL,                        // AL_METHOD(void, move_mouse, (int x, int y));
+   gfx_directx_set_mouse_sprite,
+   gfx_directx_show_mouse,
+   gfx_directx_hide_mouse,
+   gfx_directx_move_mouse,
    NULL,                        // AL_METHOD(void, drawing_mode, (void));
    NULL,                        // AL_METHOD(void, save_video_state, (void*));
    NULL,                        // AL_METHOD(void, restore_video_state, (void*));
diff -ur src/win/wmouse.c /windows/d/Program/allegro-hw-mouse/src/win/wmouse.c
--- src/win/wmouse.c	2004-09-17 00:28:16.000000000 +0200
+++ /windows/d/Program/allegro-hw-mouse/src/win/wmouse.c	2004-09-21 22:06:14.000000000 +0200
@@ -66,6 +66,9 @@
 };
 
 
+HCURSOR _win_hcursor = NULL;	/* Hardware cursor to display */
+
+
 #define DINPUT_BUFFERSIZE 256
 static HANDLE mouse_input_event = NULL;
 static LPDIRECTINPUT mouse_dinput = NULL;
@@ -456,7 +459,7 @@
 int mouse_set_syscursor(void)
 {
    if ((mouse_dinput_device && _mouse_on) || (gfx_driver && !gfx_driver->windowed)) {
-      SetCursor(NULL);
+      SetCursor(_win_hcursor);
       /* Make sure the cursor is removed by the system. */
       PostMessage(allegro_wnd, WM_MOUSEMOVE, 0, 0);
    }
diff -ur include/allegro/platform/aintwin.h /windows/d/Program/allegro-hw-mouse/include/allegro/platform/aintwin.h
--- include/allegro/platform/aintwin.h	2003-01-10 13:31:00.000000000 +0100
+++ /windows/d/Program/allegro-hw-mouse/include/allegro/platform/aintwin.h	2004-09-21 22:07:36.000000000 +0200
@@ -127,6 +127,7 @@
 
 
 /* mouse routines */
+AL_VAR(HCURSOR, _win_hcursor);
 AL_FUNC(int, mouse_dinput_acquire, (void));
 AL_FUNC(int, mouse_dinput_unacquire, (void));
 AL_FUNC(int, mouse_dinput_grab, (void));


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/