So here it goes..
I hope I have fixed all parts that don't follow our guidelines. (that python script was good start) This is the filter.. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@33847 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -2,3 +2,4 @@ SubDir HAIKU_TOP src add-ons input_server filters ;
|
||||
|
||||
SubInclude HAIKU_TOP src add-ons input_server filters screen_saver ;
|
||||
SubInclude HAIKU_TOP src add-ons input_server filters vmware_mouse ;
|
||||
SubInclude HAIKU_TOP src add-ons input_server filters shortcut_catcher ;
|
||||
|
||||
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
* Copyright 1999-2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jeremy Friesner
|
||||
*/
|
||||
|
||||
|
||||
#include "BitFieldTesters.h"
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
BitFieldTester::BitFieldTester()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
BitFieldTester::BitFieldTester(BMessage* from)
|
||||
:
|
||||
BArchivable(from)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BitFieldTester::Archive(BMessage* into, bool deep) const
|
||||
{
|
||||
return BArchivable::Archive(into, deep);
|
||||
}
|
||||
|
||||
|
||||
// ---------------- ConstantFieldTester starts -------------------------------
|
||||
ConstantFieldTester::ConstantFieldTester(bool result)
|
||||
:
|
||||
fResult(result)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
ConstantFieldTester::ConstantFieldTester(BMessage* from)
|
||||
:
|
||||
BitFieldTester(from)
|
||||
{
|
||||
if (from->FindBool("ctRes", &fResult) != B_NO_ERROR)
|
||||
printf("ConstantFieldTester: Error, no ctRes!\n");
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ConstantFieldTester::Archive(BMessage* into, bool deep) const
|
||||
{
|
||||
status_t ret = BitFieldTester::Archive(into, deep);
|
||||
into->AddBool("ctRes", fResult);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
BArchivable*
|
||||
ConstantFieldTester::Instantiate(BMessage* from)
|
||||
{
|
||||
if (validate_instantiation(from, "ConstantFieldTester"))
|
||||
return new ConstantFieldTester(from);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ConstantFieldTester::IsMatching(uint32 field)
|
||||
{
|
||||
return fResult;
|
||||
}
|
||||
|
||||
|
||||
// ---------------- HasBitsFieldTester starts -------------------------------
|
||||
HasBitsFieldTester::HasBitsFieldTester(uint32 requiredBits,
|
||||
uint32 forbiddenBits)
|
||||
:
|
||||
fRequiredBits(requiredBits),
|
||||
fForbiddenBits(forbiddenBits)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
HasBitsFieldTester::HasBitsFieldTester(BMessage* from)
|
||||
:
|
||||
BitFieldTester(from)
|
||||
{
|
||||
if (from->FindInt32("rqBits", (int32*) &fRequiredBits) != B_NO_ERROR)
|
||||
printf("HasBitsFieldTester: Error, no rqBits!\n");
|
||||
|
||||
if (from->FindInt32("fbBits", (int32*) &fForbiddenBits) != B_NO_ERROR)
|
||||
printf("HasBitsFieldTester: Error, no fbBits!\n");
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HasBitsFieldTester::Archive(BMessage* into, bool deep) const
|
||||
{
|
||||
status_t ret = BitFieldTester::Archive(into, deep);
|
||||
into->AddInt32("rqBits", fRequiredBits);
|
||||
into->AddInt32("fbBits", fForbiddenBits);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
BArchivable*
|
||||
HasBitsFieldTester::Instantiate(BMessage* from)
|
||||
{
|
||||
if (validate_instantiation(from, "HasBitsFieldTester"))
|
||||
return new HasBitsFieldTester(from);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
HasBitsFieldTester::IsMatching(uint32 field)
|
||||
{
|
||||
return ((((fRequiredBits & (~field)) == 0))
|
||||
&& ((fForbiddenBits & (~field)) == fForbiddenBits));
|
||||
}
|
||||
|
||||
|
||||
// ---------------- NotFieldTester starts -------------------------------
|
||||
NotFieldTester::NotFieldTester(BitFieldTester* slave)
|
||||
:
|
||||
fSlave(slave)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
NotFieldTester::~NotFieldTester()
|
||||
{
|
||||
delete fSlave;
|
||||
}
|
||||
|
||||
|
||||
NotFieldTester::NotFieldTester(BMessage* from)
|
||||
:
|
||||
BitFieldTester(from),
|
||||
fSlave(NULL)
|
||||
{
|
||||
BMessage slaveMsg;
|
||||
if (from->FindMessage("nSlave", &slaveMsg) == B_NO_ERROR) {
|
||||
BArchivable* slaveObj = instantiate_object(&slaveMsg);
|
||||
if (slaveObj) {
|
||||
fSlave = dynamic_cast<BitFieldTester*>(slaveObj);
|
||||
if (fSlave == NULL) {
|
||||
printf("NotFieldTester:
|
||||
Error casting slaveObj to BitFieldTester!\n");
|
||||
delete slaveObj;
|
||||
}
|
||||
} else
|
||||
printf("NotFieldTester: instantiate_object returned NULL!\n");
|
||||
} else
|
||||
printf("NotFieldTester: Couldn't unarchive NotFieldTester slave!\n");
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
NotFieldTester::Archive(BMessage* into, bool deep) const
|
||||
{
|
||||
if (fSlave == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
status_t ret = BitFieldTester::Archive(into, deep);
|
||||
|
||||
if (ret == B_NO_ERROR) {
|
||||
BMessage msg;
|
||||
ret = fSlave->Archive(&msg, deep);
|
||||
into->AddMessage("nSlave", &msg);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
BArchivable*
|
||||
NotFieldTester::Instantiate(BMessage* from)
|
||||
{
|
||||
if (validate_instantiation(from, "NotFieldTester"))
|
||||
return new NotFieldTester(from);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NotFieldTester::IsMatching(uint32 field)
|
||||
{
|
||||
return fSlave ? (!fSlave->IsMatching(field)) : false;
|
||||
}
|
||||
|
||||
|
||||
// ---------------- MinMatchFieldTester starts -------------------------------
|
||||
MinMatchFieldTester::MinMatchFieldTester(int minNum, bool deleteSlaves)
|
||||
:
|
||||
fMinNum(minNum),
|
||||
fDeleteSlaves(deleteSlaves) // fDeleteSlaves state not archived!
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
MinMatchFieldTester::~MinMatchFieldTester()
|
||||
{
|
||||
if (fDeleteSlaves) {
|
||||
int nr = fSlaves.CountItems();
|
||||
for (int i = 0; i < nr; i++)
|
||||
delete ((BitFieldTester*) fSlaves.ItemAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
MinMatchFieldTester::MinMatchFieldTester(BMessage* from)
|
||||
:
|
||||
BitFieldTester(from),
|
||||
fDeleteSlaves(true)
|
||||
{
|
||||
int i = 0;
|
||||
BMessage slaveMsg;
|
||||
while (from->FindMessage("mSlave", i++, &slaveMsg) == B_NO_ERROR) {
|
||||
BArchivable* slaveObj = instantiate_object(&slaveMsg);
|
||||
if (slaveObj) {
|
||||
BitFieldTester* nextSlave = dynamic_cast<BitFieldTester*>(slaveObj);
|
||||
if (nextSlave)
|
||||
fSlaves.AddItem(nextSlave);
|
||||
else {
|
||||
printf("MinMatchFieldTester:
|
||||
Error casting slaveObj to BitFieldTester!\n");
|
||||
delete slaveObj;
|
||||
}
|
||||
} else
|
||||
printf("MinMatchFieldTester: instantiate_object returned NULL!\n");
|
||||
}
|
||||
|
||||
if (from->FindInt32("mMin", (int32*) &fMinNum) != B_NO_ERROR)
|
||||
printf("MinMatchFieldTester: Error getting mMin!\n");
|
||||
}
|
||||
|
||||
|
||||
// (slave) should be allocated with new, becomes property of this object.
|
||||
void
|
||||
MinMatchFieldTester::AddSlave(const BitFieldTester* slave)
|
||||
{
|
||||
fSlaves.AddItem((void*) slave);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
MinMatchFieldTester::Archive(BMessage* into, bool deep) const
|
||||
{
|
||||
status_t ret = BitFieldTester::Archive(into, deep);
|
||||
|
||||
if (ret == B_NO_ERROR) {
|
||||
int nr = fSlaves.CountItems();
|
||||
for (int i = 0; i < nr; i++) {
|
||||
BMessage msg;
|
||||
ret = ((BitFieldTester*)fSlaves.ItemAt(i))->Archive(&msg, deep);
|
||||
if (ret != B_NO_ERROR)
|
||||
return ret;
|
||||
|
||||
into->AddMessage("mSlave", &msg);
|
||||
}
|
||||
}
|
||||
|
||||
into->AddInt32("mMin", fMinNum);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
BArchivable*
|
||||
MinMatchFieldTester::Instantiate(BMessage* from)
|
||||
{
|
||||
if (validate_instantiation(from, "MinMatchFieldTester"))
|
||||
return new MinMatchFieldTester(from);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
// Returns true if at least (fMinNum) slaves return true.
|
||||
bool
|
||||
MinMatchFieldTester::IsMatching(uint32 field)
|
||||
{
|
||||
int nr = fSlaves.CountItems();
|
||||
if ((fMinNum == 0) && (nr == 0))
|
||||
return true; // 0 >= 0, so this should return true!
|
||||
|
||||
int count = 0;
|
||||
|
||||
for (int i = 0; i < nr; i++)
|
||||
if ((((BitFieldTester*)fSlaves.ItemAt(i))->IsMatching(field))
|
||||
&& (++count >= fMinNum))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright 1999-2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jeremy Friesner
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BitFieldTesters_h
|
||||
#define BitFieldTesters_h
|
||||
|
||||
|
||||
#include <Archivable.h>
|
||||
#include <List.h>
|
||||
#include <Message.h>
|
||||
|
||||
|
||||
// This file contains various BitTester classes, each of which defines a
|
||||
// sequence of bit testing logics to do on a uint32.
|
||||
|
||||
#ifndef __INTEL__
|
||||
#pragma export on
|
||||
#endif
|
||||
|
||||
// The abstract base class. Defines the interface.
|
||||
_EXPORT class BitFieldTester;
|
||||
class BitFieldTester : public BArchivable {
|
||||
public:
|
||||
BitFieldTester();
|
||||
BitFieldTester(BMessage* from);
|
||||
|
||||
virtual bool IsMatching(uint32 field) = 0;
|
||||
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
||||
};
|
||||
|
||||
|
||||
// This version always returns the value specified in the constructor.
|
||||
_EXPORT class ConstantFieldTester;
|
||||
class ConstantFieldTester : public BitFieldTester {
|
||||
public:
|
||||
ConstantFieldTester(bool result);
|
||||
ConstantFieldTester(BMessage* from);
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
||||
static BArchivable* Instantiate(BMessage* from);
|
||||
virtual bool IsMatching(uint32 field);
|
||||
|
||||
private:
|
||||
bool fResult;
|
||||
};
|
||||
|
||||
|
||||
// This version matches if all requiredBits are found in the field,
|
||||
// and no forbiddenBits are found.
|
||||
_EXPORT class HasBitsFieldTester;
|
||||
class HasBitsFieldTester : public BitFieldTester {
|
||||
public:
|
||||
HasBitsFieldTester(uint32 requiredBits,
|
||||
uint32 forbiddenBits = 0);
|
||||
HasBitsFieldTester(BMessage* from);
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
||||
static BArchivable* Instantiate(BMessage* from);
|
||||
virtual bool IsMatching(uint32 field);
|
||||
|
||||
private:
|
||||
uint32 fRequiredBits;
|
||||
uint32 fForbiddenBits;
|
||||
};
|
||||
|
||||
|
||||
// This one negates the tester it holds.
|
||||
_EXPORT class NotFieldTester;
|
||||
class NotFieldTester : public BitFieldTester {
|
||||
public:
|
||||
// (slave) should be allocated with new, becomes property of this object.
|
||||
NotFieldTester(BitFieldTester* slave);
|
||||
NotFieldTester(BMessage* from);
|
||||
~NotFieldTester();
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
||||
static BArchivable* Instantiate(BMessage* from);
|
||||
virtual bool IsMatching(uint32 field);
|
||||
|
||||
private:
|
||||
BitFieldTester* fSlave;
|
||||
};
|
||||
|
||||
|
||||
// The most interesting class: This one returns true if at least (minNum) of
|
||||
// its slaves return true. It can be used for OR (i.e. minNum==1), AND
|
||||
// (i.e. minNum==numberofchildren), or anything in between!
|
||||
_EXPORT class MinMatchFieldTester;
|
||||
class MinMatchFieldTester : public BitFieldTester {
|
||||
public:
|
||||
MinMatchFieldTester(int minNum,
|
||||
bool deleteSlaves = true);
|
||||
MinMatchFieldTester(BMessage* from);
|
||||
~MinMatchFieldTester();
|
||||
|
||||
// (slave) should be allocated with new, becomes property of this object.
|
||||
void AddSlave(const BitFieldTester* slave);
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true) const;
|
||||
static BArchivable* Instantiate(BMessage* from);
|
||||
virtual bool IsMatching(uint32 field);
|
||||
|
||||
private:
|
||||
BList fSlaves;
|
||||
int32 fMinNum;
|
||||
|
||||
// true if we should delete all our slaves when we are deleted.
|
||||
bool fDeleteSlaves;
|
||||
};
|
||||
|
||||
#ifndef __INTEL__
|
||||
#pragma export reset
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,369 @@
|
||||
/*
|
||||
* Copyright 1999-2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jeremy Friesner
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CommandActuators_h
|
||||
#define CommandActuators_h
|
||||
|
||||
#include <Message.h>
|
||||
#include <String.h>
|
||||
#include <Archivable.h>
|
||||
#include <List.h>
|
||||
#include <InputServerFilter.h>
|
||||
|
||||
#ifndef __INTEL__
|
||||
#pragma export on
|
||||
#endif
|
||||
|
||||
struct key_map; // declaration
|
||||
|
||||
class CommandActuator;
|
||||
|
||||
// Factory function: Given a text string, allocates and returns a
|
||||
// CommandActuator. Returns NULL on failure (usually a parse error)
|
||||
extern CommandActuator* CreateCommandActuator(const char* command);
|
||||
|
||||
// This file contains various CommandActuator classes. Each CommandActuator
|
||||
// contains code to do something. They're functor objects, really. The input
|
||||
// server add-on will execute the CommandActuator associated with a key combo
|
||||
// when that key combo is detected.
|
||||
|
||||
// The abstract base class. Defines the interface.
|
||||
_EXPORT class CommandActuator;
|
||||
class CommandActuator : public BArchivable {
|
||||
public:
|
||||
CommandActuator(int32 argc, char** argv);
|
||||
CommandActuator(BMessage* from);
|
||||
|
||||
// Called by the InputFilter whenever a key is pressed or depressed.
|
||||
// It's important to ensure that this method returns quickly, as the
|
||||
// input_server will block while it executes. (keyMsg) is the BMessage
|
||||
// that triggered this call. (outlist) is a BList that additional input
|
||||
// events may be added to. If (*asyncData) is set to non-NULL,
|
||||
// KeyEventAsync() will be called asynchronously with (asyncData) as
|
||||
// the argument. Returns the filter_result to be given back to the
|
||||
// input_server. (Defaults to B_SKIP_MESSAGE)
|
||||
virtual filter_result KeyEvent(const BMessage* keyMsg,
|
||||
BList* outlist, void** asyncData,
|
||||
BMessage* lastMouseMove)
|
||||
{return B_SKIP_MESSAGE;}
|
||||
|
||||
// Called in a separate thread if (*setAsyncData) was set to non-NULL
|
||||
// in KeyEvent(). Defaults to a no-op.
|
||||
virtual void KeyEventAsync(const BMessage* keyUpMsg,
|
||||
void* asyncData) {}
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true)
|
||||
const;
|
||||
};
|
||||
|
||||
|
||||
// This is the most common thing to do--launch a process.
|
||||
_EXPORT class LaunchCommandActuator;
|
||||
class LaunchCommandActuator : public CommandActuator {
|
||||
public:
|
||||
LaunchCommandActuator(int32 argc, char** argv);
|
||||
LaunchCommandActuator(BMessage* from);
|
||||
~LaunchCommandActuator();
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true)
|
||||
const;
|
||||
static BArchivable* Instantiate(BMessage* from);
|
||||
virtual filter_result KeyEvent(const BMessage* keyMsg,
|
||||
BList* outlist, void** setAsyncData,
|
||||
BMessage* lastMouseMove);
|
||||
virtual void KeyEventAsync(const BMessage* keyMsg,
|
||||
void* asyncData);
|
||||
|
||||
private:
|
||||
bool _GetNextWord(char** setBegin, char** setEnd)
|
||||
const;
|
||||
|
||||
char** fArgv;
|
||||
int32 fArgc;
|
||||
};
|
||||
|
||||
|
||||
// Stupid actuator--just calls beep().
|
||||
_EXPORT class BeepCommandActuator;
|
||||
class BeepCommandActuator : public CommandActuator {
|
||||
public:
|
||||
BeepCommandActuator(int32 argc, char** argv);
|
||||
BeepCommandActuator(BMessage* from);
|
||||
~BeepCommandActuator();
|
||||
|
||||
virtual filter_result KeyEvent(const BMessage* keyMsg,
|
||||
BList* outlist, void** setAsyncData,
|
||||
BMessage* lastMouseMove);
|
||||
virtual status_t Archive(BMessage* into, bool deep = true)
|
||||
const;
|
||||
static BArchivable* Instantiate(BMessage* from);
|
||||
};
|
||||
|
||||
|
||||
// This class will insert a string of keystrokes into the input stream.
|
||||
_EXPORT class KeyStrokeSequenceCommandActuator;
|
||||
class KeyStrokeSequenceCommandActuator : public CommandActuator {
|
||||
public:
|
||||
KeyStrokeSequenceCommandActuator(int32 argc,
|
||||
char** argv);
|
||||
KeyStrokeSequenceCommandActuator(
|
||||
BMessage* from);
|
||||
~KeyStrokeSequenceCommandActuator();
|
||||
|
||||
virtual filter_result KeyEvent(const BMessage* keyMsg,
|
||||
BList* outlist, void** setAsyncData,
|
||||
BMessage* lastMouseMove);
|
||||
virtual status_t Archive(BMessage* into, bool deep = true)
|
||||
const;
|
||||
static BArchivable* Instantiate(BMessage * from);
|
||||
private:
|
||||
void _GenerateKeyCodes();
|
||||
int32 _LookupKeyCode(key_map* map, char* keys,
|
||||
int32 offsets[128], char key,
|
||||
uint8* setStates, int32& setMod,
|
||||
int32 setTo) const;
|
||||
void _SetStateBit(uint8* setStates, uint32 key,
|
||||
bool on = true) const;
|
||||
|
||||
uint8* fStates;
|
||||
int32* fKeyCodes;
|
||||
int32* fModCodes;
|
||||
BString fSequence;
|
||||
BList fOverrides;
|
||||
BList fOverrideOffsets;
|
||||
BList fOverrideModifiers;
|
||||
BList fOverrideKeyCodes;
|
||||
};
|
||||
|
||||
|
||||
// This class will insert a string of keystrokes into the input stream.
|
||||
_EXPORT class MIMEHandlerCommandActuator;
|
||||
class MIMEHandlerCommandActuator : public CommandActuator {
|
||||
public:
|
||||
MIMEHandlerCommandActuator(int32 argc,
|
||||
char** argv);
|
||||
MIMEHandlerCommandActuator(BMessage* from);
|
||||
~MIMEHandlerCommandActuator();
|
||||
|
||||
virtual filter_result KeyEvent(const BMessage* keyMsg,
|
||||
BList* outlist, void** setAsyncData,
|
||||
BMessage* lastMouseMove);
|
||||
virtual void KeyEventAsync(const BMessage* keyUpMsg,
|
||||
void* asyncData);
|
||||
virtual status_t Archive(BMessage * into, bool deep = true)
|
||||
const;
|
||||
static BArchivable* Instantiate(BMessage* from);
|
||||
|
||||
private:
|
||||
BString fMimeType;
|
||||
};
|
||||
|
||||
|
||||
// Abstract base class for actuators that affect mouse buttons
|
||||
_EXPORT class MouseCommandActuator;
|
||||
class MouseCommandActuator : public CommandActuator {
|
||||
public:
|
||||
MouseCommandActuator(int32 argc, char** argv);
|
||||
MouseCommandActuator(BMessage* from);
|
||||
~MouseCommandActuator();
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true)
|
||||
const;
|
||||
|
||||
protected:
|
||||
int32 _GetWhichButtons() const;
|
||||
void _GenerateMouseButtonEvent(bool mouseDown,
|
||||
const BMessage* keyMsg, BList* outlist,
|
||||
BMessage* lastMouseMove);
|
||||
|
||||
private:
|
||||
int32 fWhichButtons;
|
||||
};
|
||||
|
||||
|
||||
// This class sends a single mouse down event when activated, causing the mouse
|
||||
// pointer to enter a "sticky down" state. Good for some things(like dragging).
|
||||
_EXPORT class MouseDownCommandActuator;
|
||||
class MouseDownCommandActuator : public MouseCommandActuator {
|
||||
public:
|
||||
MouseDownCommandActuator(int32 argc,
|
||||
char** argv);
|
||||
MouseDownCommandActuator(BMessage* from);
|
||||
~MouseDownCommandActuator();
|
||||
|
||||
virtual filter_result KeyEvent(const BMessage* keyMsg,
|
||||
BList* outlist, void** setAsyncData,
|
||||
BMessage* lastMouseMove);
|
||||
virtual status_t Archive(BMessage* into, bool deep = true)
|
||||
const;
|
||||
static BArchivable * Instantiate(BMessage * from);
|
||||
};
|
||||
|
||||
|
||||
// This class sends a single mouse down up when activated, releasing any
|
||||
// previously set "sticky down" state. Good for some things (like dragging).
|
||||
_EXPORT class MouseUpCommandActuator;
|
||||
class MouseUpCommandActuator : public MouseCommandActuator {
|
||||
public:
|
||||
MouseUpCommandActuator(int32 argc,
|
||||
char** argv);
|
||||
MouseUpCommandActuator(BMessage * from);
|
||||
~MouseUpCommandActuator();
|
||||
|
||||
virtual filter_result KeyEvent(const BMessage* keyMsg,
|
||||
BList* outlist, void** setAsyncData,
|
||||
BMessage* lastMouseMove);
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true)
|
||||
const;
|
||||
static BArchivable* Instantiate(BMessage* from);
|
||||
};
|
||||
|
||||
|
||||
// This class will send B_MOUSE_UP and B_MOUSE_DOWN events whenever B_KEY_UP or
|
||||
// B_KEY_DOWN events are detected for its key This way a key can act sort of
|
||||
// like a mouse button.
|
||||
_EXPORT class MouseButtonCommandActuator;
|
||||
class MouseButtonCommandActuator : public MouseCommandActuator {
|
||||
public:
|
||||
MouseButtonCommandActuator(int32 argc,
|
||||
char** argv);
|
||||
MouseButtonCommandActuator(BMessage* from);
|
||||
~MouseButtonCommandActuator();
|
||||
|
||||
virtual filter_result KeyEvent(const BMessage* keyMsg,
|
||||
BList* outlist, void** setAsyncData,
|
||||
BMessage* lastMouseMove);
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true)
|
||||
const;
|
||||
static BArchivable* Instantiate(BMessage* from);
|
||||
|
||||
private:
|
||||
bool fKeyDown ;
|
||||
};
|
||||
|
||||
|
||||
// Base class for some actuators that control the position of the mouse pointer
|
||||
_EXPORT class MoveMouseCommandActuator;
|
||||
class MoveMouseCommandActuator : public CommandActuator {
|
||||
public:
|
||||
MoveMouseCommandActuator(int32 argc,
|
||||
char** argv);
|
||||
MoveMouseCommandActuator(BMessage* from);
|
||||
~MoveMouseCommandActuator();
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep) const;
|
||||
|
||||
protected:
|
||||
void CalculateCoords(float& setX, float& setY)
|
||||
const;
|
||||
BMessage* CreateMouseMovedMessage(const BMessage* origMsg
|
||||
, BPoint p, BList* outlist) const;
|
||||
|
||||
private:
|
||||
void _ParseArg(const char* arg, float& setPercent,
|
||||
float& setPixels) const;
|
||||
|
||||
float fXPercent;
|
||||
float fYPercent;
|
||||
float fXPixels;
|
||||
float fYPixels;
|
||||
};
|
||||
|
||||
|
||||
// Actuator that specifies multiple sub-actuators to be executed in series
|
||||
_EXPORT class MultiCommandActuator;
|
||||
class MultiCommandActuator : public CommandActuator {
|
||||
public:
|
||||
MultiCommandActuator(int32 argc, char** argv);
|
||||
MultiCommandActuator(BMessage* from);
|
||||
~MultiCommandActuator();
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep) const;
|
||||
virtual filter_result KeyEvent(const BMessage* keyMsg,
|
||||
BList* outlist, void** asyncData,
|
||||
BMessage* lastMouseMove);
|
||||
virtual void KeyEventAsync(const BMessage* keyUpMsg,
|
||||
void * asyncData);
|
||||
static BArchivable* Instantiate(BMessage* from);
|
||||
|
||||
private:
|
||||
BList fSubActuators;
|
||||
};
|
||||
|
||||
|
||||
// Actuator for moving a mouse relative to its current position
|
||||
_EXPORT class MoveMouseToCommandActuator;
|
||||
class MoveMouseToCommandActuator : public MoveMouseCommandActuator {
|
||||
public:
|
||||
MoveMouseToCommandActuator(int32 argc,
|
||||
char** argv);
|
||||
MoveMouseToCommandActuator(BMessage* from);
|
||||
~MoveMouseToCommandActuator();
|
||||
|
||||
virtual filter_result KeyEvent(const BMessage* keyMsg, BList* outlist
|
||||
, void** setAsyncData,
|
||||
BMessage* lastMouseMove);
|
||||
|
||||
virtual status_t Archive(BMessage* into, bool deep = true)
|
||||
const;
|
||||
static BArchivable* Instantiate(BMessage* from);
|
||||
};
|
||||
|
||||
|
||||
// Actuator for moving a mouse relative to its current position
|
||||
_EXPORT class MoveMouseByCommandActuator;
|
||||
class MoveMouseByCommandActuator : public MoveMouseCommandActuator {
|
||||
public:
|
||||
MoveMouseByCommandActuator(int32 argc,
|
||||
char** argv);
|
||||
MoveMouseByCommandActuator(BMessage* from);
|
||||
~MoveMouseByCommandActuator();
|
||||
|
||||
virtual filter_result KeyEvent(const BMessage* keyMsg,
|
||||
BList* outlist, void** setAsyncData,
|
||||
BMessage* lastMouseMove);
|
||||
virtual status_t Archive(BMessage * into, bool deep = true)
|
||||
const;
|
||||
static BArchivable* Instantiate(BMessage * from);
|
||||
};
|
||||
|
||||
|
||||
// Actuator to send BMessage to an application - written by Daniel Wesslen
|
||||
_EXPORT class SendMessageCommandActuator;
|
||||
class SendMessageCommandActuator : public CommandActuator {
|
||||
public:
|
||||
SendMessageCommandActuator(int32 argc,
|
||||
char** argv);
|
||||
SendMessageCommandActuator(BMessage* from);
|
||||
~SendMessageCommandActuator();
|
||||
|
||||
virtual filter_result KeyEvent(const BMessage* keyMsg,
|
||||
BList* outlist, void** setAsyncData,
|
||||
BMessage* lastMouseMove);
|
||||
virtual void KeyEventAsync(const BMessage* keyUpMsg,
|
||||
void* asyncData);
|
||||
virtual status_t Archive(BMessage* into, bool deep = true)
|
||||
const;
|
||||
static BArchivable* Instantiate(BMessage * from);
|
||||
|
||||
private:
|
||||
void _ParseFloatArgs(float* outArgs, int maxArgs
|
||||
, const char* str) const;
|
||||
|
||||
BString fSignature;
|
||||
BMessage fSendMsg;
|
||||
};
|
||||
|
||||
#ifndef __INTEL__
|
||||
#pragma export reset
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 1999-2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jeremy Friesner
|
||||
*/
|
||||
|
||||
|
||||
#include "CommandExecutor.h"
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
#include <image.h>
|
||||
|
||||
|
||||
#include "ShortcutsFilterConstants.h"
|
||||
#include "CommandActuators.h"
|
||||
|
||||
CommandExecutor::CommandExecutor()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
CommandExecutor::~CommandExecutor()
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
// Returns true if it is returning valid results into (*setBegin) and
|
||||
// (*setEnd). If returning true, (*setBegin) now points to the first char in a
|
||||
// new word, and (*setEnd) now points to the char after the last char in the
|
||||
// word, which has been set to a NUL byte.
|
||||
bool
|
||||
CommandExecutor::GetNextWord(char** setBegin, char** setEnd) const
|
||||
{
|
||||
char* next = *setEnd; // we'll start one after the end of the last one...
|
||||
|
||||
while (next++) {
|
||||
if (*next == '\0')
|
||||
return false; // no words left!
|
||||
else if (*next <= ' ')
|
||||
*next = '\0';
|
||||
else
|
||||
break; // found a non-whitespace char!
|
||||
}
|
||||
|
||||
*setBegin = next; // we found the first char!
|
||||
|
||||
while (next++) {
|
||||
if (*next <= ' ') {
|
||||
*next = '\0'; // terminate the word
|
||||
*setEnd = next;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; // should never get here, actually
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
CommandExecutor::MessageReceived(BMessage* msg)
|
||||
{
|
||||
switch(msg->what) {
|
||||
case B_UNMAPPED_KEY_DOWN:
|
||||
case B_KEY_DOWN:
|
||||
{
|
||||
BMessage actMessage;
|
||||
void* asyncData;
|
||||
if ((msg->FindMessage("act", &actMessage) == B_NO_ERROR)
|
||||
&& (msg->FindPointer("adata", &asyncData) == B_NO_ERROR)) {
|
||||
BArchivable* arcObj = instantiate_object(&actMessage);
|
||||
if (arcObj) {
|
||||
CommandActuator* act = dynamic_cast<CommandActuator*>(arcObj);
|
||||
|
||||
if (act)
|
||||
act->KeyEventAsync(msg, asyncData);
|
||||
delete arcObj;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 1999-2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jeremy Friesner
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CommandExecutor_h
|
||||
#define CommandExecutor_h
|
||||
|
||||
#include <Looper.h>
|
||||
#include <Message.h>
|
||||
#include <OS.h>
|
||||
|
||||
// This thread receives BMessages telling it what
|
||||
// to launch, and launches them.
|
||||
class CommandExecutor : public BLooper {
|
||||
public:
|
||||
CommandExecutor();
|
||||
~CommandExecutor();
|
||||
|
||||
virtual void MessageReceived(BMessage* msg);
|
||||
|
||||
private:
|
||||
bool GetNextWord(char** setBeginWord, char** setEndWord)
|
||||
const;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,17 @@
|
||||
SubDir HAIKU_TOP src add-ons input_server filters shortcut_catcher ;
|
||||
|
||||
SetSubDirSupportedPlatformsBeOSCompatible ;
|
||||
|
||||
# Common files used here and in the app
|
||||
StaticLibrary libshortcuts_shared.a :
|
||||
BitFieldTesters.cpp
|
||||
CommandActuators.cpp
|
||||
KeyInfos.cpp
|
||||
ParseCommandLine.cpp
|
||||
;
|
||||
|
||||
Addon shortcut_catcher :
|
||||
CommandExecutor.cpp
|
||||
KeyCommandMap.cpp
|
||||
ShortcutsServerFilter.cpp
|
||||
: be game input_server libshortcuts_shared.a $(TARGET_LIBSUPC++) ;
|
||||
@@ -0,0 +1,312 @@
|
||||
/*
|
||||
* Copyright 1999-2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jeremy Friesner
|
||||
*/
|
||||
|
||||
|
||||
#include "KeyCommandMap.h"
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include <OS.h>
|
||||
#include <File.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <Entry.h>
|
||||
#include <WindowScreen.h>
|
||||
#include <MessageFilter.h>
|
||||
#include <Beep.h>
|
||||
|
||||
|
||||
#include "ShortcutsFilterConstants.h"
|
||||
#include "BitFieldTesters.h"
|
||||
#include "CommandActuators.h"
|
||||
|
||||
#define FILE_UPDATED 'fiUp'
|
||||
|
||||
class hks {
|
||||
public:
|
||||
hks(int32 key, BitFieldTester* t, CommandActuator* act, const BMessage& a)
|
||||
:
|
||||
fKey(key),
|
||||
fTester(t),
|
||||
fActuator(act),
|
||||
fActuatorMessage(a)
|
||||
{
|
||||
// empty
|
||||
}
|
||||
|
||||
|
||||
~hks()
|
||||
{
|
||||
delete fActuator;
|
||||
delete fTester;
|
||||
}
|
||||
|
||||
int32 GetKey() const {return fKey;}
|
||||
bool DoModifiersMatch(uint32 bits) const
|
||||
{
|
||||
return fTester->IsMatching(bits);
|
||||
}
|
||||
const BMessage& GetActuatorMsg() const {return fActuatorMessage;}
|
||||
CommandActuator* GetActuator() {return fActuator;}
|
||||
|
||||
private:
|
||||
int32 fKey;
|
||||
BitFieldTester* fTester;
|
||||
CommandActuator* fActuator;
|
||||
const BMessage fActuatorMessage;
|
||||
};
|
||||
|
||||
|
||||
KeyCommandMap::KeyCommandMap(const char* file)
|
||||
:
|
||||
fSpecs(NULL)
|
||||
{
|
||||
fFileName = new char[strlen(file) + 1];
|
||||
strcpy(fFileName, file);
|
||||
|
||||
BEntry fileEntry(fFileName);
|
||||
if (fileEntry.InitCheck() == B_NO_ERROR) {
|
||||
node_ref nref;
|
||||
|
||||
if (fileEntry.GetNodeRef(&nref) == B_NO_ERROR)
|
||||
watch_node(&nref, B_WATCH_STAT, this);
|
||||
}
|
||||
|
||||
BMessage msg(FILE_UPDATED);
|
||||
PostMessage(&msg);
|
||||
|
||||
fPort = create_port(1, SHORTCUTS_CATCHER_PORT_NAME);
|
||||
_PutMessageToPort(); // advertise our BMessenger to the world
|
||||
}
|
||||
|
||||
|
||||
KeyCommandMap::~KeyCommandMap()
|
||||
{
|
||||
if (fPort >= 0)
|
||||
close_port(fPort);
|
||||
|
||||
for (int i = fInjects.CountItems() - 1; i >= 0; i--)
|
||||
delete (BMessage*)fInjects.ItemAt(i);
|
||||
|
||||
stop_watching(this); // don't know if this is necessary, but it can't hurt
|
||||
_DeleteHKSList(fSpecs);
|
||||
delete [] fFileName;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
KeyCommandMap::MouseMoved(const BMessage* mm)
|
||||
{
|
||||
// Save the mouse state for later...
|
||||
fLastMouseMessage = *mm;
|
||||
}
|
||||
|
||||
|
||||
filter_result
|
||||
KeyCommandMap::KeyEvent(const BMessage* keyMsg, BList* outlist,
|
||||
const BMessenger& sendTo)
|
||||
{
|
||||
uint32 modifiers;
|
||||
filter_result ret = B_DISPATCH_MESSAGE; // default: pass it on
|
||||
|
||||
if (keyMsg->FindInt32("modifiers", (int32*) &modifiers) == B_NO_ERROR) {
|
||||
int32 key;
|
||||
if (keyMsg->FindInt32("key", &key) == B_NO_ERROR) {
|
||||
if (fSyncSpecs.Lock()) {
|
||||
if (fSpecs != NULL) {
|
||||
int num = fSpecs->CountItems();
|
||||
|
||||
for (int i = 0; i < num; i++) {
|
||||
hks* next = (hks*) fSpecs->ItemAt(i);
|
||||
|
||||
if ((key == next->GetKey())
|
||||
&& (next->DoModifiersMatch(modifiers))) {
|
||||
void* asyncData = NULL;
|
||||
ret = next->GetActuator()->
|
||||
KeyEvent(keyMsg, outlist, &asyncData, &fLastMouseMessage);
|
||||
|
||||
if (asyncData) {
|
||||
BMessage newMsg(*keyMsg);
|
||||
newMsg.AddMessage("act", &next->GetActuatorMsg());
|
||||
newMsg.AddPointer("adata", asyncData);
|
||||
sendTo.SendMessage(&newMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fSyncSpecs.Unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
KeyCommandMap::DrainInjectedEvents(const BMessage* keyMsg, BList* outlist,
|
||||
const BMessenger& sendTo)
|
||||
{
|
||||
BList temp;
|
||||
if (fSyncSpecs.Lock()) {
|
||||
temp = fInjects;
|
||||
fInjects.MakeEmpty();
|
||||
fSyncSpecs.Unlock();
|
||||
}
|
||||
|
||||
int is = temp.CountItems();
|
||||
for (int i = 0; i < is; i++) {
|
||||
BMessage* msg = (BMessage*)temp.ItemAt(i);
|
||||
BArchivable* arc = instantiate_object(msg);
|
||||
|
||||
if (arc) {
|
||||
CommandActuator* act = dynamic_cast<CommandActuator*>(arc);
|
||||
|
||||
if (act) {
|
||||
BMessage newMsg(*keyMsg);
|
||||
newMsg.what = B_KEY_DOWN;
|
||||
void* asyncData = NULL;
|
||||
(void) act->KeyEvent(&newMsg, outlist, &asyncData,
|
||||
&fLastMouseMessage);
|
||||
|
||||
if (asyncData) {
|
||||
newMsg.AddMessage("act", msg);
|
||||
newMsg.AddPointer("adata", asyncData);
|
||||
sendTo.SendMessage(&newMsg);
|
||||
}
|
||||
}
|
||||
delete arc;
|
||||
}
|
||||
delete msg;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
KeyCommandMap::MessageReceived(BMessage* msg)
|
||||
{
|
||||
switch(msg->what) {
|
||||
case EXECUTE_COMMAND:
|
||||
{
|
||||
BMessage subMsg;
|
||||
|
||||
if (msg->FindMessage("act", &subMsg) == B_NO_ERROR) {
|
||||
if (fSyncSpecs.Lock()) {
|
||||
fInjects.AddItem(new BMessage(subMsg));
|
||||
fSyncSpecs.Unlock();
|
||||
|
||||
// This evil hack forces input_server to call Filter() on
|
||||
// us so we can process the injected event.
|
||||
BPoint lmp;
|
||||
status_t err = fLastMouseMessage.FindPoint("where", &lmp);
|
||||
if (err == B_NO_ERROR)
|
||||
set_mouse_position((int32)lmp.x, (int32)lmp.y);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case REPLENISH_MESSENGER:
|
||||
_PutMessageToPort();
|
||||
break;
|
||||
|
||||
case B_NODE_MONITOR:
|
||||
case FILE_UPDATED:
|
||||
{
|
||||
BMessage fileMsg;
|
||||
BFile file(fFileName, B_READ_ONLY);
|
||||
if ((file.InitCheck() == B_NO_ERROR)
|
||||
&& (fileMsg.Unflatten(&file) == B_NO_ERROR)) {
|
||||
BList* newList = new BList;
|
||||
|
||||
// whatever this is set to will be deleted below.
|
||||
// defaults to no deletion
|
||||
BList* oldList = NULL;
|
||||
|
||||
int i = 0;
|
||||
BMessage msg;
|
||||
while (fileMsg.FindMessage("spec", i++, &msg) == B_NO_ERROR) {
|
||||
uint32 key;
|
||||
BMessage testerMsg;
|
||||
BMessage actMsg;
|
||||
|
||||
if ((msg.FindInt32("key", (int32*) &key) == B_NO_ERROR)
|
||||
&& ((msg.FindMessage("act", &actMsg)) == B_NO_ERROR)
|
||||
&& ((msg.FindMessage("modtester", &testerMsg))
|
||||
== B_NO_ERROR)) {
|
||||
|
||||
BArchivable* arcObj = instantiate_object(&testerMsg);
|
||||
if (arcObj) {
|
||||
BitFieldTester* tester =
|
||||
dynamic_cast<BitFieldTester*>(arcObj);
|
||||
|
||||
if (tester) {
|
||||
BArchivable* barcObj =
|
||||
instantiate_object(&actMsg);
|
||||
|
||||
if (barcObj) {
|
||||
CommandActuator* act =
|
||||
dynamic_cast<CommandActuator*>(barcObj);
|
||||
|
||||
if (act)
|
||||
newList->AddItem(
|
||||
new hks(key, tester, act, actMsg));
|
||||
else {
|
||||
delete barcObj;
|
||||
delete tester;
|
||||
}
|
||||
} else
|
||||
delete tester;
|
||||
} else
|
||||
delete arcObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fSyncSpecs.Lock()) {
|
||||
// swap in the new list
|
||||
oldList = fSpecs;
|
||||
fSpecs = newList;
|
||||
fSyncSpecs.Unlock();
|
||||
} else {
|
||||
// wtf? This shouldn't happen...
|
||||
oldList = newList; // but clean up if it does
|
||||
}
|
||||
_DeleteHKSList(oldList);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Deletes an HKS-filled BList and its contents.
|
||||
void KeyCommandMap::_DeleteHKSList(BList* l)
|
||||
{
|
||||
if (l != NULL) {
|
||||
int num = l->CountItems();
|
||||
for (int i = 0; i < num; i++)
|
||||
delete ((hks*) l->ItemAt(i));
|
||||
delete l;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void KeyCommandMap::_PutMessageToPort()
|
||||
{
|
||||
if (fPort >= 0) {
|
||||
BMessenger toMe(this);
|
||||
BMessage m;
|
||||
m.AddMessenger("target", toMe);
|
||||
|
||||
char buf[2048];
|
||||
ssize_t fs = m.FlattenedSize();
|
||||
if ((fs <= sizeof(buf)) && (m.Flatten(buf, fs) == B_NO_ERROR))
|
||||
write_port_etc(fPort, 0, buf, fs, B_TIMEOUT, 250000);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright 1999-2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jeremy Friesner
|
||||
*/
|
||||
|
||||
|
||||
#ifndef KeyCommandMap_h
|
||||
#define KeyCommandMap_h
|
||||
|
||||
#include <List.h>
|
||||
#include <Locker.h>
|
||||
|
||||
|
||||
#include <Looper.h>
|
||||
#include <Messenger.h>
|
||||
#include <Message.h>
|
||||
#include <MessageFilter.h>
|
||||
|
||||
// Maps BMessages to ShortcutsSpecs!
|
||||
// The thread here gets file update messages, and updates
|
||||
// the fSpecs list to match them (asynchronously).
|
||||
class KeyCommandMap : public BLooper {
|
||||
public:
|
||||
KeyCommandMap(const char* watchFile);
|
||||
~KeyCommandMap();
|
||||
|
||||
// Called when a key is pressed or depressed, in the input_server thread.
|
||||
// (keyMsg) is the KEY_DOWN message given by the Input Server. (outlist) is
|
||||
// a BList that additional BMessages can be added to (to insert events into
|
||||
// the input stream) (sendMessagesTo) is the address of a queue to send
|
||||
// command messages to, for async effects.
|
||||
filter_result KeyEvent(const BMessage* keyMsg,
|
||||
BList* outlist,
|
||||
const BMessenger& sendMessagesTo);
|
||||
|
||||
// Called whenever the a B_MOUSE_MOVED message is received.
|
||||
void MouseMoved(const BMessage* mouseMoveMsg);
|
||||
void MessageReceived(BMessage* msg);
|
||||
void DrainInjectedEvents(const BMessage* keyMsg,
|
||||
BList* outlist,
|
||||
const BMessenger& sendMessagesTo);
|
||||
|
||||
private:
|
||||
void _PutMessageToPort();
|
||||
void _DeleteHKSList(BList* list);
|
||||
|
||||
port_id fPort;
|
||||
char* fFileName;
|
||||
BLocker fSyncSpecs; // locks the lists below
|
||||
BList fInjects;
|
||||
BList* fSpecs;
|
||||
BMessage fLastMouseMessage;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright 1999-2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jeremy Friesner
|
||||
*/
|
||||
|
||||
|
||||
#include "KeyInfos.h"
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
#include <InterfaceDefs.h>
|
||||
|
||||
|
||||
#define NUM_KEYS 256
|
||||
#define MAX_UTF8_LENGTH 5 // up to 4 chars, plus a nul terminator
|
||||
|
||||
struct KeyLabelMap {
|
||||
const char* fLabel;
|
||||
uint8 fKeyCode;
|
||||
};
|
||||
|
||||
// This is a table of keys-codes that have special, hard-coded labels.
|
||||
static const struct KeyLabelMap keyLabels[] = {
|
||||
{"<unset>", 0},
|
||||
{"Esc", 1},
|
||||
{"F1", 2},
|
||||
{"F2", 3},
|
||||
{"F3", 4},
|
||||
{"F4", 5},
|
||||
{"F5", 6},
|
||||
{"F6", 7},
|
||||
{"F7", 8},
|
||||
{"F8", 9},
|
||||
{"F9", 10},
|
||||
{"F10", 11},
|
||||
{"F11", 12},
|
||||
{"F12", 13},
|
||||
{"SysRq", 14},
|
||||
{"ScrlLck", 15},
|
||||
{"Pause", 16},
|
||||
{"Bcksp", 30},
|
||||
{"Insert", 31},
|
||||
{"Home", 32},
|
||||
{"PgUp", 33},
|
||||
{"Num Lock", 34},
|
||||
{"Kpd /", 35},
|
||||
{"Kpd *", 36},
|
||||
{"Kpd -", 37},
|
||||
{"Tab", 38},
|
||||
{"Delete", 52},
|
||||
{"End", 53},
|
||||
{"PgDn", 54},
|
||||
{"Kpd 7", 55},
|
||||
{"Kpd 8", 56},
|
||||
{"Kpd 9", 57},
|
||||
{"Kpd +", 58},
|
||||
{"Caps Lock", 59},
|
||||
{"Enter", 71},
|
||||
{"Kpd 4", 72},
|
||||
{"Kpd 5", 73},
|
||||
{"Kpd 6", 74},
|
||||
{"L.Shift", 75},
|
||||
{"R.Shift", 86},
|
||||
{"Up", 87},
|
||||
{"Kpd 1", 88},
|
||||
{"Kpd 2", 89},
|
||||
{"Kpd 3", 90},
|
||||
{"Kpd Entr", 91},
|
||||
{"L.Control", 92},
|
||||
{"L.Alt", 93},
|
||||
{"Space", 94},
|
||||
{"R.Alt", 95},
|
||||
{"R.Control", 96},
|
||||
{"Left", 97},
|
||||
{"Down", 98},
|
||||
{"Right", 99},
|
||||
{"Kpd 0", 100},
|
||||
{"Kpd .", 101},
|
||||
{"L.Command", 102},
|
||||
{"R.Command", 103},
|
||||
{"Menu", 104},
|
||||
{"PowerOn", 107},
|
||||
};
|
||||
|
||||
// Key description strings (e.g. "A" or "Escape"). Null if no description is
|
||||
// available.
|
||||
static const char* keyDescriptions[NUM_KEYS];
|
||||
|
||||
// series of optional up-to-(4+1)-byte terminated UTF-8 character strings...
|
||||
static char utfDescriptions[NUM_KEYS * MAX_UTF8_LENGTH];
|
||||
|
||||
static const char* FindSpecialKeyLabelFor(uint8 keyCode, int& last);
|
||||
|
||||
static const char*
|
||||
FindSpecialKeyLabelFor(uint8 keyCode, int& last)
|
||||
{
|
||||
while ((keyLabels[last].fKeyCode < keyCode)
|
||||
&& (last < (sizeof(keyLabels)/sizeof(struct KeyLabelMap))-1))
|
||||
last++;
|
||||
|
||||
if (keyLabels[last].fKeyCode == keyCode)
|
||||
return keyLabels[last].fLabel;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InitKeyIndices()
|
||||
{
|
||||
int nextSpecial = 0;
|
||||
key_map* map;
|
||||
char* keys;
|
||||
get_key_map(&map, &keys);
|
||||
|
||||
for (int j = 0; j < NUM_KEYS; j++) {
|
||||
keyDescriptions[j] = NULL; // default
|
||||
|
||||
const char* slabel = FindSpecialKeyLabelFor(j, nextSpecial);
|
||||
int keyCode = map->normal_map[j];
|
||||
|
||||
if (keyCode >= 0) {
|
||||
const char* mapDesc = &keys[keyCode];
|
||||
uint8 len = *mapDesc;
|
||||
|
||||
for (int m = 0; m < MAX_UTF8_LENGTH; m++)
|
||||
if (m < len)
|
||||
utfDescriptions[j * MAX_UTF8_LENGTH + m] = mapDesc[m + 1];
|
||||
else
|
||||
utfDescriptions[j * MAX_UTF8_LENGTH + m] = '\0';
|
||||
|
||||
if (slabel)
|
||||
keyDescriptions[j] = slabel;
|
||||
else {
|
||||
// If it's an ASCII letter, capitalize it.
|
||||
char& c = utfDescriptions[j * MAX_UTF8_LENGTH];
|
||||
|
||||
if ((len == 1) && (isalpha(c)))
|
||||
c = toupper(c);
|
||||
|
||||
if ((len > 1)||((len == 1) && (c > ' ')))
|
||||
keyDescriptions[j] = &c;
|
||||
}
|
||||
} else
|
||||
utfDescriptions[j * MAX_UTF8_LENGTH] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
GetKeyUTF8(uint8 keyIndex)
|
||||
{
|
||||
return &utfDescriptions[keyIndex * MAX_UTF8_LENGTH];
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
GetKeyName(uint8 keyIndex)
|
||||
{
|
||||
return keyDescriptions[keyIndex];
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
GetNumKeyIndices()
|
||||
{
|
||||
return NUM_KEYS;
|
||||
}
|
||||
|
||||
|
||||
uint8
|
||||
FindKeyCode(const char* keyName)
|
||||
{
|
||||
for (int i = 0; i < NUM_KEYS; i++)
|
||||
if ((keyDescriptions[i])
|
||||
&& (strcasecmp(keyName, keyDescriptions[i]) == 0))
|
||||
return i;
|
||||
return 0; // default to sentinel value
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 1999-2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jeremy Friesner
|
||||
*/
|
||||
|
||||
|
||||
#ifndef KeyInfos_h
|
||||
#define KeyInfos_h
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
// Returns an ASCII string for the given key index, or NULL if a bad code is
|
||||
// given.
|
||||
const char* GetKeyName(uint8 keyIndex);
|
||||
|
||||
// Inverse of GetKeyName(). Finds the index of the given string. Returns 0 if
|
||||
// the string was not found in the set of key names.
|
||||
uint8 FindKeyCode(const char* keyName);
|
||||
|
||||
// Returns the UTF8 value for the given key, or "\0" if none.
|
||||
const char* GetKeyUTF8(uint8 keyIndex);
|
||||
|
||||
// Returns the number of key indices that are known. (Currently 256). Indices
|
||||
// (0...GetNumKeyIndices()-1) are valid.
|
||||
int GetNumKeyIndices();
|
||||
|
||||
// Should be called at startup.
|
||||
void InitKeyIndices();
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* Copyright 1999-2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jeremy Friesner
|
||||
* Fredrik Modéen
|
||||
*/
|
||||
|
||||
|
||||
#include "ParseCommandLine.h"
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#include <Roster.h>
|
||||
#include <List.h>
|
||||
#include <Entry.h>
|
||||
#include <Directory.h>
|
||||
#include <SupportKit.h>
|
||||
|
||||
|
||||
// This char is used to hold words together into single words...
|
||||
#define GUNK_CHAR 0x01
|
||||
#define PATHTOTRACKER "/boot/system/Tracker"
|
||||
|
||||
// Turn all spaces that are not-to-be-counted-as-spaces into GUNK_CHAR chars.
|
||||
static void
|
||||
GunkSpaces(char* string)
|
||||
{
|
||||
bool insideQuote = false;
|
||||
bool afterBackslash = false;
|
||||
|
||||
while (*string) {
|
||||
switch(*string) {
|
||||
case '\"':
|
||||
if (!afterBackslash)
|
||||
insideQuote = !insideQuote; // toggle escapement mode
|
||||
break;
|
||||
|
||||
case ' ':
|
||||
case '\t':
|
||||
if ((insideQuote)||(afterBackslash))
|
||||
*string = GUNK_CHAR;
|
||||
break;
|
||||
}
|
||||
afterBackslash = (*string == '\\') ? !afterBackslash : false;
|
||||
string++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Removes all un-escaped quotes and backslashes from the string, in place
|
||||
static void
|
||||
RemoveQuotes(char* string)
|
||||
{
|
||||
bool afterBackslash = false;
|
||||
char* endString = strchr(string, '\0');
|
||||
char* to = string;
|
||||
|
||||
while (*string) {
|
||||
bool temp = (*string == '\\') ? !afterBackslash : false;
|
||||
switch(*string) {
|
||||
case '\"':
|
||||
case '\\':
|
||||
if (afterBackslash)
|
||||
*(to++) = *string;
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
*(to++) = afterBackslash ? '\n' : *string;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
*(to++) = afterBackslash ? '\t' : *string;
|
||||
break;
|
||||
|
||||
default:
|
||||
*(to++) = *string;
|
||||
break;
|
||||
}
|
||||
afterBackslash = temp;
|
||||
string++;
|
||||
}
|
||||
*to = '\0';
|
||||
|
||||
if (to < endString)
|
||||
*(to+1) = '\0'; // needs to be double-terminated!
|
||||
}
|
||||
|
||||
|
||||
static bool IsValidChar(char c);
|
||||
|
||||
static bool
|
||||
IsValidChar(char c)
|
||||
{
|
||||
return ((c > ' ')||(c == '\n')||(c == '\t'));
|
||||
}
|
||||
|
||||
|
||||
// Returns true if it is returning valid results into (*setBegin) & (*setEnd).
|
||||
// If returning true, (*setBegin) now points to the first char in a new word,
|
||||
// and (*setEnd) now points to the char after the last char in the word, which
|
||||
// has been set to a NUL byte.
|
||||
static bool
|
||||
GetNextWord(char** setBegin, char** setEnd)
|
||||
{
|
||||
char* next = *setEnd; // we'll start one after the end of the last one...
|
||||
|
||||
while (next++) {
|
||||
if (*next == '\0')
|
||||
return false; // no words left!
|
||||
else if ((IsValidChar(*next) == false) && (*next != GUNK_CHAR))
|
||||
*next = '\0';
|
||||
else
|
||||
break; // found a non-whitespace char!
|
||||
}
|
||||
|
||||
*setBegin = next; // we found the first char!
|
||||
|
||||
while (next++) {
|
||||
if ((IsValidChar(*next) == false) && (*next != GUNK_CHAR)) {
|
||||
*next = '\0'; // terminate the word
|
||||
*setEnd = next;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false; // should never get here, actually
|
||||
}
|
||||
|
||||
|
||||
// Turns the gunk back into spaces
|
||||
static void
|
||||
UnGunk(char* str)
|
||||
{
|
||||
char* temp = str;
|
||||
while (*temp) {
|
||||
if (*temp == GUNK_CHAR)
|
||||
*temp = ' ';
|
||||
temp++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char**
|
||||
ParseArgvFromString(const char* command, int32& argc)
|
||||
{
|
||||
// make our own copy of the string...
|
||||
int slen = strlen(command);
|
||||
|
||||
// need an extra nul byte to get GetNextWord() to stop
|
||||
char* cmd = new char[slen + 2];
|
||||
strcpy(cmd, command);
|
||||
cmd[slen+1] = '\0'; // zero out the second nul byte
|
||||
|
||||
GunkSpaces(cmd);
|
||||
RemoveQuotes(cmd);
|
||||
|
||||
BList wordlist;
|
||||
char* beginWord = NULL, *endWord = cmd - 1;
|
||||
|
||||
while (GetNextWord(&beginWord, &endWord))
|
||||
wordlist.AddItem(beginWord);
|
||||
|
||||
argc = wordlist.CountItems();
|
||||
char** argv = new char* [argc + 1];
|
||||
for (int i = 0; i < argc; i++) {
|
||||
char* temp = (char*) wordlist.ItemAt(i);
|
||||
argv[i] = new char[strlen(temp) + 1];
|
||||
strcpy(argv[i], temp);
|
||||
|
||||
// turn space-markers back into real spaces...
|
||||
UnGunk(argv[i]);
|
||||
}
|
||||
argv[argc] = NULL; // terminate the array
|
||||
|
||||
delete [] cmd; // don't need our local copy any more
|
||||
return argv;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
FreeArgv(char** argv)
|
||||
{
|
||||
if (argv) {
|
||||
int i = 0;
|
||||
|
||||
while (argv[i]) {
|
||||
delete [] argv[i];
|
||||
i++;
|
||||
}
|
||||
}
|
||||
delete [] argv;
|
||||
}
|
||||
|
||||
|
||||
// Make new, independent clone of an argv array and its strings.
|
||||
char**
|
||||
CloneArgv(char** argv)
|
||||
{
|
||||
int argc = 0;
|
||||
while (argv[argc] != NULL)
|
||||
argc++;
|
||||
|
||||
char** newArgv = new char* [argc + 1];
|
||||
for (int i = 0; i < argc; i++) {
|
||||
newArgv[i] = new char[strlen(argv[i]) + 1];
|
||||
strcpy(newArgv[i], argv[i]);
|
||||
}
|
||||
newArgv[argc] = NULL;
|
||||
return newArgv;
|
||||
}
|
||||
|
||||
|
||||
|
||||
BString
|
||||
ParseArgvZeroFromString(const char* command)
|
||||
{
|
||||
char* ret = NULL;
|
||||
|
||||
// make our own copy of the string...
|
||||
int slen = strlen(command);
|
||||
|
||||
// need an extra nul byte to get GetNextWord() to stop
|
||||
char* cmd = new char[slen + 2];
|
||||
strcpy(cmd, command);
|
||||
cmd[slen + 1] = '\0'; // zero out the second nul byte
|
||||
|
||||
GunkSpaces(cmd);
|
||||
RemoveQuotes(cmd);
|
||||
|
||||
char* beginWord = NULL, *endWord = cmd - 1;
|
||||
if (GetNextWord(&beginWord, &endWord)) {
|
||||
ret = new char[strlen(beginWord) + 1];
|
||||
strcpy(ret, beginWord);
|
||||
UnGunk(ret);
|
||||
}
|
||||
delete [] cmd;
|
||||
|
||||
BString retStr(ret?ret:"");
|
||||
delete [] ret;
|
||||
|
||||
return retStr;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
DoStandardEscapes(BString& string)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
// Escape any characters that might mess us up
|
||||
// note: check this first, or we'll detect the slashes WE put in!
|
||||
ret |= EscapeChars(string, '\\');
|
||||
ret |= EscapeChars(string, '\"');
|
||||
ret |= EscapeChars(string, ' ');
|
||||
ret |= EscapeChars(string, '\t');
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
// Modifies (string) so that each instance of (badChar) in it is preceded by a
|
||||
// backslash. Returns true iff modifications were made.
|
||||
bool
|
||||
EscapeChars(BString& string, char badChar)
|
||||
{
|
||||
if (string.FindFirst(badChar) == -1)
|
||||
return false;
|
||||
|
||||
BString temp;
|
||||
int stringLen = string.Length();
|
||||
for (int i = 0; i < stringLen; i++) {
|
||||
char next = string[i];
|
||||
if (next == badChar)
|
||||
temp += '\\';
|
||||
temp += next;
|
||||
}
|
||||
|
||||
string = temp;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Launch the given app/project file. Put here so that Shortcuts and
|
||||
// BartLauncher can share this code!
|
||||
status_t
|
||||
LaunchCommand(char** argv, int32 argc)
|
||||
{
|
||||
BEntry entry(argv[0], true);
|
||||
if (entry.Exists()) {
|
||||
// See if it's a directory. If it is, ask Tracker to open it, rather
|
||||
// than launch.
|
||||
BDirectory testDir(&entry);
|
||||
if (testDir.InitCheck() == B_NO_ERROR) {
|
||||
// Hack way to do this--really I should be able to do this by
|
||||
// sending a BMessage. But how? When I finally get my copy of the
|
||||
// BeOS Bible, maybe then I'll find out.
|
||||
const char* trackerFile = PATHTOTRACKER;
|
||||
char* temp = new char[strlen(trackerFile) + strlen(argv[0]) + 10];
|
||||
sprintf(temp, "%s '%s'", trackerFile, argv[0]);
|
||||
system(temp);
|
||||
delete [] temp;
|
||||
return B_NO_ERROR;
|
||||
} else {
|
||||
// It's not a directory. Must be a file.
|
||||
entry_ref ref;
|
||||
if (entry.GetRef(&ref) == B_NO_ERROR) {
|
||||
if (argc > 1)
|
||||
be_roster->Launch(&ref, argc-1, &argv[1]);
|
||||
else
|
||||
be_roster->Launch(&ref);
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
return B_ERROR;
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 1999-2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jeremy Friesner
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ParseCommandString_h
|
||||
#define ParseCommandString_h
|
||||
|
||||
#include <String.h>
|
||||
|
||||
// Utility methods to extract arguments from a typed-in string.
|
||||
|
||||
// Returns an NULL-terminated argv array. Sets (setArgc) to the number of
|
||||
// valid arguments in the array. It becomes the responsibility of the calling
|
||||
// code to delete[] the array and each string in it. If (padFront > 0), then
|
||||
// (padFront) extra "slots" will be allocated at the beginning of the returned
|
||||
// argv array. These slots will be NULL, and will be counted in the (setArgc)
|
||||
// result. It is the caller's responsibility to fill them...
|
||||
char** ParseArgvFromString(const char* string, int32& setArgc);
|
||||
|
||||
// Call this to free the argv array returned by ParseArgvFromString().
|
||||
char** CloneArgv(char** argv);
|
||||
|
||||
// Call this to free the argv array returned by ParseArgvFromString().
|
||||
void FreeArgv(char** argv);
|
||||
|
||||
// Returns the first argument in the string.
|
||||
BString ParseArgvZeroFromString(const char* string);
|
||||
|
||||
// Calls EscapeChars() on (string) for the following characters: backslash,
|
||||
// single quote, double quote, space, and tab. The returns string should be
|
||||
// parsable as a single word by the functions above.
|
||||
bool DoStandardEscapes(BString& string);
|
||||
|
||||
// Modifies (string) by inserting slashes in front of each instance of badChar.
|
||||
// Returns false iff no modifications were done.
|
||||
bool EscapeChars(BString& string, char badChar);
|
||||
|
||||
// Launch an app, Tracker style. Put here so that it can be shared amongst
|
||||
// my various apps...
|
||||
status_t LaunchCommand(char** argv, int32 argc);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 1999-2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jeremy Friesner
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ShortcutsConstants_h
|
||||
#define ShortcutsConstants_h
|
||||
|
||||
#define SHORTCUTS_SETTING_FILE_NAME "shortcuts_settings"
|
||||
|
||||
#define SHORTCUTS_CATCHER_PORT_NAME "ShortcutsCatcherPort"
|
||||
|
||||
enum {
|
||||
EXECUTE_COMMAND = 'exec', // Code: Execute "command" as given
|
||||
REPLENISH_MESSENGER, // sent to tell us to write our port again
|
||||
NUM_ACTION_CODES
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 1999-2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jeremy Friesner
|
||||
*/
|
||||
|
||||
|
||||
#include "ShortcutsServerFilter.h"
|
||||
|
||||
|
||||
#include <Path.h>
|
||||
#include <FindDirectory.h>
|
||||
|
||||
|
||||
#include "KeyCommandMap.h"
|
||||
#include "KeyInfos.h"
|
||||
#include "CommandExecutor.h"
|
||||
#include "ShortcutsFilterConstants.h"
|
||||
|
||||
class BInputServerFilter;
|
||||
|
||||
// Called by input_server on startup. Must be exported as a "C" function!
|
||||
BInputServerFilter* instantiate_input_filter()
|
||||
{
|
||||
return new ShortcutsServerFilter;
|
||||
}
|
||||
|
||||
|
||||
ShortcutsServerFilter::ShortcutsServerFilter()
|
||||
:
|
||||
fExecutor(new CommandExecutor)
|
||||
{
|
||||
BPath path;
|
||||
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK)
|
||||
path.Append(SHORTCUTS_SETTING_FILE_NAME);
|
||||
|
||||
fMap = new KeyCommandMap(path.Path());
|
||||
|
||||
InitKeyIndices();
|
||||
fMessenger = BMessenger(fExecutor);
|
||||
fMap->Run();
|
||||
fExecutor->Run();
|
||||
}
|
||||
|
||||
|
||||
ShortcutsServerFilter::~ShortcutsServerFilter()
|
||||
{
|
||||
if (fMap->Lock())
|
||||
fMap->Quit();
|
||||
|
||||
if (fExecutor->Lock())
|
||||
fExecutor->Quit();
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ShortcutsServerFilter::InitCheck()
|
||||
{
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
filter_result
|
||||
ShortcutsServerFilter::Filter(BMessage* msg, BList* outlist)
|
||||
{
|
||||
filter_result ret = B_DISPATCH_MESSAGE;
|
||||
|
||||
switch(msg->what)
|
||||
{
|
||||
case B_KEY_DOWN:
|
||||
case B_KEY_UP:
|
||||
case B_UNMAPPED_KEY_DOWN:
|
||||
case B_UNMAPPED_KEY_UP:
|
||||
ret = fMap->KeyEvent(msg, outlist, fMessenger);
|
||||
break;
|
||||
|
||||
case B_MOUSE_MOVED:
|
||||
case B_MOUSE_UP:
|
||||
case B_MOUSE_DOWN:
|
||||
fMap->MouseMoved(msg);
|
||||
break;
|
||||
}
|
||||
fMap->DrainInjectedEvents(msg, outlist, fMessenger);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 1999-2009 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Jeremy Friesner
|
||||
*/
|
||||
|
||||
|
||||
#ifndef ShortcutsServerFilter_h
|
||||
#define ShortcutsServerFilter_h
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#include <Messenger.h>
|
||||
#include <Message.h>
|
||||
#include <List.h>
|
||||
#include <InputServerFilter.h>
|
||||
|
||||
#ifdef __POWERPC__
|
||||
#pragma export on
|
||||
#endif
|
||||
|
||||
// export this for the input_server
|
||||
extern "C" _EXPORT BInputServerFilter* instantiate_input_filter();
|
||||
|
||||
class KeyCommandMap;
|
||||
class CommandExecutor;
|
||||
|
||||
class ShortcutsServerFilter : public BInputServerFilter {
|
||||
public:
|
||||
ShortcutsServerFilter();
|
||||
virtual ~ShortcutsServerFilter();
|
||||
virtual status_t InitCheck();
|
||||
virtual filter_result Filter(BMessage* message, BList* outlist);
|
||||
private:
|
||||
// Tells us what command goes with a given key
|
||||
KeyCommandMap* fMap;
|
||||
|
||||
// Executes the given commands
|
||||
CommandExecutor* fExecutor;
|
||||
|
||||
// Points to fExecutor:declaration order is important!
|
||||
BMessenger fMessenger;
|
||||
};
|
||||
|
||||
#ifdef __POWERPC__
|
||||
#pragma export reset
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user