Kamujin's picture

Input Exceptions under 64bit Windows

I have noticed a number of exceptions when I build my projects with Platform Target = Any CPU and run them under Vista x64. If I change the Platform Target to x86, the exceptions are not triggered. It seems the problem may be related to the sign bit getting moved around improperly during type conversions.

The following exception occurs when I release the shift key (right or left) on my macBookPro.

System.OverflowException occurred
Message="Arithmetic operation resulted in an overflow."
Source="mscorlib"
StackTrace:
at System.IntPtr.op_Explicit(IntPtr value)
at OpenTK.Platform.Windows.WMInput.WndProc(Message& msg) in C:\...\OpenTK\Source\OpenTK\Platform\Windows\WMInput.cs:line 147

The following exception occurs when I spin the mouse wheel backward. Small moves backward do not trigger the exception.

System.OverflowException occurred
Message="Arithmetic operation resulted in an overflow."
Source="mscorlib"
StackTrace:
at System.IntPtr.ToInt32()
at OpenTK.Platform.Windows.WMInput.WndProc(Message& msg) in C:\...\OpenTK\Source\OpenTK\Platform\Windows\WMInput.cs:line 83


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Kamujin's picture

I think the problem is the way your converting the IntPtr.

Remember, on 64bit arch, an IntPtr is a 64 bit pointer to a 32bit number.

I think you should use do this instead.

mouse.Wheel +=  (((int)msg.WParam) >> 16) / 120;

This should drop the left most 32 bits which are causing the overflow.

***edit*** Sorry, I didn't see your reply when I posted. Clearly, you are suggesting the same thing.

the Fiddler's picture

Np. I was thrown a little off-balance because I thought that ToInt32() did not throw overflow exceptions, when it actually does. What's more, placing the ToInt32() call inside an unchecked region does not seem to work - hopefully this code will fare better :)

Kamujin's picture

OK, this is ugly, but it works.

Can we reduce this?

case WindowMessage.MOUSEWHEEL:
                    {
                        int value;
                        if (IntPtr.Size == 8)
                        {
                            value = (int)(((long)msg.WParam << 32) >> 32); // This is due to inconsistent behavior of the WParam value. IE wparam=0xffffffffff880000 or wparam=0x00000000ff100000
                        }
                        else
                        {
                            value = (int)msg.WParam;
                        }
                        value = (value >> 16) / 120;
                        mouse.Wheel += value;
                    }
                    return;

or more densely

                case WindowMessage.MOUSEWHEEL:
                    {
                        // This is due to inconsistent behavior of the WParam value on 64bit arch. IE wparam=0xffffffffff880000 or wparam=0x00000000ff100000
                        int value = (IntPtr.Size == 8) ? (int)((long)msg.WParam << 32 >> 32) : (int)msg.WParam;
                        mouse.Wheel += (value >> 16) / 120;
                    }
                    return;
Kamujin's picture

Oh duh, how about?

                        // This is due to inconsistent behavior of the WParam value on 64bit arch. IE wparam=0xffffffffff880000 or wparam=0x00000000ff100000
                        mouse.Wheel += (int)((long)msg.WParam << 32 >> 48) / 120;

This should work on any platform right?

the Fiddler's picture

Yes, this looks like the simplest solution. I'm committing this now, thanks.

Edit: bug added to the issue tracker.