Author: modeenf Date: 2009-10-30 22:35:17 +0100 (Fri, 30 Oct 2009) New Revision: 33847 Changeset: http://dev.haiku-os.org/changeset/33847/haiku Added: haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/ haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/BitFieldTesters.cpp haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/BitFieldTesters.h haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/CommandActuators.cpp haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/CommandActuators.h haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/CommandExecutor.cpp haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/CommandExecutor.h haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/Jamfile haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/KeyCommandMap.cpp haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/KeyCommandMap.h haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/KeyInfos.cpp haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/KeyInfos.h haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/ParseCommandLine.cpp haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/ParseCommandLine.h haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/ShortcutsFilterConstants.h haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/ShortcutsServerFilter.cpp haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/ShortcutsServerFilter.h Modified: haiku/trunk/src/add-ons/input_server/filters/Jamfile Log: 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.. Modified: haiku/trunk/src/add-ons/input_server/filters/Jamfile =================================================================== --- haiku/trunk/src/add-ons/input_server/filters/Jamfile 2009-10-30 15:52:07 UTC (rev 33846) +++ haiku/trunk/src/add-ons/input_server/filters/Jamfile 2009-10-30 21:35:17 UTC (rev 33847) @@ -2,3 +2,4 @@ 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 ; Added: haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/BitFieldTesters.cpp =================================================================== --- haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/BitFieldTesters.cpp (rev 0) +++ haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/BitFieldTesters.cpp 2009-10-30 21:35:17 UTC (rev 33847) @@ -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; +} Added: haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/BitFieldTesters.h =================================================================== --- haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/BitFieldTesters.h (rev 0) +++ haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/BitFieldTesters.h 2009-10-30 21:35:17 UTC (rev 33847) @@ -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 Added: haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/CommandActuators.cpp =================================================================== --- haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/CommandActuators.cpp (rev 0) +++ haiku/trunk/src/add-ons/input_server/filters/shortcut_catcher/CommandActuators.cpp 2009-10-30 21:35:17 UTC (rev 33847) @@ -0,0 +1,1713 @@ +/* + * Copyright 1999-2009 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Jeremy Friesner + * Fredrik Modéen + */ + + +#include "CommandActuators.h" + + +#include <stdio.h> +#include <stdlib.h> + + +#include <String.h> +#include <Roster.h> +#include <Alert.h> +#include <Screen.h> +#include <Rect.h> +#include <View.h> +#include <Directory.h> +#include <Entry.h> +#include <List.h> +#include <Beep.h> + + +#include "ParseCommandLine.h" +#include "KeyInfos.h" + +#define IS_KEY_DOWN(msg) ((msg->what == B_KEY_DOWN) \ + || (msg->what == B_UNMAPPED_KEY_DOWN)) + +// Factory function +CommandActuator* +CreateCommandActuator(const char* command) +{ + CommandActuator* act = NULL; + int32 argc; + char** argv = ParseArgvFromString(command, argc); + if (command[0] == '*') { + if (argc > 0) { + char* c = argv[0] + 1; + if (strcmp(c, "InsertString") == 0) + act = new KeyStrokeSequenceCommandActuator(argc, argv); + else if (strcmp(c, "MoveMouse") == 0) + act = new MoveMouseByCommandActuator(argc, argv); + else if (strcmp(c, "MoveMouseTo") == 0) + act = new MoveMouseToCommandActuator(argc, argv); + else if (strcmp(c, "MouseButton") == 0) + act = new MouseButtonCommandActuator(argc, argv); + else if (strcmp(c, "LaunchHandler") == 0) + act = new MIMEHandlerCommandActuator(argc, argv); + else if (strcmp(c, "Multi") == 0) + act = new MultiCommandActuator(argc, argv); + else if (strcmp(c, "MouseDown") == 0) + act = new MouseDownCommandActuator(argc, argv); + else if (strcmp(c, "MouseUp") == 0) + act = new MouseUpCommandActuator(argc, argv); + else if (strcmp(c, "SendMessage") == 0) + act = new SendMessageCommandActuator(argc, argv); + else + act = new BeepCommandActuator(argc, argv); + } + } else + act = new LaunchCommandActuator(argc, argv); + + FreeArgv(argv); + return act; +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// CommandActuator +// +/////////////////////////////////////////////////////////////////////////////// +CommandActuator::CommandActuator(int32 argc, char** argv) +{ + // empty +} + + +CommandActuator::CommandActuator(BMessage* from) + : + BArchivable(from) +{ + // empty +} + + +status_t +CommandActuator::Archive(BMessage* into, bool deep) const +{ + status_t ret = BArchivable::Archive(into, deep); + return ret; +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// LaunchCommandActuator +// +/////////////////////////////////////////////////////////////////////////////// +LaunchCommandActuator::LaunchCommandActuator(int32 argc, char** argv) + : + CommandActuator(argc, argv), + fArgv(CloneArgv(argv)), + fArgc(argc) +{ + // empty +} + + +LaunchCommandActuator::LaunchCommandActuator(BMessage* from) + : + CommandActuator(from) +{ + BList argList; + const char* temp; + int idx = 0; + while (from->FindString("largv", idx++, &temp) == B_NO_ERROR) { + if (temp) { + char* copy = new char[strlen(temp) + 1]; + strcpy(copy, temp); + argList.AddItem(copy); + } + } + + fArgc = argList.CountItems(); + fArgv = new char*[fArgc+ 1]; + + for (int i = 0; i < fArgc; i++) + fArgv[i] = (char*) argList.ItemAt(i); + + fArgv[fArgc] = NULL;// terminate the array +} + + +LaunchCommandActuator::~LaunchCommandActuator() +{ + FreeArgv(fArgv); +} + + +filter_result +LaunchCommandActuator::KeyEvent(const BMessage* keyMsg, BList* outlist, + void** setAsyncData, BMessage* lastMouseMove) +{ + if (IS_KEY_DOWN(keyMsg)) { + // cause KeyEventAsync() to be called asynchronously + *setAsyncData = (void*) true; + } + return B_SKIP_MESSAGE; +} + + +status_t +LaunchCommandActuator::Archive(BMessage* into, bool deep) const +{ + status_t ret = CommandActuator::Archive(into, deep); + + for (int i = 0; i < fArgc; i++) + into->AddString("largv", fArgv[i]); + + return ret; +} + + +BArchivable* +LaunchCommandActuator ::Instantiate(BMessage* from) +{ + if (validate_instantiation(from, "LaunchCommandActuator")) + return new LaunchCommandActuator(from); + else + return NULL; +} + + +void +LaunchCommandActuator::KeyEventAsync(const BMessage* keyMsg, + void* asyncData) +{ + if (be_roster) { + status_t err = B_OK; + BString str; + BString str1("Shortcuts Launcher Error"); + if (fArgc < 1) + str << "You didn't specify a command for this hotkey."; + else if ((err = LaunchCommand(fArgv, fArgc)) != B_NO_ERROR) { + str << "Can't launch " << fArgv[0]; + str << ", no such file exists."; + str << " Please check your Shortcuts settings."; + } + + if (fArgc < 1 || err != B_NO_ERROR) + (new BAlert(str1.String(), str.String(), "Ok"))->Go(NULL); + } +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// MouseCommandActuator +// +/////////////////////////////////////////////////////////////////////////////// +MouseCommandActuator::MouseCommandActuator(int32 argc, char** argv) + : + CommandActuator(argc, argv), + fWhichButtons(B_PRIMARY_MOUSE_BUTTON) +{ + if (argc > 1) { + fWhichButtons = 0; + + for (int i = 1; i < argc; i++) { + int buttonNumber = atoi(argv[i]); + + switch(buttonNumber) { + case 1: + fWhichButtons |= B_PRIMARY_MOUSE_BUTTON; + break; + case 2: + fWhichButtons |= B_SECONDARY_MOUSE_BUTTON; + break; + case 3: + fWhichButtons |= B_TERTIARY_MOUSE_BUTTON; + break; + } + } + } +} + + +MouseCommandActuator::MouseCommandActuator(BMessage* from) + : + CommandActuator(from), + fWhichButtons(B_PRIMARY_MOUSE_BUTTON) +{ + from->FindInt32("buttons", &fWhichButtons); +} + + +MouseCommandActuator::~MouseCommandActuator() +{ + // empty +} + + +status_t +MouseCommandActuator::Archive(BMessage* into, bool deep) const +{ + status_t ret = CommandActuator::Archive(into, deep); + into->AddInt32("buttons", fWhichButtons); + return ret; +} + + +int32 +MouseCommandActuator::_GetWhichButtons() const +{ + return fWhichButtons; +} + + +void +MouseCommandActuator::_GenerateMouseButtonEvent(bool mouseDown, + const BMessage* keyMsg, BList* outlist, BMessage* lastMouseMove) +{ + BMessage* fakeMouse = new BMessage(*lastMouseMove); + fakeMouse->what = mouseDown ? B_MOUSE_DOWN : B_MOUSE_UP; + + // Update the buttons to reflect which mouse buttons we are faking + fakeMouse->RemoveName("buttons"); + + if (mouseDown) + fakeMouse->AddInt32("buttons", fWhichButtons); + + // Trey sez you gotta keep then "when"'s increasing if you want + // click & drag to work! + int64 when; + + const BMessage* lastMessage; + + if (outlist->CountItems() > 0) { + int nr = outlist->CountItems() - 1; + lastMessage = (const BMessage*)outlist->ItemAt(nr); + } else + lastMessage =keyMsg; + + if (lastMessage->FindInt64("when", &when) == B_NO_ERROR) { + when++; + fakeMouse->RemoveName("when"); + fakeMouse->AddInt64("when", when); + } + outlist->AddItem(fakeMouse); +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// MouseDownCommandActuator +// +/////////////////////////////////////////////////////////////////////////////// +MouseDownCommandActuator::MouseDownCommandActuator(int32 argc, char** argv) + : + MouseCommandActuator(argc, argv) +{ + // empty +} + + +MouseDownCommandActuator::MouseDownCommandActuator(BMessage* from) + : + MouseCommandActuator(from) +{ + // empty +} + + +MouseDownCommandActuator::~MouseDownCommandActuator() +{ + // empty +} + + +filter_result +MouseDownCommandActuator::KeyEvent(const BMessage* keyMsg, BList* outlist, + void** setAsyncData, BMessage* lastMouseMove) +{ + if (IS_KEY_DOWN(keyMsg)) + _GenerateMouseButtonEvent(true, keyMsg, outlist, lastMouseMove); + + return B_DISPATCH_MESSAGE; +} + + +status_t +MouseDownCommandActuator::Archive(BMessage* into, bool deep) const +{ + return MouseCommandActuator::Archive(into, deep); +} + + +BArchivable* +MouseDownCommandActuator ::Instantiate(BMessage* from) +{ + if (validate_instantiation(from, "MouseDownCommandActuator")) + return new MouseDownCommandActuator(from); + else + return NULL; +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// MouseUpCommandActuator +// +/////////////////////////////////////////////////////////////////////////////// +MouseUpCommandActuator::MouseUpCommandActuator(int32 argc, char** argv) + : + MouseCommandActuator(argc, argv) +{ + // empty +} + + +MouseUpCommandActuator::MouseUpCommandActuator(BMessage* from) + : + MouseCommandActuator(from) +{ + // empty +} + + +MouseUpCommandActuator::~MouseUpCommandActuator() +{ + // empty +} + + +filter_result +MouseUpCommandActuator::KeyEvent(const BMessage* keyMsg, BList* outlist, + void** setAsyncData, BMessage* lastMouseMove) +{ + if (IS_KEY_DOWN(keyMsg)) + _GenerateMouseButtonEvent(false, keyMsg, outlist, lastMouseMove); + return B_DISPATCH_MESSAGE; +} + + +status_t +MouseUpCommandActuator::Archive(BMessage* into, bool deep) const +{ + return MouseCommandActuator::Archive(into, deep); +} + + +BArchivable* +MouseUpCommandActuator ::Instantiate(BMessage* from) +{ + if (validate_instantiation(from, "MouseUpCommandActuator")) + return new MouseUpCommandActuator(from); + else + return NULL; +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// MouseButtonCommandActuator +// +/////////////////////////////////////////////////////////////////////////////// +MouseButtonCommandActuator::MouseButtonCommandActuator(int32 argc, char** argv) + : + MouseCommandActuator(argc, argv), + fKeyDown(false) +{ + // empty +} + + +MouseButtonCommandActuator::MouseButtonCommandActuator(BMessage* from) + : + MouseCommandActuator(from), + fKeyDown(false) +{ + // empty +} + + +MouseButtonCommandActuator::~MouseButtonCommandActuator() +{ + // empty +} + + +filter_result +MouseButtonCommandActuator::KeyEvent(const BMessage* keyMsg, BList* outlist, + void** setAsyncData, BMessage* lastMouseMove) +{ + if (IS_KEY_DOWN(keyMsg) != fKeyDown) { + _GenerateMouseButtonEvent(IS_KEY_DOWN(keyMsg), keyMsg, outlist, + lastMouseMove); + fKeyDown = IS_KEY_DOWN(keyMsg); + return B_DISPATCH_MESSAGE; + } else + // This will handle key-repeats, which we don't want turned into lots + // of B_MOUSE_DOWN messages. + return B_SKIP_MESSAGE; +} + + +status_t +MouseButtonCommandActuator::Archive(BMessage* into, bool deep) const +{ + return MouseCommandActuator::Archive(into, deep); +} + + +BArchivable* +MouseButtonCommandActuator ::Instantiate(BMessage* from) +{ + if (validate_instantiation(from, "MouseButtonCommandActuator")) + return new MouseButtonCommandActuator(from); + else + return NULL; +} + + +/////////////////////////////////////////////////////////////////////////////// +// +// KeyStrokeSequenceCommandActuator +// +/////////////////////////////////////////////////////////////////////////////// +KeyStrokeSequenceCommandActuator::KeyStrokeSequenceCommandActuator(int32 argc, + char** argv) + : + CommandActuator(argc, argv) +{ + for (int s = 1; s < argc; s++) { + fSequence.Append(argv[s]); + if (s < argc - 1) + fSequence.Append(" "); + } + + // Find any insert-unicode-here sequences and replace them with spaces... + int32 nextStart; + while ((nextStart = fSequence.FindFirst("$$")) >= 0) { + int32 nextEnd = fSequence.FindFirst("$$", nextStart + 2); + if (nextEnd >= 0) { + uint32 customKey= 0; + int32 unicodeVal= 0; + uint32 customMods = 0; + BString sub; + fSequence.CopyInto(sub, nextStart + 2, nextEnd-(nextStart + 2)); + sub.ToLower(); + + if ((sub.FindFirst('-') >= 0) || ((sub.Length() > 0) + && ((sub.String()[0] < '0') || (sub.String()[0] > '9')))) { + + const char* s = sub.String(); + while (*s == '-') s++;// go past any initial dashes + + bool lastWasDash = true; + while (*s) { + if (lastWasDash) { + if (strncmp(s, "shift",5) == 0) + customMods |=B_LEFT_SHIFT_KEY| B_SHIFT_KEY; + else if (strncmp(s, "leftsh", 6) == 0) + customMods |=B_LEFT_SHIFT_KEY| B_SHIFT_KEY; + else if (strncmp(s, "rightsh",7) == 0) + customMods |=B_RIGHT_SHIFT_KEY | B_SHIFT_KEY; + else if (strncmp(s, "alt",3) == 0) + customMods |=B_LEFT_COMMAND_KEY| B_COMMAND_KEY; + else if (strncmp(s, "leftalt",7) == 0) + customMods |=B_LEFT_COMMAND_KEY| B_COMMAND_KEY; + else if (strncmp(s, "rightalt", 8) == 0) + customMods |=B_RIGHT_COMMAND_KEY | B_COMMAND_KEY; + else if (strncmp(s, "com",3) == 0) + customMods |=B_LEFT_COMMAND_KEY| B_COMMAND_KEY; + else if (strncmp(s, "leftcom",7) == 0) + customMods |=B_LEFT_COMMAND_KEY| B_COMMAND_KEY; + else if (strncmp(s, "rightcom", 8) == 0) + customMods |=B_RIGHT_COMMAND_KEY | B_COMMAND_KEY; + else if (strncmp(s, "con",3) == 0) + customMods |=B_LEFT_CONTROL_KEY| B_CONTROL_KEY; + else if (strncmp(s, "leftcon",7) == 0) + customMods |=B_LEFT_CONTROL_KEY| B_CONTROL_KEY; + else if (strncmp(s, "rightcon", 8) == 0) + customMods |=B_RIGHT_CONTROL_KEY | B_CONTROL_KEY; + else if (strncmp(s, "win",3) == 0) + customMods |=B_LEFT_OPTION_KEY | B_OPTION_KEY; + else if (strncmp(s, "leftwin",7) == 0) + customMods |=B_LEFT_OPTION_KEY | B_OPTION_KEY; + else if (strncmp(s, "rightwin", 8) == 0) + customMods |=B_RIGHT_OPTION_KEY| B_OPTION_KEY; + else if (strncmp(s, "opt",3) == 0) + customMods |=B_LEFT_OPTION_KEY | B_OPTION_KEY; + else if (strncmp(s, "leftopt",7) == 0) + customMods |=B_LEFT_OPTION_KEY | B_OPTION_KEY; + else if (strncmp(s, "rightopt", 8) == 0) + customMods |=B_RIGHT_OPTION_KEY| B_OPTION_KEY; + else if (strncmp(s, "menu", 4) == 0) + customMods |=B_MENU_KEY; + else if (strncmp(s, "caps", 4) == 0) [... truncated: 2873 lines follow ...]