mirror of https://github.com/PCSX2/pcsx2.git
pcsx2: zzogl:onepad: gsdx: merge linux-gsopen2 branch (4730) into trunk
* Gsopen2 support for GS plugins => Support of the PCSX2 GS window configuration panel. Support of all PCSX2 shortcut. * new shortcut: shift-f12 to stole the input. ZZogl shortcut must be prefixed with ctrl * onepad: Support/fix/improve of configuration gui, multiple key, mouse/wiimote for analog joystick, dualshock3/sixaxis (basic), dual pad and experimental forcefeedback Note: it is advices to delete OnePAD.ini git-svn-id: http://pcsx2.googlecode.com/svn/trunk@4731 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
0543f24466
commit
35b9dfce3f
|
@ -512,7 +512,9 @@ X11_CreateWindow(_THIS, SDL_Window * window)
|
|||
int
|
||||
X11_CreateWindowFrom(_THIS, SDL_Window * window, const void *data)
|
||||
{
|
||||
Window w = (Window) data;
|
||||
// For me it is a bug -- Gregory
|
||||
// Window w = (Window) data;
|
||||
Window w = *(Window*) data;
|
||||
|
||||
window->title = X11_GetWindowTitle(_this, w);
|
||||
|
||||
|
@ -537,8 +539,12 @@ X11_GetWindowTitle(_THIS, Window xwindow)
|
|||
0L, 8192L, False, data->UTF8_STRING, &real_type, &real_format,
|
||||
&items_read, &items_left, &propdata);
|
||||
if (status == Success) {
|
||||
title = SDL_strdup(SDL_static_cast(char*, propdata));
|
||||
XFree(propdata);
|
||||
// Propdata can be null I do not know if it normal or not.
|
||||
// At least handle gracefully and dont crash. -- Gregory
|
||||
if (propdata) {
|
||||
title = SDL_strdup(SDL_static_cast(char*, propdata));
|
||||
XFree(propdata);
|
||||
}
|
||||
} else {
|
||||
status = XGetWindowProperty(display, xwindow, XA_WM_NAME,
|
||||
0L, 8192L, False, XA_STRING, &real_type, &real_format,
|
||||
|
|
|
@ -322,6 +322,11 @@ u32 CALLBACK PADquery();
|
|||
// have to be added to maintain data integrity.
|
||||
void CALLBACK PADupdate(int pad);
|
||||
|
||||
// Send a key event from wx-gui to pad
|
||||
// Note: On linux GSOpen2, wx-gui and pad share the same event buffer. Wx-gui reads and deletes event
|
||||
// before the pad saw them. So the gui needs to send them back to the pad.
|
||||
void CALLBACK PADWriteEvent(keyEvent &evt);
|
||||
|
||||
// extended funcs
|
||||
|
||||
void CALLBACK PADgsDriverInfo(GSdriverInfo *info);
|
||||
|
@ -603,6 +608,7 @@ typedef keyEvent* (CALLBACK* _PADkeyEvent)();
|
|||
typedef void (CALLBACK* _PADgsDriverInfo)(GSdriverInfo *info);
|
||||
typedef s32 (CALLBACK* _PADsetSlot)(u8 port, u8 slot);
|
||||
typedef s32 (CALLBACK* _PADqueryMtap)(u8 port);
|
||||
typedef void (CALLBACK* _PADWriteEvent)(keyEvent &evt);
|
||||
|
||||
// SPU2
|
||||
typedef s32 (CALLBACK* _SPU2open)(void *pDsp);
|
||||
|
@ -755,6 +761,7 @@ extern _PADkeyEvent PADkeyEvent;
|
|||
extern _PADgsDriverInfo PADgsDriverInfo;
|
||||
extern _PADsetSlot PADsetSlot;
|
||||
extern _PADqueryMtap PADqueryMtap;
|
||||
extern _PADWriteEvent PADWriteEvent;
|
||||
|
||||
// SPU2
|
||||
extern _SPU2open SPU2open;
|
||||
|
|
|
@ -188,9 +188,9 @@ void SysMtgsThread::OpenPlugin()
|
|||
int result;
|
||||
|
||||
if( GSopen2 != NULL )
|
||||
result = GSopen2( (void*)&pDsp, 1 | (renderswitch ? 4 : 0) );
|
||||
result = GSopen2( (void*)pDsp, 1 | (renderswitch ? 4 : 0) );
|
||||
else
|
||||
result = GSopen( (void*)&pDsp, "PCSX2", renderswitch ? 2 : 1 );
|
||||
result = GSopen( (void*)pDsp, "PCSX2", renderswitch ? 2 : 1 );
|
||||
|
||||
// Vsync on / off ?
|
||||
if( renderswitch )
|
||||
|
|
|
@ -252,6 +252,7 @@ _PADupdate PADupdate;
|
|||
_PADkeyEvent PADkeyEvent;
|
||||
_PADsetSlot PADsetSlot;
|
||||
_PADqueryMtap PADqueryMtap;
|
||||
_PADWriteEvent PADWriteEvent;
|
||||
|
||||
static void PAD_update( u32 padslot ) { }
|
||||
|
||||
|
@ -323,7 +324,7 @@ _FWirqCallback FWirqCallback;
|
|||
|
||||
DEV9handler dev9Handler;
|
||||
USBhandler usbHandler;
|
||||
uptr pDsp;
|
||||
uptr pDsp[2];
|
||||
|
||||
static s32 CALLBACK _hack_PADinit()
|
||||
{
|
||||
|
@ -417,6 +418,7 @@ static const LegacyApi_ReqMethod s_MethMessReq_PAD[] =
|
|||
static const LegacyApi_OptMethod s_MethMessOpt_PAD[] =
|
||||
{
|
||||
{ "PADupdate", (vMeth**)&PADupdate },
|
||||
{ "PADWriteEvent", (vMeth**)&PADWriteEvent },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
@ -1058,12 +1060,12 @@ bool SysCorePlugins::OpenPlugin_GS()
|
|||
|
||||
bool SysCorePlugins::OpenPlugin_PAD()
|
||||
{
|
||||
return !PADopen( (void*)&pDsp );
|
||||
return !PADopen( (void*)pDsp );
|
||||
}
|
||||
|
||||
bool SysCorePlugins::OpenPlugin_SPU2()
|
||||
{
|
||||
if( SPU2open((void*)&pDsp) ) return false;
|
||||
if( SPU2open((void*)pDsp) ) return false;
|
||||
|
||||
#ifdef ENABLE_NEW_IOPDMA_SPU2
|
||||
SPU2irqCallback( spu2Irq );
|
||||
|
@ -1079,7 +1081,7 @@ bool SysCorePlugins::OpenPlugin_DEV9()
|
|||
{
|
||||
dev9Handler = NULL;
|
||||
|
||||
if( DEV9open( (void*)&pDsp ) ) return false;
|
||||
if( DEV9open( (void*)pDsp ) ) return false;
|
||||
DEV9irqCallback( dev9Irq );
|
||||
dev9Handler = DEV9irqHandler();
|
||||
return true;
|
||||
|
@ -1089,7 +1091,7 @@ bool SysCorePlugins::OpenPlugin_USB()
|
|||
{
|
||||
usbHandler = NULL;
|
||||
|
||||
if( USBopen((void*)&pDsp) ) return false;
|
||||
if( USBopen((void*)pDsp) ) return false;
|
||||
USBirqCallback( usbIrq );
|
||||
usbHandler = USBirqHandler();
|
||||
if( USBsetRAM != NULL )
|
||||
|
@ -1099,7 +1101,7 @@ bool SysCorePlugins::OpenPlugin_USB()
|
|||
|
||||
bool SysCorePlugins::OpenPlugin_FW()
|
||||
{
|
||||
if( FWopen((void*)&pDsp) ) return false;
|
||||
if( FWopen((void*)pDsp) ) return false;
|
||||
FWirqCallback( fwIrq );
|
||||
return true;
|
||||
}
|
||||
|
@ -1159,7 +1161,15 @@ void SysCorePlugins::Open()
|
|||
// If GS doesn't support GSopen2, need to wait until call to GSopen
|
||||
// returns to populate pDsp. If it does, can initialize other plugins
|
||||
// at same time as GS, as long as GSopen2 does not subclass its window.
|
||||
#ifdef __LINUX__
|
||||
// On linux, application have also a channel (named display) to communicate with the
|
||||
// Xserver. The safe rule is 1 thread, 1 channel. In our case we use the display in
|
||||
// several places. Save yourself of multithread headache. Wait few seconds the end of
|
||||
// gsopen -- Gregory
|
||||
if (pi->id == PluginId_GS) GetMTGS().WaitForOpen();
|
||||
#else
|
||||
if (pi->id == PluginId_GS && !GSopen2) GetMTGS().WaitForOpen();
|
||||
#endif
|
||||
} while( ++pi, pi->shortname != NULL );
|
||||
|
||||
if (GSopen2) GetMTGS().WaitForOpen();
|
||||
|
|
|
@ -392,5 +392,5 @@ extern "C" const PS2E_LibraryAPI* FileMcd_InitAPI( const PS2E_EmulatorInfo* emui
|
|||
|
||||
// Per ChickenLiver, this is being used to pass the GS plugins window handle to the Pad plugins.
|
||||
// So a rename to pDisplay is in the works, but it will not, in fact, be removed.
|
||||
extern uptr pDsp;
|
||||
extern uptr pDsp[2];
|
||||
|
||||
|
|
|
@ -36,6 +36,14 @@
|
|||
# include <wx/msw/wrapwin.h> // needed to implement the app!
|
||||
#endif
|
||||
|
||||
#ifdef __WXGTK__
|
||||
// Need to tranform the GSPanel to a X11 window/display for the GS plugins
|
||||
#include <wx/gtk/win_gtk.h> // GTK_PIZZA interface
|
||||
#include <gdk/gdkx.h>
|
||||
#include <gtk/gtk.h>
|
||||
#endif
|
||||
|
||||
|
||||
IMPLEMENT_APP(Pcsx2App)
|
||||
|
||||
DEFINE_EVENT_TYPE( pxEvt_LoadPluginsComplete );
|
||||
|
@ -862,12 +870,30 @@ void Pcsx2App::OpenGsPanel()
|
|||
}
|
||||
|
||||
pxAssertDev( !GetCorePlugins().IsOpen( PluginId_GS ), "GS Plugin must be closed prior to opening a new Gs Panel!" );
|
||||
pDsp = (uptr)gsFrame->GetViewport()->GetHandle();
|
||||
|
||||
#ifdef __WXGTK__
|
||||
// The x window/display are actually very deeper in the widget. You need both display and window
|
||||
// because unlike window there are unrelated. One could think it would be easier to send directly the GdkWindow.
|
||||
// Unfortunately there is a race condition between gui and gs threads when you called the
|
||||
// GDK_WINDOW_* macro. To be safe I think it is best to do here. It only cost a slight
|
||||
// extension (fully compatible) of the plugins API. -- Gregory
|
||||
GtkWidget *child_window = gtk_bin_get_child(GTK_BIN(gsFrame->GetViewport()->GetHandle()));
|
||||
|
||||
gtk_widget_realize(child_window); // create the widget to allow to use GDK_WINDOW_* macro
|
||||
gtk_widget_set_double_buffered(child_window, false); // Disable the widget double buffer, you will use the opengl one
|
||||
|
||||
GdkWindow* draw_window = GTK_PIZZA(child_window)->bin_window;
|
||||
Window Xwindow = GDK_WINDOW_XWINDOW(draw_window);
|
||||
Display* XDisplay = GDK_WINDOW_XDISPLAY(draw_window);
|
||||
|
||||
pDsp[0] = (uptr)XDisplay;
|
||||
pDsp[1] = (uptr)Xwindow;
|
||||
#else
|
||||
pDsp[0] = (uptr)gsFrame->GetViewport()->GetHandle();
|
||||
pDsp[1] = NULL;
|
||||
#endif
|
||||
|
||||
gsFrame->ShowFullScreen( g_Conf->GSWindow.IsFullscreen );
|
||||
|
||||
// The "in the main window" quickie hack...
|
||||
//pDsp = (uptr)m_MainFrame->m_background.GetHandle();
|
||||
}
|
||||
|
||||
void Pcsx2App::CloseGsPanel()
|
||||
|
|
|
@ -48,11 +48,11 @@ void GSPanel::InitDefaultAccelerators()
|
|||
|
||||
m_Accels->Map( AAC( WXK_F6 ), "GSwindow_CycleAspectRatio" );
|
||||
|
||||
m_Accels->Map( AAC( WXK_NUMPAD_ADD ).Cmd(), "GSwindow_ZoomIn" ); //CTRL on Windows (probably linux too), CMD on OSX
|
||||
m_Accels->Map( AAC( WXK_NUMPAD_ADD ).Cmd(), "GSwindow_ZoomIn" ); //CTRL on Windows/linux, CMD on OSX
|
||||
m_Accels->Map( AAC( WXK_NUMPAD_SUBTRACT ).Cmd(), "GSwindow_ZoomOut" );
|
||||
m_Accels->Map( AAC( WXK_NUMPAD_MULTIPLY ).Cmd(), "GSwindow_ZoomToggle" );
|
||||
|
||||
m_Accels->Map( AAC( WXK_NUMPAD_ADD ).Cmd().Alt(), "GSwindow_ZoomInY" ); //CTRL on Windows (probably linux too), CMD on OSX
|
||||
m_Accels->Map( AAC( WXK_NUMPAD_ADD ).Cmd().Alt(), "GSwindow_ZoomInY" ); //CTRL on Windows/linux, CMD on OSX
|
||||
m_Accels->Map( AAC( WXK_NUMPAD_SUBTRACT ).Cmd().Alt(), "GSwindow_ZoomOutY" );
|
||||
m_Accels->Map( AAC( WXK_NUMPAD_MULTIPLY ).Cmd().Alt(), "GSwindow_ZoomResetY" );
|
||||
|
||||
|
@ -97,6 +97,7 @@ GSPanel::GSPanel( wxWindow* parent )
|
|||
|
||||
Connect(wxEVT_CLOSE_WINDOW, wxCloseEventHandler (GSPanel::OnCloseWindow));
|
||||
Connect(wxEVT_SIZE, wxSizeEventHandler (GSPanel::OnResize));
|
||||
Connect(wxEVT_KEY_UP, wxKeyEventHandler (GSPanel::OnKeyDown));
|
||||
Connect(wxEVT_KEY_DOWN, wxKeyEventHandler (GSPanel::OnKeyDown));
|
||||
|
||||
Connect(wxEVT_SET_FOCUS, wxFocusEventHandler (GSPanel::OnFocus));
|
||||
|
@ -107,16 +108,18 @@ GSPanel::GSPanel( wxWindow* parent )
|
|||
// Any and all events which should result in the mouse cursor being made visible
|
||||
// are connected here. If I missed one, feel free to add it in! --air
|
||||
|
||||
Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_RIGHT_UP, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_MOTION, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler (GSPanel::OnMouseEvent));
|
||||
Connect(wxEVT_LEFT_UP, wxMouseEventHandler (GSPanel::OnMouseEvent));
|
||||
Connect(wxEVT_MIDDLE_DOWN, wxMouseEventHandler (GSPanel::OnMouseEvent));
|
||||
Connect(wxEVT_MIDDLE_UP, wxMouseEventHandler (GSPanel::OnMouseEvent));
|
||||
Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler (GSPanel::OnMouseEvent));
|
||||
Connect(wxEVT_RIGHT_UP, wxMouseEventHandler (GSPanel::OnMouseEvent));
|
||||
Connect(wxEVT_MOTION, wxMouseEventHandler (GSPanel::OnMouseEvent));
|
||||
Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler (GSPanel::OnMouseEvent));
|
||||
Connect(wxEVT_LEFT_DCLICK, wxMouseEventHandler (GSPanel::OnLeftDclick));
|
||||
Connect(wxEVT_MIDDLE_DCLICK, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_RIGHT_DCLICK, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (GSPanel::OnShowMouse));
|
||||
Connect(wxEVT_MIDDLE_DCLICK, wxMouseEventHandler (GSPanel::OnMouseEvent));
|
||||
Connect(wxEVT_RIGHT_DCLICK, wxMouseEventHandler (GSPanel::OnMouseEvent));
|
||||
Connect(wxEVT_MOUSEWHEEL, wxMouseEventHandler (GSPanel::OnMouseEvent));
|
||||
}
|
||||
|
||||
GSPanel::~GSPanel() throw()
|
||||
|
@ -188,11 +191,60 @@ void GSPanel::OnCloseWindow(wxCloseEvent& evt)
|
|||
evt.Skip(); // and close it.
|
||||
}
|
||||
|
||||
void GSPanel::OnShowMouse( wxMouseEvent& evt )
|
||||
void GSPanel::OnMouseEvent( wxMouseEvent& evt )
|
||||
{
|
||||
if( IsBeingDeleted() ) return;
|
||||
evt.Skip();
|
||||
DoShowMouse();
|
||||
|
||||
// Do nothing for left-button event
|
||||
if (!evt.Button(1)) {
|
||||
evt.Skip();
|
||||
DoShowMouse();
|
||||
}
|
||||
|
||||
#ifdef __LINUX__
|
||||
// HACK2: In gsopen2 there is one event buffer read by both wx/gui and pad plugin. Wx deletes
|
||||
// the event before the pad see it. So you send key event directly to the pad.
|
||||
if( (PADWriteEvent != NULL) && (GSopen2 != NULL) ) {
|
||||
keyEvent event;
|
||||
// FIXME how to handle double click ???
|
||||
if (evt.ButtonDown()) {
|
||||
event.evt = 4; // X equivalent of ButtonPress
|
||||
event.key = evt.GetButton();
|
||||
} else if (evt.ButtonUp()) {
|
||||
event.evt = 5; // X equivalent of ButtonRelease
|
||||
event.key = evt.GetButton();
|
||||
} else if (evt.Moving() || evt.Dragging()) {
|
||||
event.evt = 6; // X equivalent of MotionNotify
|
||||
long x,y;
|
||||
evt.GetPosition(&x, &y);
|
||||
|
||||
wxCoord w, h;
|
||||
wxWindowDC dc( this );
|
||||
dc.GetSize(&w, &h);
|
||||
|
||||
// Special case to allow continuous mouvement near the border
|
||||
if (x < 10)
|
||||
x = 0;
|
||||
else if (x > (w-10))
|
||||
x = 0xFFFF;
|
||||
|
||||
if (y < 10)
|
||||
y = 0;
|
||||
else if (y > (w-10))
|
||||
y = 0xFFFF;
|
||||
|
||||
// For compatibility purpose with the existing structure. I decide to reduce
|
||||
// the position to 16 bits.
|
||||
event.key = ((y & 0xFFFF) << 16) | (x & 0xFFFF);
|
||||
|
||||
} else {
|
||||
event.key = 0;
|
||||
event.evt = 0;
|
||||
}
|
||||
|
||||
PADWriteEvent(event);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GSPanel::OnHideMouseTimeout( wxTimerEvent& evt )
|
||||
|
@ -206,11 +258,29 @@ void GSPanel::OnHideMouseTimeout( wxTimerEvent& evt )
|
|||
|
||||
void GSPanel::OnKeyDown( wxKeyEvent& evt )
|
||||
{
|
||||
|
||||
// HACK: Legacy PAD plugins expect PCSX2 to ignore keyboard messages on the GS Window while
|
||||
// the PAD plugin is open, so ignore here (PCSX2 will direct messages routed from PAD directly
|
||||
// to the APP level message handler, which in turn routes them right back here -- yes it's
|
||||
// silly, but oh well).
|
||||
|
||||
#ifdef __LINUX__
|
||||
// HACK2: In gsopen2 there is one event buffer read by both wx/gui and pad plugin. Wx deletes
|
||||
// the event before the pad see it. So you send key event directly to the pad.
|
||||
if( (PADWriteEvent != NULL) && (GSopen2 != NULL) ) {
|
||||
keyEvent event;
|
||||
event.key = evt.GetRawKeyCode();
|
||||
if (evt.GetEventType() == wxEVT_KEY_UP)
|
||||
event.evt = 3; // X equivalent of KEYRELEASE;
|
||||
else if (evt.GetEventType() == wxEVT_KEY_DOWN)
|
||||
event.evt = 2; // X equivalent of KEYPRESS;
|
||||
else
|
||||
event.evt = 0;
|
||||
|
||||
PADWriteEvent(event);
|
||||
}
|
||||
#endif
|
||||
|
||||
if( (PADopen != NULL) && CoreThread.IsOpen() ) return;
|
||||
DirectKeyCommand( evt );
|
||||
}
|
||||
|
@ -246,6 +316,14 @@ void GSPanel::OnFocus( wxFocusEvent& evt )
|
|||
else
|
||||
DoShowMouse();
|
||||
|
||||
#ifdef __LINUX__
|
||||
// HACK2: In gsopen2 there is one event buffer read by both wx/gui and pad plugin. Wx deletes
|
||||
// the event before the pad see it. So you send key event directly to the pad.
|
||||
if( (PADWriteEvent != NULL) && (GSopen2 != NULL) ) {
|
||||
keyEvent event = {0, 9}; // X equivalent of FocusIn;
|
||||
PADWriteEvent(event);
|
||||
}
|
||||
#endif
|
||||
//Console.Warning("GS frame > focus set");
|
||||
}
|
||||
|
||||
|
@ -254,6 +332,14 @@ void GSPanel::OnFocusLost( wxFocusEvent& evt )
|
|||
evt.Skip();
|
||||
m_HasFocus = false;
|
||||
DoShowMouse();
|
||||
#ifdef __LINUX__
|
||||
// HACK2: In gsopen2 there is one event buffer read by both wx/gui and pad plugin. Wx deletes
|
||||
// the event before the pad see it. So you send key event directly to the pad.
|
||||
if( (PADWriteEvent != NULL) && (GSopen2 != NULL) ) {
|
||||
keyEvent event = {0, 10}; // X equivalent of FocusOut
|
||||
PADWriteEvent(event);
|
||||
}
|
||||
#endif
|
||||
//Console.Warning("GS frame > focus lost");
|
||||
}
|
||||
|
||||
|
|
|
@ -64,7 +64,7 @@ protected:
|
|||
|
||||
void OnCloseWindow( wxCloseEvent& evt );
|
||||
void OnResize(wxSizeEvent& event);
|
||||
void OnShowMouse( wxMouseEvent& evt );
|
||||
void OnMouseEvent( wxMouseEvent& evt );
|
||||
void OnHideMouseTimeout( wxTimerEvent& evt );
|
||||
void OnKeyDown( wxKeyEvent& evt );
|
||||
void OnFocus( wxFocusEvent& evt );
|
||||
|
|
|
@ -281,7 +281,12 @@ static int _GSopen(void** dsp, char* title, int renderer, int threads = -1)
|
|||
{
|
||||
s_gs->SetMultithreaded(true);
|
||||
|
||||
#ifdef __LINUX__
|
||||
// Get the Xwindow from dsp.
|
||||
s_gs->m_wnd.Attach((void*)((uint32*)(dsp)+1), false);
|
||||
#else
|
||||
s_gs->m_wnd.Attach(*dsp, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
if(!s_gs->CreateDevice(dev))
|
||||
|
@ -298,8 +303,6 @@ static int _GSopen(void** dsp, char* title, int renderer, int threads = -1)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _WINDOWS
|
||||
|
||||
EXPORT_C_(int) GSopen2(void** dsp, uint32 flags)
|
||||
{
|
||||
int renderer = theApp.GetConfig("renderer", 0);
|
||||
|
@ -320,8 +323,6 @@ EXPORT_C_(int) GSopen2(void** dsp, uint32 flags)
|
|||
return retval;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
EXPORT_C_(int) GSopen(void** dsp, char* title, int mt)
|
||||
{
|
||||
/*
|
||||
|
|
|
@ -50,20 +50,15 @@ GSDeviceSDL::~GSDeviceSDL()
|
|||
|
||||
bool GSDeviceSDL::Create(GSWnd* wnd)
|
||||
{
|
||||
void* handle = wnd->GetHandle();
|
||||
|
||||
if(handle == wnd->GetDisplay())
|
||||
{
|
||||
// HACK: no SDL window
|
||||
|
||||
m_window = SDL_CreateWindowFrom(handle);
|
||||
|
||||
m_free_window = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_window = (SDL_Window*)handle;
|
||||
if (m_window == NULL) {
|
||||
m_window = SDL_CreateWindowFrom(wnd->GetHandle());
|
||||
m_free_window = true;
|
||||
}
|
||||
#ifdef __LINUX__
|
||||
// In GSopen2, sdl failed to received any resize event. GSWnd::GetClientRect need to manually
|
||||
// set the window size... So we send the m_window to the wnd object to allow some manipulation on it.
|
||||
wnd->SetWindow(m_window);
|
||||
#endif
|
||||
|
||||
return GSDeviceSW::Create(wnd);
|
||||
}
|
||||
|
|
|
@ -312,28 +312,44 @@ void GSWnd::HideFrame()
|
|||
*/
|
||||
|
||||
GSWnd::GSWnd()
|
||||
: m_window(NULL)
|
||||
: m_window(NULL), m_Xwindow(0), m_XDisplay(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
GSWnd::~GSWnd()
|
||||
{
|
||||
if(m_window != NULL)
|
||||
if(m_window != NULL && m_managed)
|
||||
{
|
||||
SDL_DestroyWindow(m_window);
|
||||
m_window = NULL;
|
||||
}
|
||||
if (m_XDisplay) {
|
||||
XCloseDisplay(m_XDisplay);
|
||||
m_XDisplay = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool GSWnd::Attach(void* handle, bool managed)
|
||||
{
|
||||
m_Xwindow = *(Window*)handle;
|
||||
m_managed = managed;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Actually the destructor is not called when there is a GSclose or GSshutdown
|
||||
// The window still need to be closed
|
||||
void GSWnd::Detach()
|
||||
{
|
||||
if(m_window != NULL)
|
||||
// Actually the destructor is not called when there is only a GSclose/GSshutdown
|
||||
// The window still need to be closed
|
||||
if(m_window != NULL && m_managed)
|
||||
{
|
||||
SDL_DestroyWindow(m_window);
|
||||
m_window = NULL;
|
||||
}
|
||||
if (m_XDisplay) {
|
||||
XCloseDisplay(m_XDisplay);
|
||||
m_XDisplay = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool GSWnd::Create(const string& title, int w, int h)
|
||||
|
@ -359,8 +375,21 @@ bool GSWnd::Create(const string& title, int w, int h)
|
|||
if (SDL_GetNumVideoDisplays() <= 0) return false;
|
||||
#endif
|
||||
|
||||
m_managed = true;
|
||||
m_window = SDL_CreateWindow(title.c_str(), 100, 100, w, h, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
|
||||
|
||||
// Get the X window from the newly created window
|
||||
// It would be needed to get the current size
|
||||
SDL_SysWMinfo wminfo;
|
||||
memset(&wminfo, 0, sizeof(wminfo));
|
||||
|
||||
wminfo.version.major = SDL_MAJOR_VERSION;
|
||||
wminfo.version.minor = SDL_MINOR_VERSION;
|
||||
|
||||
SDL_GetWindowWMInfo(m_window, &wminfo);
|
||||
m_Xwindow = wminfo.info.x11.window;
|
||||
|
||||
|
||||
return (m_window != NULL);
|
||||
}
|
||||
|
||||
|
@ -380,16 +409,25 @@ Display* GSWnd::GetDisplay()
|
|||
|
||||
GSVector4i GSWnd::GetClientRect()
|
||||
{
|
||||
// Get all SDL events. It refreshes the window parameter do not ask why.
|
||||
// Anyway it allow to properly resize the window surface
|
||||
// FIXME: it does not feel a good solution -- Gregory
|
||||
SDL_PumpEvents();
|
||||
unsigned int h = 480;
|
||||
unsigned int w = 640;
|
||||
|
||||
int h = 480;
|
||||
int w = 640;
|
||||
if (m_window) SDL_GetWindowSize(m_window, &w, &h);
|
||||
unsigned int borderDummy;
|
||||
unsigned int depthDummy;
|
||||
Window winDummy;
|
||||
int xDummy;
|
||||
int yDummy;
|
||||
|
||||
return GSVector4i(0, 0, w, h);
|
||||
// In gsopen2, pcsx2 stoles all event (including resize event). SDL is not able to update its structure
|
||||
// so you must do it yourself
|
||||
// In perfect world:
|
||||
// if (m_window) SDL_GetWindowSize(m_window, &w, &h);
|
||||
// In real world...:
|
||||
if (!m_XDisplay) m_XDisplay = XOpenDisplay(NULL);
|
||||
XGetGeometry(m_XDisplay, m_Xwindow, &winDummy, &xDummy, &yDummy, &w, &h, &borderDummy, &depthDummy);
|
||||
SDL_SetWindowSize(m_window, w, h);
|
||||
|
||||
return GSVector4i(0, 0, (int)w, (int)h);
|
||||
}
|
||||
|
||||
// Returns FALSE if the window has no title, or if th window title is under the strict
|
||||
|
@ -397,17 +435,21 @@ GSVector4i GSWnd::GetClientRect()
|
|||
|
||||
bool GSWnd::SetWindowText(const char* title)
|
||||
{
|
||||
if (!m_managed) return true;
|
||||
|
||||
// Do not find anyway to check the current fullscreen status
|
||||
// Better than nothing heuristic, check the window position. Fullscreen = (0,0)
|
||||
// if(!(m_window->flags & SDL_WINDOW_FULLSCREEN) ) // Do not compile
|
||||
//
|
||||
// Same as GetClientRect. We call SDL_PumpEvents to refresh x and y value
|
||||
// We call SDL_PumpEvents to refresh x and y value.
|
||||
// but we not use this function anyway.
|
||||
// FIXME: it does not feel a good solution -- Gregory
|
||||
// NOte: it might be more thread safe to use a call to XGetGeometry
|
||||
SDL_PumpEvents();
|
||||
int x,y = 0;
|
||||
SDL_GetWindowPosition(m_window, &x, &y);
|
||||
if ( x && y )
|
||||
SDL_SetWindowTitle(m_window, title);
|
||||
SDL_SetWindowTitle(m_window, title);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -94,20 +94,24 @@ public:
|
|||
class GSWnd
|
||||
{
|
||||
SDL_Window* m_window;
|
||||
Window m_Xwindow;
|
||||
Display* m_XDisplay;
|
||||
bool m_managed;
|
||||
|
||||
public:
|
||||
GSWnd();
|
||||
virtual ~GSWnd();
|
||||
|
||||
bool Create(const string& title, int w, int h);
|
||||
bool Attach(void* handle, bool managed = true) {return false;}
|
||||
bool Attach(void* handle, bool managed = true);
|
||||
void Detach();
|
||||
bool IsManaged() const {return true;}
|
||||
bool IsManaged() const {return m_managed;}
|
||||
|
||||
Display* GetDisplay();
|
||||
void* GetHandle() {return m_window;}
|
||||
void* GetHandle() {return (void*)&m_Xwindow;}
|
||||
GSVector4i GetClientRect();
|
||||
bool SetWindowText(const char* title);
|
||||
void SetWindow(SDL_Window* current_window) { if (current_window) m_window = current_window; }
|
||||
|
||||
void Show();
|
||||
void Hide();
|
||||
|
|
|
@ -20,18 +20,16 @@
|
|||
*/
|
||||
|
||||
#include "joystick.h"
|
||||
#include "keyboard.h"
|
||||
#include "onepad.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
extern bool PollX11Keyboard(char* &temp, u32 &pkey);
|
||||
extern string KeyName(int pad, int key);
|
||||
|
||||
void config_key(int pad, int key);
|
||||
void on_conf_key(GtkButton *button, gpointer user_data);
|
||||
void on_toggle_option(GtkToggleButton *togglebutton, gpointer user_data);
|
||||
|
||||
static int current_pad = 0;
|
||||
static int current_joystick = -1;
|
||||
GtkWidget *rev_lx_check, *rev_ly_check, *force_feedback_check, *rev_rx_check, *rev_ry_check;
|
||||
static GtkComboBox *joy_choose_cbox;
|
||||
|
||||
const char* s_pGuiKeyMap[] =
|
||||
{
|
||||
|
@ -39,7 +37,6 @@ const char* s_pGuiKeyMap[] =
|
|||
"Triangle", "Circle", "Cross", "Square",
|
||||
"Select", "L3", "R3", "Start",
|
||||
"Up", "Right", "Down", "Left",
|
||||
"Lx", "Rx", "Ly", "Ry",
|
||||
"L_Up", "L_Right", "L_Down", "L_Left",
|
||||
"R_Up", "R_Right", "R_Down", "R_Left"
|
||||
};
|
||||
|
@ -51,71 +48,94 @@ enum
|
|||
COL_KEY,
|
||||
COL_PAD_NUM,
|
||||
COL_VALUE,
|
||||
COL_KEYSYM,
|
||||
NUM_COLS
|
||||
};
|
||||
|
||||
|
||||
class keys_tree
|
||||
{
|
||||
private:
|
||||
GtkTreeStore *treestore;
|
||||
GtkTreeModel *model;
|
||||
GtkTreeView *view;
|
||||
GtkTreeView *view[2];
|
||||
bool has_columns;
|
||||
|
||||
int show_pad;
|
||||
bool show_keyboard_key[2];
|
||||
bool show_joy_key[2];
|
||||
|
||||
void repopulate()
|
||||
{
|
||||
GtkTreeIter toplevel;
|
||||
|
||||
gtk_tree_store_clear(treestore);
|
||||
|
||||
for (int pad = 0; pad < 2 * MAX_SUB_KEYS; pad++)
|
||||
{
|
||||
string pad_value;
|
||||
switch(show_pad) {
|
||||
case 0: pad_value = "Pad 1"; break;
|
||||
case 1: pad_value = "Pad 2"; break;
|
||||
default: pad_value = "Invalid"; break;
|
||||
}
|
||||
|
||||
// joystick key
|
||||
if (show_joy_key[show_pad]) {
|
||||
for (int key = 0; key < MAX_KEYS; key++)
|
||||
{
|
||||
if (get_key(pad, key) != 0)
|
||||
if (get_key(show_pad, key) != 0)
|
||||
{
|
||||
string pad_value;
|
||||
switch(pad)
|
||||
{
|
||||
case 0: pad_value = "Pad 1"; break;
|
||||
case 2: pad_value = "Pad 1"; break;
|
||||
case 1: pad_value = "Pad 2"; break;
|
||||
case 3: pad_value = "Pad 2"; break;
|
||||
default: pad_value = "Invalid"; break;
|
||||
}
|
||||
gtk_tree_store_append(treestore, &toplevel, NULL);
|
||||
gtk_tree_store_set(treestore, &toplevel,
|
||||
COL_PAD, pad_value.c_str(),
|
||||
COL_BUTTON, s_pGuiKeyMap[key],
|
||||
COL_KEY, KeyName(show_pad, key).c_str(),
|
||||
COL_PAD_NUM, show_pad,
|
||||
COL_VALUE, key,
|
||||
COL_KEYSYM, 0,
|
||||
-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// keyboard/mouse key
|
||||
if (show_keyboard_key[show_pad]) {
|
||||
map<u32,u32>::iterator it;
|
||||
for (it = conf->keysym_map[show_pad].begin(); it != conf->keysym_map[show_pad].end(); ++it) {
|
||||
int keysym = it->first;
|
||||
int key = it->second;
|
||||
gtk_tree_store_append(treestore, &toplevel, NULL);
|
||||
gtk_tree_store_set(treestore, &toplevel,
|
||||
COL_PAD, pad_value.c_str(),
|
||||
COL_BUTTON, s_pGuiKeyMap[key],
|
||||
COL_KEY, KeyName(pad, key).c_str(),
|
||||
COL_PAD_NUM, pad,
|
||||
COL_KEY, KeyName(show_pad, key, keysym).c_str(),
|
||||
COL_PAD_NUM, show_pad,
|
||||
COL_VALUE, key,
|
||||
-1);
|
||||
}
|
||||
COL_KEYSYM, keysym,
|
||||
-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void create_a_column(const char *name, int num, bool visible)
|
||||
{
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeViewColumn *col;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
GtkCellRenderer *renderer;
|
||||
GtkTreeViewColumn *col;
|
||||
|
||||
col = gtk_tree_view_column_new();
|
||||
gtk_tree_view_column_set_title(col, name);
|
||||
col = gtk_tree_view_column_new();
|
||||
gtk_tree_view_column_set_title(col, name);
|
||||
|
||||
/* pack tree view column into tree view */
|
||||
gtk_tree_view_append_column(view, col);
|
||||
/* pack tree view column into tree view */
|
||||
gtk_tree_view_append_column(view[i], col);
|
||||
|
||||
renderer = gtk_cell_renderer_text_new();
|
||||
renderer = gtk_cell_renderer_text_new();
|
||||
|
||||
/* pack cell renderer into tree view column */
|
||||
gtk_tree_view_column_pack_start(col, renderer, TRUE);
|
||||
/* pack cell renderer into tree view column */
|
||||
gtk_tree_view_column_pack_start(col, renderer, TRUE);
|
||||
|
||||
/* connect 'text' property of the cell renderer to
|
||||
* model column that contains the first name */
|
||||
gtk_tree_view_column_add_attribute(col, renderer, "text", num);
|
||||
gtk_tree_view_column_set_visible(col, visible);
|
||||
/* connect 'text' property of the cell renderer to
|
||||
* model column that contains the first name */
|
||||
gtk_tree_view_column_add_attribute(col, renderer, "text", num);
|
||||
gtk_tree_view_column_set_visible(col, visible);
|
||||
}
|
||||
}
|
||||
|
||||
void create_columns()
|
||||
|
@ -127,125 +147,126 @@ class keys_tree
|
|||
create_a_column("Key Value", COL_KEY, true);
|
||||
create_a_column("Pad Num", COL_PAD_NUM, false);
|
||||
create_a_column("Internal", COL_VALUE, false);
|
||||
create_a_column("Keysym", COL_KEYSYM, false);
|
||||
has_columns = true;
|
||||
}
|
||||
}
|
||||
public:
|
||||
GtkWidget *view_widget()
|
||||
GtkWidget *view_widget(int i)
|
||||
{
|
||||
return GTK_WIDGET(view);
|
||||
return GTK_WIDGET(view[i]);
|
||||
}
|
||||
|
||||
|
||||
void init()
|
||||
{
|
||||
show_pad = 0;
|
||||
has_columns = false;
|
||||
view = GTK_TREE_VIEW(gtk_tree_view_new());
|
||||
for (int i = 0; i < 2; i++)
|
||||
show_keyboard_key[i] = show_joy_key[i] = true;
|
||||
|
||||
treestore = gtk_tree_store_new(NUM_COLS,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_UINT,
|
||||
G_TYPE_UINT);
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_STRING,
|
||||
G_TYPE_UINT,
|
||||
G_TYPE_UINT,
|
||||
G_TYPE_UINT);
|
||||
|
||||
model = GTK_TREE_MODEL(treestore);
|
||||
gtk_tree_view_set_model(view, model);
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
view[i] = GTK_TREE_VIEW(gtk_tree_view_new());
|
||||
gtk_tree_view_set_model(view[i], model);
|
||||
gtk_tree_selection_set_mode(gtk_tree_view_get_selection(view[i]), GTK_SELECTION_SINGLE);
|
||||
}
|
||||
g_object_unref(model); /* destroy model automatically with view */
|
||||
gtk_tree_selection_set_mode(gtk_tree_view_get_selection(view), GTK_SELECTION_SINGLE);
|
||||
}
|
||||
|
||||
|
||||
void set_show_pad(int pad) { show_pad = pad; }
|
||||
|
||||
void set_show_joy(bool flag) { show_joy_key[show_pad] = flag; }
|
||||
|
||||
void set_show_key(bool flag) { show_keyboard_key[show_pad] = flag; }
|
||||
|
||||
void update()
|
||||
{
|
||||
create_columns();
|
||||
repopulate();
|
||||
}
|
||||
|
||||
|
||||
void clear_all()
|
||||
{
|
||||
clearPAD();
|
||||
clearPAD(show_pad);
|
||||
update();
|
||||
}
|
||||
|
||||
bool get_selected(int &pad, int &key)
|
||||
|
||||
bool get_selected(int &pad, int &key, int &keysym)
|
||||
{
|
||||
GtkTreeSelection *selection;
|
||||
GtkTreeIter iter;
|
||||
|
||||
selection = gtk_tree_view_get_selection(view);
|
||||
selection = gtk_tree_view_get_selection(view[show_pad&1]);
|
||||
if (gtk_tree_selection_get_selected(selection, &model, &iter))
|
||||
{
|
||||
gtk_tree_model_get(model, &iter, COL_PAD_NUM, &pad, COL_VALUE, &key,-1);
|
||||
gtk_tree_model_get(model, &iter, COL_PAD_NUM, &pad, COL_VALUE, &key, COL_KEYSYM, &keysym,-1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void remove_selected()
|
||||
{
|
||||
int key, pad;
|
||||
if (get_selected(pad, key))
|
||||
int key, pad, keysym;
|
||||
if (get_selected(pad, key, keysym))
|
||||
{
|
||||
set_key(pad, key, 0);
|
||||
if (keysym)
|
||||
conf->keysym_map[pad].erase(keysym);
|
||||
else
|
||||
set_key(pad, key, 0);
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void modify_selected()
|
||||
{
|
||||
int key, pad;
|
||||
if (get_selected(pad, key))
|
||||
int key, pad, keysym;
|
||||
if (get_selected(pad, key, keysym))
|
||||
{
|
||||
remove_selected();
|
||||
config_key(pad,key);
|
||||
update();
|
||||
}
|
||||
}
|
||||
};
|
||||
keys_tree *fir;
|
||||
|
||||
int _GetJoystickId()
|
||||
{
|
||||
// select the right joystick id
|
||||
u32 joyid = -1;
|
||||
|
||||
if (!JoystickIdWithinBounds(joyid))
|
||||
{
|
||||
// get first unused joystick
|
||||
for (joyid = 0; joyid < s_vjoysticks.size(); ++joyid)
|
||||
{
|
||||
if (s_vjoysticks[joyid]->GetPAD() < 0) break;
|
||||
}
|
||||
}
|
||||
|
||||
return joyid;
|
||||
}
|
||||
|
||||
int Get_Current_Joystick()
|
||||
{
|
||||
// check bounds
|
||||
int joyid = _GetJoystickId();
|
||||
|
||||
if (JoystickIdWithinBounds(joyid))
|
||||
return joyid + 1; // select the combo
|
||||
else
|
||||
return 0; //s_vjoysticks.size(); // no gamepad
|
||||
}
|
||||
keys_tree *key_tree_manager;
|
||||
|
||||
void populate_new_joysticks(GtkComboBox *box)
|
||||
{
|
||||
char str[255];
|
||||
JoystickInfo::EnumerateJoysticks(s_vjoysticks);
|
||||
|
||||
gtk_combo_box_append_text(box, "No Gamepad");
|
||||
gtk_combo_box_append_text(box, "Keyboard/mouse only");
|
||||
|
||||
vector<JoystickInfo*>::iterator it = s_vjoysticks.begin();
|
||||
|
||||
// Delete everything in the vector vjoysticks.
|
||||
// Get everything in the vector vjoysticks.
|
||||
while (it != s_vjoysticks.end())
|
||||
{
|
||||
sprintf(str, "%d: %s - but: %d, axes: %d, hats: %d", (*it)->GetId(), (*it)->GetName().c_str(),
|
||||
sprintf(str, "Keyboard/mouse and %s - but: %d, axes: %d, hats: %d", (*it)->GetName().c_str(),
|
||||
(*it)->GetNumButtons(), (*it)->GetNumAxes(), (*it)->GetNumHats());
|
||||
gtk_combo_box_append_text(box, str);
|
||||
it++;
|
||||
}
|
||||
current_joystick = Get_Current_Joystick();
|
||||
}
|
||||
|
||||
void set_current_joy()
|
||||
{
|
||||
u32 joyid = conf->get_joyid(current_pad);
|
||||
if (JoystickIdWithinBounds(joyid))
|
||||
// 0 is special case for no gamepad. So you must increase of 1.
|
||||
gtk_combo_box_set_active(joy_choose_cbox, joyid+1);
|
||||
else
|
||||
gtk_combo_box_set_active(joy_choose_cbox, 0);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
|
@ -255,16 +276,33 @@ typedef struct
|
|||
void put(const char* lbl, int i, GtkFixed *fix, int x, int y)
|
||||
{
|
||||
widget = gtk_button_new_with_label(lbl);
|
||||
index = i;
|
||||
|
||||
gtk_fixed_put(fix, widget, x, y);
|
||||
gtk_widget_set_size_request(widget, 64, 24);
|
||||
index = i;
|
||||
g_signal_connect(GTK_OBJECT (widget), "clicked", G_CALLBACK(on_conf_key), this);
|
||||
}
|
||||
} dialog_buttons;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkWidget *widget;
|
||||
unsigned int mask;
|
||||
void create(GtkWidget* area, const char* label, u32 x, u32 y, u32 mask_value)
|
||||
{
|
||||
widget = gtk_check_button_new_with_label(label);
|
||||
mask = mask_value;
|
||||
|
||||
gtk_fixed_put(GTK_FIXED(area), widget, x, y);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), mask & conf->options);
|
||||
g_signal_connect(GTK_OBJECT (widget), "toggled", G_CALLBACK(on_toggle_option), this);
|
||||
}
|
||||
} dialog_checkbox;
|
||||
|
||||
void config_key(int pad, int key)
|
||||
{
|
||||
bool captured = false;
|
||||
u32 key_pressed = 0;
|
||||
|
||||
// save the joystick states
|
||||
UpdateJoysticks();
|
||||
|
@ -272,13 +310,14 @@ void config_key(int pad, int key)
|
|||
while (!captured)
|
||||
{
|
||||
vector<JoystickInfo*>::iterator itjoy;
|
||||
char *tmp;
|
||||
|
||||
u32 pkey = get_key(pad, key);
|
||||
if (PollX11Keyboard(tmp, pkey))
|
||||
if (PollX11KeyboardMouseEvent(key_pressed))
|
||||
{
|
||||
set_key(pad, key, pkey);
|
||||
PAD_LOG("%s\n", KeyName(pad, key).c_str());
|
||||
// special case for keyboard/mouse to handle multiple keys
|
||||
// Note: key_pressed == 0 when ESC is hit to abort the capture
|
||||
if (key_pressed > 0)
|
||||
set_keyboad_key(pad, key_pressed, key);
|
||||
|
||||
captured = true;
|
||||
break;
|
||||
}
|
||||
|
@ -288,53 +327,28 @@ void config_key(int pad, int key)
|
|||
itjoy = s_vjoysticks.begin();
|
||||
while ((itjoy != s_vjoysticks.end()) && (!captured))
|
||||
{
|
||||
int button_id, direction;
|
||||
|
||||
pkey = get_key(pad, key);
|
||||
if ((*itjoy)->PollButtons(button_id, pkey))
|
||||
{
|
||||
set_key(pad, key, pkey);
|
||||
PAD_LOG("%s\n", KeyName(pad, key).c_str());
|
||||
if ((*itjoy)->PollButtons(key_pressed)) {
|
||||
set_key(pad, key, key_pressed);
|
||||
captured = true;
|
||||
break;
|
||||
}
|
||||
|
||||
bool sign = false;
|
||||
bool pov = (!((key == PAD_RY) || (key == PAD_LY) || (key == PAD_RX) || (key == PAD_LX)));
|
||||
|
||||
int axis_id;
|
||||
|
||||
if (pov)
|
||||
{
|
||||
if ((*itjoy)->PollPOV(axis_id, sign, pkey))
|
||||
{
|
||||
set_key(pad, key, pkey);
|
||||
PAD_LOG("%s\n", KeyName(pad, key).c_str());
|
||||
captured = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((*itjoy)->PollAxes(axis_id, pkey))
|
||||
{
|
||||
set_key(pad, key, pkey);
|
||||
PAD_LOG("%s\n", KeyName(pad, key).c_str());
|
||||
captured = true;
|
||||
break;
|
||||
}
|
||||
if ((*itjoy)->PollAxes(key_pressed)) {
|
||||
set_key(pad, key, key_pressed);
|
||||
captured = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((*itjoy)->PollHats(axis_id, direction, pkey))
|
||||
{
|
||||
set_key(pad, key, pkey);
|
||||
PAD_LOG("%s\n", KeyName(pad, key).c_str());
|
||||
if ((*itjoy)->PollHats(key_pressed)) {
|
||||
set_key(pad, key, key_pressed);
|
||||
captured = true;
|
||||
break;
|
||||
}
|
||||
itjoy++;
|
||||
}
|
||||
}
|
||||
|
||||
PAD_LOG("%s\n", KeyName(pad, key).c_str());
|
||||
}
|
||||
|
||||
void on_conf_key(GtkButton *button, gpointer user_data)
|
||||
|
@ -345,93 +359,74 @@ void on_conf_key(GtkButton *button, gpointer user_data)
|
|||
if (key == -1) return;
|
||||
|
||||
config_key(current_pad, key);
|
||||
fir->update();
|
||||
key_tree_manager->update();
|
||||
}
|
||||
|
||||
void on_remove_clicked(GtkButton *button, gpointer user_data)
|
||||
{
|
||||
fir->remove_selected();
|
||||
key_tree_manager->remove_selected();
|
||||
}
|
||||
|
||||
void on_clear_clicked(GtkButton *button, gpointer user_data)
|
||||
{
|
||||
fir->clear_all();
|
||||
key_tree_manager->clear_all();
|
||||
}
|
||||
|
||||
void on_modify_clicked(GtkButton *button, gpointer user_data)
|
||||
{
|
||||
fir->modify_selected();
|
||||
key_tree_manager->modify_selected();
|
||||
}
|
||||
|
||||
void on_view_joy_clicked(GtkToggleButton *togglebutton, gpointer user_data)
|
||||
{
|
||||
key_tree_manager->set_show_joy(gtk_toggle_button_get_active(togglebutton));
|
||||
key_tree_manager->update();
|
||||
}
|
||||
|
||||
void on_view_key_clicked(GtkToggleButton *togglebutton, gpointer user_data)
|
||||
{
|
||||
key_tree_manager->set_show_key(gtk_toggle_button_get_active(togglebutton));
|
||||
key_tree_manager->update();
|
||||
}
|
||||
|
||||
void on_toggle_option(GtkToggleButton *togglebutton, gpointer user_data)
|
||||
{
|
||||
dialog_checkbox *checkbox = (dialog_checkbox*)user_data;
|
||||
|
||||
if (gtk_toggle_button_get_active(togglebutton))
|
||||
conf->options |= checkbox->mask;
|
||||
else
|
||||
conf->options &= ~checkbox->mask;
|
||||
}
|
||||
|
||||
|
||||
void joy_changed(GtkComboBox *box, gpointer user_data)
|
||||
{
|
||||
int joyid = gtk_combo_box_get_active(box);
|
||||
// Note position 0 of the combo box is no gamepad
|
||||
joyid--;
|
||||
|
||||
// FIXME: might be a good idea to ask the user first ;)
|
||||
// FIXME: do you need to clean the previous key association. or what the user want
|
||||
// 1 : keep previous joy
|
||||
// 2 : use new joy with old key binding
|
||||
// 3 : use new joy with fresh key binding
|
||||
|
||||
// unassign every joystick with this pad
|
||||
for (int i = 0; i < (int)s_vjoysticks.size(); ++i)
|
||||
{
|
||||
if (s_vjoysticks[i]->GetPAD() == current_pad) s_vjoysticks[i]->Assign(-1);
|
||||
}
|
||||
for (int i = 0; i < 2; ++i)
|
||||
if (joyid == conf->get_joyid(i)) conf->set_joyid(i, -1);
|
||||
|
||||
if (joyid >= 0 && joyid < (int)s_vjoysticks.size()) s_vjoysticks[joyid]->Assign(current_pad);
|
||||
conf->set_joyid(current_pad, joyid);
|
||||
}
|
||||
|
||||
void pad_changed(GtkComboBox *box, gpointer user_data)
|
||||
void pad_changed(GtkNotebook *notebook, GtkNotebookPage *notebook_page, int page, void *data)
|
||||
{
|
||||
int temp = gtk_combo_box_get_active(box);
|
||||
if (temp >= 0) current_pad = temp;
|
||||
fir->update();
|
||||
int options = (conf.options >> (16 * current_pad));
|
||||
current_pad = page;
|
||||
key_tree_manager->set_show_pad(current_pad&1);
|
||||
key_tree_manager->update();
|
||||
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rev_lx_check), (options & PADOPTION_REVERSELX));
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rev_ly_check), (options & PADOPTION_REVERSELY));
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rev_rx_check), (options & PADOPTION_REVERSERX));
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rev_ry_check), (options & PADOPTION_REVERSERY));
|
||||
}
|
||||
|
||||
void update_option(int option, bool value)
|
||||
{
|
||||
int mask = (option << (16 * current_pad));
|
||||
|
||||
if (value)
|
||||
conf.options |= mask;
|
||||
else
|
||||
conf.options &= ~mask;
|
||||
}
|
||||
|
||||
void on_refresh(GtkComboBox *box, gpointer user_data)
|
||||
{
|
||||
GtkComboBox *joy_choose_cbox = (GtkComboBox*)user_data;
|
||||
|
||||
if (current_joystick < 0) current_joystick = Get_Current_Joystick();
|
||||
|
||||
for(int i=0; i <= (int)s_vjoysticks.size(); i++)
|
||||
{
|
||||
gtk_combo_box_remove_text(joy_choose_cbox, 0);
|
||||
}
|
||||
populate_new_joysticks(joy_choose_cbox);
|
||||
if (gtk_combo_box_get_active(joy_choose_cbox) != current_joystick)
|
||||
gtk_combo_box_set_active(joy_choose_cbox, current_joystick);
|
||||
}
|
||||
|
||||
void on_rev_lx(GtkComboBox *box, gpointer user_data)
|
||||
{
|
||||
update_option(PADOPTION_REVERSELX, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rev_lx_check)));
|
||||
}
|
||||
|
||||
void on_rev_ly(GtkComboBox *box, gpointer user_data)
|
||||
{
|
||||
update_option(PADOPTION_REVERSELY, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rev_ly_check)));
|
||||
}
|
||||
|
||||
void on_rev_rx(GtkComboBox *box, gpointer user_data)
|
||||
{
|
||||
update_option(PADOPTION_REVERSERX, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rev_rx_check)));
|
||||
}
|
||||
|
||||
void on_rev_ry(GtkComboBox *box, gpointer user_data)
|
||||
{
|
||||
update_option(PADOPTION_REVERSERY, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rev_ry_check)));
|
||||
// update joy
|
||||
set_current_joy();
|
||||
}
|
||||
|
||||
//void on_forcefeedback_toggled(GtkToggleButton *togglebutton, gpointer user_data)
|
||||
|
@ -440,106 +435,125 @@ void on_rev_ry(GtkComboBox *box, gpointer user_data)
|
|||
//
|
||||
// if (gtk_toggle_button_get_active(togglebutton))
|
||||
// {
|
||||
// conf.options |= mask;
|
||||
// conf->options |= mask;
|
||||
//
|
||||
// int joyid = gtk_combo_box_get_active(GTK_COMBO_BOX(s_devicecombo));
|
||||
//
|
||||
// if (joyid >= 0 && joyid < (int)s_vjoysticks.size()) s_vjoysticks[joyid]->TestForce();
|
||||
// u32 joyid = conf->get_joyid(current_pad);
|
||||
// if (JoystickIdWithinBounds(joyid)) s_vjoysticks[joyid]->TestForce();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// conf.options &= ~mask;
|
||||
// conf->options &= ~mask;
|
||||
// }
|
||||
//}
|
||||
|
||||
void DisplayDialog()
|
||||
struct button_positions
|
||||
{
|
||||
int return_value;
|
||||
const char* label;
|
||||
u32 x,y;
|
||||
};
|
||||
|
||||
GtkWidget *dialog;
|
||||
GtkWidget *main_frame, *main_box;
|
||||
// Warning position is important and must match the order of the gamePadValues structure
|
||||
button_positions b_pos[MAX_KEYS] =
|
||||
{
|
||||
{ "L2", 64, 8},
|
||||
{ "R2", 392, 8},
|
||||
{ "L1", 64, 32},
|
||||
{ "R1", 392, 32},
|
||||
|
||||
{ "Triangle", 392, 80},
|
||||
{ "Circle", 456, 104},
|
||||
{ "Cross", 392, 128},
|
||||
{ "Square", 328, 104},
|
||||
|
||||
{ "Select", 200, 48},
|
||||
{ "L3", 64, 224},
|
||||
{ "R3", 392, 224},
|
||||
{ "Start", 272, 48},
|
||||
|
||||
// Arrow pad
|
||||
{ "Up", 64, 80},
|
||||
{ "Right", 128, 104},
|
||||
{ "Down", 64, 128},
|
||||
{ "Left", 0, 104},
|
||||
|
||||
// Left Analog joystick
|
||||
{ "Up", 64, 200},
|
||||
{ "Right", 128, 224},
|
||||
{ "Down", 64, 248},
|
||||
{ "Left", 0, 224},
|
||||
|
||||
// Right Analog joystick
|
||||
{ "Up", 392, 200},
|
||||
{ "Right", 456, 224},
|
||||
{ "Down", 392, 248},
|
||||
{ "Left", 328, 224}
|
||||
};
|
||||
|
||||
GtkWidget *pad_choose_frame, *pad_choose_box;
|
||||
GtkComboBox *pad_choose_cbox;
|
||||
|
||||
// Warning position is important and must match the order of the PadOptions structure
|
||||
button_positions check_pos[7] =
|
||||
{
|
||||
{ "Enable force feedback", 40, 400},
|
||||
{ "Reverse Lx", 40, 304},
|
||||
{ "Reverse Ly", 40, 328},
|
||||
{ "Reverse Rx", 368, 304},
|
||||
{ "Reverse Ry", 368, 328},
|
||||
{ "Use mouse for left analog joy", 40, 352},
|
||||
{ "Use mouse for right analog joy", 368,352},
|
||||
};
|
||||
|
||||
GtkWidget *create_notebook_page_dialog(int page, dialog_buttons btn[MAX_KEYS], dialog_checkbox checkbox[7])
|
||||
{
|
||||
GtkWidget *main_box;
|
||||
GtkWidget *joy_choose_frame, *joy_choose_box;
|
||||
GtkComboBox *joy_choose_cbox;
|
||||
//GtkWidget *joy_refresh;
|
||||
|
||||
GtkWidget *keys_frame, *keys_box;
|
||||
|
||||
GtkWidget *keys_tree_frame, *keys_tree_box;
|
||||
GtkWidget *keys_tree_clear_btn, *keys_tree_remove_btn, *keys_tree_modify_btn;
|
||||
GtkWidget *keys_btn_box, *keys_btn_frame;
|
||||
GtkWidget *keys_tree_box, *keys_tree_scroll;
|
||||
GtkWidget *keys_tree_clear_btn, *keys_tree_remove_btn, *keys_tree_modify_btn, *keys_tree_show_key_btn, *keys_tree_show_joy_btn;
|
||||
GtkWidget *keys_btn_box, *keys_filter_box;
|
||||
|
||||
GtkWidget *keys_static_frame, *keys_static_box;
|
||||
GtkWidget *keys_static_area;
|
||||
dialog_buttons btn[29];
|
||||
|
||||
LoadConfig();
|
||||
fir = new keys_tree;
|
||||
fir->init();
|
||||
|
||||
/* Create the widgets */
|
||||
dialog = gtk_dialog_new_with_buttons (
|
||||
"OnePAD Config",
|
||||
NULL, /* parent window*/
|
||||
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
|
||||
GTK_STOCK_OK,
|
||||
GTK_RESPONSE_ACCEPT,
|
||||
GTK_STOCK_CANCEL,
|
||||
GTK_RESPONSE_REJECT,
|
||||
NULL);
|
||||
|
||||
pad_choose_cbox = GTK_COMBO_BOX(gtk_combo_box_new_text());
|
||||
gtk_combo_box_append_text(pad_choose_cbox, "Pad 1");
|
||||
gtk_combo_box_append_text(pad_choose_cbox, "Pad 2");
|
||||
gtk_combo_box_append_text(pad_choose_cbox, "Pad 1 (alt)");
|
||||
gtk_combo_box_append_text(pad_choose_cbox, "Pad 2 (alt)");
|
||||
gtk_combo_box_set_active(pad_choose_cbox, current_pad);
|
||||
g_signal_connect(GTK_OBJECT (pad_choose_cbox), "changed", G_CALLBACK(pad_changed), NULL);
|
||||
|
||||
if (current_joystick == -1) current_joystick = Get_Current_Joystick();
|
||||
joy_choose_cbox = GTK_COMBO_BOX(gtk_combo_box_new_text());
|
||||
populate_new_joysticks(joy_choose_cbox);
|
||||
gtk_combo_box_set_active(joy_choose_cbox, current_joystick);
|
||||
set_current_joy();
|
||||
g_signal_connect(GTK_OBJECT (joy_choose_cbox), "changed", G_CALLBACK(joy_changed), NULL);
|
||||
|
||||
//joy_refresh = gtk_button_new_with_label("Refresh");
|
||||
//g_signal_connect(GTK_OBJECT (joy_refresh), "clicked", G_CALLBACK(on_refresh), joy_choose_cbox);
|
||||
//gtk_widget_set_size_request(joy_refresh, 64, 24);
|
||||
|
||||
|
||||
keys_tree_scroll = gtk_scrolled_window_new(NULL, NULL);
|
||||
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(keys_tree_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||
gtk_container_add (GTK_CONTAINER(keys_tree_scroll), key_tree_manager->view_widget(page));
|
||||
gtk_widget_set_size_request(keys_tree_scroll, 300, 600);
|
||||
|
||||
keys_tree_clear_btn = gtk_button_new_with_label("Clear All");
|
||||
g_signal_connect(GTK_OBJECT (keys_tree_clear_btn), "clicked", G_CALLBACK(on_clear_clicked), NULL);
|
||||
gtk_widget_set_size_request(keys_tree_clear_btn, 64, 24);
|
||||
gtk_widget_set_size_request(keys_tree_clear_btn, 70, 24);
|
||||
|
||||
keys_tree_remove_btn = gtk_button_new_with_label("Remove");
|
||||
g_signal_connect(GTK_OBJECT (keys_tree_remove_btn), "clicked", G_CALLBACK(on_remove_clicked), NULL);
|
||||
gtk_widget_set_size_request(keys_tree_remove_btn, 64, 24);
|
||||
gtk_widget_set_size_request(keys_tree_remove_btn, 70, 24);
|
||||
|
||||
keys_tree_modify_btn = gtk_button_new_with_label("Modify");
|
||||
g_signal_connect(GTK_OBJECT (keys_tree_modify_btn), "clicked", G_CALLBACK(on_modify_clicked), NULL);
|
||||
gtk_widget_set_size_request(keys_tree_modify_btn, 64, 24);
|
||||
|
||||
main_box = gtk_vbox_new(false, 5);
|
||||
main_frame = gtk_frame_new ("Onepad Config");
|
||||
gtk_container_add (GTK_CONTAINER(main_frame), main_box);
|
||||
gtk_widget_set_size_request(keys_tree_modify_btn, 70, 24);
|
||||
|
||||
pad_choose_box = gtk_vbox_new(false, 5);
|
||||
pad_choose_frame = gtk_frame_new ("Choose a Pad to modify:");
|
||||
gtk_container_add (GTK_CONTAINER(pad_choose_frame), pad_choose_box);
|
||||
keys_tree_show_joy_btn = gtk_check_button_new_with_label("Show joy");
|
||||
g_signal_connect(GTK_OBJECT (keys_tree_show_joy_btn), "toggled", G_CALLBACK(on_view_joy_clicked), NULL);
|
||||
gtk_widget_set_size_request(keys_tree_show_joy_btn, 100, 24);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(keys_tree_show_joy_btn), true);
|
||||
|
||||
keys_tree_show_key_btn = gtk_check_button_new_with_label("Show key");
|
||||
g_signal_connect(GTK_OBJECT (keys_tree_show_key_btn), "toggled", G_CALLBACK(on_view_key_clicked), NULL);
|
||||
gtk_widget_set_size_request(keys_tree_show_key_btn, 100, 24);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(keys_tree_show_key_btn), true);
|
||||
|
||||
joy_choose_box = gtk_hbox_new(false, 5);
|
||||
joy_choose_frame = gtk_frame_new ("Joystick to use for this pad");
|
||||
gtk_container_add (GTK_CONTAINER(joy_choose_frame), joy_choose_box);
|
||||
|
||||
keys_btn_box = gtk_hbox_new(false, 5);
|
||||
keys_btn_frame = gtk_frame_new ("");
|
||||
gtk_container_add (GTK_CONTAINER(keys_btn_frame), keys_btn_box);
|
||||
|
||||
keys_filter_box = gtk_hbox_new(false, 5);
|
||||
keys_tree_box = gtk_vbox_new(false, 5);
|
||||
keys_tree_frame = gtk_frame_new ("");
|
||||
gtk_container_add (GTK_CONTAINER(keys_tree_frame), keys_tree_box);
|
||||
|
||||
keys_static_box = gtk_hbox_new(false, 5);
|
||||
keys_static_frame = gtk_frame_new ("");
|
||||
|
@ -547,98 +561,96 @@ void DisplayDialog()
|
|||
|
||||
keys_static_area = gtk_fixed_new();
|
||||
|
||||
u32 static_offset = 0; //320
|
||||
btn[0].put("L2", 0, GTK_FIXED(keys_static_area), static_offset + 64, 8);
|
||||
btn[1].put("R2", 1, GTK_FIXED(keys_static_area), static_offset + 392, 8);
|
||||
btn[2].put("L1", 2, GTK_FIXED(keys_static_area), static_offset + 64, 32);
|
||||
btn[3].put("R1", 3, GTK_FIXED(keys_static_area), static_offset + 392, 32);
|
||||
|
||||
btn[4].put("Triangle", 4, GTK_FIXED(keys_static_area), static_offset + 392, 80);
|
||||
btn[5].put("Circle", 5, GTK_FIXED(keys_static_area), static_offset + 456, 104);
|
||||
btn[6].put("Cross", 6, GTK_FIXED(keys_static_area), static_offset + 392,128);
|
||||
btn[7].put("Square", 7, GTK_FIXED(keys_static_area), static_offset + 328, 104);
|
||||
|
||||
btn[8].put("Select", 8, GTK_FIXED(keys_static_area), static_offset + 200, 48);
|
||||
btn[9].put("L3", 9, GTK_FIXED(keys_static_area), static_offset + 200, 8);
|
||||
btn[10].put("R3", 10, GTK_FIXED(keys_static_area), static_offset + 272, 8);
|
||||
btn[11].put("Start", 11, GTK_FIXED(keys_static_area), static_offset + 272, 48);
|
||||
|
||||
// Arrow pad
|
||||
btn[12].put("Up", 12, GTK_FIXED(keys_static_area), static_offset + 64, 80);
|
||||
btn[13].put("Right", 13, GTK_FIXED(keys_static_area), static_offset + 128, 104);
|
||||
btn[14].put("Down", 14, GTK_FIXED(keys_static_area), static_offset + 64, 128);
|
||||
btn[15].put("Left", 15, GTK_FIXED(keys_static_area), static_offset + 0, 104);
|
||||
|
||||
//btn[xx].put("Analog", GTK_FIXED(keys_static_area), static_offset + 232, 104);
|
||||
|
||||
btn[16].put("Lx", 16, GTK_FIXED(keys_static_area), static_offset + 64, 264);
|
||||
btn[17].put("Rx", 17, GTK_FIXED(keys_static_area), static_offset + 392, 264);
|
||||
btn[18].put("Ly", 18, GTK_FIXED(keys_static_area), static_offset + 64, 288);
|
||||
btn[19].put("Ry", 19, GTK_FIXED(keys_static_area), static_offset + 392, 288);
|
||||
|
||||
// Left Joystick
|
||||
btn[20].put("Up", 20, GTK_FIXED(keys_static_area), static_offset + 64, 240);
|
||||
btn[21].put("Right", 21, GTK_FIXED(keys_static_area), static_offset + 128, 272);
|
||||
btn[22].put("Down", 22, GTK_FIXED(keys_static_area), static_offset + 64, 312);
|
||||
btn[23].put("Left", 23, GTK_FIXED(keys_static_area), static_offset + 0, 272);
|
||||
|
||||
// Right Joystick
|
||||
btn[24].put("Up", 24, GTK_FIXED(keys_static_area), static_offset + 392, 240);
|
||||
btn[25].put("Right", 25, GTK_FIXED(keys_static_area), static_offset + 456, 272);
|
||||
btn[26].put("Down", 26, GTK_FIXED(keys_static_area), static_offset + 392, 312);
|
||||
btn[27].put("Left", 27, GTK_FIXED(keys_static_area), static_offset + 328, 272);
|
||||
|
||||
int options = (conf.options >> (16 * current_pad));
|
||||
rev_lx_check = gtk_check_button_new_with_label("Reverse Lx");
|
||||
gtk_fixed_put(GTK_FIXED(keys_static_area), rev_lx_check, static_offset + 40, 344);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rev_lx_check), (options & PADOPTION_REVERSELX));
|
||||
g_signal_connect(GTK_OBJECT (rev_lx_check), "toggled", G_CALLBACK(on_rev_lx), NULL);
|
||||
|
||||
rev_ly_check = gtk_check_button_new_with_label("Reverse Ly");
|
||||
gtk_fixed_put(GTK_FIXED(keys_static_area), rev_ly_check, static_offset + 40, 368);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rev_ly_check), (options & PADOPTION_REVERSELY));
|
||||
g_signal_connect(GTK_OBJECT (rev_ly_check), "toggled", G_CALLBACK(on_rev_ly), NULL);
|
||||
|
||||
rev_rx_check = gtk_check_button_new_with_label("Reverse Rx");
|
||||
gtk_fixed_put(GTK_FIXED(keys_static_area), rev_rx_check, static_offset + 368, 344);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rev_rx_check), (options & PADOPTION_REVERSERX));
|
||||
g_signal_connect(GTK_OBJECT (rev_rx_check), "toggled", G_CALLBACK(on_rev_rx), NULL);
|
||||
|
||||
rev_ry_check = gtk_check_button_new_with_label("Reverse Ry");
|
||||
gtk_fixed_put(GTK_FIXED(keys_static_area), rev_ry_check, static_offset + 368, 368);
|
||||
gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(rev_ry_check), (options & PADOPTION_REVERSERY));
|
||||
g_signal_connect(GTK_OBJECT (rev_ry_check), "toggled", G_CALLBACK(on_rev_ry), NULL);
|
||||
for(int i = 0; i < MAX_KEYS; i++)
|
||||
{
|
||||
btn[i].put(b_pos[i].label, i, GTK_FIXED(keys_static_area), b_pos[i].x, b_pos[i].y);
|
||||
}
|
||||
|
||||
u32 mask = 1 << (16*page);
|
||||
for(int i = 0; i < 7; i++) {
|
||||
checkbox[i].create(keys_static_area, check_pos[i].label, check_pos[i].x, check_pos[i].y, mask);
|
||||
mask = mask << 1;
|
||||
}
|
||||
|
||||
keys_box = gtk_hbox_new(false, 5);
|
||||
keys_frame = gtk_frame_new ("Key Settings");
|
||||
gtk_container_add (GTK_CONTAINER(keys_frame), keys_box);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (keys_tree_box), fir->view_widget(), true, true, 0);
|
||||
gtk_box_pack_end (GTK_BOX (keys_btn_box), keys_tree_clear_btn, false, false, 0);
|
||||
gtk_box_pack_end (GTK_BOX (keys_btn_box), keys_tree_remove_btn, false, false, 0);
|
||||
gtk_box_pack_end (GTK_BOX (keys_btn_box), keys_tree_modify_btn, false, false, 0);
|
||||
gtk_box_pack_start (GTK_BOX (keys_tree_box), keys_tree_scroll, true, true, 0);
|
||||
gtk_box_pack_start (GTK_BOX (keys_tree_box), keys_btn_box, false, false, 0);
|
||||
gtk_box_pack_start (GTK_BOX (keys_tree_box), keys_filter_box, false, false, 0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (keys_filter_box), keys_tree_show_joy_btn, false, false, 0);
|
||||
gtk_box_pack_start (GTK_BOX (keys_filter_box), keys_tree_show_key_btn, false, false, 0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (keys_btn_box), keys_tree_clear_btn, false, false, 0);
|
||||
gtk_box_pack_start (GTK_BOX (keys_btn_box), keys_tree_remove_btn, false, false, 0);
|
||||
gtk_box_pack_start (GTK_BOX (keys_btn_box), keys_tree_modify_btn, false, false, 0);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(pad_choose_box), GTK_WIDGET(pad_choose_cbox));
|
||||
gtk_container_add(GTK_CONTAINER(joy_choose_box), GTK_WIDGET(joy_choose_cbox));
|
||||
//gtk_container_add(GTK_CONTAINER(joy_choose_box), joy_refresh);
|
||||
gtk_container_add(GTK_CONTAINER(keys_tree_box), keys_btn_frame);
|
||||
gtk_box_pack_start (GTK_BOX (keys_box), keys_tree_frame, true, true, 0);
|
||||
gtk_box_pack_start(GTK_BOX (keys_box), keys_tree_box, false, false, 0);
|
||||
gtk_container_add(GTK_CONTAINER(keys_box), keys_static_area);
|
||||
|
||||
gtk_container_add(GTK_CONTAINER(main_box), pad_choose_frame);
|
||||
main_box = gtk_vbox_new(false, 5);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), joy_choose_frame);
|
||||
gtk_container_add(GTK_CONTAINER(main_box), keys_frame);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), main_frame);
|
||||
return main_box;
|
||||
}
|
||||
|
||||
void DisplayDialog()
|
||||
{
|
||||
int return_value;
|
||||
|
||||
GtkWidget *dialog;
|
||||
|
||||
GtkWidget *notebook, *page[2];
|
||||
GtkWidget *page_label[2];
|
||||
|
||||
dialog_buttons btn[2][MAX_KEYS];
|
||||
dialog_checkbox checkbox[2][7];
|
||||
|
||||
LoadConfig();
|
||||
key_tree_manager = new keys_tree;
|
||||
key_tree_manager->init();
|
||||
|
||||
/* Create the widgets */
|
||||
dialog = gtk_dialog_new_with_buttons (
|
||||
"OnePAD Config",
|
||||
NULL, /* parent window*/
|
||||
(GtkDialogFlags)(GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT),
|
||||
GTK_STOCK_OK,
|
||||
GTK_RESPONSE_ACCEPT,
|
||||
GTK_STOCK_APPLY,
|
||||
GTK_RESPONSE_APPLY,
|
||||
GTK_STOCK_CANCEL,
|
||||
GTK_RESPONSE_REJECT,
|
||||
NULL);
|
||||
|
||||
notebook = gtk_notebook_new();
|
||||
|
||||
page_label[0] = gtk_label_new("Pad 1");
|
||||
page_label[1] = gtk_label_new("Pad 2");
|
||||
for (int i = 0; i < 2; i++) {
|
||||
page[i] = create_notebook_page_dialog(i, btn[i], checkbox[i]);
|
||||
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page[i], page_label[i]);
|
||||
}
|
||||
g_signal_connect(GTK_OBJECT (notebook), "switch-page", G_CALLBACK(pad_changed), NULL);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), notebook);
|
||||
|
||||
fir->update();
|
||||
key_tree_manager->update();
|
||||
|
||||
gtk_widget_show_all (dialog);
|
||||
|
||||
return_value = gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
if (return_value == GTK_RESPONSE_ACCEPT) SaveConfig();
|
||||
|
||||
do {
|
||||
return_value = gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
if (return_value == GTK_RESPONSE_APPLY || return_value == GTK_RESPONSE_ACCEPT) {
|
||||
SaveConfig();
|
||||
}
|
||||
} while (return_value == GTK_RESPONSE_APPLY);
|
||||
|
||||
LoadConfig();
|
||||
delete fir;
|
||||
delete key_tree_manager;
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
|
|
@ -23,93 +23,97 @@
|
|||
#include <gtk/gtk.h>
|
||||
|
||||
#include "joystick.h"
|
||||
#include "keyboard.h"
|
||||
#include "onepad.h"
|
||||
#include "linux.h"
|
||||
|
||||
extern char* KeysymToChar(int keysym);
|
||||
extern std::string s_strIniPath;
|
||||
|
||||
string KeyName(int pad, int key)
|
||||
string KeyName(int pad, int key, int keysym)
|
||||
{
|
||||
string tmp;
|
||||
KeyType k = type_of_key(pad, key);
|
||||
tmp.resize(28);
|
||||
|
||||
switch (k)
|
||||
if (keysym) {
|
||||
if (keysym < 10) {
|
||||
// mouse
|
||||
switch (keysym) {
|
||||
case 1: sprintf(&tmp[0], "Mouse Left"); break;
|
||||
case 2: sprintf(&tmp[0], "Mouse Middle"); break;
|
||||
case 3: sprintf(&tmp[0], "Mouse Right"); break;
|
||||
default: // Use only number for extra button
|
||||
sprintf(&tmp[0], "Mouse %d", keysym);
|
||||
}
|
||||
} else {
|
||||
// keyboard
|
||||
char* pstr = XKeysymToString(keysym);
|
||||
if (pstr != NULL) tmp = pstr;
|
||||
}
|
||||
} else {
|
||||
// joystick
|
||||
KeyType k = type_of_joykey(pad, key);
|
||||
switch (k)
|
||||
{
|
||||
case PAD_KEYBOARD:
|
||||
{
|
||||
char* pstr = KeysymToChar(pad_to_key(pad, key));
|
||||
if (pstr != NULL) tmp = pstr;
|
||||
break;
|
||||
}
|
||||
case PAD_JOYBUTTONS:
|
||||
{
|
||||
int button = key_to_button(pad, key);
|
||||
tmp.resize(28);
|
||||
|
||||
sprintf(&tmp[0], "JBut %d", button);
|
||||
break;
|
||||
}
|
||||
case PAD_JOYSTICK:
|
||||
{
|
||||
int axis = key_to_axis(pad, key);
|
||||
tmp.resize(28);
|
||||
|
||||
sprintf(&tmp[0], "JAxis %d", axis);
|
||||
break;
|
||||
}
|
||||
case PAD_HAT:
|
||||
{
|
||||
int axis = key_to_axis(pad, key);
|
||||
tmp.resize(28);
|
||||
|
||||
switch(key_to_hat_dir(pad, key))
|
||||
{
|
||||
case SDL_HAT_UP:
|
||||
sprintf(&tmp[0], "JPOVU-%d", axis);
|
||||
break;
|
||||
|
||||
case SDL_HAT_RIGHT:
|
||||
sprintf(&tmp[0], "JPOVR-%d", axis);
|
||||
break;
|
||||
|
||||
case SDL_HAT_DOWN:
|
||||
sprintf(&tmp[0], "JPOVD-%d", axis);
|
||||
break;
|
||||
|
||||
case SDL_HAT_LEFT:
|
||||
sprintf(&tmp[0], "JPOVL-%d", axis);
|
||||
break;
|
||||
int button = key_to_button(pad, key);
|
||||
sprintf(&tmp[0], "JBut %d", button);
|
||||
break;
|
||||
}
|
||||
case PAD_AXIS:
|
||||
{
|
||||
if (key_to_axis_type(pad,key))
|
||||
sprintf(&tmp[0], "JAxis %d Full", key_to_axis(pad, key), key_to_axis_sign(pad, key) ? "-" : "+");
|
||||
else
|
||||
sprintf(&tmp[0], "JAxis %d Half%s", key_to_axis(pad, key), key_to_axis_sign(pad, key) ? "-" : "+");
|
||||
break;
|
||||
}
|
||||
case PAD_HAT:
|
||||
{
|
||||
int axis = key_to_axis(pad, key);
|
||||
switch(key_to_hat_dir(pad, key))
|
||||
{
|
||||
case SDL_HAT_UP:
|
||||
sprintf(&tmp[0], "JPOVU-%d", axis);
|
||||
break;
|
||||
|
||||
case SDL_HAT_RIGHT:
|
||||
sprintf(&tmp[0], "JPOVR-%d", axis);
|
||||
break;
|
||||
|
||||
case SDL_HAT_DOWN:
|
||||
sprintf(&tmp[0], "JPOVD-%d", axis);
|
||||
break;
|
||||
|
||||
case SDL_HAT_LEFT:
|
||||
sprintf(&tmp[0], "JPOVL-%d", axis);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PAD_POV:
|
||||
{
|
||||
tmp.resize(28);
|
||||
sprintf(&tmp[0], "JPOV %d%s", key_to_axis(pad, key), key_to_pov_sign(pad, key) ? "-" : "+");
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void DefaultValues()
|
||||
void DefaultKeyboardValues()
|
||||
{
|
||||
set_key(0, PAD_L2, XK_a);
|
||||
set_key(0, PAD_R2, XK_semicolon);
|
||||
set_key(0, PAD_L1, XK_w);
|
||||
set_key(0, PAD_R1, XK_p);
|
||||
set_key(0, PAD_TRIANGLE, XK_i);
|
||||
set_key(0, PAD_CIRCLE, XK_l);
|
||||
set_key(0, PAD_CROSS, XK_k);
|
||||
set_key(0, PAD_SQUARE, XK_j);
|
||||
set_key(0, PAD_SELECT, XK_v);
|
||||
set_key(0, PAD_START, XK_n);
|
||||
set_key(0, PAD_UP, XK_e);
|
||||
set_key(0, PAD_RIGHT, XK_f);
|
||||
set_key(0, PAD_DOWN, XK_d);
|
||||
set_key(0, PAD_LEFT, XK_s);
|
||||
set_keyboad_key(0, XK_a, PAD_L2);
|
||||
set_keyboad_key(0, XK_semicolon, PAD_R2);
|
||||
set_keyboad_key(0, XK_w, PAD_L1);
|
||||
set_keyboad_key(0, XK_p, PAD_R1);
|
||||
set_keyboad_key(0, XK_i, PAD_TRIANGLE);
|
||||
set_keyboad_key(0, XK_l, PAD_CIRCLE);
|
||||
set_keyboad_key(0, XK_k, PAD_CROSS);
|
||||
set_keyboad_key(0, XK_j, PAD_SQUARE);
|
||||
set_keyboad_key(0, XK_v, PAD_SELECT);
|
||||
set_keyboad_key(0, XK_n, PAD_START);
|
||||
set_keyboad_key(0, XK_e, PAD_UP);
|
||||
set_keyboad_key(0, XK_f, PAD_RIGHT);
|
||||
set_keyboad_key(0, XK_d, PAD_DOWN);
|
||||
set_keyboad_key(0, XK_s, PAD_LEFT);
|
||||
}
|
||||
|
||||
void SaveConfig()
|
||||
|
@ -124,15 +128,24 @@ void SaveConfig()
|
|||
return;
|
||||
}
|
||||
|
||||
for (int pad = 0; pad < 2 * MAX_SUB_KEYS; pad++)
|
||||
fprintf(f, "log = %d\n", conf->log);
|
||||
fprintf(f, "options = %d\n", conf->options);
|
||||
fprintf(f, "mouse_sensibility = %d\n", conf->sensibility);
|
||||
fprintf(f, "joy_pad_map = %d\n", conf->joyid_map);
|
||||
|
||||
for (int pad = 0; pad < 2; pad++)
|
||||
{
|
||||
for (int key = 0; key < MAX_KEYS; key++)
|
||||
{
|
||||
fprintf(f, "[%d][%d] = 0x%lx\n", pad, key, get_key(pad,key));
|
||||
fprintf(f, "[%d][%d] = 0x%x\n", pad, key, get_key(pad,key));
|
||||
}
|
||||
}
|
||||
fprintf(f, "log = %d\n", conf.log);
|
||||
fprintf(f, "options = %d\n", conf.options);
|
||||
|
||||
map<u32,u32>::iterator it;
|
||||
for (int pad = 0; pad < 2 ; pad++)
|
||||
for (it = conf->keysym_map[pad].begin(); it != conf->keysym_map[pad].end(); ++it)
|
||||
fprintf(f, "PAD %d:KEYSYM 0x%x = %d\n", pad, it->first, it->second);
|
||||
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
|
@ -140,10 +153,12 @@ void LoadConfig()
|
|||
{
|
||||
FILE *f;
|
||||
char str[256];
|
||||
bool have_user_setting = false;
|
||||
|
||||
memset(&conf, 0, sizeof(conf));
|
||||
DefaultValues();
|
||||
conf.log = 0;
|
||||
if (!conf)
|
||||
conf = new PADconf;
|
||||
|
||||
conf->init();
|
||||
|
||||
const std::string iniFile(s_strIniPath + "OnePAD.ini");
|
||||
f = fopen(iniFile.c_str(), "r");
|
||||
|
@ -154,18 +169,33 @@ void LoadConfig()
|
|||
return;
|
||||
}
|
||||
|
||||
for (int pad = 0; pad < 2 * MAX_SUB_KEYS; pad++)
|
||||
fscanf(f, "log = %d\n", &conf->log);
|
||||
fscanf(f, "options = %d\n", &conf->options);
|
||||
fscanf(f, "mouse_sensibility = %d\n", &conf->sensibility);
|
||||
fscanf(f, "joy_pad_map = %d\n", &conf->joyid_map);
|
||||
for (int pad = 0; pad < 2; pad++)
|
||||
|
||||
{
|
||||
for (int key = 0; key < MAX_KEYS; key++)
|
||||
{
|
||||
sprintf(str, "[%d][%d] = 0x%%x\n", pad, key);
|
||||
u32 temp;
|
||||
u32 temp = 0;
|
||||
|
||||
if (fscanf(f, str, &temp) == 0) temp = 0;
|
||||
set_key(pad, key, temp);
|
||||
if (temp && pad == 0) have_user_setting = true;
|
||||
}
|
||||
}
|
||||
fscanf(f, "log = %d\n", &conf.log);
|
||||
fscanf(f, "options = %d\n", &conf.options);
|
||||
|
||||
u32 pad;
|
||||
u32 keysym;
|
||||
u32 index;
|
||||
while( fscanf(f, "PAD %d:KEYSYM 0x%x = %d\n", &pad, &keysym, &index) != EOF ) {
|
||||
set_keyboad_key(pad, keysym, index);
|
||||
if(pad == 0) have_user_setting = true;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (!have_user_setting) DefaultKeyboardValues();
|
||||
}
|
||||
|
|
|
@ -21,17 +21,15 @@
|
|||
|
||||
#include "joystick.h"
|
||||
#include "onepad.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include "linux.h"
|
||||
#include <gdk/gdkx.h>
|
||||
|
||||
extern void PollForKeyboardInput(int pad);
|
||||
extern void SetAutoRepeat(bool autorep);
|
||||
Display *GSdsp;
|
||||
|
||||
extern string KeyName(int pad, int key);
|
||||
Window GSwin;
|
||||
|
||||
void SysMessage(const char *fmt, ...)
|
||||
{
|
||||
|
@ -66,22 +64,8 @@ EXPORT_C_(s32) PADtest()
|
|||
|
||||
s32 _PADopen(void *pDsp)
|
||||
{
|
||||
GtkScrolledWindow *win;
|
||||
|
||||
win = *(GtkScrolledWindow**) pDsp;
|
||||
|
||||
if (GTK_IS_WIDGET(win))
|
||||
{
|
||||
// Since we have a GtkScrolledWindow, for now we'll grab whatever display
|
||||
// comes along instead. Later, we can fiddle with this, but I'm not sure the
|
||||
// best way to get a Display* out of a GtkScrolledWindow. A GtkWindow I might
|
||||
// be able to manage... --arcum42
|
||||
GSdsp = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
|
||||
}
|
||||
else
|
||||
{
|
||||
GSdsp = *(Display**)pDsp;
|
||||
}
|
||||
GSdsp = *(Display**)pDsp;
|
||||
GSwin = (Window)*(((u32*)pDsp)+1);
|
||||
|
||||
SetAutoRepeat(false);
|
||||
return 0;
|
||||
|
@ -103,98 +87,105 @@ void _PADclose()
|
|||
s_vjoysticks.clear();
|
||||
}
|
||||
|
||||
static bool used_by_keyboard = false;
|
||||
EXPORT_C_(void) PADupdate(int pad)
|
||||
{
|
||||
// Poll keyboard.
|
||||
PollForKeyboardInput(pad);
|
||||
// FIXME joystick directly update the status variable
|
||||
// Keyboard does a nice roadtrip (with semaphore in the middle)
|
||||
// s_keyRelease (by UpdateKeys) -> status (by _PADupdate -> by _PADpoll)
|
||||
// If we need semaphore, joy part must be updated
|
||||
|
||||
// joystick info
|
||||
SDL_JoystickUpdate();
|
||||
// Actually PADupdate is always call with pad == 0. So you need to update both
|
||||
// pads -- Gregory
|
||||
for (int cpad = 0; cpad < 2; cpad++) {
|
||||
int keyPress = 0, keyRelease = 0;
|
||||
|
||||
for (int i = 0; i < MAX_KEYS; i++)
|
||||
{
|
||||
int cpad = PadEnum[pad][0];
|
||||
// Poll keyboard.
|
||||
PollForX11KeyboardInput(cpad, keyPress, keyRelease, used_by_keyboard);
|
||||
|
||||
if (JoystickIdWithinBounds(key_to_joystick_id(cpad, i)))
|
||||
{
|
||||
JoystickInfo* pjoy = s_vjoysticks[key_to_joystick_id(cpad, i)];
|
||||
int pad = (pjoy)->GetPAD();
|
||||
UpdateKeys(pad, keyPress, keyRelease);
|
||||
|
||||
switch (type_of_key(cpad, i))
|
||||
// joystick info
|
||||
SDL_JoystickUpdate();
|
||||
|
||||
int joyid = conf->get_joyid(cpad);
|
||||
|
||||
if (JoystickIdWithinBounds(joyid)) {
|
||||
for (int i = 0; i < MAX_KEYS; i++)
|
||||
{
|
||||
case PAD_JOYBUTTONS:
|
||||
{
|
||||
int value = SDL_JoystickGetButton((pjoy)->GetJoy(), key_to_button(cpad, i));
|
||||
JoystickInfo* pjoy = s_vjoysticks[joyid];
|
||||
|
||||
if (value)
|
||||
clear_bit(status[pad], i); // released
|
||||
else
|
||||
set_bit(status[pad], i); // pressed
|
||||
break;
|
||||
}
|
||||
case PAD_HAT:
|
||||
switch (type_of_joykey(cpad, i))
|
||||
{
|
||||
int value = SDL_JoystickGetHat((pjoy)->GetJoy(), key_to_axis(cpad, i));
|
||||
case PAD_JOYBUTTONS:
|
||||
{
|
||||
|
||||
if (key_to_hat_dir(cpad, i) == value)
|
||||
{
|
||||
clear_bit(status[pad], i);
|
||||
//PAD_LOG("Registered %s\n", HatName(value), i);
|
||||
//PAD_LOG("%s\n", KeyName(cpad, i).c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
set_bit(status[pad], i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PAD_POV:
|
||||
{
|
||||
int value = pjoy->GetAxisFromKey(cpad, i);
|
||||
|
||||
PAD_LOG("%s: %d (%d)\n", KeyName(cpad, i).c_str(), value, key_to_pov_sign(cpad, i));
|
||||
if (key_to_pov_sign(cpad, i) && (value < -2048))
|
||||
{
|
||||
//PAD_LOG("%s Released+.\n", KeyName(cpad, i).c_str());
|
||||
clear_bit(status[pad], i);
|
||||
}
|
||||
else if (!key_to_pov_sign(cpad, i) && (value > 2048))
|
||||
{
|
||||
//PAD_LOG("%s Released-\n", KeyName(cpad, i).c_str());
|
||||
clear_bit(status[pad], i);
|
||||
}
|
||||
else
|
||||
{
|
||||
//PAD_LOG("%s Pressed.\n", KeyName(cpad, i).c_str());
|
||||
set_bit(status[pad], i);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PAD_JOYSTICK:
|
||||
{
|
||||
int value = pjoy->GetAxisFromKey(cpad, i);
|
||||
|
||||
switch (i)
|
||||
{
|
||||
case PAD_LX:
|
||||
case PAD_LY:
|
||||
case PAD_RX:
|
||||
case PAD_RY:
|
||||
if (abs(value) > (pjoy)->GetDeadzone(/*value*/))
|
||||
Analog::ConfigurePad(pad, i, value);
|
||||
int value = SDL_JoystickGetButton((pjoy)->GetJoy(), key_to_button(cpad, i));
|
||||
if (value)
|
||||
clear_bit(status[cpad], i); // released
|
||||
else
|
||||
Analog::ResetPad(pad, i);
|
||||
set_bit(status[cpad], i); // pressed
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PAD_HAT:
|
||||
{
|
||||
int value = SDL_JoystickGetHat((pjoy)->GetJoy(), key_to_axis(cpad, i));
|
||||
|
||||
if (key_to_hat_dir(cpad, i) == value)
|
||||
clear_bit(status[cpad], i);
|
||||
else
|
||||
set_bit(status[cpad], i);
|
||||
|
||||
break;
|
||||
}
|
||||
case PAD_AXIS:
|
||||
{
|
||||
int value = pjoy->GetAxisFromKey(cpad, i);
|
||||
bool sign = key_to_axis_sign(cpad, i);
|
||||
bool full_axis = key_to_axis_type(cpad, i);
|
||||
|
||||
if (IsAnalogKey(i)) {
|
||||
if (abs(value) > (pjoy)->GetDeadzone())
|
||||
Analog::ConfigurePad(cpad, i, value);
|
||||
else if (! (conf->options & ((PADOPTION_MOUSE_R|PADOPTION_MOUSE_L) << 16 * cpad ))
|
||||
&& !(used_by_keyboard) )
|
||||
// There is a conflict between keyboard/mouse and joystick configuration.
|
||||
// Do nothing when either the mouse or the keyboad is pressed/enabled.
|
||||
// It avoid to be stuck in reset mode --Gregory
|
||||
Analog::ResetPad(cpad, i);
|
||||
|
||||
} else {
|
||||
if (full_axis) {
|
||||
value += 0x8000;
|
||||
if (value > 2048) {
|
||||
clear_bit(status[cpad], i);
|
||||
status_pressure[cpad][i] = min(value/256 , 0xFF); // Max pressure is 255
|
||||
} else {
|
||||
set_bit(status[cpad], i);
|
||||
status_pressure[cpad][i] = 0; // no pressure
|
||||
}
|
||||
} else {
|
||||
if (sign && (value < -2048)) {
|
||||
clear_bit(status[cpad], i);
|
||||
status_pressure[cpad][i] = min(-value /128, 0xFF); // Max pressure is 255
|
||||
} else if (!sign && (value > 2048)) {
|
||||
clear_bit(status[cpad], i);
|
||||
status_pressure[cpad][i] = min(value /128, 0xFF); // Max pressure is 255
|
||||
} else {
|
||||
set_bit(status[cpad], i);
|
||||
status_pressure[cpad][i] = 0; // no pressure
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
EXPORT_C_(void) PADconfigure()
|
||||
{
|
||||
LoadConfig();
|
||||
|
|
|
@ -18,14 +18,9 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
//
|
||||
//#include "joystick.h"
|
||||
//#include "keyboard.h"
|
||||
//#include "onepad.h"
|
||||
//
|
||||
//#include <string.h>
|
||||
//#include <gtk/gtk.h>
|
||||
//#include <gdk/gdkkeysyms.h>
|
||||
//#include <pthread.h>
|
||||
|
||||
#ifndef __LINUX_H__
|
||||
#define __LINUX_H__
|
||||
extern void DisplayDialog();
|
||||
extern string KeyName(int pad, int key, int keysym = 0);
|
||||
#endif
|
||||
|
|
|
@ -19,8 +19,8 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "analog.h"
|
||||
PADAnalog g_lanalog[NUM_OF_PADS], g_ranalog[NUM_OF_PADS];
|
||||
#include "analog.h"
|
||||
static PADAnalog g_lanalog[NUM_OF_PADS], g_ranalog[NUM_OF_PADS];
|
||||
|
||||
namespace Analog
|
||||
{
|
||||
|
@ -28,58 +28,42 @@ namespace Analog
|
|||
{
|
||||
switch (index)
|
||||
{
|
||||
case PAD_LX:
|
||||
return g_lanalog[pad].x;
|
||||
break;
|
||||
case PAD_R_LEFT:
|
||||
case PAD_R_RIGHT: return g_ranalog[pad].x;
|
||||
|
||||
case PAD_RX:
|
||||
return g_ranalog[pad].x;
|
||||
break;
|
||||
case PAD_R_DOWN:
|
||||
case PAD_R_UP: return g_ranalog[pad].y;
|
||||
|
||||
case PAD_LY:
|
||||
return g_lanalog[pad].y;
|
||||
break;
|
||||
case PAD_L_LEFT:
|
||||
case PAD_L_RIGHT: return g_lanalog[pad].x;
|
||||
|
||||
case PAD_RY:
|
||||
return g_ranalog[pad].y;
|
||||
break;
|
||||
case PAD_L_DOWN:
|
||||
case PAD_L_UP: return g_lanalog[pad].y;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void SetPad(u8 pad, int index, u8 value)
|
||||
static void SetPad(u8 pad, int index, u8 value)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case PAD_LX:
|
||||
g_lanalog[pad].x = value;
|
||||
break;
|
||||
case PAD_R_LEFT:
|
||||
case PAD_R_RIGHT: g_ranalog[pad].x = value; break;
|
||||
|
||||
case PAD_RX:
|
||||
g_ranalog[ pad].x = value;
|
||||
break;
|
||||
case PAD_R_DOWN:
|
||||
case PAD_R_UP: g_ranalog[pad].y = value; break;
|
||||
|
||||
case PAD_LY:
|
||||
g_lanalog[ pad].y = value;
|
||||
break;
|
||||
case PAD_L_LEFT:
|
||||
case PAD_L_RIGHT: g_lanalog[pad].x = value; break;
|
||||
|
||||
case PAD_RY:
|
||||
g_ranalog[pad].y = value;
|
||||
break;
|
||||
case PAD_L_DOWN:
|
||||
case PAD_L_UP: g_lanalog[pad].y = value; break;
|
||||
|
||||
default:
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
void InvertPad(u8 pad, int key)
|
||||
{
|
||||
SetPad(pad, key, -Pad(pad, key));
|
||||
}
|
||||
|
||||
void ResetPad( u8 pad, int key)
|
||||
{
|
||||
SetPad(pad, key, 0x80);
|
||||
|
@ -89,76 +73,47 @@ namespace Analog
|
|||
{
|
||||
for (u8 pad = 0; pad < 2; ++pad)
|
||||
{
|
||||
ResetPad(pad, PAD_LX);
|
||||
ResetPad(pad, PAD_LY);
|
||||
ResetPad(pad, PAD_RX);
|
||||
ResetPad(pad, PAD_RY);
|
||||
// no need to put the 2 part of the axis
|
||||
ResetPad(pad, PAD_R_LEFT);
|
||||
ResetPad(pad, PAD_R_DOWN);
|
||||
ResetPad(pad, PAD_L_LEFT);
|
||||
ResetPad(pad, PAD_L_DOWN);
|
||||
}
|
||||
}
|
||||
|
||||
bool ReversePad(u8 index)
|
||||
static bool ReversePad(u8 index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case PAD_LX:
|
||||
return ((conf.options & PADOPTION_REVERSELX) != 0);
|
||||
break;
|
||||
case PAD_L_RIGHT:
|
||||
case PAD_L_LEFT:
|
||||
return ((conf->options & PADOPTION_REVERSELX) != 0);
|
||||
|
||||
case PAD_RX:
|
||||
return ((conf.options & PADOPTION_REVERSERX) != 0);
|
||||
break;
|
||||
case PAD_R_LEFT:
|
||||
case PAD_R_RIGHT:
|
||||
return ((conf->options & PADOPTION_REVERSERX) != 0);
|
||||
|
||||
case PAD_LY:
|
||||
return ((conf.options & PADOPTION_REVERSELY) != 0);
|
||||
break;
|
||||
case PAD_L_UP:
|
||||
case PAD_L_DOWN:
|
||||
return ((conf->options & PADOPTION_REVERSELY) != 0);
|
||||
|
||||
case PAD_RY:
|
||||
return ((conf.options & PADOPTION_REVERSERY) != 0);
|
||||
break;
|
||||
case PAD_R_DOWN:
|
||||
case PAD_R_UP:
|
||||
return ((conf->options & PADOPTION_REVERSERY) != 0);
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ConfigurePad( u8 pad, int index, int value)
|
||||
{
|
||||
Pad(pad, index);
|
||||
SetPad(pad, index, value / 256);
|
||||
if (ReversePad(index)) InvertPad(pad,index);
|
||||
SetPad(pad, index, Pad(pad, index) + 0x80);
|
||||
}
|
||||
|
||||
int AnalogToPad(int index)
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case PAD_R_LEFT:
|
||||
return PAD_RX;
|
||||
break;
|
||||
case PAD_R_UP:
|
||||
return PAD_RY;
|
||||
break;
|
||||
case PAD_L_LEFT:
|
||||
return PAD_LX;
|
||||
break;
|
||||
case PAD_L_UP:
|
||||
return PAD_LY;
|
||||
break;
|
||||
case PAD_R_DOWN:
|
||||
return PAD_RY;
|
||||
break;
|
||||
case PAD_R_RIGHT:
|
||||
return PAD_RX;
|
||||
break;
|
||||
case PAD_L_DOWN:
|
||||
return PAD_LY;
|
||||
break;
|
||||
case PAD_L_RIGHT:
|
||||
return PAD_LX;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
// Left -> -- -> Right
|
||||
// Value range : FFFF8002 -> 0 -> 7FFE
|
||||
// Force range : 80 -> 0 -> 7F
|
||||
// Normal mode : expect value 0 -> 80 -> FF
|
||||
// Reverse mode: expect value FF -> 7F -> 0
|
||||
u8 force = (value / 256);
|
||||
if (ReversePad(index)) SetPad(pad, index, 0x7F - force);
|
||||
else SetPad(pad, index, 0x80 + force);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,18 +19,14 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#define NUM_OF_PADS 2
|
||||
#define NUM_OF_PADS 2
|
||||
|
||||
#include "onepad.h"
|
||||
namespace Analog
|
||||
#include "onepad.h"
|
||||
|
||||
namespace Analog
|
||||
{
|
||||
extern void Init();
|
||||
extern u8 Pad(int pad, u8 index);
|
||||
extern void SetPad(u8 pad, int index, u8 value);
|
||||
extern void InvertPad(u8 pad, int key);
|
||||
extern bool ReversePad(u8 index);
|
||||
extern void ResetPad( u8 pad, int key);
|
||||
extern void ConfigurePad( u8 pad, int index, int value);
|
||||
extern int KeypadToPad(u8 keypress);
|
||||
extern int AnalogToPad(int index);
|
||||
}
|
||||
|
|
|
@ -24,74 +24,89 @@
|
|||
|
||||
HatPins hat_position = {false, false, false, false};
|
||||
|
||||
__forceinline void set_keyboad_key(int pad, int keysym, int index)
|
||||
{
|
||||
conf->keysym_map[pad][keysym] = index;
|
||||
}
|
||||
|
||||
__forceinline int get_keyboard_key(int pad, int keysym)
|
||||
{
|
||||
// You must use find instead of []
|
||||
// [] will create an element if the key does not exist and return 0
|
||||
map<u32,u32>::iterator it = conf->keysym_map[pad].find(keysym);
|
||||
if (it != conf->keysym_map[pad].end())
|
||||
return it->second;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
__forceinline void set_key(int pad, int index, int value)
|
||||
{
|
||||
conf.keys[pad][index] = value;
|
||||
conf->keys[pad][index] = value;
|
||||
}
|
||||
|
||||
__forceinline int get_key(int pad, int index)
|
||||
{
|
||||
return conf.keys[pad][index];
|
||||
return conf->keys[pad][index];
|
||||
}
|
||||
|
||||
__forceinline KeyType type_of_key(int pad, int index)
|
||||
{
|
||||
int key = conf.keys[pad][index];
|
||||
|
||||
if (key < 0x10000) return PAD_KEYBOARD;
|
||||
else if (key >= 0x10000 && key < 0x20000) return PAD_JOYBUTTONS;
|
||||
else if (key >= 0x20000 && key < 0x30000) return PAD_JOYSTICK;
|
||||
else if (key >= 0x30000 && key < 0x40000) return PAD_POV;
|
||||
else if (key >= 0x40000 && key < 0x50000) return PAD_HAT;
|
||||
else return PAD_NULL;
|
||||
}
|
||||
|
||||
__forceinline int pad_to_key(int pad, int index)
|
||||
{
|
||||
return ((conf.keys[pad][index]) & 0xffff);
|
||||
}
|
||||
|
||||
__forceinline int key_to_joystick_id(int pad, int index)
|
||||
__forceinline KeyType type_of_joykey(int pad, int index)
|
||||
{
|
||||
return (((conf.keys[pad][index]) & 0xf000) >> 12);
|
||||
int key = get_key(pad, index);
|
||||
|
||||
if (key >= 0x10000 && key < 0x20000) return PAD_JOYBUTTONS;
|
||||
else if (key >= 0x20000 && key < 0x30000) return PAD_AXIS;
|
||||
else if (key >= 0x30000 && key < 0x40000) return PAD_HAT;
|
||||
else return PAD_NULL;
|
||||
}
|
||||
|
||||
__forceinline bool IsAnalogKey(int index)
|
||||
{
|
||||
return ((index >= PAD_L_UP) && (index <= PAD_R_LEFT));
|
||||
}
|
||||
|
||||
//*******************************************************
|
||||
// onepad key -> joy input
|
||||
//*******************************************************
|
||||
__forceinline int key_to_button(int pad, int index)
|
||||
{
|
||||
return ((conf.keys[pad][index]) & 0xff);
|
||||
return (get_key(pad, index) & 0xff);
|
||||
}
|
||||
|
||||
__forceinline int key_to_axis(int pad, int index)
|
||||
{
|
||||
return ((conf.keys[pad][index]) & 0xff);
|
||||
return (get_key(pad, index) & 0xff);
|
||||
}
|
||||
|
||||
__forceinline int button_to_key(int joy_id, int button_id)
|
||||
__forceinline bool key_to_axis_sign(int pad, int index)
|
||||
{
|
||||
return (0x10000 | ((joy_id) << 12) | (button_id));
|
||||
return ((get_key(pad, index) >> 8) & 0x1);
|
||||
}
|
||||
|
||||
__forceinline int joystick_to_key(int joy_id, int axis_id)
|
||||
__forceinline bool key_to_axis_type(int pad, int index)
|
||||
{
|
||||
return (0x20000 | ((joy_id) << 12) | (axis_id));
|
||||
}
|
||||
|
||||
__forceinline int pov_to_key(int joy_id, int sign, int axis_id)
|
||||
{
|
||||
return (0x30000 | ((joy_id) << 12) | ((sign) << 8) | (axis_id));
|
||||
}
|
||||
|
||||
__forceinline int hat_to_key(int joy_id, int dir, int axis_id)
|
||||
{
|
||||
return (0x40000 | ((joy_id) << 12) | ((dir) << 8) | (axis_id));
|
||||
}
|
||||
|
||||
__forceinline int key_to_pov_sign(int pad, int index)
|
||||
{
|
||||
return (((conf.keys[pad][index]) & 0x100) >> 8);
|
||||
return ((get_key(pad, index) >> 9) & 0x1);
|
||||
}
|
||||
|
||||
__forceinline int key_to_hat_dir(int pad, int index)
|
||||
{
|
||||
return (((conf.keys[pad][index]) & 0xF00) >> 8);
|
||||
return ((get_key(pad, index) >> 8) & 0xF);
|
||||
}
|
||||
|
||||
//*******************************************************
|
||||
// joy input -> onepad key
|
||||
//*******************************************************
|
||||
__forceinline int button_to_key(int button_id)
|
||||
{
|
||||
return (0x10000 | button_id);
|
||||
}
|
||||
|
||||
__forceinline int axis_to_key(int full_axis, int sign, int axis_id)
|
||||
{
|
||||
return (0x20000 | (full_axis << 9) | (sign << 8) | axis_id);
|
||||
}
|
||||
|
||||
__forceinline int hat_to_key(int dir, int axis_id)
|
||||
{
|
||||
return (0x30000 | (dir << 8) | axis_id);
|
||||
}
|
||||
|
|
|
@ -23,42 +23,35 @@
|
|||
#define __CONTROLLER_H__
|
||||
|
||||
#ifdef __LINUX__
|
||||
#define MAX_KEYS 28
|
||||
#define MAX_KEYS 24
|
||||
#else
|
||||
#define MAX_KEYS 20
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define MAX_SUB_KEYS 1
|
||||
#else
|
||||
#define MAX_SUB_KEYS 2
|
||||
#endif
|
||||
|
||||
enum KeyType
|
||||
{
|
||||
PAD_KEYBOARD = 0,
|
||||
PAD_JOYBUTTONS,
|
||||
PAD_JOYSTICK,
|
||||
PAD_POV,
|
||||
PAD_JOYBUTTONS = 0,
|
||||
PAD_AXIS,
|
||||
PAD_HAT,
|
||||
PAD_NULL = -1
|
||||
};
|
||||
|
||||
extern void set_keyboad_key(int pad, int keysym, int index);
|
||||
extern int get_keyboard_key(int pad, int keysym);
|
||||
extern void set_key(int pad, int index, int value);
|
||||
extern int get_key(int pad, int index);
|
||||
extern bool IsAnalogKey(int index);
|
||||
|
||||
extern KeyType type_of_key(int pad, int index);
|
||||
extern int pad_to_key(int pad, int index);
|
||||
extern int key_to_joystick_id(int pad, int index);
|
||||
extern KeyType type_of_joykey(int pad, int index);
|
||||
extern int key_to_button(int pad, int index);
|
||||
extern int key_to_axis(int pad, int index);
|
||||
extern int key_to_pov_sign(int pad, int index);
|
||||
extern bool key_to_axis_sign(int pad, int index);
|
||||
extern bool key_to_axis_type(int pad, int index);
|
||||
extern int key_to_hat_dir(int pad, int index);
|
||||
|
||||
extern int button_to_key(int joy_id, int button_id);
|
||||
extern int joystick_to_key(int joy_id, int axis_id);
|
||||
extern int pov_to_key(int joy_id, int sign, int axis_id);
|
||||
extern int hat_to_key(int joy_id, int dir, int axis_id);
|
||||
extern int button_to_key(int button_id);
|
||||
extern int axis_to_key(int full_axis, int sign, int axis_id);
|
||||
extern int hat_to_key(int dir, int axis_id);
|
||||
|
||||
extern int PadEnum[2][2];
|
||||
|
||||
|
@ -111,19 +104,41 @@ static __forceinline void set_hat_pins(int tilt_o_the_hat)
|
|||
}
|
||||
}
|
||||
|
||||
typedef struct
|
||||
struct PADconf
|
||||
{
|
||||
u32 keys[2 * MAX_SUB_KEYS][MAX_KEYS];
|
||||
public:
|
||||
u32 keys[2][MAX_KEYS];
|
||||
u32 log;
|
||||
u32 options; // upper 16 bits are for pad2
|
||||
} PADconf;
|
||||
u32 sensibility;
|
||||
u32 joyid_map;
|
||||
map<u32,u32> keysym_map[2];
|
||||
|
||||
PADconf() { init(); }
|
||||
|
||||
void init() {
|
||||
memset(&keys, 0, sizeof(keys));
|
||||
log = options = joyid_map = 0;
|
||||
sensibility = 500;
|
||||
for (int pad = 0; pad < 2 ; pad++)
|
||||
keysym_map[pad].clear();
|
||||
}
|
||||
|
||||
void set_joyid(u32 pad, u32 joy_id) {
|
||||
int shift = 8 * pad;
|
||||
joyid_map &= ~(0xFF << shift); // clear
|
||||
joyid_map |= (joy_id & 0xFF) << shift; // set
|
||||
}
|
||||
|
||||
u32 get_joyid(u32 pad) {
|
||||
int shift = 8 * pad;
|
||||
return ((joyid_map >> shift) & 0xFF);
|
||||
}
|
||||
};
|
||||
extern PADconf *conf;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 x, y;
|
||||
} PADAnalog;
|
||||
|
||||
extern PADconf conf;
|
||||
extern PADAnalog g_lanalog[2], g_ranalog[2];
|
||||
|
||||
#endif
|
||||
|
|
|
@ -65,6 +65,7 @@ bool JoystickIdWithinBounds(int joyid)
|
|||
{
|
||||
return ((joyid >= 0) && (joyid < (int)s_vjoysticks.size()));
|
||||
}
|
||||
|
||||
// opens handles to all possible joysticks
|
||||
void JoystickInfo::EnumerateJoysticks(vector<JoystickInfo*>& vjoysticks)
|
||||
{
|
||||
|
@ -75,9 +76,7 @@ void JoystickInfo::EnumerateJoysticks(vector<JoystickInfo*>& vjoysticks)
|
|||
// SDL in 3rdparty wrap X11 call. In order to get x11 symbols loaded
|
||||
// video must be loaded too.
|
||||
// Example of X11 symbol are XAutoRepeatOn/XAutoRepeatOff
|
||||
// Just to play it safe I separate 1.2 and 1.3 but I think it will be
|
||||
// fine in 1.2 too -- greg
|
||||
if (SDL_Init(SDL_INIT_JOYSTICK|SDL_INIT_VIDEO) < 0) return;
|
||||
if (SDL_Init(SDL_INIT_JOYSTICK|SDL_INIT_VIDEO|SDL_INIT_HAPTIC) < 0) return;
|
||||
#else
|
||||
if (SDL_Init(SDL_INIT_JOYSTICK) < 0) return;
|
||||
#endif
|
||||
|
@ -101,32 +100,118 @@ void JoystickInfo::EnumerateJoysticks(vector<JoystickInfo*>& vjoysticks)
|
|||
vjoysticks[i] = new JoystickInfo();
|
||||
vjoysticks[i]->Init(i);
|
||||
}
|
||||
}
|
||||
|
||||
// set the pads
|
||||
for (int pad = 0; pad < 2; ++pad)
|
||||
{
|
||||
// select the right joystick id
|
||||
int joyid = -1;
|
||||
void JoystickInfo::InitHapticEffect()
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
if (haptic == NULL) return;
|
||||
|
||||
for (int i = 0; i < MAX_KEYS; ++i)
|
||||
{
|
||||
KeyType k = type_of_key(pad,i);
|
||||
if (k == PAD_JOYSTICK || k == PAD_JOYBUTTONS)
|
||||
{
|
||||
joyid = key_to_joystick_id(pad,i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
additional field of the effect
|
||||
/* Trigger */
|
||||
Uint16 button; /**< Button that triggers the effect. */
|
||||
Uint16 interval; /**< How soon it can be triggered again after button. */
|
||||
|
||||
if ((joyid >= 0) && (joyid < (int)s_vjoysticks.size())) s_vjoysticks[joyid]->Assign(pad);
|
||||
// periodic parameter
|
||||
Sint16 offset; /**< Mean value of the wave. */
|
||||
Uint16 phase; /**< Horizontal shift given by hundredth of a cycle. */
|
||||
#endif
|
||||
|
||||
/*******************************************************************/
|
||||
/* Effect small */
|
||||
/*******************************************************************/
|
||||
haptic_effect_data[0].type = SDL_HAPTIC_SQUARE;
|
||||
|
||||
// Direction of the effect SDL_HapticDirection
|
||||
haptic_effect_data[0].periodic.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates
|
||||
haptic_effect_data[0].periodic.direction.dir[0] = 18000; // Force comes from south
|
||||
|
||||
// periodic parameter
|
||||
haptic_effect_data[0].periodic.period = 1000; // 1000 ms
|
||||
haptic_effect_data[0].periodic.magnitude = 2000; // 2000/32767 strength
|
||||
|
||||
// Replay
|
||||
haptic_effect_data[0].periodic.length = 2000; // 2 seconds long
|
||||
haptic_effect_data[0].periodic.delay = 0; // start 0 second after the upload
|
||||
|
||||
// enveloppe
|
||||
haptic_effect_data[0].periodic.attack_length = 500;// Takes 0.5 second to get max strength
|
||||
haptic_effect_data[0].periodic.attack_level = 0; // start at 0
|
||||
haptic_effect_data[0].periodic.fade_length = 500; // Takes 0.5 second to fade away
|
||||
haptic_effect_data[0].periodic.fade_level = 0; // finish at 0
|
||||
|
||||
/*******************************************************************/
|
||||
/* Effect big */
|
||||
/*******************************************************************/
|
||||
haptic_effect_data[1].type = SDL_HAPTIC_TRIANGLE;
|
||||
|
||||
// Direction of the effect SDL_HapticDirection
|
||||
haptic_effect_data[1].periodic.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates
|
||||
haptic_effect_data[1].periodic.direction.dir[0] = 18000; // Force comes from south
|
||||
|
||||
// periodic parameter
|
||||
haptic_effect_data[1].periodic.period = 1000; // 1000 ms
|
||||
haptic_effect_data[1].periodic.magnitude = 2000; // 2000/32767 strength
|
||||
|
||||
// Replay
|
||||
haptic_effect_data[1].periodic.length = 2000; // 2 seconds long
|
||||
haptic_effect_data[1].periodic.delay = 0; // start 0 second after the upload
|
||||
|
||||
// enveloppe
|
||||
haptic_effect_data[1].periodic.attack_length = 500;// Takes 0.5 second to get max strength
|
||||
haptic_effect_data[1].periodic.attack_level = 0; // start at 0
|
||||
haptic_effect_data[1].periodic.fade_length = 500; // Takes 0.5 second to fade away
|
||||
haptic_effect_data[1].periodic.fade_level = 0; // finish at 0
|
||||
|
||||
/*******************************************************************/
|
||||
/* Upload effect to the device */
|
||||
/*******************************************************************/
|
||||
for (int i = 0 ; i < 2 ; i++)
|
||||
haptic_effect_id[i] = SDL_HapticNewEffect(haptic, &haptic_effect_data[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void JoystickInfo::DoHapticEffect(int type, int pad, int force)
|
||||
{
|
||||
if (type > 1) return;
|
||||
if ( !(conf->options & (PADOPTION_FORCEFEEDBACK << 16 * pad)) ) return;
|
||||
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
// first search the joy associated to the pad
|
||||
vector<JoystickInfo*>::iterator itjoy = s_vjoysticks.begin();
|
||||
while (itjoy != s_vjoysticks.end()) {
|
||||
if ((*itjoy)->GetPAD() == pad) break;
|
||||
itjoy++;
|
||||
}
|
||||
|
||||
if (itjoy == s_vjoysticks.end()) return;
|
||||
if ((*itjoy)->haptic == NULL) return;
|
||||
if ((*itjoy)->haptic_effect_id[type] < 0) return;
|
||||
|
||||
// FIXME: might need to multiply force
|
||||
(*itjoy)->haptic_effect_data[type].periodic.magnitude = force; // force/32767 strength
|
||||
// Upload the new effect
|
||||
SDL_HapticUpdateEffect((*itjoy)->haptic, (*itjoy)->haptic_effect_id[type], &(*itjoy)->haptic_effect_data[type]);
|
||||
|
||||
// run the effect once
|
||||
SDL_HapticRunEffect( (*itjoy)->haptic, (*itjoy)->haptic_effect_id[type], 1 );
|
||||
#endif
|
||||
}
|
||||
|
||||
void JoystickInfo::Destroy()
|
||||
{
|
||||
if (joy != NULL)
|
||||
{
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
// Haptic must be closed before the joystick
|
||||
if (haptic != NULL) {
|
||||
SDL_HapticClose(haptic);
|
||||
haptic = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SDL_JoystickOpened(_id)) SDL_JoystickClose(joy);
|
||||
joy = NULL;
|
||||
}
|
||||
|
@ -153,32 +238,20 @@ bool JoystickInfo::Init(int id)
|
|||
vbuttonstate.resize(numbuttons);
|
||||
vhatstate.resize(numhats);
|
||||
|
||||
//PAD_LOG("There are %d buttons, %d axises, and %d hats.\n", numbuttons, numaxes, numhats);
|
||||
return true;
|
||||
}
|
||||
|
||||
// assigns a joystick to a pad
|
||||
void JoystickInfo::Assign(int newpad)
|
||||
{
|
||||
if (pad == newpad) return;
|
||||
pad = newpad;
|
||||
|
||||
if (pad >= 0)
|
||||
{
|
||||
for (int i = 0; i < MAX_KEYS; ++i)
|
||||
{
|
||||
KeyType k = type_of_key(pad,i);
|
||||
|
||||
if (k == PAD_JOYBUTTONS)
|
||||
{
|
||||
set_key(pad, i, button_to_key(_id, key_to_button(pad,i)));
|
||||
}
|
||||
else if (k == PAD_JOYSTICK)
|
||||
{
|
||||
set_key(pad, i, joystick_to_key(_id, key_to_button(pad,i)));
|
||||
}
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
if ( haptic == NULL ) {
|
||||
if (!SDL_JoystickIsHaptic(joy)) {
|
||||
PAD_LOG("Haptic devices not supported!\n");
|
||||
} else {
|
||||
haptic = SDL_HapticOpenFromJoystick(joy);
|
||||
// upload some default effect
|
||||
InitHapticEffect();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//PAD_LOG("There are %d buttons, %d axises, and %d hats.\n", numbuttons, numaxes, numhats);
|
||||
return true;
|
||||
}
|
||||
|
||||
void JoystickInfo::SaveState()
|
||||
|
@ -195,7 +268,7 @@ void JoystickInfo::TestForce()
|
|||
{
|
||||
}
|
||||
|
||||
bool JoystickInfo::PollButtons(int &jbutton, u32 &pkey)
|
||||
bool JoystickInfo::PollButtons(u32 &pkey)
|
||||
{
|
||||
// MAKE sure to look for changes in the state!!
|
||||
for (int i = 0; i < GetNumButtons(); ++i)
|
||||
|
@ -206,12 +279,21 @@ bool JoystickInfo::PollButtons(int &jbutton, u32 &pkey)
|
|||
{
|
||||
if (!but) // released, we don't really want this
|
||||
{
|
||||
SetButtonState(i, 0);
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
// Pressure sensitive button are detected as both button (digital) and axe (analog). So better
|
||||
// drop the button to emulate the pressure sensiblity of the ds2 :) -- Gregory
|
||||
for (int j = 0; j < GetNumAxes(); ++j) {
|
||||
int value = SDL_JoystickGetAxis(GetJoy(), j);
|
||||
int old_value = GetAxisState(j);
|
||||
bool full_axis = (old_value < -0x3FFF) ? true : false;
|
||||
if (value != old_value && ((full_axis && value > -0x6FFF ) || (!full_axis && abs(value) > old_value))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pkey = button_to_key(GetId(), i);
|
||||
jbutton = i;
|
||||
pkey = button_to_key(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -219,29 +301,33 @@ bool JoystickInfo::PollButtons(int &jbutton, u32 &pkey)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool JoystickInfo::PollPOV(int &axis_id, bool &sign, u32 &pkey)
|
||||
bool JoystickInfo::PollAxes(u32 &pkey)
|
||||
{
|
||||
for (int i = 0; i < GetNumAxes(); ++i)
|
||||
{
|
||||
int value = SDL_JoystickGetAxis(GetJoy(), i);
|
||||
int old_value = GetAxisState(i);
|
||||
|
||||
if (value != GetAxisState(i))
|
||||
if (value != old_value)
|
||||
{
|
||||
PAD_LOG("Change in joystick %d: %d.\n", i, value);
|
||||
// There is several kinds of axes
|
||||
// Half+: 0 (release) -> 32768
|
||||
// Half-: 0 (release) -> -32768
|
||||
// Full (like dualshock 3): -32768 (release) ->32768
|
||||
bool full_axis = (old_value < -0x2FFF) ? true : false;
|
||||
|
||||
if (abs(value) <= GetAxisState(i)) // we don't want this
|
||||
if ((!full_axis && abs(value) <= 0x1FFF)
|
||||
|| (full_axis && value <= -0x6FFF)) // we don't want this
|
||||
{
|
||||
// released, we don't really want this
|
||||
SetAxisState(i, value);
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (abs(value) > 0x3fff)
|
||||
if ((!full_axis && abs(value) > 0x3FFF)
|
||||
|| (full_axis && value > -0x6FFF))
|
||||
{
|
||||
axis_id = i;
|
||||
|
||||
sign = (value < 0);
|
||||
pkey = pov_to_key(GetId(), sign, i);
|
||||
bool sign = (value < 0);
|
||||
pkey = axis_to_key(full_axis, sign, i);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -250,36 +336,7 @@ bool JoystickInfo::PollPOV(int &axis_id, bool &sign, u32 &pkey)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool JoystickInfo::PollAxes(int &axis_id, u32 &pkey)
|
||||
{
|
||||
for (int i = 0; i < GetNumAxes(); ++i)
|
||||
{
|
||||
int value = SDL_JoystickGetAxis(GetJoy(), i);
|
||||
|
||||
if (value != GetAxisState(i))
|
||||
{
|
||||
PAD_LOG("Change in joystick %d: %d.\n", i, value);
|
||||
|
||||
if (abs(value) <= GetAxisState(i)) // we don't want this
|
||||
{
|
||||
// released, we don't really want this
|
||||
SetAxisState(i, value);
|
||||
break;
|
||||
}
|
||||
|
||||
if (abs(value) > 0x3fff)
|
||||
{
|
||||
axis_id = i;
|
||||
pkey = joystick_to_key(GetId(), i);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool JoystickInfo::PollHats(int &jbutton, int &dir, u32 &pkey)
|
||||
bool JoystickInfo::PollHats(u32 &pkey)
|
||||
{
|
||||
for (int i = 0; i < GetNumHats(); ++i)
|
||||
{
|
||||
|
@ -293,9 +350,7 @@ bool JoystickInfo::PollHats(int &jbutton, int &dir, u32 &pkey)
|
|||
case SDL_HAT_RIGHT:
|
||||
case SDL_HAT_DOWN:
|
||||
case SDL_HAT_LEFT:
|
||||
pkey = hat_to_key(GetId(), value, i);
|
||||
jbutton = i;
|
||||
dir = value;
|
||||
pkey = hat_to_key(value, i);
|
||||
PAD_LOG("Hat Pressed!");
|
||||
return true;
|
||||
default:
|
||||
|
|
|
@ -22,10 +22,9 @@
|
|||
#ifndef __JOYSTICK_H__
|
||||
#define __JOYSTICK_H__
|
||||
|
||||
#ifdef __LINUX__
|
||||
#include <SDL/SDL.h>
|
||||
#else
|
||||
#include <SDL.h>
|
||||
#include "SDL.h"
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
#include "SDL_haptic.h"
|
||||
#endif
|
||||
|
||||
#include "onepad.h"
|
||||
|
@ -36,7 +35,17 @@ class JoystickInfo
|
|||
{
|
||||
public:
|
||||
JoystickInfo() : devname(""), _id(-1), numbuttons(0), numaxes(0), numhats(0), axisrange(0x7fff),
|
||||
deadzone(2000), pad(-1), vbuttonstate(NULL), vaxisstate(NULL), vhatstate(NULL), joy(NULL) {}
|
||||
deadzone(2000), pad(-1), joy(NULL) {
|
||||
vbuttonstate.clear();
|
||||
vaxisstate.clear();
|
||||
vhatstate.clear();
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
haptic = NULL;
|
||||
for (int i = 0 ; i < 2 ; i++)
|
||||
haptic_effect_id[i] = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
~JoystickInfo()
|
||||
{
|
||||
Destroy();
|
||||
|
@ -49,15 +58,16 @@ class JoystickInfo
|
|||
// opens handles to all possible joysticks
|
||||
static void EnumerateJoysticks(vector<JoystickInfo*>& vjoysticks);
|
||||
|
||||
void InitHapticEffect();
|
||||
static void DoHapticEffect(int type, int pad, int force);
|
||||
|
||||
bool Init(int id); // opens a handle and gets information
|
||||
void Assign(int pad); // assigns a joystick to a pad
|
||||
|
||||
void TestForce();
|
||||
|
||||
bool PollButtons(int &jbutton, u32 &pkey);
|
||||
bool PollAxes(int &axis_id, u32 &pkey);
|
||||
bool PollHats(int &jbutton, int &dir, u32 &pkey);
|
||||
bool PollPOV(int &axis_id, bool &sign, u32 &pkey);
|
||||
bool PollButtons(u32 &pkey);
|
||||
bool PollAxes(u32 &pkey);
|
||||
bool PollHats(u32 &pkey);
|
||||
|
||||
const string& GetName()
|
||||
{
|
||||
|
@ -79,11 +89,6 @@ class JoystickInfo
|
|||
return numhats;
|
||||
}
|
||||
|
||||
int GetId()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
int GetPAD()
|
||||
{
|
||||
return pad;
|
||||
|
@ -145,7 +150,12 @@ class JoystickInfo
|
|||
|
||||
vector<int> vbuttonstate, vaxisstate, vhatstate;
|
||||
|
||||
SDL_Joystick* joy;
|
||||
SDL_Joystick* joy;
|
||||
#if SDL_VERSION_ATLEAST(1,3,0)
|
||||
SDL_Haptic* haptic;
|
||||
SDL_HapticEffect haptic_effect_data[2];
|
||||
int haptic_effect_id[2];
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -28,32 +28,15 @@
|
|||
#include <gdk/gdkkeysyms.h>
|
||||
#include "keyboard.h"
|
||||
|
||||
int FindKey(int key, int pad)
|
||||
{
|
||||
for (int p = 0; p < MAX_SUB_KEYS; p++)
|
||||
for (int i = 0; i < MAX_KEYS; i++)
|
||||
if (key == get_key(PadEnum[pad][p], i)) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef __LINUX__
|
||||
char* KeysymToChar(int keysym)
|
||||
{
|
||||
#ifdef __LINUX__
|
||||
return XKeysymToString(keysym);
|
||||
#else
|
||||
LPWORD temp;
|
||||
|
||||
ToAscii((UINT) keysym, NULL, NULL, temp, NULL);
|
||||
return (char*)temp;
|
||||
#endif
|
||||
}
|
||||
|
||||
void PollForKeyboardInput(int pad)
|
||||
{
|
||||
#ifdef __LINUX__
|
||||
PollForX11KeyboardInput(pad);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SetAutoRepeat(bool autorep)
|
||||
{
|
||||
|
@ -69,117 +52,232 @@ void SetAutoRepeat(bool autorep)
|
|||
}
|
||||
|
||||
#ifdef __LINUX__
|
||||
void PollForX11KeyboardInput(int pad)
|
||||
static bool s_grab_input = false;
|
||||
static bool s_Shift = false;
|
||||
static unsigned int s_previous_mouse_x = 0;
|
||||
static unsigned int s_previous_mouse_y = 0;
|
||||
void AnalyzeKeyEvent(int pad, keyEvent &evt, int& keyPress, int& keyRelease, bool& used_by_keyboard)
|
||||
{
|
||||
XEvent E;
|
||||
KeySym key;
|
||||
int keyPress = 0, keyRelease = 0;
|
||||
int i;
|
||||
KeySym key = (KeySym)evt.key;
|
||||
|
||||
// keyboard input
|
||||
while (XPending(GSdsp) > 0)
|
||||
switch (evt.evt)
|
||||
{
|
||||
XNextEvent(GSdsp, &E);
|
||||
switch (E.type)
|
||||
{
|
||||
case KeyPress:
|
||||
key = XLookupKeysym((XKeyEvent *) & E, 0);
|
||||
case KeyPress:
|
||||
// Shift F12 is not yet use by pcsx2. So keep it to grab/ungrab input
|
||||
// I found it very handy vs the automatic fullscreen detection
|
||||
// 1/ Does not need to detect full-screen
|
||||
// 2/ Can use a debugger in full-screen
|
||||
// 3/ Can grab input in window without the need of a pixelated full-screen
|
||||
if (key == XK_Shift_R || key == XK_Shift_L) s_Shift = true;
|
||||
if (key == XK_F12 && s_Shift) {
|
||||
if(!s_grab_input) {
|
||||
s_grab_input = true;
|
||||
XGrabPointer(GSdsp, GSwin, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, GSwin, None, CurrentTime);
|
||||
XGrabKeyboard(GSdsp, GSwin, True, GrabModeAsync, GrabModeAsync, CurrentTime);
|
||||
} else {
|
||||
s_grab_input = false;
|
||||
XUngrabPointer(GSdsp, CurrentTime);
|
||||
XUngrabKeyboard(GSdsp, CurrentTime);
|
||||
}
|
||||
}
|
||||
|
||||
i = FindKey(key, pad);
|
||||
i = get_keyboard_key(pad, key);
|
||||
|
||||
// Analog controls.
|
||||
if ((i > PAD_RY) && (i <= PAD_R_LEFT))
|
||||
{
|
||||
// Analog controls.
|
||||
if (IsAnalogKey(i))
|
||||
{
|
||||
used_by_keyboard = true; // avoid the joystick to reset the analog pad...
|
||||
switch (i)
|
||||
{
|
||||
case PAD_R_LEFT:
|
||||
case PAD_R_UP:
|
||||
case PAD_L_LEFT:
|
||||
case PAD_L_UP:
|
||||
Analog::ConfigurePad(pad, Analog::AnalogToPad(i), DEF_VALUE);
|
||||
Analog::ConfigurePad(pad, i, -DEF_VALUE);
|
||||
break;
|
||||
case PAD_R_RIGHT:
|
||||
case PAD_R_DOWN:
|
||||
case PAD_L_RIGHT:
|
||||
case PAD_L_DOWN:
|
||||
Analog::ConfigurePad(pad, Analog::AnalogToPad(i), -DEF_VALUE);
|
||||
Analog::ConfigurePad(pad, i, DEF_VALUE);
|
||||
break;
|
||||
}
|
||||
i += 0xff00;
|
||||
}
|
||||
|
||||
if (i != -1)
|
||||
{
|
||||
clear_bit(keyRelease, i);
|
||||
set_bit(keyPress, i);
|
||||
}
|
||||
//PAD_LOG("Key pressed:%d\n", i);
|
||||
|
||||
event.evt = KEYPRESS;
|
||||
event.key = key;
|
||||
break;
|
||||
|
||||
case KeyRelease:
|
||||
if (key == XK_Shift_R || key == XK_Shift_L) s_Shift = false;
|
||||
|
||||
i = get_keyboard_key(pad, key);
|
||||
|
||||
// Analog Controls.
|
||||
if (IsAnalogKey(i))
|
||||
{
|
||||
used_by_keyboard = false; // allow the joystick to reset the analog pad...
|
||||
Analog::ResetPad(pad, i);
|
||||
i += 0xff00;
|
||||
}
|
||||
|
||||
if (i != -1)
|
||||
{
|
||||
clear_bit(keyPress, i);
|
||||
set_bit(keyRelease, i);
|
||||
}
|
||||
|
||||
event.evt = KEYRELEASE;
|
||||
event.key = key;
|
||||
break;
|
||||
|
||||
case FocusIn:
|
||||
XAutoRepeatOff(GSdsp);
|
||||
break;
|
||||
|
||||
case FocusOut:
|
||||
XAutoRepeatOn(GSdsp);
|
||||
break;
|
||||
|
||||
case ButtonPress:
|
||||
i = get_keyboard_key(pad, evt.key);
|
||||
if (i != -1)
|
||||
{
|
||||
clear_bit(keyRelease, i);
|
||||
set_bit(keyPress, i);
|
||||
}
|
||||
break;
|
||||
|
||||
case ButtonRelease:
|
||||
i = get_keyboard_key(pad, evt.key);
|
||||
if (i != -1)
|
||||
{
|
||||
clear_bit(keyPress, i);
|
||||
set_bit(keyRelease, i);
|
||||
}
|
||||
break;
|
||||
|
||||
case MotionNotify:
|
||||
// FIXME: How to handle when the mouse does not move, no event generated!!!
|
||||
// 1/ small move == no move. Cons : can not do small movement
|
||||
// 2/ use a watchdog timer thread
|
||||
// 3/ ??? idea welcome ;)
|
||||
if (conf->options & ((PADOPTION_MOUSE_L|PADOPTION_MOUSE_R) << 16 * pad )) {
|
||||
unsigned int pad_x;
|
||||
unsigned int pad_y;
|
||||
// Note when both PADOPTION_MOUSE_R and PADOPTION_MOUSE_L are set, take only the right one
|
||||
if (conf->options & (PADOPTION_MOUSE_R << 16 * pad)) {
|
||||
pad_x = PAD_R_RIGHT;
|
||||
pad_y = PAD_R_UP;
|
||||
} else {
|
||||
pad_x = PAD_L_RIGHT;
|
||||
pad_y = PAD_L_UP;
|
||||
}
|
||||
|
||||
if (i != -1)
|
||||
{
|
||||
clear_bit(keyRelease, i);
|
||||
set_bit(keyPress, i);
|
||||
}
|
||||
//PAD_LOG("Key pressed:%d\n", i);
|
||||
unsigned x = evt.key & 0xFFFF;
|
||||
unsigned int value = abs(s_previous_mouse_x - x) * conf->sensibility;
|
||||
value = max(value, (unsigned int)DEF_VALUE);
|
||||
|
||||
event.evt = KEYPRESS;
|
||||
event.key = key;
|
||||
break;
|
||||
if (x == 0)
|
||||
Analog::ConfigurePad(pad, pad_x, -DEF_VALUE);
|
||||
else if (x == 0xFFFF)
|
||||
Analog::ConfigurePad(pad, pad_x, DEF_VALUE);
|
||||
else if (x < (s_previous_mouse_x -2))
|
||||
Analog::ConfigurePad(pad, pad_x, -value);
|
||||
else if (x > (s_previous_mouse_x +2))
|
||||
Analog::ConfigurePad(pad, pad_x, value);
|
||||
else
|
||||
Analog::ResetPad(pad, pad_x);
|
||||
|
||||
case KeyRelease:
|
||||
key = XLookupKeysym((XKeyEvent *) & E, 0);
|
||||
|
||||
i = FindKey(key, pad);
|
||||
unsigned y = evt.key >> 16;
|
||||
value = abs(s_previous_mouse_y - y) * conf->sensibility;
|
||||
value = max(value, (unsigned int)DEF_VALUE);
|
||||
|
||||
// Analog Controls.
|
||||
if ((i > PAD_RY) && (i <= PAD_R_LEFT))
|
||||
{
|
||||
Analog::ResetPad(pad, Analog::AnalogToPad(i));
|
||||
i += 0xff00;
|
||||
}
|
||||
if (y == 0)
|
||||
Analog::ConfigurePad(pad, pad_y, -DEF_VALUE);
|
||||
else if (y == 0xFFFF)
|
||||
Analog::ConfigurePad(pad, pad_y, DEF_VALUE);
|
||||
else if (y < (s_previous_mouse_y -2))
|
||||
Analog::ConfigurePad(pad, pad_y, -value);
|
||||
else if (y > (s_previous_mouse_y +2))
|
||||
Analog::ConfigurePad(pad, pad_y, value);
|
||||
else
|
||||
Analog::ResetPad(pad, pad_y);
|
||||
|
||||
if (i != -1)
|
||||
{
|
||||
clear_bit(keyPress, i);
|
||||
set_bit(keyRelease, i);
|
||||
}
|
||||
s_previous_mouse_x = x;
|
||||
s_previous_mouse_y = y;
|
||||
}
|
||||
|
||||
event.evt = KEYRELEASE;
|
||||
event.key = key;
|
||||
break;
|
||||
|
||||
case FocusIn:
|
||||
XAutoRepeatOff(GSdsp);
|
||||
break;
|
||||
|
||||
case FocusOut:
|
||||
XAutoRepeatOn(GSdsp);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
UpdateKeys(pad, keyPress, keyRelease);
|
||||
}
|
||||
|
||||
bool PollX11Keyboard(char* &temp, u32 &pkey)
|
||||
void PollForX11KeyboardInput(int pad, int& keyPress, int& keyRelease, bool& used_by_keyboard)
|
||||
{
|
||||
keyEvent evt;
|
||||
XEvent E;
|
||||
XButtonEvent* BE;
|
||||
|
||||
// Keyboard input send by PCSX2
|
||||
while (!ev_fifo.empty()) {
|
||||
AnalyzeKeyEvent(pad, ev_fifo.front(), keyPress, keyRelease, used_by_keyboard);
|
||||
pthread_mutex_lock(&mutex_KeyEvent);
|
||||
ev_fifo.pop();
|
||||
pthread_mutex_unlock(&mutex_KeyEvent);
|
||||
}
|
||||
|
||||
// keyboard input
|
||||
while (XPending(GSdsp) > 0)
|
||||
{
|
||||
XNextEvent(GSdsp, &E);
|
||||
evt.evt = E.type;
|
||||
evt.key = (int)XLookupKeysym((XKeyEvent *) & E, 0);
|
||||
// Change the format of the structure to be compatible with GSOpen2
|
||||
// mode (event come from pcsx2 not X)
|
||||
BE = (XButtonEvent*)&E;
|
||||
switch (evt.evt) {
|
||||
case MotionNotify: evt.key = (BE->x & 0xFFFF) | (BE->y << 16); break;
|
||||
case ButtonRelease:
|
||||
case ButtonPress: evt.key = BE->button; break;
|
||||
default: break;
|
||||
}
|
||||
AnalyzeKeyEvent(pad, evt, keyPress, keyRelease, used_by_keyboard);
|
||||
}
|
||||
}
|
||||
|
||||
bool PollX11KeyboardMouseEvent(u32 &pkey)
|
||||
{
|
||||
GdkEvent *ev = gdk_event_get();
|
||||
|
||||
if (ev != NULL)
|
||||
{
|
||||
if (ev->type == GDK_KEY_PRESS)
|
||||
{
|
||||
if (ev->type == GDK_KEY_PRESS) {
|
||||
|
||||
if (ev->key.keyval == GDK_Escape)
|
||||
{
|
||||
temp = "Unknown";
|
||||
pkey = NULL;
|
||||
}
|
||||
pkey = 0;
|
||||
else
|
||||
{
|
||||
temp = KeysymToChar(ev->key.keyval);
|
||||
pkey = ev->key.keyval;
|
||||
}
|
||||
|
||||
return true;
|
||||
} else if(ev->type == GDK_BUTTON_PRESS) {
|
||||
pkey = ev->button.button;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#else
|
||||
LRESULT WINAPI PADwndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
|
|
|
@ -29,19 +29,18 @@
|
|||
#include "Linux/linux.h"
|
||||
|
||||
extern Display *GSdsp;
|
||||
extern void PollForX11KeyboardInput(int pad);
|
||||
extern bool PollX11Keyboard(char* &temp, u32 &pkey);
|
||||
extern void PollForX11KeyboardInput(int pad, int& keyPress, int& keyRelease, bool& used_by_keyboard);
|
||||
extern bool PollX11KeyboardMouseEvent(u32 &pkey);
|
||||
extern Window GSwin;
|
||||
|
||||
#else
|
||||
|
||||
extern char* KeysymToChar(int keysym);
|
||||
extern WNDPROC GSwndProc;
|
||||
extern HWND GShwnd;
|
||||
|
||||
#endif
|
||||
|
||||
extern char* KeysymToChar(int keysym);
|
||||
extern void PollForKeyboardInput(int pad);
|
||||
extern void SetAutoRepeat(bool autorep);
|
||||
extern int FindKey(int key, int pad);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -34,14 +34,13 @@
|
|||
#include "svnrev.h"
|
||||
#endif
|
||||
|
||||
PADconf* conf;
|
||||
char libraryName[256];
|
||||
|
||||
PADconf conf;
|
||||
|
||||
keyEvent event;
|
||||
|
||||
u16 status[2];
|
||||
int pressure;
|
||||
int status_pressure[2][MAX_KEYS];
|
||||
static keyEvent s_event;
|
||||
std::string s_strIniPath("inis/");
|
||||
std::string s_strLogPath("logs/");
|
||||
|
@ -125,7 +124,15 @@ int ds2mode = 0; // DS Mode at start
|
|||
FILE *padLog = NULL;
|
||||
|
||||
pthread_spinlock_t s_mutexStatus;
|
||||
u32 s_keyPress[2], s_keyRelease[2];
|
||||
pthread_mutex_t mutex_KeyEvent;
|
||||
static u32 s_keyPress[2], s_keyRelease[2];
|
||||
|
||||
queue<keyEvent> ev_fifo;
|
||||
|
||||
static int padVib0[2];
|
||||
static int padVib1[2];
|
||||
static int padVibC[2];
|
||||
static int padVibF[2][4];
|
||||
|
||||
static void InitLibraryName()
|
||||
{
|
||||
|
@ -239,15 +246,11 @@ void CloseLogging()
|
|||
#endif
|
||||
}
|
||||
|
||||
void clearPAD()
|
||||
void clearPAD(int pad)
|
||||
{
|
||||
for (int pad = 0; pad < MAX_SUB_KEYS; pad++)
|
||||
{
|
||||
for (int key= 0; key < MAX_KEYS; ++key)
|
||||
{
|
||||
set_key(pad, key, 0);
|
||||
}
|
||||
}
|
||||
conf->keysym_map[pad].clear();
|
||||
for (int key= 0; key < MAX_KEYS; ++key)
|
||||
set_key(pad, key, 0);
|
||||
}
|
||||
|
||||
EXPORT_C_(s32) PADinit(u32 flags)
|
||||
|
@ -255,15 +258,17 @@ EXPORT_C_(s32) PADinit(u32 flags)
|
|||
initLogging();
|
||||
|
||||
pads |= flags;
|
||||
status[0] = 0xffff;
|
||||
status[1] = 0xffff;
|
||||
for (int i = 0 ; i < 2 ; i++) {
|
||||
status[i] = 0xffff;
|
||||
for (int j = 0 ; j < MAX_KEYS ; j++)
|
||||
status_pressure[i][j] = 255;
|
||||
}
|
||||
|
||||
LoadConfig();
|
||||
|
||||
PADsetMode(0, 0);
|
||||
PADsetMode(1, 0);
|
||||
|
||||
pressure = 100;
|
||||
Analog::Init();
|
||||
|
||||
return 0;
|
||||
|
@ -272,13 +277,16 @@ EXPORT_C_(s32) PADinit(u32 flags)
|
|||
EXPORT_C_(void) PADshutdown()
|
||||
{
|
||||
CloseLogging();
|
||||
if (conf) delete conf;
|
||||
}
|
||||
|
||||
EXPORT_C_(s32) PADopen(void *pDsp)
|
||||
{
|
||||
memset(&event, 0, sizeof(event));
|
||||
|
||||
while (!ev_fifo.empty()) ev_fifo.pop();
|
||||
pthread_spin_init(&s_mutexStatus, PTHREAD_PROCESS_PRIVATE);
|
||||
pthread_mutex_init(&mutex_KeyEvent, NULL);
|
||||
s_keyPress[0] = s_keyPress[1] = 0;
|
||||
s_keyRelease[0] = s_keyRelease[1] = 0;
|
||||
|
||||
|
@ -306,7 +314,9 @@ EXPORT_C_(void) PADsetLogDir(const char* dir)
|
|||
|
||||
EXPORT_C_(void) PADclose()
|
||||
{
|
||||
while (!ev_fifo.empty()) ev_fifo.pop();
|
||||
pthread_spin_destroy(&s_mutexStatus);
|
||||
pthread_mutex_destroy(&mutex_KeyEvent);
|
||||
_PADclose();
|
||||
}
|
||||
|
||||
|
@ -338,6 +348,11 @@ EXPORT_C_(u32) PADquery()
|
|||
void PADsetMode(int pad, int mode)
|
||||
{
|
||||
padMode[pad] = mode;
|
||||
// FIXME FEEDBACK
|
||||
padVib0[pad] = 0;
|
||||
padVib1[pad] = 0;
|
||||
padVibF[pad][0] = 0;
|
||||
padVibF[pad][1] = 0;
|
||||
switch (ds2mode)
|
||||
{
|
||||
case 0: // dualshock
|
||||
|
@ -381,7 +396,8 @@ EXPORT_C_(u8) PADstartPoll(int pad)
|
|||
u8 _PADpoll(u8 value)
|
||||
{
|
||||
u8 button_check = 0;
|
||||
const int avg_pressure = (pressure * 255) / 100;
|
||||
int vib_small;
|
||||
int vib_big;
|
||||
|
||||
if (curByte == 0)
|
||||
{
|
||||
|
@ -408,10 +424,10 @@ u8 _PADpoll(u8 value)
|
|||
|
||||
stdpar[curPad][2] = status[curPad] >> 8;
|
||||
stdpar[curPad][3] = status[curPad] & 0xff;
|
||||
stdpar[curPad][4] = Analog::Pad(curPad, PAD_RX);
|
||||
stdpar[curPad][5] = Analog::Pad(curPad, PAD_RY);
|
||||
stdpar[curPad][6] = Analog::Pad(curPad, PAD_LX);
|
||||
stdpar[curPad][7] = Analog::Pad(curPad, PAD_LY);
|
||||
stdpar[curPad][4] = Analog::Pad(curPad, PAD_R_RIGHT);
|
||||
stdpar[curPad][5] = Analog::Pad(curPad, PAD_R_UP);
|
||||
stdpar[curPad][6] = Analog::Pad(curPad, PAD_L_RIGHT);
|
||||
stdpar[curPad][7] = Analog::Pad(curPad, PAD_L_UP);
|
||||
|
||||
if (padMode[curPad] == 1)
|
||||
cmdLen = 20;
|
||||
|
@ -422,35 +438,35 @@ u8 _PADpoll(u8 value)
|
|||
switch (stdpar[curPad][3])
|
||||
{
|
||||
case 0xBF: // X
|
||||
stdpar[curPad][14] = avg_pressure;
|
||||
stdpar[curPad][14] = status_pressure[curPad][PAD_CROSS];
|
||||
break;
|
||||
|
||||
case 0xDF: // Circle
|
||||
stdpar[curPad][13] = avg_pressure;
|
||||
stdpar[curPad][13] = status_pressure[curPad][PAD_CIRCLE];
|
||||
break;
|
||||
|
||||
case 0xEF: // Triangle
|
||||
stdpar[curPad][12] = avg_pressure;
|
||||
stdpar[curPad][12] = status_pressure[curPad][PAD_TRIANGLE];
|
||||
break;
|
||||
|
||||
case 0x7F: // Square
|
||||
stdpar[curPad][15] = avg_pressure;
|
||||
stdpar[curPad][15] = status_pressure[curPad][PAD_SQUARE];
|
||||
break;
|
||||
|
||||
case 0xFB: // L1
|
||||
stdpar[curPad][16] = avg_pressure;
|
||||
stdpar[curPad][16] = status_pressure[curPad][PAD_L1];
|
||||
break;
|
||||
|
||||
case 0xF7: // R1
|
||||
stdpar[curPad][17] = avg_pressure;
|
||||
stdpar[curPad][17] = status_pressure[curPad][PAD_R1];
|
||||
break;
|
||||
|
||||
case 0xFE: // L2
|
||||
stdpar[curPad][18] = avg_pressure;
|
||||
stdpar[curPad][18] = status_pressure[curPad][PAD_L2];
|
||||
break;
|
||||
|
||||
case 0xFD: // R2
|
||||
stdpar[curPad][19] = avg_pressure;
|
||||
stdpar[curPad][19] = status_pressure[curPad][PAD_R2];
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -467,19 +483,19 @@ u8 _PADpoll(u8 value)
|
|||
switch (button_check)
|
||||
{
|
||||
case 0xE: // UP
|
||||
stdpar[curPad][10] = avg_pressure;
|
||||
stdpar[curPad][10] = status_pressure[curPad][PAD_UP];
|
||||
break;
|
||||
|
||||
case 0xB: // DOWN
|
||||
stdpar[curPad][11] = avg_pressure;
|
||||
stdpar[curPad][11] =status_pressure[curPad][PAD_DOWN];
|
||||
break;
|
||||
|
||||
case 0x7: // LEFT
|
||||
stdpar[curPad][9] = avg_pressure;
|
||||
stdpar[curPad][9] = status_pressure[curPad][PAD_LEFT];
|
||||
break;
|
||||
|
||||
case 0xD: // RIGHT
|
||||
stdpar[curPad][8] = avg_pressure;
|
||||
stdpar[curPad][8] = status_pressure[curPad][PAD_RIGHT];
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -490,6 +506,28 @@ u8 _PADpoll(u8 value)
|
|||
break;
|
||||
}
|
||||
buf = stdpar[curPad];
|
||||
|
||||
// FIXME FEEDBACK. Set effect here
|
||||
/* Small Motor */
|
||||
vib_small = padVibF[curPad][0] ? 2000 : 0;
|
||||
// if ((padVibF[curPad][2] != vib_small) && (padVibC[curPad] >= 0))
|
||||
if (padVibF[curPad][2] != vib_small)
|
||||
{
|
||||
padVibF[curPad][2] = vib_small;
|
||||
// SetDeviceForceS (padVibC[curPad], vib_small);
|
||||
JoystickInfo::DoHapticEffect(0, curPad, vib_small);
|
||||
}
|
||||
|
||||
/* Big Motor */
|
||||
vib_big = padVibF[curPad][1] ? 500 + 37*padVibF[curPad][1] : 0;
|
||||
// if ((padVibF[curPad][3] != vib_big) && (padVibC[curPad] >= 0))
|
||||
if (padVibF[curPad][3] != vib_big)
|
||||
{
|
||||
padVibF[curPad][3] = vib_big;
|
||||
// SetDeviceForceB (padVibC[curPad], vib_big);
|
||||
JoystickInfo::DoHapticEffect(1, curPad, vib_big);
|
||||
}
|
||||
|
||||
return padID[curPad];
|
||||
|
||||
case CMD_CONFIG_MODE: // CONFIG_MODE
|
||||
|
@ -546,6 +584,13 @@ u8 _PADpoll(u8 value)
|
|||
|
||||
switch (curCmd)
|
||||
{
|
||||
case CMD_READ_DATA_AND_VIBRATE:
|
||||
// FIXME FEEDBACK
|
||||
if (curByte == padVib0[curPad])
|
||||
padVibF[curPad][0] = value;
|
||||
if (curByte == padVib1[curPad])
|
||||
padVibF[curPad][1] = value;
|
||||
break;
|
||||
case CMD_CONFIG_MODE:
|
||||
if (curByte == 2)
|
||||
{
|
||||
|
@ -604,6 +649,31 @@ u8 _PADpoll(u8 value)
|
|||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_VIBRATION_TOGGLE:
|
||||
// FIXME FEEDBACK
|
||||
if (curByte >= 2)
|
||||
{
|
||||
if (curByte == padVib0[curPad])
|
||||
buf[curByte] = 0x00;
|
||||
if (curByte == padVib1[curPad])
|
||||
buf[curByte] = 0x01;
|
||||
if (value == 0x00)
|
||||
{
|
||||
padVib0[curPad] = curByte;
|
||||
// FIXME: code from SSSXPAD I'm not sure we need this part
|
||||
// if ((padID[curPad] & 0x0f) < (curByte - 1) / 2)
|
||||
// padID[curPad] = (padID[curPad] & 0xf0) + (curByte - 1) / 2;
|
||||
}
|
||||
else if (value == 0x01)
|
||||
{
|
||||
padVib1[curPad] = curByte;
|
||||
// FIXME: code from SSSXPAD I'm not sure we need this part
|
||||
// if ((padID[curPad] & 0x0f) < (curByte - 1) / 2)
|
||||
// padID[curPad] = (padID[curPad] & 0xf0) + (curByte - 1) / 2;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (curByte >= cmdLen) return 0;
|
||||
|
@ -627,3 +697,12 @@ EXPORT_C_(keyEvent*) PADkeyEvent()
|
|||
event.key = 0;
|
||||
return &s_event;
|
||||
}
|
||||
|
||||
#ifdef __LINUX__
|
||||
EXPORT_C_(void) PADWriteEvent(keyEvent &evt)
|
||||
{
|
||||
pthread_mutex_lock(&mutex_KeyEvent);
|
||||
ev_fifo.push(evt);
|
||||
pthread_mutex_unlock(&mutex_KeyEvent);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <queue>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
|
@ -67,7 +68,9 @@ enum PadOptions
|
|||
PADOPTION_REVERSELX = 0x2,
|
||||
PADOPTION_REVERSELY = 0x4,
|
||||
PADOPTION_REVERSERX = 0x8,
|
||||
PADOPTION_REVERSERY = 0x10
|
||||
PADOPTION_REVERSERY = 0x10,
|
||||
PADOPTION_MOUSE_L = 0x20,
|
||||
PADOPTION_MOUSE_R = 0x40
|
||||
};
|
||||
|
||||
extern FILE *padLog;
|
||||
|
@ -94,34 +97,30 @@ enum PadCommands
|
|||
|
||||
enum gamePadValues
|
||||
{
|
||||
PAD_R_LEFT = 27,
|
||||
PAD_R_DOWN = 26,
|
||||
PAD_R_RIGHT = 25,
|
||||
PAD_R_UP = 24,
|
||||
PAD_L_LEFT = 23,
|
||||
PAD_L_DOWN = 22,
|
||||
PAD_L_RIGHT = 21,
|
||||
PAD_L_UP = 20,
|
||||
PAD_RY = 19,
|
||||
PAD_LY = 18,
|
||||
PAD_RX = 17,
|
||||
PAD_LX = 16,
|
||||
PAD_LEFT = 15,
|
||||
PAD_DOWN = 14,
|
||||
PAD_RIGHT = 13,
|
||||
PAD_UP = 12,
|
||||
PAD_START = 11,
|
||||
PAD_R3 = 10,
|
||||
PAD_L3 = 9,
|
||||
PAD_SELECT = 8,
|
||||
PAD_SQUARE = 7,
|
||||
PAD_CROSS = 6,
|
||||
PAD_CIRCLE = 5,
|
||||
PAD_TRIANGLE = 4,
|
||||
PAD_R1 = 3,
|
||||
PAD_L1 = 2,
|
||||
PAD_R2 = 1,
|
||||
PAD_L2 = 0
|
||||
PAD_L2 = 0,
|
||||
PAD_R2,
|
||||
PAD_L1,
|
||||
PAD_R1,
|
||||
PAD_TRIANGLE,
|
||||
PAD_CIRCLE,
|
||||
PAD_CROSS,
|
||||
PAD_SQUARE,
|
||||
PAD_SELECT,
|
||||
PAD_L3,
|
||||
PAD_R3,
|
||||
PAD_START,
|
||||
PAD_UP,
|
||||
PAD_RIGHT,
|
||||
PAD_DOWN,
|
||||
PAD_LEFT,
|
||||
PAD_L_UP,
|
||||
PAD_L_RIGHT,
|
||||
PAD_L_DOWN,
|
||||
PAD_L_LEFT,
|
||||
PAD_R_UP,
|
||||
PAD_R_RIGHT,
|
||||
PAD_R_DOWN,
|
||||
PAD_R_LEFT
|
||||
};
|
||||
|
||||
// Activate bolche's analog controls hack
|
||||
|
@ -134,10 +133,14 @@ enum gamePadValues
|
|||
|
||||
extern keyEvent event;
|
||||
|
||||
extern queue<keyEvent> ev_fifo;
|
||||
extern pthread_mutex_t mutex_KeyEvent;
|
||||
|
||||
extern u16 status[2];
|
||||
extern int status_pressure[2][MAX_KEYS];
|
||||
extern u32 pads;
|
||||
|
||||
void clearPAD();
|
||||
void clearPAD(int pad);
|
||||
int POV(u32 direction, u32 angle);
|
||||
s32 _PADopen(void *pDsp);
|
||||
void _PADclose();
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
#ifndef GLWIN_H_INCLUDED
|
||||
#define GLWIN_H_INCLUDED
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define GL_WIN32_WINDOW
|
||||
#else
|
||||
#define USE_GSOPEN2
|
||||
#define GL_X11_WINDOW
|
||||
#endif
|
||||
|
||||
|
@ -37,7 +37,6 @@ class GLWindow
|
|||
private:
|
||||
#ifdef GL_X11_WINDOW
|
||||
Display *glDisplay;
|
||||
int glScreen;
|
||||
GLXContext context;
|
||||
XVisualInfo *vi;
|
||||
|
||||
|
@ -49,6 +48,7 @@ class GLWindow
|
|||
void GetWindowSize();
|
||||
void UpdateGrabKey();
|
||||
void Force43Ratio();
|
||||
void CreateContextGL();
|
||||
#endif
|
||||
bool fullScreen, doubleBuffered;
|
||||
u32 width, height, depth;
|
||||
|
|
|
@ -25,14 +25,24 @@
|
|||
#include <X11/Xlib.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef USE_GSOPEN2
|
||||
bool GLWindow::CreateWindow(void *pDisplay)
|
||||
{
|
||||
glWindow = (Window)*((u32*)(pDisplay)+1);
|
||||
// Do not take the display which come from pcsx2 neither change it.
|
||||
// You need a new one to do the operation in the GS thread
|
||||
glDisplay = XOpenDisplay(NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
bool GLWindow::CreateWindow(void *pDisplay)
|
||||
{
|
||||
// init support of multi thread
|
||||
if (!XInitThreads())
|
||||
ZZLog::Error_Log("Failed to init the xlib concurent threads");
|
||||
|
||||
glDisplay = XOpenDisplay(0);
|
||||
glScreen = DefaultScreen(glDisplay);
|
||||
glDisplay = XOpenDisplay(NULL);
|
||||
|
||||
if (pDisplay == NULL)
|
||||
{
|
||||
|
@ -40,10 +50,15 @@ bool GLWindow::CreateWindow(void *pDisplay)
|
|||
return false;
|
||||
}
|
||||
|
||||
// Allow pad to use the display
|
||||
*(Display**)pDisplay = glDisplay;
|
||||
// Pad can use the window to grab the input. For the moment just set to 0 to avoid
|
||||
// to grab an unknow window... Anyway GSopen1 might be dropped in the future
|
||||
*((u32*)(pDisplay)+1) = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool GLWindow::ReleaseContext()
|
||||
{
|
||||
|
@ -102,11 +117,11 @@ bool GLWindow::CreateVisual()
|
|||
};
|
||||
|
||||
/* get an appropriate visual */
|
||||
vi = glXChooseVisual(glDisplay, glScreen, attrListDbl);
|
||||
vi = glXChooseVisual(glDisplay, DefaultScreen(glDisplay), attrListDbl);
|
||||
|
||||
if (vi == NULL)
|
||||
{
|
||||
vi = glXChooseVisual(glDisplay, glScreen, attrListSgl);
|
||||
vi = glXChooseVisual(glDisplay, DefaultScreen(glDisplay), attrListSgl);
|
||||
doubleBuffered = false;
|
||||
ZZLog::Error_Log("Only Singlebuffered Visual!");
|
||||
}
|
||||
|
@ -140,7 +155,10 @@ void GLWindow::GetWindowSize()
|
|||
// update the gl buffer size
|
||||
UpdateWindowSize(width, height);
|
||||
|
||||
#ifndef USE_GSOPEN2
|
||||
// too verbose!
|
||||
ZZLog::Dev_Log("Resolution %dx%d. Depth %d bpp. Position (%d,%d)", width, height, depth, conf.x, conf.y);
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLWindow::GetGLXVersion()
|
||||
|
@ -149,7 +167,184 @@ void GLWindow::GetGLXVersion()
|
|||
|
||||
glXQueryVersion(glDisplay, &glxMajorVersion, &glxMinorVersion);
|
||||
|
||||
ZZLog::Error_Log("glX-Version %d.%d", glxMajorVersion, glxMinorVersion);
|
||||
if (glXIsDirect(glDisplay, context))
|
||||
ZZLog::Error_Log("glX-Version %d.%d with Direct Rendering", glxMajorVersion, glxMinorVersion);
|
||||
else
|
||||
ZZLog::Error_Log("glX-Version %d.%d with Indirect Rendering !!! It will be slow", glxMajorVersion, glxMinorVersion);
|
||||
|
||||
}
|
||||
|
||||
void GLWindow::CreateContextGL()
|
||||
{
|
||||
if (!glDisplay) return;
|
||||
|
||||
// Create a 2.0 opengl context. My understanding, you need it to call the gl function to get the 3.0 context
|
||||
context = glXCreateContext(glDisplay, vi, NULL, GL_TRUE);
|
||||
|
||||
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddress((GLubyte *) "glXCreateContextAttribsARB");
|
||||
PFNGLXCHOOSEFBCONFIGPROC glXChooseFBConfig = (PFNGLXCHOOSEFBCONFIGPROC) glXGetProcAddress((GLubyte *) "glXChooseFBConfig");
|
||||
if (!glXCreateContextAttribsARB or !glXChooseFBConfig) {
|
||||
ZZLog::Error_Log("No support of OpenGL 3.0\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Note this part seems linux specific
|
||||
int fbcount = 0;
|
||||
GLXFBConfig *framebuffer_config = glXChooseFBConfig(glDisplay, DefaultScreen(glDisplay), NULL, &fbcount);
|
||||
if (!framebuffer_config or !fbcount) return;
|
||||
|
||||
// At least create a 3.0 context with compatibility profile
|
||||
int attribs[] = {
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 0,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
0
|
||||
};
|
||||
GLXContext context_temp = glXCreateContextAttribsARB(glDisplay, framebuffer_config[0], NULL, true, attribs);
|
||||
if (context_temp) {
|
||||
ZZLog::Error_Log("Create a 3.0 opengl context");
|
||||
glXDestroyContext(glDisplay, context);
|
||||
context = context_temp;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_GSOPEN2
|
||||
bool GLWindow::DisplayWindow(int _width, int _height)
|
||||
{
|
||||
GetWindowSize();
|
||||
|
||||
if (!CreateVisual()) return false;
|
||||
|
||||
// connect the glx-context to the window
|
||||
CreateContextGL();
|
||||
glXMakeCurrent(glDisplay, glWindow, context);
|
||||
|
||||
GetGLXVersion();
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
bool GLWindow::DisplayWindow(int _width, int _height)
|
||||
{
|
||||
backbuffer.w = _width;
|
||||
backbuffer.h = _height;
|
||||
|
||||
if (!CreateVisual()) return false;
|
||||
|
||||
/* create a color map */
|
||||
attr.colormap = XCreateColormap(glDisplay, RootWindow(glDisplay, vi->screen),
|
||||
vi->visual, AllocNone);
|
||||
attr.border_pixel = 0;
|
||||
attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask |
|
||||
StructureNotifyMask | SubstructureRedirectMask | SubstructureNotifyMask |
|
||||
EnterWindowMask | LeaveWindowMask | FocusChangeMask ;
|
||||
|
||||
// Create a window at the last position/size
|
||||
glWindow = XCreateWindow(glDisplay, RootWindow(glDisplay, vi->screen),
|
||||
conf.x , conf.y , _width, _height, 0, vi->depth, InputOutput, vi->visual,
|
||||
CWBorderPixel | CWColormap | CWEventMask,
|
||||
&attr);
|
||||
|
||||
/* Allow to kill properly the window */
|
||||
Atom wmDelete = XInternAtom(glDisplay, "WM_DELETE_WINDOW", True);
|
||||
XSetWMProtocols(glDisplay, glWindow, &wmDelete, 1);
|
||||
|
||||
// Set icon name
|
||||
XSetIconName(glDisplay, glWindow, "ZZogl-pg");
|
||||
|
||||
// Draw the window
|
||||
XMapRaised(glDisplay, glWindow);
|
||||
XSync(glDisplay, false);
|
||||
|
||||
// connect the glx-context to the window
|
||||
CreateContextGL();
|
||||
glXMakeCurrent(glDisplay, glWindow, context);
|
||||
|
||||
GetGLXVersion();
|
||||
|
||||
// Always start in window mode
|
||||
fullScreen = 0;
|
||||
GetWindowSize();
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
void GLWindow::SwapGLBuffers()
|
||||
{
|
||||
if (glGetError() != GL_NO_ERROR) ZZLog::Debug_Log("glError before swap!");
|
||||
// FIXME I think we need to flush when there is only 1 visual buffer
|
||||
glXSwapBuffers(glDisplay, glWindow);
|
||||
// glClear(GL_COLOR_BUFFER_BIT);
|
||||
}
|
||||
|
||||
u32 THR_KeyEvent = 0; // Value for key event processing between threads
|
||||
bool THR_bShift = false;
|
||||
bool THR_bCtrl = false;
|
||||
|
||||
void GLWindow::ProcessEvents()
|
||||
{
|
||||
FUNCLOG
|
||||
|
||||
#ifdef USE_GSOPEN2
|
||||
GetWindowSize();
|
||||
#else
|
||||
ResizeCheck();
|
||||
#endif
|
||||
|
||||
if (THR_KeyEvent) // This value was passed from GSKeyEvents which could be in another thread
|
||||
{
|
||||
int my_KeyEvent = THR_KeyEvent;
|
||||
bool my_bShift = THR_bShift;
|
||||
bool my_bCtrl = THR_bCtrl;
|
||||
THR_KeyEvent = 0;
|
||||
|
||||
switch (my_KeyEvent)
|
||||
{
|
||||
case XK_F5:
|
||||
case XK_F6:
|
||||
case XK_F7:
|
||||
case XK_F9:
|
||||
// Note: to avoid some clash with PCSX2 shortcut in GSOpen2.
|
||||
// GS shortcut will only be activated when ctrl is press
|
||||
if (my_bCtrl)
|
||||
OnFKey(my_KeyEvent - XK_F1 + 1, my_bShift);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************** Function that are either stub or useless in GSOPEN2
|
||||
#define _NET_WM_STATE_REMOVE 0
|
||||
#define _NET_WM_STATE_ADD 1
|
||||
#define _NET_WM_STATE_TOGGLE 2
|
||||
|
||||
void GLWindow::Force43Ratio()
|
||||
{
|
||||
#ifndef USE_GSOPEN2
|
||||
// avoid black border in fullscreen
|
||||
if (fullScreen && conf.isWideScreen) {
|
||||
conf.width = width;
|
||||
conf.height = height;
|
||||
}
|
||||
|
||||
if(!fullScreen && !conf.isWideScreen) {
|
||||
// Compute the width based on height
|
||||
s32 new_width = (4*height)/3;
|
||||
// do not bother to resize for 5 pixels. Avoid a loop
|
||||
// due to round value
|
||||
if ( abs(new_width - width) > 5) {
|
||||
width = new_width;
|
||||
conf.width = new_width;
|
||||
// resize the window
|
||||
XLockDisplay(glDisplay);
|
||||
XResizeWindow(glDisplay, glWindow, new_width, height);
|
||||
XSync(glDisplay, False);
|
||||
XUnlockDisplay(glDisplay);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLWindow::UpdateGrabKey()
|
||||
|
@ -168,37 +363,9 @@ void GLWindow::UpdateGrabKey()
|
|||
#endif
|
||||
}
|
||||
|
||||
void GLWindow::Force43Ratio()
|
||||
{
|
||||
// avoid black border in fullscreen
|
||||
if (fullScreen && conf.isWideScreen) {
|
||||
conf.width = width;
|
||||
conf.height = height;
|
||||
}
|
||||
|
||||
if(!fullScreen && !conf.isWideScreen) {
|
||||
// Compute the width based on height
|
||||
s32 new_width = (4*height)/3;
|
||||
// do not bother to resize for 5 pixels. Avoid a loop
|
||||
// due to round value
|
||||
if ( abs(new_width - width) > 5) {
|
||||
width = new_width;
|
||||
conf.width = new_width;
|
||||
// resize the window
|
||||
XLockDisplay(glDisplay);
|
||||
XResizeWindow(glDisplay, glWindow, new_width, height);
|
||||
XSync(glDisplay, False);
|
||||
XUnlockDisplay(glDisplay);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define _NET_WM_STATE_REMOVE 0
|
||||
#define _NET_WM_STATE_ADD 1
|
||||
#define _NET_WM_STATE_TOGGLE 2
|
||||
|
||||
void GLWindow::ToggleFullscreen()
|
||||
{
|
||||
#ifndef USE_GSOPEN2
|
||||
if (!glDisplay or !glWindow) return;
|
||||
|
||||
Force43Ratio();
|
||||
|
@ -239,7 +406,7 @@ void GLWindow::ToggleFullscreen()
|
|||
// update info structure
|
||||
GetWindowSize();
|
||||
|
||||
UpdateGrabKey();
|
||||
UpdateGrabKey();
|
||||
|
||||
// avoid black border in widescreen fullscreen
|
||||
if (fullScreen && conf.isWideScreen) {
|
||||
|
@ -251,82 +418,7 @@ void GLWindow::ToggleFullscreen()
|
|||
if(fullScreen)
|
||||
XWarpPointer(glDisplay, None, glWindow, 0, 0, 0, 0, 2*width, 2*height);
|
||||
|
||||
}
|
||||
|
||||
bool GLWindow::DisplayWindow(int _width, int _height)
|
||||
{
|
||||
backbuffer.w = _width;
|
||||
backbuffer.h = _height;
|
||||
|
||||
if (!CreateVisual()) return false;
|
||||
|
||||
/* create a GLX context */
|
||||
context = glXCreateContext(glDisplay, vi, NULL, GL_TRUE);
|
||||
|
||||
/* create a color map */
|
||||
attr.colormap = XCreateColormap(glDisplay, RootWindow(glDisplay, vi->screen),
|
||||
vi->visual, AllocNone);
|
||||
attr.border_pixel = 0;
|
||||
attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask |
|
||||
StructureNotifyMask | SubstructureRedirectMask | SubstructureNotifyMask |
|
||||
EnterWindowMask | LeaveWindowMask | FocusChangeMask ;
|
||||
|
||||
GetGLXVersion();
|
||||
|
||||
// Create a window at the last position/size
|
||||
glWindow = XCreateWindow(glDisplay, RootWindow(glDisplay, vi->screen),
|
||||
conf.x , conf.y , _width, _height, 0, vi->depth, InputOutput, vi->visual,
|
||||
CWBorderPixel | CWColormap | CWEventMask,
|
||||
&attr);
|
||||
|
||||
/* Allow to kill properly the window */
|
||||
Atom wmDelete = XInternAtom(glDisplay, "WM_DELETE_WINDOW", True);
|
||||
XSetWMProtocols(glDisplay, glWindow, &wmDelete, 1);
|
||||
|
||||
// Set icon name
|
||||
XSetIconName(glDisplay, glWindow, "ZZogl-pg");
|
||||
|
||||
// Draw the window
|
||||
XMapRaised(glDisplay, glWindow);
|
||||
XSync(glDisplay, false);
|
||||
|
||||
// connect the glx-context to the window
|
||||
glXMakeCurrent(glDisplay, glWindow, context);
|
||||
|
||||
if (glXIsDirect(glDisplay, context))
|
||||
ZZLog::Error_Log("You have Direct Rendering!");
|
||||
else
|
||||
ZZLog::Error_Log("No Direct Rendering possible!");
|
||||
|
||||
// Always start in window mode
|
||||
fullScreen = 0;
|
||||
GetWindowSize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void GLWindow::SwapGLBuffers()
|
||||
{
|
||||
if (glGetError() != GL_NO_ERROR) ZZLog::Debug_Log("glError before swap!");
|
||||
glXSwapBuffers(glDisplay, glWindow);
|
||||
}
|
||||
|
||||
void GLWindow::SetTitle(char *strtitle)
|
||||
{
|
||||
if (!glDisplay or !glWindow) return;
|
||||
if (fullScreen) return;
|
||||
|
||||
XTextProperty prop;
|
||||
memset(&prop, 0, sizeof(prop));
|
||||
|
||||
char* ptitle = strtitle;
|
||||
if (XStringListToTextProperty(&ptitle, 1, &prop)) {
|
||||
XLockDisplay(glDisplay);
|
||||
XSetWMName(glDisplay, glWindow, &prop);
|
||||
XUnlockDisplay(glDisplay);
|
||||
}
|
||||
|
||||
XFree(prop.value);
|
||||
#endif
|
||||
}
|
||||
|
||||
void GLWindow::ResizeCheck()
|
||||
|
@ -358,32 +450,24 @@ void GLWindow::ResizeCheck()
|
|||
XUnlockDisplay(glDisplay);
|
||||
}
|
||||
|
||||
u32 THR_KeyEvent = 0; // Value for key event processing between threads
|
||||
bool THR_bShift = false;
|
||||
|
||||
void GLWindow::ProcessEvents()
|
||||
void GLWindow::SetTitle(char *strtitle)
|
||||
{
|
||||
FUNCLOG
|
||||
#ifndef USE_GSOPEN2
|
||||
if (!glDisplay or !glWindow) return;
|
||||
if (fullScreen) return;
|
||||
|
||||
// check resizing
|
||||
ResizeCheck();
|
||||
XTextProperty prop;
|
||||
memset(&prop, 0, sizeof(prop));
|
||||
|
||||
if (THR_KeyEvent) // This value was passed from GSKeyEvents which could be in another thread
|
||||
{
|
||||
int my_KeyEvent = THR_KeyEvent;
|
||||
bool my_bShift = THR_bShift;
|
||||
THR_KeyEvent = 0;
|
||||
char* ptitle = strtitle;
|
||||
if (XStringListToTextProperty(&ptitle, 1, &prop)) {
|
||||
XLockDisplay(glDisplay);
|
||||
XSetWMName(glDisplay, glWindow, &prop);
|
||||
XUnlockDisplay(glDisplay);
|
||||
}
|
||||
|
||||
switch (my_KeyEvent)
|
||||
{
|
||||
case XK_F5:
|
||||
case XK_F6:
|
||||
case XK_F7:
|
||||
case XK_F9:
|
||||
OnFKey(my_KeyEvent - XK_F1 + 1, my_bShift);
|
||||
break;
|
||||
}
|
||||
}
|
||||
XFree(prop.value);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -31,6 +31,12 @@ using namespace std;
|
|||
|
||||
extern float fFPS;
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define EXPORT_C_(type) extern "C" type CALLBACK
|
||||
#else
|
||||
#define EXPORT_C_(type) extern "C" __attribute__((externally_visible,visibility("default"))) type
|
||||
#endif
|
||||
|
||||
extern int g_LastCRC;
|
||||
|
||||
struct Vector_16F
|
||||
|
|
|
@ -307,8 +307,8 @@ s32 CALLBACK GSopen(void *pDsp, char *Title, int multithread)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef USE_GOPEN2
|
||||
s32 CALLBACK GSopen2( void* pDsp, INT32 flags )
|
||||
#ifdef USE_GSOPEN2
|
||||
EXPORT_C_(s32) GSopen2( void* pDsp, u32 flags )
|
||||
{
|
||||
FUNCLOG
|
||||
|
||||
|
@ -327,7 +327,7 @@ s32 CALLBACK GSopen2( void* pDsp, INT32 flags )
|
|||
ZZLog::GS_Log("Using %s:%d.%d.%d.", libraryName, zgsrevision, zgsbuild, zgsminor);
|
||||
|
||||
ZZLog::WriteLn("Capturing ZZOgl window.");
|
||||
if ((!GLWin.GetWindow(pDsp)) || (!ZZCreate2(conf.width, conf.height))) return -1;// Needs to be added.
|
||||
if ((!GLWin.CreateWindow(pDsp)) || (!ZZCreate(conf.width, conf.height))) return -1;
|
||||
|
||||
ZZLog::WriteLn("Initialization successful.");
|
||||
|
||||
|
@ -492,7 +492,10 @@ void CALLBACK GSvsync(int interlace)
|
|||
fFPS = UPDATE_FRAMES * 1000.0f / (float)max(d - dwTime, (u32)1);
|
||||
dwTime = d;
|
||||
g_nFrame += UPDATE_FRAMES;
|
||||
#ifndef USE_GSOPEN2
|
||||
// let PCSX2 manage the title
|
||||
SetGSTitle();
|
||||
#endif
|
||||
|
||||
// if( g_nFrame > 100 && fFPS > 60.0f ) {
|
||||
// ZZLog::Debug_Log("Set profile.");
|
||||
|
|
|
@ -30,13 +30,13 @@
|
|||
|
||||
extern u32 THR_KeyEvent; // value for passing out key events beetwen threads
|
||||
extern bool THR_bShift;
|
||||
extern bool THR_bCtrl;
|
||||
|
||||
static map<string, confOptsStruct> mapConfOpts;
|
||||
static gameHacks tempHacks;
|
||||
|
||||
void CALLBACK GSkeyEvent(keyEvent *ev)
|
||||
{
|
||||
//static bool bShift = false;
|
||||
static bool bAlt = false;
|
||||
|
||||
switch (ev->evt)
|
||||
|
@ -57,10 +57,14 @@ void CALLBACK GSkeyEvent(keyEvent *ev)
|
|||
|
||||
case XK_Shift_L:
|
||||
case XK_Shift_R:
|
||||
//bShift = true;
|
||||
THR_bShift = true;
|
||||
break;
|
||||
|
||||
case XK_Control_L:
|
||||
case XK_Control_R:
|
||||
THR_bCtrl = true;
|
||||
break;
|
||||
|
||||
case XK_Alt_L:
|
||||
case XK_Alt_R:
|
||||
bAlt = true;
|
||||
|
@ -77,10 +81,14 @@ void CALLBACK GSkeyEvent(keyEvent *ev)
|
|||
{
|
||||
case XK_Shift_L:
|
||||
case XK_Shift_R:
|
||||
//bShift = false;
|
||||
THR_bShift = false;
|
||||
break;
|
||||
|
||||
case XK_Control_L:
|
||||
case XK_Control_R:
|
||||
THR_bCtrl = false;
|
||||
break;
|
||||
|
||||
case XK_Alt_L:
|
||||
case XK_Alt_R:
|
||||
bAlt = false;
|
||||
|
|
|
@ -379,10 +379,10 @@ inline bool CreateFillExtensionsMap()
|
|||
|
||||
PFNGLGETSTRINGIPROC glGetStringi = 0;
|
||||
glGetStringi = (PFNGLGETSTRINGIPROC)wglGetProcAddress("glGetStringi");
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &max_ext);
|
||||
|
||||
if (glGetStringi) {
|
||||
if (glGetStringi && max_ext) {
|
||||
// Get opengl extension (opengl3)
|
||||
glGetIntegerv(GL_NUM_EXTENSIONS, &max_ext);
|
||||
for (GLint i = 0; i < max_ext; i++)
|
||||
{
|
||||
string extension((const char*)glGetStringi(GL_EXTENSIONS, i));
|
||||
|
@ -392,14 +392,14 @@ inline bool CreateFillExtensionsMap()
|
|||
if (i != (max_ext - 1)) all_ext += ", ";
|
||||
}
|
||||
} else {
|
||||
// fallback to old method (pre opengl3, intel gma ...)
|
||||
// fallback to old method (pre opengl3, intel gma, geforce 7 ...)
|
||||
ZZLog::Error_Log("glGetStringi opengl 3 interface not supported, fallback to opengl 2");
|
||||
|
||||
const char* ptoken = (const char*)glGetString(GL_EXTENSIONS);
|
||||
all_ext = string(ptoken); // save the string to print a nice debug message
|
||||
|
||||
if (ptoken == NULL) return false;
|
||||
|
||||
all_ext = string(ptoken); // save the string to print a nice debug message
|
||||
|
||||
const char* pend = NULL;
|
||||
while (ptoken != NULL)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue