From: Stefanos A. Date: Tue, 7 Jan 2014 23:02:27 +0000 (+0100) Subject: [Win] Refactor huge wndproc into functions X-Git-Tag: 2.0-0~268^2~4 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e260a429549f9cc23fa62cefd661c9e2a5b8a718;p=platform%2Fcore%2Fcsapi%2Fopentk.git [Win] Refactor huge wndproc into functions --- diff --git a/Source/OpenTK/Platform/Windows/WinGLNative.cs b/Source/OpenTK/Platform/Windows/WinGLNative.cs index 48f7c4b..220f82c 100644 --- a/Source/OpenTK/Platform/Windows/WinGLNative.cs +++ b/Source/OpenTK/Platform/Windows/WinGLNative.cs @@ -240,6 +240,316 @@ namespace OpenTK.Platform.Windows #endregion + #region Message Handlers + + void HandleActivate(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + // See http://msdn.microsoft.com/en-us/library/ms646274(VS.85).aspx (WM_ACTIVATE notification): + // wParam: The low-order word specifies whether the window is being activated or deactivated. + bool new_focused_state = Focused; + if (IntPtr.Size == 4) + focused = (wParam.ToInt32() & 0xFFFF) != 0; + else + focused = (wParam.ToInt64() & 0xFFFF) != 0; + + if (new_focused_state != Focused) + FocusedChanged(this, EventArgs.Empty); + } + + void HandleEnterModalLoop(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + // Entering the modal size/move loop: we don't want rendering to + // stop during this time, so we register a timer callback to continue + // processing from time to time. + is_in_modal_loop = true; + StartTimer(handle); + + if (!CursorVisible) + UngrabCursor(); + } + + void HandleExitModalLoop(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + // Exiting from Modal size/move loop: the timer callback is no longer + // necessary. + is_in_modal_loop = false; + StopTimer(handle); + + // Ensure cursor remains grabbed + if (!CursorVisible) + GrabCursor(); + } + + void HandleWindowPositionChanged(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + unsafe + { + WindowPosition* pos = (WindowPosition*)lParam; + if (window != null && pos->hwnd == window.Handle) + { + Point new_location = new Point(pos->x, pos->y); + if (Location != new_location) + { + bounds.Location = new_location; + Move(this, EventArgs.Empty); + } + + Size new_size = new Size(pos->cx, pos->cy); + if (Size != new_size) + { + bounds.Width = pos->cx; + bounds.Height = pos->cy; + + Win32Rectangle rect; + Functions.GetClientRect(handle, out rect); + client_rectangle = rect.ToRectangle(); + + Functions.SetWindowPos(child_window.Handle, IntPtr.Zero, 0, 0, ClientRectangle.Width, ClientRectangle.Height, + SetWindowPosFlags.NOZORDER | SetWindowPosFlags.NOOWNERZORDER | + SetWindowPosFlags.NOACTIVATE | SetWindowPosFlags.NOSENDCHANGING); + + if (suppress_resize <= 0) + Resize(this, EventArgs.Empty); + } + + if (!is_in_modal_loop) + { + // If we are in a modal resize/move loop, cursor grabbing is + // handled inside [ENTER|EXIT]SIZEMOVE case above. + // If not, then we have to handle cursor grabbing here. + if (!CursorVisible) + GrabCursor(); + } + } + } + } + + void HandleStyleChanged(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + unsafe + { + Debug.WriteLine(wParam.ToString()); + if (wParam == new IntPtr((int)GWL.STYLE)) + { + WindowStyle style = ((StyleStruct*)lParam)->New; + Debug.WriteLine(style.ToString()); + if ((style & WindowStyle.Popup) != 0) + windowBorder = WindowBorder.Hidden; + else if ((style & WindowStyle.ThickFrame) != 0) + windowBorder = WindowBorder.Resizable; + else if ((style & ~(WindowStyle.ThickFrame | WindowStyle.MaximizeBox)) != 0) + windowBorder = WindowBorder.Fixed; + } + } + + // Ensure cursor remains grabbed + if (!CursorVisible) + GrabCursor(); + } + + void HandleSize(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + SizeMessage state = (SizeMessage)wParam.ToInt64(); + WindowState new_state = windowState; + switch (state) + { + case SizeMessage.RESTORED: new_state = borderless_maximized_window_state ? + WindowState.Maximized : WindowState.Normal; break; + case SizeMessage.MINIMIZED: new_state = WindowState.Minimized; break; + case SizeMessage.MAXIMIZED: new_state = WindowBorder == WindowBorder.Hidden ? + WindowState.Fullscreen : WindowState.Maximized; + break; + } + + if (new_state != windowState) + { + windowState = new_state; + WindowStateChanged(this, EventArgs.Empty); + + // Ensure cursor remains grabbed + if (!CursorVisible) + GrabCursor(); + } + } + + void HandleChar(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + + if (IntPtr.Size == 4) + key_press.KeyChar = (char)wParam.ToInt32(); + else + key_press.KeyChar = (char)wParam.ToInt64(); + + KeyPress(this, key_press); + } + + void HandleMouseMove(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + Point point = new Point( + (short)((uint)lParam.ToInt32() & 0x0000FFFF), + (short)(((uint)lParam.ToInt32() & 0xFFFF0000) >> 16)); + mouse.Position = point; + + if (mouse_outside_window) + { + // Once we receive a mouse move event, it means that the mouse has + // re-entered the window. + mouse_outside_window = false; + EnableMouseTracking(); + + MouseEnter(this, EventArgs.Empty); + } + } + + void HandleMouseLeave(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + mouse_outside_window = true; + // Mouse tracking is disabled automatically by the OS + + MouseLeave(this, EventArgs.Empty); + } + + void HandleMouseWheel(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + // This is due to inconsistent behavior of the WParam value on 64bit arch, whese + // wparam = 0xffffffffff880000 or wparam = 0x00000000ff100000 + mouse.WheelPrecise += ((long)wParam << 32 >> 48) / 120.0f; + } + + void HandleLButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + Functions.SetCapture(window.Handle); + mouse[MouseButton.Left] = true; + } + + void HandleMButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + Functions.SetCapture(window.Handle); + mouse[MouseButton.Middle] = true; + } + + void HandleRButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + Functions.SetCapture(window.Handle); + mouse[MouseButton.Right] = true; + } + + void HandleXButtonDown(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + Functions.SetCapture(window.Handle); + mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) != + (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = true; + } + + void HandleLButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + Functions.ReleaseCapture(); + mouse[MouseButton.Left] = false; + } + + void HandleMButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + Functions.ReleaseCapture(); + mouse[MouseButton.Middle] = false; + } + + void HandleRButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + Functions.ReleaseCapture(); + mouse[MouseButton.Right] = false; + } + + void HandleXButtonUp(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + Functions.ReleaseCapture(); + mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) != + (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = false; + } + + void HandleKeyboard(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + bool pressed = + message == WindowMessage.KEYDOWN || + message == WindowMessage.SYSKEYDOWN; + + // Shift/Control/Alt behave strangely when e.g. ShiftRight is held down and ShiftLeft is pressed + // and released. It looks like neither key is released in this case, or that the wrong key is + // released in the case of Control and Alt. + // To combat this, we are going to release both keys when either is released. Hacky, but should work. + // Win95 does not distinguish left/right key constants (GetAsyncKeyState returns 0). + // In this case, both keys will be reported as pressed. + + bool extended = (lParam.ToInt64() & ExtendedBit) != 0; + short scancode = (short)((lParam.ToInt64() >> 16) & 0xFF); + VirtualKeys vkey = (VirtualKeys)wParam; + bool is_valid; + Key key = KeyMap.TranslateKey(scancode, vkey, extended, false, out is_valid); + + if (is_valid) + { + keyboard.SetKey(key, (byte)scancode, pressed); + + if (pressed) + { + key_down.Key = key; + KeyDown(this, key_down); + } + else + { + key_up.Key = key; + KeyUp(this, key_up); + } + } + } + + void HandleKillFocus(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + keyboard.ClearKeys(); + } + + void HandleCreate(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + CreateStruct cs = (CreateStruct)Marshal.PtrToStructure(lParam, typeof(CreateStruct)); + if (cs.hwndParent == IntPtr.Zero) + { + bounds.X = cs.x; + bounds.Y = cs.y; + bounds.Width = cs.cx; + bounds.Height = cs.cy; + + Win32Rectangle rect; + Functions.GetClientRect(handle, out rect); + client_rectangle = rect.ToRectangle(); + + invisible_since_creation = true; + } + } + + void HandleClose(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + System.ComponentModel.CancelEventArgs e = new System.ComponentModel.CancelEventArgs(); + + Closing(this, e); + + if (!e.Cancel) + { + DestroyWindow(); + } + } + + void HandleDestroy(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) + { + exists = false; + + Functions.UnregisterClass(ClassName, Instance); + window.Dispose(); + child_window.Dispose(); + + Closed(this, EventArgs.Empty); + } + + #endregion + #region WindowProcedure IntPtr WindowProcedure(IntPtr handle, WindowMessage message, IntPtr wParam, IntPtr lParam) @@ -249,132 +559,32 @@ namespace OpenTK.Platform.Windows #region Size / Move / Style events case WindowMessage.ACTIVATE: - // See http://msdn.microsoft.com/en-us/library/ms646274(VS.85).aspx (WM_ACTIVATE notification): - // wParam: The low-order word specifies whether the window is being activated or deactivated. - bool new_focused_state = Focused; - if (IntPtr.Size == 4) - focused = (wParam.ToInt32() & 0xFFFF) != 0; - else - focused = (wParam.ToInt64() & 0xFFFF) != 0; - - if (new_focused_state != Focused) - FocusedChanged(this, EventArgs.Empty); + HandleActivate(handle, message, wParam, lParam); break; case WindowMessage.ENTERMENULOOP: case WindowMessage.ENTERSIZEMOVE: - // Entering the modal size/move loop: we don't want rendering to - // stop during this time, so we register a timer callback to continue - // processing from time to time. - is_in_modal_loop = true; - StartTimer(handle); - - if (!CursorVisible) - UngrabCursor(); + HandleEnterModalLoop(handle, message, wParam, lParam); break; case WindowMessage.EXITMENULOOP: case WindowMessage.EXITSIZEMOVE: - // Exiting from Modal size/move loop: the timer callback is no longer - // necessary. - is_in_modal_loop = false; - StopTimer(handle); - - // Ensure cursor remains grabbed - if (!CursorVisible) - GrabCursor(); + HandleExitModalLoop(handle, message, wParam, lParam); break; case WindowMessage.ERASEBKGND: return new IntPtr(1); case WindowMessage.WINDOWPOSCHANGED: - unsafe - { - WindowPosition* pos = (WindowPosition*)lParam; - if (window != null && pos->hwnd == window.Handle) - { - Point new_location = new Point(pos->x, pos->y); - if (Location != new_location) - { - bounds.Location = new_location; - Move(this, EventArgs.Empty); - } - - Size new_size = new Size(pos->cx, pos->cy); - if (Size != new_size) - { - bounds.Width = pos->cx; - bounds.Height = pos->cy; - - Win32Rectangle rect; - Functions.GetClientRect(handle, out rect); - client_rectangle = rect.ToRectangle(); - - Functions.SetWindowPos(child_window.Handle, IntPtr.Zero, 0, 0, ClientRectangle.Width, ClientRectangle.Height, - SetWindowPosFlags.NOZORDER | SetWindowPosFlags.NOOWNERZORDER | - SetWindowPosFlags.NOACTIVATE | SetWindowPosFlags.NOSENDCHANGING); - - if (suppress_resize <= 0) - Resize(this, EventArgs.Empty); - } - - if (!is_in_modal_loop) - { - // If we are in a modal resize/move loop, cursor grabbing is - // handled inside [ENTER|EXIT]SIZEMOVE case above. - // If not, then we have to handle cursor grabbing here. - if (!CursorVisible) - GrabCursor(); - } - } - } + HandleWindowPositionChanged(handle, message, wParam, lParam); break; case WindowMessage.STYLECHANGED: - unsafe - { - if (wParam.ToInt64() == (long)GWL.STYLE) - { - WindowStyle style = ((StyleStruct*)lParam)->New; - if ((style & WindowStyle.Popup) != 0) - windowBorder = WindowBorder.Hidden; - else if ((style & WindowStyle.ThickFrame) != 0) - windowBorder = WindowBorder.Resizable; - else if ((style & ~(WindowStyle.ThickFrame | WindowStyle.MaximizeBox)) != 0) - windowBorder = WindowBorder.Fixed; - } - } - - // Ensure cursor remains grabbed - if (!CursorVisible) - GrabCursor(); - + HandleStyleChanged(handle, message, wParam, lParam); break; case WindowMessage.SIZE: - SizeMessage state = (SizeMessage)wParam.ToInt64(); - WindowState new_state = windowState; - switch (state) - { - case SizeMessage.RESTORED: new_state = borderless_maximized_window_state ? - WindowState.Maximized : WindowState.Normal; break; - case SizeMessage.MINIMIZED: new_state = WindowState.Minimized; break; - case SizeMessage.MAXIMIZED: new_state = WindowBorder == WindowBorder.Hidden ? - WindowState.Fullscreen : WindowState.Maximized; - break; - } - - if (new_state != windowState) - { - windowState = new_state; - WindowStateChanged(this, EventArgs.Empty); - - // Ensure cursor remains grabbed - if (!CursorVisible) - GrabCursor(); - } - + HandleSize(handle, message, wParam, lParam); break; #endregion @@ -382,84 +592,51 @@ namespace OpenTK.Platform.Windows #region Input events case WindowMessage.CHAR: - if (IntPtr.Size == 4) - key_press.KeyChar = (char)wParam.ToInt32(); - else - key_press.KeyChar = (char)wParam.ToInt64(); - - KeyPress(this, key_press); + HandleChar(handle, message, wParam, lParam); break; case WindowMessage.MOUSEMOVE: - Point point = new Point( - (short)((uint)lParam.ToInt32() & 0x0000FFFF), - (short)(((uint)lParam.ToInt32() & 0xFFFF0000) >> 16)); - mouse.Position = point; - - if (mouse_outside_window) - { - // Once we receive a mouse move event, it means that the mouse has - // re-entered the window. - mouse_outside_window = false; - EnableMouseTracking(); - - MouseEnter(this, EventArgs.Empty); - } + HandleMouseMove(handle, message, wParam, lParam); break; case WindowMessage.MOUSELEAVE: - mouse_outside_window = true; - // Mouse tracking is disabled automatically by the OS - - MouseLeave(this, EventArgs.Empty); + HandleMouseLeave(handle, message, wParam, lParam); break; case WindowMessage.MOUSEWHEEL: - // This is due to inconsistent behavior of the WParam value on 64bit arch, whese - // wparam = 0xffffffffff880000 or wparam = 0x00000000ff100000 - mouse.WheelPrecise += ((long)wParam << 32 >> 48) / 120.0f; + HandleMouseWheel(handle, message, wParam, lParam); break; case WindowMessage.LBUTTONDOWN: - Functions.SetCapture(window.Handle); - mouse[MouseButton.Left] = true; + HandleLButtonDown(handle, message, wParam, lParam); break; case WindowMessage.MBUTTONDOWN: - Functions.SetCapture(window.Handle); - mouse[MouseButton.Middle] = true; + HandleMButtonDown(handle, message, wParam, lParam); break; case WindowMessage.RBUTTONDOWN: - Functions.SetCapture(window.Handle); - mouse[MouseButton.Right] = true; + HandleRButtonDown(handle, message, wParam, lParam); break; case WindowMessage.XBUTTONDOWN: - Functions.SetCapture(window.Handle); - mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) != - (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = true; + HandleXButtonDown(handle, message, wParam, lParam); break; case WindowMessage.LBUTTONUP: - Functions.ReleaseCapture(); - mouse[MouseButton.Left] = false; + HandleLButtonUp(handle, message, wParam, lParam); break; case WindowMessage.MBUTTONUP: - Functions.ReleaseCapture(); - mouse[MouseButton.Middle] = false; + HandleMButtonUp(handle, message, wParam, lParam); break; case WindowMessage.RBUTTONUP: - Functions.ReleaseCapture(); - mouse[MouseButton.Right] = false; + HandleRButtonUp(handle, message, wParam, lParam); break; case WindowMessage.XBUTTONUP: - Functions.ReleaseCapture(); - mouse[((wParam.ToInt32() & 0xFFFF0000) >> 16) != - (int)MouseKeys.XButton1 ? MouseButton.Button1 : MouseButton.Button2] = false; + HandleXButtonUp(handle, message, wParam, lParam); break; // Keyboard events: @@ -467,47 +644,14 @@ namespace OpenTK.Platform.Windows case WindowMessage.KEYUP: case WindowMessage.SYSKEYDOWN: case WindowMessage.SYSKEYUP: - bool pressed = - message == WindowMessage.KEYDOWN || - message == WindowMessage.SYSKEYDOWN; - - // Shift/Control/Alt behave strangely when e.g. ShiftRight is held down and ShiftLeft is pressed - // and released. It looks like neither key is released in this case, or that the wrong key is - // released in the case of Control and Alt. - // To combat this, we are going to release both keys when either is released. Hacky, but should work. - // Win95 does not distinguish left/right key constants (GetAsyncKeyState returns 0). - // In this case, both keys will be reported as pressed. - - bool extended = (lParam.ToInt64() & ExtendedBit) != 0; - short scancode = (short)((lParam.ToInt64() >> 16) & 0xFF); - VirtualKeys vkey = (VirtualKeys)wParam; - bool is_valid; - Key key = KeyMap.TranslateKey(scancode, vkey, extended, false, out is_valid); - - if (is_valid) - { - keyboard.SetKey(key, (byte)scancode, pressed); - - if (pressed) - { - key_down.Key = key; - KeyDown(this, key_down); - } - else - { - key_up.Key = key; - KeyUp(this, key_up); - } - - } - + HandleKeyboard(handle, message, wParam, lParam); return IntPtr.Zero; case WindowMessage.SYSCHAR: return IntPtr.Zero; case WindowMessage.KILLFOCUS: - keyboard.ClearKeys(); + HandleKillFocus(handle, message, wParam, lParam); break; #endregion @@ -515,44 +659,15 @@ namespace OpenTK.Platform.Windows #region Creation / Destruction events case WindowMessage.CREATE: - CreateStruct cs = (CreateStruct)Marshal.PtrToStructure(lParam, typeof(CreateStruct)); - if (cs.hwndParent == IntPtr.Zero) - { - bounds.X = cs.x; - bounds.Y = cs.y; - bounds.Width = cs.cx; - bounds.Height = cs.cy; - - Win32Rectangle rect; - Functions.GetClientRect(handle, out rect); - client_rectangle = rect.ToRectangle(); - - invisible_since_creation = true; - } + HandleCreate(handle, message, wParam, lParam); break; case WindowMessage.CLOSE: - System.ComponentModel.CancelEventArgs e = new System.ComponentModel.CancelEventArgs(); - - Closing(this, e); - - if (!e.Cancel) - { - DestroyWindow(); - break; - } - + HandleClose(handle, message, wParam, lParam); return IntPtr.Zero; case WindowMessage.DESTROY: - exists = false; - - Functions.UnregisterClass(ClassName, Instance); - window.Dispose(); - child_window.Dispose(); - - Closed(this, EventArgs.Empty); - + HandleDestroy(handle, message, wParam, lParam); break; #endregion