Tracker: store default add-ons shortcuts in resource
* Default shortcuts for add-ons are now stored within the binary as a resource (it was previously appended to the file name, as Open Terminal-T, for example) * Use ~/config/shortcuts_settings to override those default shortcuts (editable with Shortcuts preflet) * Tracker avoid rescanning the add-ons directories when unnecessary * Monitor the shortcuts_settings to apply changes on the fly * Fallback to default shortcuts whenever appropriate (settings file deleted, etc.) * Should fix #4446 (with resource rather than attributes)
This commit is contained in:
@@ -145,6 +145,8 @@ const int32 kWindowStaggerBy = 17;
|
|||||||
|
|
||||||
BRect BContainerWindow::sNewWindRect(85, 50, 548, 280);
|
BRect BContainerWindow::sNewWindRect(85, 50, 548, 280);
|
||||||
|
|
||||||
|
LockingList<AddonShortcut>* BContainerWindow::fAddonsList
|
||||||
|
= new LockingList<struct AddonShortcut>(10, true);
|
||||||
|
|
||||||
namespace BPrivate {
|
namespace BPrivate {
|
||||||
|
|
||||||
@@ -165,48 +167,6 @@ ActivateWindowFilter(BMessage*, BHandler** target, BMessageFilter*)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
StripShortcut(const Model* model, char* result, uint32 &shortcut)
|
|
||||||
{
|
|
||||||
// model name (possibly localized) for the menu item label
|
|
||||||
strlcpy(result, model->Name(), B_FILE_NAME_LENGTH);
|
|
||||||
|
|
||||||
// check if there is a shortcut in the model name
|
|
||||||
uint32 length = strlen(result);
|
|
||||||
if (length > 2 && result[length - 2] == '-') {
|
|
||||||
shortcut = result[length - 1];
|
|
||||||
result[length - 2] = '\0';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if there is a shortcut in the filename
|
|
||||||
char* refName = model->EntryRef()->name;
|
|
||||||
length = strlen(refName);
|
|
||||||
if (length > 2 && refName[length - 2] == '-') {
|
|
||||||
shortcut = refName[length - 1];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
shortcut = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static const Model*
|
|
||||||
MatchOne(const Model* model, void* castToName)
|
|
||||||
{
|
|
||||||
char buffer[B_FILE_NAME_LENGTH];
|
|
||||||
uint32 dummy;
|
|
||||||
StripShortcut(model, buffer, dummy);
|
|
||||||
|
|
||||||
if (strcmp(buffer, (const char*)castToName) == 0) {
|
|
||||||
// found match, bail out
|
|
||||||
return model;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
CompareLabels(const BMenuItem* item1, const BMenuItem* item2)
|
CompareLabels(const BMenuItem* item1, const BMenuItem* item2)
|
||||||
{
|
{
|
||||||
@@ -217,8 +177,8 @@ CompareLabels(const BMenuItem* item1, const BMenuItem* item2)
|
|||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
AddOneAddon(const Model* model, const char* name, uint32 shortcut,
|
AddOneAddon(const Model* model, const char* name, uint32 shortcut,
|
||||||
bool primary, void* context)
|
uint32 modifiers, bool primary, void* context)
|
||||||
{
|
{
|
||||||
AddOneAddonParams* params = (AddOneAddonParams*)context;
|
AddOneAddonParams* params = (AddOneAddonParams*)context;
|
||||||
|
|
||||||
@@ -226,7 +186,7 @@ AddOneAddon(const Model* model, const char* name, uint32 shortcut,
|
|||||||
message->AddRef("refs", model->EntryRef());
|
message->AddRef("refs", model->EntryRef());
|
||||||
|
|
||||||
ModelMenuItem* item = new ModelMenuItem(model, name, message,
|
ModelMenuItem* item = new ModelMenuItem(model, name, message,
|
||||||
(char)shortcut, B_OPTION_KEY);
|
(char)shortcut, modifiers);
|
||||||
|
|
||||||
if (primary)
|
if (primary)
|
||||||
params->primaryList->AddItem(item);
|
params->primaryList->AddItem(item);
|
||||||
@@ -2919,114 +2879,56 @@ BContainerWindow::AddTrashContextMenus(BMenu* menu)
|
|||||||
|
|
||||||
void
|
void
|
||||||
BContainerWindow::EachAddon(bool (*eachAddon)(const Model*, const char*,
|
BContainerWindow::EachAddon(bool (*eachAddon)(const Model*, const char*,
|
||||||
uint32 shortcut, bool primary, void* context), void* passThru,
|
uint32 shortcut, uint32 modifiers, bool primary, void* context),
|
||||||
BObjectList<BString> &mimeTypes)
|
void* passThru, BObjectList<BString> &mimeTypes)
|
||||||
{
|
{
|
||||||
BObjectList<Model> uniqueList(10, true);
|
AutoLock<LockingList<AddonShortcut> > lock(fAddonsList);
|
||||||
BPath path;
|
if (lock.IsLocked()) {
|
||||||
bool bail = false;
|
for (int i = fAddonsList->CountItems() - 1; i >= 0; i--) {
|
||||||
if (find_directory(B_BEOS_ADDONS_DIRECTORY, &path) == B_OK)
|
struct AddonShortcut* item = fAddonsList->ItemAt(i);
|
||||||
bail = EachAddon(path, eachAddon, &uniqueList, passThru, mimeTypes);
|
bool primary = false;
|
||||||
|
|
||||||
if (!bail && find_directory(B_USER_ADDONS_DIRECTORY, &path) == B_OK)
|
if (mimeTypes.CountItems()) {
|
||||||
bail = EachAddon(path, eachAddon, &uniqueList, passThru, mimeTypes);
|
BFile file(item->model->EntryRef(), B_READ_ONLY);
|
||||||
|
if (file.InitCheck() == B_OK) {
|
||||||
|
BAppFileInfo info(&file);
|
||||||
|
if (info.InitCheck() == B_OK) {
|
||||||
|
bool secondary = true;
|
||||||
|
|
||||||
if (!bail && find_directory(B_COMMON_ADDONS_DIRECTORY, &path) == B_OK)
|
// does this add-on has types set at all?
|
||||||
EachAddon(path, eachAddon, &uniqueList, passThru, mimeTypes);
|
BMessage message;
|
||||||
}
|
if (info.GetSupportedTypes(&message) == B_OK) {
|
||||||
|
type_code type;
|
||||||
|
int32 count;
|
||||||
|
if (message.GetInfo("types", &type,
|
||||||
|
&count) == B_OK)
|
||||||
|
secondary = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check all supported types if it has some set
|
||||||
bool
|
if (!secondary) {
|
||||||
BContainerWindow::EachAddon(BPath &path, bool (*eachAddon)(const Model*,
|
for (int32 i = mimeTypes.CountItems();
|
||||||
const char*, uint32 shortcut, bool primary, void*),
|
!primary && i-- > 0;) {
|
||||||
BObjectList<Model>* uniqueList, void* params,
|
BString* type = mimeTypes.ItemAt(i);
|
||||||
BObjectList<BString> &mimeTypes)
|
if (info.IsSupportedType(type->String())) {
|
||||||
{
|
BMimeType mimeType(type->String());
|
||||||
path.Append("Tracker");
|
if (info.Supports(&mimeType))
|
||||||
|
primary = true;
|
||||||
BDirectory dir;
|
else
|
||||||
BEntry entry;
|
secondary = true;
|
||||||
|
}
|
||||||
if (dir.SetTo(path.Path()) != B_OK)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
dir.Rewind();
|
|
||||||
while (dir.GetNextEntry(&entry) == B_OK) {
|
|
||||||
Model* model = new Model(&entry);
|
|
||||||
|
|
||||||
if (model->InitCheck() == B_OK && model->IsSymLink()) {
|
|
||||||
// resolve symlinks
|
|
||||||
Model* resolved = new Model(model->EntryRef(), true, true);
|
|
||||||
if (resolved->InitCheck() == B_OK)
|
|
||||||
model->SetLinkTo(resolved);
|
|
||||||
else
|
|
||||||
delete resolved;
|
|
||||||
}
|
|
||||||
if (model->InitCheck() != B_OK
|
|
||||||
|| !model->ResolveIfLink()->IsExecutable()) {
|
|
||||||
delete model;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if it supports at least one of the selected entries
|
|
||||||
|
|
||||||
bool primary = false;
|
|
||||||
|
|
||||||
if (mimeTypes.CountItems()) {
|
|
||||||
BFile file(&entry, B_READ_ONLY);
|
|
||||||
if (file.InitCheck() == B_OK) {
|
|
||||||
BAppFileInfo info(&file);
|
|
||||||
if (info.InitCheck() == B_OK) {
|
|
||||||
bool secondary = true;
|
|
||||||
|
|
||||||
// does this add-on has types set at all?
|
|
||||||
BMessage message;
|
|
||||||
if (info.GetSupportedTypes(&message) == B_OK) {
|
|
||||||
type_code type;
|
|
||||||
int32 count;
|
|
||||||
if (message.GetInfo("types", &type, &count) == B_OK)
|
|
||||||
secondary = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check all supported types if it has some set
|
|
||||||
if (!secondary) {
|
|
||||||
for (int32 i = mimeTypes.CountItems();
|
|
||||||
!primary && i-- > 0;) {
|
|
||||||
BString* type = mimeTypes.ItemAt(i);
|
|
||||||
if (info.IsSupportedType(type->String())) {
|
|
||||||
BMimeType mimeType(type->String());
|
|
||||||
if (info.Supports(&mimeType))
|
|
||||||
primary = true;
|
|
||||||
else
|
|
||||||
secondary = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!secondary && !primary) {
|
if (!secondary && !primary)
|
||||||
delete model;
|
continue;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
((eachAddon)(item->model, item->model->Name(), item->key,
|
||||||
|
item->modifiers, primary, passThru));
|
||||||
}
|
}
|
||||||
|
|
||||||
char name[B_FILE_NAME_LENGTH];
|
|
||||||
uint32 key;
|
|
||||||
StripShortcut(model, name, key);
|
|
||||||
|
|
||||||
// do a uniqueness check
|
|
||||||
if (uniqueList->EachElement(MatchOne, name)) {
|
|
||||||
// found one already in the list
|
|
||||||
delete model;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
uniqueList->AddItem(model);
|
|
||||||
|
|
||||||
if ((eachAddon)(model, name, key, primary, params))
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,13 @@ enum {
|
|||||||
kRestoreDecor = 0x4
|
kRestoreDecor = 0x4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AddonShortcut {
|
||||||
|
Model* model;
|
||||||
|
char key;
|
||||||
|
char defaultKey;
|
||||||
|
uint32 modifiers;
|
||||||
|
};
|
||||||
|
|
||||||
class BContainerWindow : public BWindow {
|
class BContainerWindow : public BWindow {
|
||||||
public:
|
public:
|
||||||
BContainerWindow(LockingList<BWindow>* windowList,
|
BContainerWindow(LockingList<BWindow>* windowList,
|
||||||
@@ -173,7 +180,8 @@ class BContainerWindow : public BWindow {
|
|||||||
|
|
||||||
// add-on iteration
|
// add-on iteration
|
||||||
void EachAddon(bool (*)(const Model*, const char*, uint32 shortcut,
|
void EachAddon(bool (*)(const Model*, const char*, uint32 shortcut,
|
||||||
bool primary, void*), void*, BObjectList<BString> &);
|
uint32 modifiers, bool primary, void*), void*,
|
||||||
|
BObjectList<BString> &);
|
||||||
|
|
||||||
BPopUpMenu* ContextMenu();
|
BPopUpMenu* ContextMenu();
|
||||||
|
|
||||||
@@ -291,6 +299,8 @@ class BContainerWindow : public BWindow {
|
|||||||
uint32 fContainerWindowFlags;
|
uint32 fContainerWindowFlags;
|
||||||
BackgroundImage* fBackgroundImage;
|
BackgroundImage* fBackgroundImage;
|
||||||
|
|
||||||
|
static LockingList<struct AddonShortcut>* fAddonsList;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BRect fSavedZoomRect;
|
BRect fSavedZoomRect;
|
||||||
BRect fPreviousBounds;
|
BRect fPreviousBounds;
|
||||||
|
|||||||
+245
-54
@@ -38,7 +38,9 @@ All rights reserved.
|
|||||||
#include <Locale.h>
|
#include <Locale.h>
|
||||||
#include <NodeMonitor.h>
|
#include <NodeMonitor.h>
|
||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
|
#include <PathMonitor.h>
|
||||||
#include <PopUpMenu.h>
|
#include <PopUpMenu.h>
|
||||||
|
#include <Resources.h>
|
||||||
#include <Roster.h>
|
#include <Roster.h>
|
||||||
#include <Screen.h>
|
#include <Screen.h>
|
||||||
#include <Volume.h>
|
#include <Volume.h>
|
||||||
@@ -55,6 +57,7 @@ All rights reserved.
|
|||||||
#include "DeskWindow.h"
|
#include "DeskWindow.h"
|
||||||
#include "FSUtils.h"
|
#include "FSUtils.h"
|
||||||
#include "IconMenuItem.h"
|
#include "IconMenuItem.h"
|
||||||
|
#include "KeyInfos.h"
|
||||||
#include "MountMenu.h"
|
#include "MountMenu.h"
|
||||||
#include "PoseView.h"
|
#include "PoseView.h"
|
||||||
#include "Tracker.h"
|
#include "Tracker.h"
|
||||||
@@ -64,47 +67,120 @@ All rights reserved.
|
|||||||
const char* kShelfPath = "tracker_shelf";
|
const char* kShelfPath = "tracker_shelf";
|
||||||
// replicant support
|
// replicant support
|
||||||
|
|
||||||
|
const char* kShortcutsSettings = "shortcuts_settings";
|
||||||
|
const char* kDefaultShortcut = "default_shortcut";
|
||||||
|
const uint32 kDefaultModifiers = B_OPTION_KEY | B_COMMAND_KEY;
|
||||||
|
|
||||||
|
static struct AddonShortcut*
|
||||||
|
MatchOne(struct AddonShortcut* item, void* castToName)
|
||||||
|
{
|
||||||
|
if (strcmp(item->model->Name(), (const char*)castToName) == 0) {
|
||||||
|
// found match, bail out
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
WatchAddOnDir(directory_which dirName, BDeskWindow* window)
|
AddOneShortcut(Model* model, char key, uint32 modifiers, BDeskWindow* window)
|
||||||
|
{
|
||||||
|
if (key == '\0')
|
||||||
|
return;
|
||||||
|
BMessage* runAddon = new BMessage(kLoadAddOn);
|
||||||
|
runAddon->AddRef("refs", model->EntryRef());
|
||||||
|
window->AddShortcut(key, modifiers, runAddon);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static struct AddonShortcut*
|
||||||
|
RevertToDefault(struct AddonShortcut* item, void* castToWindow)
|
||||||
|
{
|
||||||
|
if (item->key != item->defaultKey || item->modifiers != kDefaultModifiers) {
|
||||||
|
BDeskWindow* window = static_cast<BDeskWindow*>(castToWindow);
|
||||||
|
if (window != NULL) {
|
||||||
|
window->RemoveShortcut(item->key, item->modifiers);
|
||||||
|
item->key = item->defaultKey;
|
||||||
|
item->modifiers = kDefaultModifiers;
|
||||||
|
AddOneShortcut(item->model, item->key, item->modifiers, window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct AddonShortcut*
|
||||||
|
FindElement(struct AddonShortcut* item, void* castToOther)
|
||||||
|
{
|
||||||
|
Model* other = static_cast<Model*>(castToOther);
|
||||||
|
if (*item->model->EntryRef() == *other->EntryRef())
|
||||||
|
return item;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
LoadAddOnDir(directory_which dirName, BDeskWindow* window,
|
||||||
|
LockingList<AddonShortcut>* list)
|
||||||
{
|
{
|
||||||
BPath path;
|
BPath path;
|
||||||
if (find_directory(dirName, &path) == B_OK) {
|
if (find_directory(dirName, &path) == B_OK) {
|
||||||
path.Append("Tracker");
|
path.Append("Tracker");
|
||||||
|
|
||||||
|
BDirectory dir;
|
||||||
|
BEntry entry;
|
||||||
|
|
||||||
|
if (dir.SetTo(path.Path()) != B_OK)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (dir.GetNextEntry(&entry) == B_OK) {
|
||||||
|
Model* model = new Model(&entry);
|
||||||
|
if (model->InitCheck() == B_OK && model->IsSymLink()) {
|
||||||
|
// resolve symlinks
|
||||||
|
Model* resolved = new Model(model->EntryRef(), true, true);
|
||||||
|
if (resolved->InitCheck() == B_OK)
|
||||||
|
model->SetLinkTo(resolved);
|
||||||
|
else
|
||||||
|
delete resolved;
|
||||||
|
}
|
||||||
|
if (model->InitCheck() != B_OK
|
||||||
|
|| !model->ResolveIfLink()->IsExecutable()) {
|
||||||
|
delete model;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* name = strdup(model->Name());
|
||||||
|
if (!list->EachElement(MatchOne, name)) {
|
||||||
|
struct AddonShortcut* item = new struct AddonShortcut;
|
||||||
|
item->model = model;
|
||||||
|
|
||||||
|
BResources resources(model->ResolveIfLink()->EntryRef());
|
||||||
|
size_t size;
|
||||||
|
char* shortcut = (char*)resources.LoadResource(B_STRING_TYPE,
|
||||||
|
kDefaultShortcut, &size);
|
||||||
|
if (shortcut == NULL || strlen(shortcut) > 1)
|
||||||
|
item->key = '\0';
|
||||||
|
else
|
||||||
|
item->key = shortcut[0];
|
||||||
|
AddOneShortcut(model, item->key, kDefaultModifiers, window);
|
||||||
|
item->defaultKey = item->key;
|
||||||
|
list->AddItem(item);
|
||||||
|
}
|
||||||
|
free(name);
|
||||||
|
}
|
||||||
|
|
||||||
BNode node(path.Path());
|
BNode node(path.Path());
|
||||||
node_ref nodeRef;
|
node_ref nodeRef;
|
||||||
node.GetNodeRef(&nodeRef);
|
node.GetNodeRef(&nodeRef);
|
||||||
|
|
||||||
TTracker::WatchNode(&nodeRef, B_WATCH_DIRECTORY, window);
|
TTracker::WatchNode(&nodeRef, B_WATCH_DIRECTORY, window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct AddOneShortcutParams {
|
|
||||||
BDeskWindow* window;
|
|
||||||
std::set<uint32>* currentAddonShortcuts;
|
|
||||||
};
|
|
||||||
|
|
||||||
static bool
|
|
||||||
AddOneShortcut(const Model* model, const char*, uint32 shortcut,
|
|
||||||
bool /*primary*/, void* context)
|
|
||||||
{
|
|
||||||
if (!shortcut)
|
|
||||||
// no shortcut, bail
|
|
||||||
return false;
|
|
||||||
|
|
||||||
AddOneShortcutParams* params = (AddOneShortcutParams*)context;
|
|
||||||
BMessage* runAddon = new BMessage(kLoadAddOn);
|
|
||||||
runAddon->AddRef("refs", model->EntryRef());
|
|
||||||
|
|
||||||
params->window->AddShortcut(shortcut, B_OPTION_KEY | B_COMMAND_KEY,
|
|
||||||
runAddon);
|
|
||||||
params->currentAddonShortcuts->insert(shortcut);
|
|
||||||
PRINT(("adding new shortcut %c\n", (char)shortcut));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
|
||||||
#undef B_TRANSLATION_CONTEXT
|
#undef B_TRANSLATION_CONTEXT
|
||||||
@@ -118,7 +194,8 @@ BDeskWindow::BDeskWindow(LockingList<BWindow>* windowList)
|
|||||||
| B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS, B_ALL_WORKSPACES),
|
| B_NOT_RESIZABLE | B_ASYNCHRONOUS_CONTROLS, B_ALL_WORKSPACES),
|
||||||
fDeskShelf(0),
|
fDeskShelf(0),
|
||||||
fTrashContextMenu(0),
|
fTrashContextMenu(0),
|
||||||
fShouldUpdateAddonShortcuts(true)
|
fNodeRef(NULL),
|
||||||
|
fShortcutsSettings(NULL)
|
||||||
{
|
{
|
||||||
// Add icon view switching shortcuts. These are displayed in the context
|
// Add icon view switching shortcuts. These are displayed in the context
|
||||||
// menu, although they obviously don't work from those menu items.
|
// menu, although they obviously don't work from those menu items.
|
||||||
@@ -173,43 +250,133 @@ BDeskWindow::Init(const BMessage*)
|
|||||||
if (fDeskShelf)
|
if (fDeskShelf)
|
||||||
fDeskShelf->SetDisplaysZombies(true);
|
fDeskShelf->SetDisplaysZombies(true);
|
||||||
}
|
}
|
||||||
|
InitKeyIndices();
|
||||||
// watch add-on directories so that we can track the addons with
|
InitAddonsList(false);
|
||||||
// corresponding shortcuts
|
ApplyShortcutPreferences(false);
|
||||||
WatchAddOnDir(B_USER_ADDONS_DIRECTORY, this);
|
|
||||||
WatchAddOnDir(B_COMMON_ADDONS_DIRECTORY, this);
|
|
||||||
WatchAddOnDir(B_SYSTEM_ADDONS_DIRECTORY, this);
|
|
||||||
|
|
||||||
_inherited::Init();
|
_inherited::Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BDeskWindow::MenusBeginning()
|
BDeskWindow::InitAddonsList(bool update)
|
||||||
{
|
{
|
||||||
_inherited::MenusBeginning();
|
AutoLock<LockingList<AddonShortcut> > lock(fAddonsList);
|
||||||
|
if (lock.IsLocked()) {
|
||||||
if (fShouldUpdateAddonShortcuts) {
|
if (update) {
|
||||||
PRINT(("updating addon shortcuts\n"));
|
for (int i = fAddonsList->CountItems() - 1; i >= 0; i--) {
|
||||||
fShouldUpdateAddonShortcuts = false;
|
AddonShortcut* item = fAddonsList->ItemAt(i);
|
||||||
|
RemoveShortcut(item->key, B_OPTION_KEY | B_COMMAND_KEY);
|
||||||
// remove all current addon shortcuts
|
}
|
||||||
for (std::set<uint32>::iterator it= fCurrentAddonShortcuts.begin();
|
fAddonsList->MakeEmpty(true);
|
||||||
it != fCurrentAddonShortcuts.end(); it++) {
|
|
||||||
PRINT(("removing shortcut %c\n", (int)*it));
|
|
||||||
RemoveShortcut(*it, B_OPTION_KEY | B_COMMAND_KEY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fCurrentAddonShortcuts.clear();
|
LoadAddOnDir(B_USER_ADDONS_DIRECTORY, this, fAddonsList);
|
||||||
|
LoadAddOnDir(B_COMMON_ADDONS_DIRECTORY, this, fAddonsList);
|
||||||
|
LoadAddOnDir(B_SYSTEM_ADDONS_DIRECTORY, this, fAddonsList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AddOneShortcutParams params;
|
|
||||||
params.window = this;
|
|
||||||
params.currentAddonShortcuts = &fCurrentAddonShortcuts;
|
|
||||||
|
|
||||||
BObjectList<BString> mimeTypes(10, true);
|
void
|
||||||
BuildMimeTypeList(mimeTypes);
|
BDeskWindow::ApplyShortcutPreferences(bool update)
|
||||||
|
{
|
||||||
|
AutoLock<LockingList<AddonShortcut> > lock(fAddonsList);
|
||||||
|
if (lock.IsLocked()) {
|
||||||
|
if (!update) {
|
||||||
|
BPath path;
|
||||||
|
if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
|
||||||
|
BPathMonitor::StartWatching(path.Path(), B_WATCH_STAT | B_WATCH_FILES_ONLY, this);
|
||||||
|
path.Append(kShortcutsSettings);
|
||||||
|
fShortcutsSettings = new char[strlen(path.Path()) + 1];
|
||||||
|
strcpy(fShortcutsSettings, path.Path());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
EachAddon(&AddOneShortcut, ¶ms, mimeTypes);
|
fAddonsList->EachElement(RevertToDefault, this);
|
||||||
|
|
||||||
|
BFile shortcutSettings(fShortcutsSettings, B_READ_ONLY);
|
||||||
|
BMessage fileMsg;
|
||||||
|
if (shortcutSettings.InitCheck() != B_OK
|
||||||
|
|| fileMsg.Unflatten(&shortcutSettings) != B_OK) {
|
||||||
|
fNodeRef = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
shortcutSettings.GetNodeRef(fNodeRef);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
BMessage message;
|
||||||
|
while (fileMsg.FindMessage("spec", i++, &message) == B_OK) {
|
||||||
|
|
||||||
|
int32 key;
|
||||||
|
BMessage actMsg;
|
||||||
|
|
||||||
|
if (message.FindInt32("key", &key) == B_OK
|
||||||
|
&& message.FindMessage("act", &actMsg) == B_OK) {
|
||||||
|
|
||||||
|
// only handle shortcuts referring add-ons
|
||||||
|
BString command;
|
||||||
|
if (actMsg.FindString("largv", &command) != B_OK)
|
||||||
|
continue;
|
||||||
|
BPath path;
|
||||||
|
bool isInAddons = false;
|
||||||
|
if (find_directory(B_SYSTEM_ADDONS_DIRECTORY, &path)
|
||||||
|
== B_OK) {
|
||||||
|
path.Append("Tracker/");
|
||||||
|
isInAddons = command.FindFirst(path.Path()) == 0;
|
||||||
|
}
|
||||||
|
if (!isInAddons
|
||||||
|
&& (find_directory(B_COMMON_ADDONS_DIRECTORY, &path)
|
||||||
|
== B_OK)) {
|
||||||
|
path.Append("Tracker/");
|
||||||
|
isInAddons = command.FindFirst(path.Path()) == 0;
|
||||||
|
}
|
||||||
|
if (!isInAddons
|
||||||
|
&& (find_directory(B_USER_ADDONS_DIRECTORY, &path)
|
||||||
|
== B_OK)) {
|
||||||
|
path.Append("Tracker/");
|
||||||
|
isInAddons = command.FindFirst(path.Path()) == 0;
|
||||||
|
}
|
||||||
|
if (!isInAddons)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
BEntry entry(command);
|
||||||
|
if (entry.InitCheck() != B_OK)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const char* shortcut = GetKeyName(key);
|
||||||
|
if (strlen(shortcut) != 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint32 modifiers = 0;
|
||||||
|
int32 value;
|
||||||
|
if (message.FindInt32("mcidx", 0, &value) == B_OK)
|
||||||
|
modifiers |= (value != 0 ? B_SHIFT_KEY : 0);
|
||||||
|
|
||||||
|
if (message.FindInt32("mcidx", 1, &value) == B_OK)
|
||||||
|
modifiers |= (value != 0 ? B_CONTROL_KEY : 0);
|
||||||
|
|
||||||
|
if (message.FindInt32("mcidx", 2, &value) == B_OK)
|
||||||
|
modifiers |= (value != 0 ? B_COMMAND_KEY : 0);
|
||||||
|
|
||||||
|
if (message.FindInt32("mcidx", 3, &value) == B_OK)
|
||||||
|
modifiers |= (value != 0 ? B_OPTION_KEY : 0);
|
||||||
|
|
||||||
|
if (modifiers == 0)
|
||||||
|
modifiers = kDefaultModifiers;
|
||||||
|
|
||||||
|
Model model(&entry);
|
||||||
|
AddonShortcut* item = fAddonsList->EachElement(FindElement,
|
||||||
|
&model);
|
||||||
|
if (item != NULL) {
|
||||||
|
if (item->key != '\0')
|
||||||
|
RemoveShortcut(item->key, item->modifiers);
|
||||||
|
item->key = shortcut[0];
|
||||||
|
item->modifiers = modifiers;
|
||||||
|
AddOneShortcut(&model, item->key, item->modifiers, this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,6 +395,11 @@ BDeskWindow::Quit()
|
|||||||
fNavigationItem = 0;
|
fNavigationItem = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while (fAddonsList->CountItems())
|
||||||
|
fAddonsList->RemoveItem(0);
|
||||||
|
|
||||||
|
delete fAddonsList;
|
||||||
|
|
||||||
delete fTrashContextMenu;
|
delete fTrashContextMenu;
|
||||||
fTrashContextMenu = NULL;
|
fTrashContextMenu = NULL;
|
||||||
|
|
||||||
@@ -482,9 +654,28 @@ BDeskWindow::MessageReceived(BMessage* message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
switch (message->what) {
|
switch (message->what) {
|
||||||
|
case B_PATH_MONITOR:
|
||||||
|
{
|
||||||
|
const char* path = "";
|
||||||
|
if (!(message->FindString("path", &path) == B_OK
|
||||||
|
&& strcmp(path, fShortcutsSettings) == 0)) {
|
||||||
|
|
||||||
|
dev_t device;
|
||||||
|
ino_t node;
|
||||||
|
if (fNodeRef == NULL
|
||||||
|
|| message->FindInt32("device", &device) != B_OK
|
||||||
|
|| message->FindInt64("node", &node) != B_OK
|
||||||
|
|| device != fNodeRef->device
|
||||||
|
|| node != fNodeRef->node)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ApplyShortcutPreferences(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case B_NODE_MONITOR:
|
case B_NODE_MONITOR:
|
||||||
PRINT(("will update addon shortcuts\n"));
|
PRINT(("will update addon shortcuts\n"));
|
||||||
fShouldUpdateAddonShortcuts = true;
|
InitAddonsList(true);
|
||||||
|
ApplyShortcutPreferences(true);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -75,24 +75,20 @@ protected:
|
|||||||
virtual BPoseView* NewPoseView(Model*, BRect, uint32);
|
virtual BPoseView* NewPoseView(Model*, BRect, uint32);
|
||||||
|
|
||||||
virtual void WorkspaceActivated(int32, bool);
|
virtual void WorkspaceActivated(int32, bool);
|
||||||
virtual void MenusBeginning();
|
|
||||||
virtual void MessageReceived(BMessage*);
|
virtual void MessageReceived(BMessage*);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void InitAddonsList(bool);
|
||||||
|
void ApplyShortcutPreferences(bool);
|
||||||
|
|
||||||
BShelf* fDeskShelf;
|
BShelf* fDeskShelf;
|
||||||
// shelf for replicant support
|
// shelf for replicant support
|
||||||
BPopUpMenu* fTrashContextMenu;
|
BPopUpMenu* fTrashContextMenu;
|
||||||
|
|
||||||
BRect fOldFrame;
|
BRect fOldFrame;
|
||||||
|
|
||||||
// in the desktop window addon shortcuts have to be added by AddShortcut
|
node_ref* fNodeRef;
|
||||||
// and we don't always get the MenusBeginning call to check for new
|
char* fShortcutsSettings;
|
||||||
// addons/update the shortcuts -- instead we need to node monitor the
|
|
||||||
// addon directory and keep a dirty flag that triggers shortcut
|
|
||||||
// reinstallation
|
|
||||||
bool fShouldUpdateAddonShortcuts;
|
|
||||||
std::set<uint32> fCurrentAddonShortcuts;
|
|
||||||
// keeps track of which shortcuts are installed for Tracker addons
|
|
||||||
|
|
||||||
typedef BContainerWindow _inherited;
|
typedef BContainerWindow _inherited;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ UsePrivateHeaders interface mount shared storage support tracker ;
|
|||||||
|
|
||||||
AddResources libtracker.so : TrackerIcons.rdef libtracker.rdef ;
|
AddResources libtracker.so : TrackerIcons.rdef libtracker.rdef ;
|
||||||
|
|
||||||
|
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons input_server filters shortcut_catcher ] ;
|
||||||
|
|
||||||
SubDirC++Flags
|
SubDirC++Flags
|
||||||
-D_BUILDING_tracker=1
|
-D_BUILDING_tracker=1
|
||||||
# -D_INCLUDES_CLASS_DEVICE_MAP=1
|
# -D_INCLUDES_CLASS_DEVICE_MAP=1
|
||||||
@@ -89,7 +91,8 @@ SharedLibrary libtracker.so :
|
|||||||
VolumeWindow.cpp
|
VolumeWindow.cpp
|
||||||
WidgetAttributeText.cpp
|
WidgetAttributeText.cpp
|
||||||
|
|
||||||
: be translation $(vector_icon_libs) $(TARGET_LIBSTDC++) $(HAIKU_LOCALE_LIBS) libshared.a
|
: be translation $(vector_icon_libs) $(TARGET_LIBSTDC++) $(HAIKU_LOCALE_LIBS) libshared.a
|
||||||
|
libshortcuts_shared.a
|
||||||
;
|
;
|
||||||
|
|
||||||
DoCatalogs libtracker.so :
|
DoCatalogs libtracker.so :
|
||||||
|
|||||||
Reference in New Issue
Block a user