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 screen_saver ;
|
||||||
SubInclude HAIKU_TOP src add-ons input_server filters vmware_mouse ;
|
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