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
This commit is contained in:
parent
e4269dcd65
commit
c1c1f54c59
|
@ -837,12 +837,20 @@ void CFrame::OnKeyDown(wxKeyEvent& event)
|
||||||
X11Utils::SendKeyEvent(X11Utils::XDisplayFromHandle(GetHandle()), event.GetKeyCode());
|
X11Utils::SendKeyEvent(X11Utils::XDisplayFromHandle(GetHandle()), event.GetKeyCode());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
|
||||||
// Send the freelook hotkeys to the video plugin
|
// 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)
|
&& event.GetModifiers() == wxMOD_SHIFT)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
PostMessage((HWND)Core::GetWindowHandle(), WM_USER, WM_USER_KEYDOWN, event.GetKeyCode());
|
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
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
event.Skip();
|
event.Skip();
|
||||||
|
@ -853,6 +861,21 @@ void CFrame::OnKeyUp(wxKeyEvent& event)
|
||||||
event.Skip();
|
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)
|
void CFrame::DoFullscreen(bool bF)
|
||||||
{
|
{
|
||||||
ToggleDisplayMode(bF);
|
ToggleDisplayMode(bF);
|
||||||
|
|
|
@ -311,9 +311,12 @@ class CFrame : public CRenderFrame
|
||||||
void DoToggleToolbar(bool);
|
void DoToggleToolbar(bool);
|
||||||
void OnToggleStatusbar(wxCommandEvent& event);
|
void OnToggleStatusbar(wxCommandEvent& event);
|
||||||
void OnToggleWindow(wxCommandEvent& event);
|
void OnToggleWindow(wxCommandEvent& event);
|
||||||
void OnKeyDown(wxKeyEvent& event);
|
|
||||||
|
void OnKeyDown(wxKeyEvent& event); // Keyboard
|
||||||
void OnKeyUp(wxKeyEvent& event);
|
void OnKeyUp(wxKeyEvent& event);
|
||||||
|
|
||||||
|
void OnMouse(wxMouseEvent& event); // Mouse
|
||||||
|
|
||||||
void OnHostMessage(wxCommandEvent& event);
|
void OnHostMessage(wxCommandEvent& event);
|
||||||
|
|
||||||
void OnMemcard(wxCommandEvent& event); // Misc
|
void OnMemcard(wxCommandEvent& event); // Misc
|
||||||
|
|
|
@ -838,6 +838,21 @@ void CFrame::StartGame(const std::string& filename)
|
||||||
wxTheApp->Connect(wxID_ANY, wxEVT_KEY_UP,
|
wxTheApp->Connect(wxID_ANY, wxEVT_KEY_UP,
|
||||||
wxKeyEventHandler(CFrame::OnKeyUp),
|
wxKeyEventHandler(CFrame::OnKeyUp),
|
||||||
(wxObject*)0, this);
|
(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,
|
m_RenderParent->Connect(wxID_ANY, wxEVT_SIZE,
|
||||||
wxSizeEventHandler(CFrame::OnRenderParentResize),
|
wxSizeEventHandler(CFrame::OnRenderParentResize),
|
||||||
(wxObject*)0, this);
|
(wxObject*)0, this);
|
||||||
|
@ -939,6 +954,21 @@ void CFrame::DoStop()
|
||||||
wxTheApp->Disconnect(wxID_ANY, wxEVT_KEY_UP,
|
wxTheApp->Disconnect(wxID_ANY, wxEVT_KEY_UP,
|
||||||
wxKeyEventHandler(CFrame::OnKeyUp),
|
wxKeyEventHandler(CFrame::OnKeyUp),
|
||||||
(wxObject*)0, this);
|
(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)
|
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bHideCursor)
|
||||||
m_RenderParent->SetCursor(wxCURSOR_ARROW);
|
m_RenderParent->SetCursor(wxCURSOR_ARROW);
|
||||||
DoFullscreen(FALSE);
|
DoFullscreen(FALSE);
|
||||||
|
|
|
@ -64,6 +64,37 @@ void SendKeyEvent(Display *dpy, int key)
|
||||||
ERROR_LOG(VIDEO, "Failed to send key press event to the emulator window.");
|
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)
|
void EWMH_Fullscreen(Display *dpy, int action)
|
||||||
{
|
{
|
||||||
_assert_(action == _NET_WM_STATE_REMOVE || action == _NET_WM_STATE_ADD
|
_assert_(action == _NET_WM_STATE_REMOVE || action == _NET_WM_STATE_ADD
|
||||||
|
|
|
@ -46,6 +46,8 @@ namespace X11Utils
|
||||||
void SendClientEvent(Display *dpy, const char *message,
|
void SendClientEvent(Display *dpy, const char *message,
|
||||||
int data1, int data2, int data3, int data4);
|
int data1, int data2, int data3, int data4);
|
||||||
void SendKeyEvent(Display *dpy, int key);
|
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);
|
void EWMH_Fullscreen(Display *dpy, int action);
|
||||||
#if defined(HAVE_WX) && HAVE_WX
|
#if defined(HAVE_WX) && HAVE_WX
|
||||||
Window XWindowFromHandle(void *Handle);
|
Window XWindowFromHandle(void *Handle);
|
||||||
|
|
|
@ -124,7 +124,9 @@ KeyboardMouse::Key::Key(Display* const display, KeyCode keycode)
|
||||||
|
|
||||||
ControlState KeyboardMouse::Key::GetState(const State* const state) const
|
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
|
ControlState KeyboardMouse::Button::GetState(const State* const state) const
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include "../ControllerInterface.h"
|
#include "../ControllerInterface.h"
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
|
#include <X11/keysym.h>
|
||||||
|
|
||||||
namespace ciface
|
namespace ciface
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "Setup.h"
|
#include "Setup.h"
|
||||||
|
|
||||||
#include "Render.h"
|
#include "Render.h"
|
||||||
|
#include "VertexShaderManager.h"
|
||||||
|
|
||||||
#include "GLUtil.h"
|
#include "GLUtil.h"
|
||||||
|
|
||||||
|
@ -150,11 +151,16 @@ void DestroyXWindow(void)
|
||||||
|
|
||||||
THREAD_RETURN XEventThread(void *pArg)
|
THREAD_RETURN XEventThread(void *pArg)
|
||||||
{
|
{
|
||||||
|
// Free look variables
|
||||||
|
static bool mouseLookEnabled = false;
|
||||||
|
static bool mouseMoveEnabled = false;
|
||||||
|
static float lastMouse[2];
|
||||||
while (GLWin.win)
|
while (GLWin.win)
|
||||||
{
|
{
|
||||||
XEvent event;
|
XEvent event;
|
||||||
KeySym key;
|
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);
|
XNextEvent(GLWin.evdpy, &event);
|
||||||
switch(event.type) {
|
switch(event.type) {
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
|
@ -196,6 +202,86 @@ THREAD_RETURN XEventThread(void *pArg)
|
||||||
default:
|
default:
|
||||||
break;
|
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;
|
break;
|
||||||
case ConfigureNotify:
|
case ConfigureNotify:
|
||||||
Window winDummy;
|
Window winDummy;
|
||||||
|
|
Loading…
Reference in New Issue