From c1c1f54c59b97696ca373b460a90332675f42910 Mon Sep 17 00:00:00 2001 From: Glenn Rice Date: Tue, 21 Dec 2010 23:58:25 +0000 Subject: [PATCH] Implement free look on linux. Patch due to artart78. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6638 8ced0084-cf51-0410-be5f-012b33b47a6e --- Source/Core/DolphinWX/Src/Frame.cpp | 27 +++++- Source/Core/DolphinWX/Src/Frame.h | 5 +- Source/Core/DolphinWX/Src/FrameTools.cpp | 30 +++++++ Source/Core/DolphinWX/Src/X11Utils.cpp | 31 +++++++ Source/Core/DolphinWX/Src/X11Utils.h | 2 + .../Src/ControllerInterface/Xlib/Xlib.cpp | 4 +- .../Src/ControllerInterface/Xlib/Xlib.h | 1 + Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp | 88 ++++++++++++++++++- 8 files changed, 183 insertions(+), 5 deletions(-) diff --git a/Source/Core/DolphinWX/Src/Frame.cpp b/Source/Core/DolphinWX/Src/Frame.cpp index 0bb43dabd6..78e343e3d0 100644 --- a/Source/Core/DolphinWX/Src/Frame.cpp +++ b/Source/Core/DolphinWX/Src/Frame.cpp @@ -837,12 +837,20 @@ void CFrame::OnKeyDown(wxKeyEvent& event) X11Utils::SendKeyEvent(X11Utils::XDisplayFromHandle(GetHandle()), event.GetKeyCode()); #endif } -#ifdef _WIN32 // Send the freelook hotkeys to the video plugin - if ((event.GetKeyCode() == '0', '9', 'W', 'S', 'A', 'D', 'R') + if ((event.GetKeyCode() == ')' || event.GetKeyCode() == '(' || + event.GetKeyCode() == '0' || event.GetKeyCode() == '9' || + event.GetKeyCode() == 'W' || event.GetKeyCode() == 'S' || + event.GetKeyCode() == 'A' || event.GetKeyCode() == 'D' || + event.GetKeyCode() == 'R') && event.GetModifiers() == wxMOD_SHIFT) + { +#ifdef _WIN32 PostMessage((HWND)Core::GetWindowHandle(), WM_USER, WM_USER_KEYDOWN, event.GetKeyCode()); +#elif defined(HAVE_X11) && HAVE_X11 + X11Utils::SendKeyEvent(X11Utils::XDisplayFromHandle(GetHandle()), event.GetKeyCode()); #endif + } } else event.Skip(); @@ -853,6 +861,21 @@ void CFrame::OnKeyUp(wxKeyEvent& event) event.Skip(); } +void CFrame::OnMouse(wxMouseEvent& event) +{ +#if defined(HAVE_X11) && HAVE_X11 + if(Core::GetState() != Core::CORE_UNINITIALIZED) + { + if(event.Dragging()) + X11Utils::SendMotionEvent(X11Utils::XDisplayFromHandle(GetHandle()), + event.GetPosition().x, event.GetPosition().y); + else + X11Utils::SendButtonEvent(X11Utils::XDisplayFromHandle(GetHandle()), event.GetButton(), + event.GetPosition().x, event.GetPosition().y, event.ButtonDown()); + } +#endif +} + void CFrame::DoFullscreen(bool bF) { ToggleDisplayMode(bF); diff --git a/Source/Core/DolphinWX/Src/Frame.h b/Source/Core/DolphinWX/Src/Frame.h index 7e325d48f3..24a0d0d31f 100644 --- a/Source/Core/DolphinWX/Src/Frame.h +++ b/Source/Core/DolphinWX/Src/Frame.h @@ -311,8 +311,11 @@ class CFrame : public CRenderFrame void DoToggleToolbar(bool); void OnToggleStatusbar(wxCommandEvent& event); void OnToggleWindow(wxCommandEvent& event); - void OnKeyDown(wxKeyEvent& event); + + void OnKeyDown(wxKeyEvent& event); // Keyboard void OnKeyUp(wxKeyEvent& event); + + void OnMouse(wxMouseEvent& event); // Mouse void OnHostMessage(wxCommandEvent& event); diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index 845a5b6f74..4e30ecb224 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.cpp @@ -838,6 +838,21 @@ void CFrame::StartGame(const std::string& filename) wxTheApp->Connect(wxID_ANY, wxEVT_KEY_UP, wxKeyEventHandler(CFrame::OnKeyUp), (wxObject*)0, this); + wxTheApp->Connect(wxID_ANY, wxEVT_RIGHT_DOWN, // Mouse + wxMouseEventHandler(CFrame::OnMouse), + (wxObject*)0, this); + wxTheApp->Connect(wxID_ANY, wxEVT_RIGHT_UP, + wxMouseEventHandler(CFrame::OnMouse), + (wxObject*)0, this); + wxTheApp->Connect(wxID_ANY, wxEVT_MIDDLE_DOWN, + wxMouseEventHandler(CFrame::OnMouse), + (wxObject*)0, this); + wxTheApp->Connect(wxID_ANY, wxEVT_MIDDLE_UP, + wxMouseEventHandler(CFrame::OnMouse), + (wxObject*)0, this); + wxTheApp->Connect(wxID_ANY, wxEVT_MOTION, + wxMouseEventHandler(CFrame::OnMouse), + (wxObject*)0, this); m_RenderParent->Connect(wxID_ANY, wxEVT_SIZE, wxSizeEventHandler(CFrame::OnRenderParentResize), (wxObject*)0, this); @@ -939,6 +954,21 @@ void CFrame::DoStop() wxTheApp->Disconnect(wxID_ANY, wxEVT_KEY_UP, wxKeyEventHandler(CFrame::OnKeyUp), (wxObject*)0, this); + wxTheApp->Disconnect(wxID_ANY, wxEVT_RIGHT_DOWN, // Mouse + wxMouseEventHandler(CFrame::OnMouse), + (wxObject*)0, this); + wxTheApp->Disconnect(wxID_ANY, wxEVT_RIGHT_UP, + wxMouseEventHandler(CFrame::OnMouse), + (wxObject*)0, this); + wxTheApp->Disconnect(wxID_ANY, wxEVT_MIDDLE_DOWN, + wxMouseEventHandler(CFrame::OnMouse), + (wxObject*)0, this); + wxTheApp->Disconnect(wxID_ANY, wxEVT_MIDDLE_UP, + wxMouseEventHandler(CFrame::OnMouse), + (wxObject*)0, this); + wxTheApp->Disconnect(wxID_ANY, wxEVT_MOTION, + wxMouseEventHandler(CFrame::OnMouse), + (wxObject*)0, this); if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor) m_RenderParent->SetCursor(wxCURSOR_ARROW); DoFullscreen(FALSE); diff --git a/Source/Core/DolphinWX/Src/X11Utils.cpp b/Source/Core/DolphinWX/Src/X11Utils.cpp index 1990088de2..8db7265bfb 100644 --- a/Source/Core/DolphinWX/Src/X11Utils.cpp +++ b/Source/Core/DolphinWX/Src/X11Utils.cpp @@ -64,6 +64,37 @@ void SendKeyEvent(Display *dpy, int key) ERROR_LOG(VIDEO, "Failed to send key press event to the emulator window."); } +void SendButtonEvent(Display *dpy, int button, int x, int y, bool pressed) +{ + XEvent event; + Window win = (Window)Core::GetWindowHandle(); + + // Init X event structure for mouse button press event + event.xbutton.type = pressed ? ButtonPress : ButtonRelease; + event.xbutton.x = x; + event.xbutton.y = y; + event.xbutton.button = button; + + // Send the event + if (!XSendEvent(dpy, win, False, False, &event)) + ERROR_LOG(VIDEO, "Failed to send mouse button event to the emulator window."); +} + +void SendMotionEvent(Display *dpy, int x, int y) +{ + XEvent event; + Window win = (Window)Core::GetWindowHandle(); + + // Init X event structure for mouse motion + event.xmotion.type = MotionNotify; + event.xmotion.x = x; + event.xmotion.y = y; + + // Send the event + if (!XSendEvent(dpy, win, False, False, &event)) + ERROR_LOG(VIDEO, "Failed to send mouse button event to the emulator window."); +} + void EWMH_Fullscreen(Display *dpy, int action) { _assert_(action == _NET_WM_STATE_REMOVE || action == _NET_WM_STATE_ADD diff --git a/Source/Core/DolphinWX/Src/X11Utils.h b/Source/Core/DolphinWX/Src/X11Utils.h index 32a508ac92..33f4c8fbb9 100644 --- a/Source/Core/DolphinWX/Src/X11Utils.h +++ b/Source/Core/DolphinWX/Src/X11Utils.h @@ -46,6 +46,8 @@ namespace X11Utils void SendClientEvent(Display *dpy, const char *message, int data1, int data2, int data3, int data4); void SendKeyEvent(Display *dpy, int key); +void SendButtonEvent(Display *dpy, int button, int x, int y, bool pressed); +void SendMotionEvent(Display *dpy, int x, int y); void EWMH_Fullscreen(Display *dpy, int action); #if defined(HAVE_WX) && HAVE_WX Window XWindowFromHandle(void *Handle); diff --git a/Source/Core/InputCommon/Src/ControllerInterface/Xlib/Xlib.cpp b/Source/Core/InputCommon/Src/ControllerInterface/Xlib/Xlib.cpp index c83eb892c0..536f105dee 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/Xlib/Xlib.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/Xlib/Xlib.cpp @@ -124,7 +124,9 @@ KeyboardMouse::Key::Key(Display* const display, KeyCode keycode) ControlState KeyboardMouse::Key::GetState(const State* const state) const { - return (state->keyboard[m_keycode/8] & (1 << (m_keycode%8))) != 0; + KeyCode shift = XKeysymToKeycode(m_display, XK_Shift_L); + return (state->keyboard[m_keycode/8] & (1 << (m_keycode%8))) != 0 + && (state->keyboard[shift/8] & (1 << (shift%8))) == 0; } ControlState KeyboardMouse::Button::GetState(const State* const state) const diff --git a/Source/Core/InputCommon/Src/ControllerInterface/Xlib/Xlib.h b/Source/Core/InputCommon/Src/ControllerInterface/Xlib/Xlib.h index ab5b8cca42..ca65344b0a 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/Xlib/Xlib.h +++ b/Source/Core/InputCommon/Src/ControllerInterface/Xlib/Xlib.h @@ -4,6 +4,7 @@ #include "../ControllerInterface.h" #include +#include namespace ciface { diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp index 8a75a522a1..5c77a7581f 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.cpp @@ -21,6 +21,7 @@ #include "Setup.h" #include "Render.h" +#include "VertexShaderManager.h" #include "GLUtil.h" @@ -150,11 +151,16 @@ void DestroyXWindow(void) THREAD_RETURN XEventThread(void *pArg) { + // Free look variables + static bool mouseLookEnabled = false; + static bool mouseMoveEnabled = false; + static float lastMouse[2]; while (GLWin.win) { XEvent event; KeySym key; - for (int num_events = XPending(GLWin.evdpy); num_events > 0; num_events--) { + for (int num_events = XPending(GLWin.evdpy); num_events > 0; num_events--) + { XNextEvent(GLWin.evdpy, &event); switch(event.type) { case KeyPress: @@ -196,6 +202,86 @@ THREAD_RETURN XEventThread(void *pArg) default: break; } + if (g_Config.bFreeLook) + { + static float debugSpeed = 1.0f; + switch (key) + { + case XK_parenleft: + debugSpeed /= 2.0f; + break; + case XK_parenright: + debugSpeed *= 2.0f; + break; + case XK_w: + VertexShaderManager::TranslateView(0.0f, debugSpeed); + break; + case XK_s: + VertexShaderManager::TranslateView(0.0f, -debugSpeed); + break; + case XK_a: + VertexShaderManager::TranslateView(debugSpeed, 0.0f); + break; + case XK_d: + VertexShaderManager::TranslateView(-debugSpeed, 0.0f); + break; + case XK_r: + VertexShaderManager::ResetView(); + break; + } + } + break; + case ButtonPress: + if (g_Config.bFreeLook) + { + switch (event.xbutton.button) + { + case 2: // Middle button + lastMouse[0] = event.xbutton.x; + lastMouse[1] = event.xbutton.y; + mouseMoveEnabled = true; + break; + case 3: // Right button + lastMouse[0] = event.xbutton.x; + lastMouse[1] = event.xbutton.y; + mouseLookEnabled = true; + break; + } + } + break; + case ButtonRelease: + if (g_Config.bFreeLook) + { + switch (event.xbutton.button) + { + case 2: // Middle button + mouseMoveEnabled = false; + break; + case 3: // Right button + mouseLookEnabled = false; + break; + } + } + break; + case MotionNotify: + if (g_Config.bFreeLook) + { + if (mouseLookEnabled) + { + VertexShaderManager::RotateView((event.xmotion.x - lastMouse[0]) / 200.0f, + (event.xmotion.y - lastMouse[1]) / 200.0f); + lastMouse[0] = event.xmotion.x; + lastMouse[1] = event.xmotion.y; + } + + if (mouseMoveEnabled) + { + VertexShaderManager::TranslateView((event.xmotion.x - lastMouse[0]) / 50.0f, + (event.xmotion.y - lastMouse[1]) / 50.0f); + lastMouse[0] = event.xmotion.x; + lastMouse[1] = event.xmotion.y; + } + } break; case ConfigureNotify: Window winDummy;