mirror of
https://github.com/RPCS3/hidapi.git
synced 2024-11-27 12:00:43 +00:00
Update mac implementation.
Made a Mac Application Bundle (TestGUI.app) for this application. Handle dock actions properly for Quit and Show (single click) events.
This commit is contained in:
parent
54c8061ec5
commit
f41f06cadd
@ -11,14 +11,17 @@ all: testgui
|
||||
CC=gcc
|
||||
CXX=g++
|
||||
COBJS=../mac/hid.o
|
||||
CPPOBJS=test.o
|
||||
CPPOBJS=test.o mac_support.o
|
||||
OBJS=$(COBJS) $(CPPOBJS)
|
||||
CFLAGS=-I../hidapi -Wall -g -c `fox-config --cflags`
|
||||
LIBS=`fox-config --libs` -framework IOKit -framework CoreFoundation
|
||||
LIBS=`fox-config --libs` -framework IOKit -framework CoreFoundation -framework Carbon
|
||||
|
||||
|
||||
testgui: $(OBJS)
|
||||
g++ -Wall -g $^ $(LIBS) -o testgui
|
||||
./copy_to_bundle.sh
|
||||
#cp TestGUI.app/Contents/MacOS/testgui TestGUI.app/Contents/MacOS/tg
|
||||
#cp start.sh TestGUI.app/Contents/MacOS/testgui
|
||||
|
||||
$(COBJS): %.o: %.c
|
||||
$(CC) $(CFLAGS) $< -o $@
|
||||
|
28
testgui/TestGUI.app/Contents/Info.plist
Normal file
28
testgui/TestGUI.app/Contents/Info.plist
Normal file
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string></string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>TestGUI</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>Signal11.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>us.signal11.hidtestgui</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>testgui</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>CSResourcesFileMapped</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
BIN
testgui/TestGUI.app/Contents/MacOS/libFOX-1.7.0.dylib
Executable file
BIN
testgui/TestGUI.app/Contents/MacOS/libFOX-1.7.0.dylib
Executable file
Binary file not shown.
BIN
testgui/TestGUI.app/Contents/MacOS/libpng12.0.dylib
Executable file
BIN
testgui/TestGUI.app/Contents/MacOS/libpng12.0.dylib
Executable file
Binary file not shown.
BIN
testgui/TestGUI.app/Contents/MacOS/libz.1.dylib
Executable file
BIN
testgui/TestGUI.app/Contents/MacOS/libz.1.dylib
Executable file
Binary file not shown.
1
testgui/TestGUI.app/Contents/PkgInfo
Normal file
1
testgui/TestGUI.app/Contents/PkgInfo
Normal file
@ -0,0 +1 @@
|
||||
APPL????
|
Binary file not shown.
BIN
testgui/TestGUI.app/Contents/Resources/Signal11.icns
Normal file
BIN
testgui/TestGUI.app/Contents/Resources/Signal11.icns
Normal file
Binary file not shown.
80
testgui/copy_to_bundle.sh
Executable file
80
testgui/copy_to_bundle.sh
Executable file
@ -0,0 +1,80 @@
|
||||
#!/bin/bash
|
||||
|
||||
#### Configuration:
|
||||
# The name of the executable. It is assumed
|
||||
# that it is in the current working directory.
|
||||
EXE_NAME=testgui
|
||||
# Path to the executable directory inside the bundle.
|
||||
EXEPATH=./TestGUI.app/Contents/MacOS
|
||||
# Libraries to explicitly bundle, even though they
|
||||
# may not be in /opt/local. One per line. These
|
||||
# are used with grep, so only a portion of the name
|
||||
# is required. eg: libFOX, libz, etc.
|
||||
LIBS_TO_BUNDLE=libFOX
|
||||
|
||||
|
||||
function copydeps {
|
||||
local file=$1
|
||||
# echo "Copying deps for $file...."
|
||||
local BASE_OF_EXE=`basename $file`
|
||||
|
||||
# A will contain the dependencies of this library
|
||||
local A=`otool -LX $file |cut -f 1 -d " "`
|
||||
local i
|
||||
for i in $A; do
|
||||
local BASE=`basename $i`
|
||||
|
||||
# See if it's a lib we specifically want to bundle
|
||||
local bundle_this_lib=0
|
||||
local j
|
||||
for j in $LIBS_TO_BUNDLE; do
|
||||
echo $i |grep -q $j
|
||||
if [ $? -eq 0 ]; then
|
||||
bundle_this_lib=1
|
||||
echo "bundling $i because it's in the list."
|
||||
break;
|
||||
fi
|
||||
done
|
||||
|
||||
# See if it's in /opt/local. Bundle all in /opt/local
|
||||
local isOptLocal=0
|
||||
echo $i |grep -q /opt/local
|
||||
if [ $? -eq 0 ]; then
|
||||
isOptLocal=1
|
||||
echo "bundling $i because it's in /opt/local."
|
||||
fi
|
||||
|
||||
# Bundle the library
|
||||
if [ $isOptLocal -ne 0 ] || [ $bundle_this_lib -ne 0 ]; then
|
||||
|
||||
# Copy the file into the bundle if it exists.
|
||||
if [ -f $EXEPATH/$BASE ]; then
|
||||
z=0
|
||||
else
|
||||
cp $i $EXEPATH
|
||||
fi
|
||||
|
||||
|
||||
# echo "$BASE_OF_EXE depends on $BASE"
|
||||
|
||||
# Fix the paths using install_name_tool and then
|
||||
# call this function recursively for each dependency
|
||||
# of this library.
|
||||
if [ $BASE_OF_EXE != $BASE ]; then
|
||||
|
||||
# Fix the paths
|
||||
install_name_tool -id @executable_path/$BASE $EXEPATH/$BASE
|
||||
install_name_tool -change $i @executable_path/$BASE $EXEPATH/$BASE_OF_EXE
|
||||
|
||||
# Call this function (recursive) on
|
||||
# on each dependency of this library.
|
||||
copydeps $EXEPATH/$BASE
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
rm $EXEPATH/*
|
||||
cp $EXE_NAME $EXEPATH
|
||||
copydeps $EXEPATH/$EXE_NAME
|
||||
|
117
testgui/mac_support.cpp
Normal file
117
testgui/mac_support.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
/*******************************
|
||||
Mac support for HID Test GUI
|
||||
|
||||
Alan Ott
|
||||
Signal 11 Software
|
||||
|
||||
Some of this code is from Apple Documentation, most notably
|
||||
http://developer.apple.com/legacy/mac/library/documentation/AppleScript/Conceptual/AppleEvents/AppleEvents.pdf
|
||||
*******************************/
|
||||
|
||||
#include <Carbon/Carbon.h>
|
||||
#include <fx.h>
|
||||
|
||||
|
||||
extern FXMainWindow *g_main_window;
|
||||
|
||||
static pascal OSErr HandleQuitMessage(const AppleEvent *theAppleEvent, AppleEvent
|
||||
*reply, long handlerRefcon)
|
||||
{
|
||||
puts("Quitting\n");
|
||||
FXApp::instance()->exit();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static pascal OSErr HandleReopenMessage(const AppleEvent *theAppleEvent, AppleEvent
|
||||
*reply, long handlerRefcon)
|
||||
{
|
||||
puts("Showing");
|
||||
g_main_window->show();
|
||||
return 0;
|
||||
}
|
||||
|
||||
OSStatus AEHandler(EventHandlerCallRef inCaller, EventRef inEvent, void* inRefcon)
|
||||
{
|
||||
Boolean release = false;
|
||||
EventRecord eventRecord;
|
||||
OSErr ignoreErrForThisSample;
|
||||
|
||||
// Events of type kEventAppleEvent must be removed from the queue
|
||||
// before being passed to AEProcessAppleEvent.
|
||||
if (IsEventInQueue(GetMainEventQueue(), inEvent))
|
||||
{
|
||||
// RemoveEventFromQueue will release the event, which will
|
||||
// destroy it if we don't retain it first.
|
||||
RetainEvent(inEvent);
|
||||
release = true;
|
||||
RemoveEventFromQueue(GetMainEventQueue(), inEvent);
|
||||
}
|
||||
// Convert the event ref to the type AEProcessAppleEvent expects.
|
||||
ConvertEventRefToEventRecord(inEvent, &eventRecord);
|
||||
ignoreErrForThisSample = AEProcessAppleEvent(&eventRecord);
|
||||
if (release)
|
||||
ReleaseEvent(inEvent);
|
||||
// This Carbon event has been handled, even if no AppleEvent handlers
|
||||
// were installed for the Apple event.
|
||||
return noErr;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void HandleEvent(EventRecord *event)
|
||||
{
|
||||
switch (event->what)
|
||||
{
|
||||
case mouseDown:
|
||||
//HandleMouseDown(event);
|
||||
break;
|
||||
case keyDown:
|
||||
case autoKey:
|
||||
//HandleKeyPress(event);
|
||||
break;
|
||||
case kHighLevelEvent:
|
||||
puts("Calling ProcessAppleEvent\n");
|
||||
AEProcessAppleEvent(event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
init_apple_message_system()
|
||||
{
|
||||
OSErr err;
|
||||
static const EventTypeSpec appleEvents[] =
|
||||
{
|
||||
{ kEventClassAppleEvent, kEventAppleEvent }
|
||||
};
|
||||
|
||||
/* Install the handler for Apple Events */
|
||||
InstallApplicationEventHandler(NewEventHandlerUPP(AEHandler),
|
||||
GetEventTypeCount(appleEvents), appleEvents, 0, NULL);
|
||||
|
||||
/* Install handlers for the individual Apple Events that come
|
||||
from the Dock icon: the Reopen (click), and the Quit messages. */
|
||||
err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
|
||||
NewAEEventHandlerUPP(HandleQuitMessage), 0, false);
|
||||
err = AEInstallEventHandler(kCoreEventClass, kAEReopenApplication,
|
||||
NewAEEventHandlerUPP(HandleReopenMessage), 0, false);
|
||||
}
|
||||
|
||||
void
|
||||
check_apple_events()
|
||||
{
|
||||
RgnHandle cursorRgn = NULL;
|
||||
Boolean gotEvent=TRUE;
|
||||
EventRecord event;
|
||||
|
||||
while (gotEvent) {
|
||||
gotEvent = WaitNextEvent(everyEvent, &event, 0L/*timeout*/, cursorRgn);
|
||||
if (gotEvent) {
|
||||
// No need to handle the events here. The Apple
|
||||
// Events are handled automatically by just calling
|
||||
// waitNextEvent();
|
||||
|
||||
//HandleEvent(&event);
|
||||
}
|
||||
}
|
||||
}
|
15
testgui/mac_support.h
Normal file
15
testgui/mac_support.h
Normal file
@ -0,0 +1,15 @@
|
||||
/*******************************
|
||||
Mac support for HID Test GUI
|
||||
|
||||
Alan Ott
|
||||
Signal 11 Software
|
||||
|
||||
*******************************/
|
||||
|
||||
#ifndef MAC_SUPPORT_H__
|
||||
#define MAC_SUPPORT_H__
|
||||
|
||||
void init_apple_message_system();
|
||||
void check_apple_events();
|
||||
|
||||
#endif
|
2
testgui/start.sh
Executable file
2
testgui/start.sh
Executable file
@ -0,0 +1,2 @@
|
||||
#!/bin/bash
|
||||
xterm -e /Users/alan/work/hidapi/testgui/TestGUI.app/Contents/MacOS/tg
|
@ -17,6 +17,7 @@
|
||||
#include <fx.h>
|
||||
|
||||
#include "hidapi.h"
|
||||
#include "mac_support.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
@ -38,6 +39,7 @@ public:
|
||||
ID_SEND_FEATURE_REPORT,
|
||||
ID_CLEAR,
|
||||
ID_TIMER,
|
||||
ID_MAC_TIMER,
|
||||
ID_LAST,
|
||||
};
|
||||
|
||||
@ -68,6 +70,7 @@ public:
|
||||
long onSendFeatureReport(FXObject *sender, FXSelector sel, void *ptr);
|
||||
long onClear(FXObject *sender, FXSelector sel, void *ptr);
|
||||
long onTimeout(FXObject *sender, FXSelector sel, void *ptr);
|
||||
long onMacTimeout(FXObject *sender, FXSelector sel, void *ptr);
|
||||
};
|
||||
|
||||
// FOX 1.7 changes the timeouts to all be nanoseconds.
|
||||
@ -78,6 +81,9 @@ public:
|
||||
const int timeout_scalar = 1;
|
||||
#endif
|
||||
|
||||
FXMainWindow *g_main_window;
|
||||
|
||||
|
||||
FXDEFMAP(MainWindow) MainWindowMap [] = {
|
||||
FXMAPFUNC(SEL_COMMAND, MainWindow::ID_CONNECT, MainWindow::onConnect ),
|
||||
FXMAPFUNC(SEL_COMMAND, MainWindow::ID_DISCONNECT, MainWindow::onDisconnect ),
|
||||
@ -85,6 +91,7 @@ FXDEFMAP(MainWindow) MainWindowMap [] = {
|
||||
FXMAPFUNC(SEL_COMMAND, MainWindow::ID_SEND_FEATURE_REPORT, MainWindow::onSendFeatureReport ),
|
||||
FXMAPFUNC(SEL_COMMAND, MainWindow::ID_CLEAR, MainWindow::onClear ),
|
||||
FXMAPFUNC(SEL_TIMEOUT, MainWindow::ID_TIMER, MainWindow::onTimeout ),
|
||||
FXMAPFUNC(SEL_TIMEOUT, MainWindow::ID_MAC_TIMER, MainWindow::onMacTimeout ),
|
||||
};
|
||||
|
||||
FXIMPLEMENT(MainWindow, FXMainWindow, MainWindowMap, ARRAYNUMBER(MainWindowMap));
|
||||
@ -187,6 +194,12 @@ MainWindow::create()
|
||||
device_list->selectItem(0);
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
init_apple_message_system();
|
||||
#endif
|
||||
|
||||
getApp()->addTimeout(this, ID_MAC_TIMER,
|
||||
50 * timeout_scalar /*50ms*/);
|
||||
}
|
||||
|
||||
long
|
||||
@ -320,11 +333,24 @@ MainWindow::onTimeout(FXObject *sender, FXSelector sel, void *ptr)
|
||||
return 1;
|
||||
}
|
||||
|
||||
long
|
||||
MainWindow::onMacTimeout(FXObject *sender, FXSelector sel, void *ptr)
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
check_apple_events();
|
||||
|
||||
getApp()->addTimeout(this, ID_MAC_TIMER,
|
||||
50 * timeout_scalar /*50ms*/);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FXApp app("HIDAPI Test Application", "Signal 11 Software");
|
||||
app.init(argc, argv);
|
||||
new MainWindow(&app);
|
||||
g_main_window = new MainWindow(&app);
|
||||
app.create();
|
||||
app.run();
|
||||
return 0;
|
||||
|
Loading…
Reference in New Issue
Block a user