[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));