From da24e53cf8e071a1bf41e6bffdffdf07e2a2cf4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Sun, 25 Apr 2010 16:40:29 +0000 Subject: [PATCH] Changed the behavior for BRoster::FindApp(), Launch() and related functionality: Instead of only checking the preferred applications of a given MIME type and its super type (i.e. "text/html" and "text"), build a list of all supporting apps, where the preferred types of the sub and super type lead the respective sections of the list. Then try to find the first valid application in the list. This makes it possible to double click "Welcome" on the Desktop, even though the text/html MIME type still has BeZillaBrowser set as preferred application. Previously it would launch StyledEdit, even though WebPositive was readily available. The previous behavior was probably implementing exactly the BeOS behavior, but I can't see a good reason why we should be compatible here. Until now, my testing has also not revealed any regression. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@36471 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/kits/app/Roster.cpp | 87 +++++++++++++++++++++++++++++------------ 1 file changed, 61 insertions(+), 26 deletions(-) diff --git a/src/kits/app/Roster.cpp b/src/kits/app/Roster.cpp index 102bb5f2c1..bcbf5e04fe 100644 --- a/src/kits/app/Roster.cpp +++ b/src/kits/app/Roster.cpp @@ -2563,11 +2563,11 @@ BRoster::_TranslateType(const char* mimeType, BMimeType* appMeta, || appFile == NULL || strlen(mimeType) >= B_MIME_TYPE_LENGTH) return B_BAD_VALUE; - // create a BMimeType and check, if the type is installed + // Create a BMimeType and check, if the type is installed. BMimeType type; status_t error = type.SetTo(mimeType); - // get the preferred app + // Get the preferred apps from the sub and super type. char primarySignature[B_MIME_TYPE_LENGTH]; char secondarySignature[B_MIME_TYPE_LENGTH]; primarySignature[0] = '\0'; @@ -2579,12 +2579,9 @@ BRoster::_TranslateType(const char* mimeType, BMimeType* appMeta, if (type.GetSupertype(&superType) == B_OK) superType.GetPreferredApp(secondarySignature); - if (type.GetPreferredApp(primarySignature) != B_OK - && !secondarySignature[0]) { + if (type.GetPreferredApp(primarySignature) != B_OK) { // The type is installed, but has no preferred app. - // In fact it might be an app signature and even having a - // valid app hint. Nevertheless we fail. - error = B_LAUNCH_FAILED_NO_PREFERRED_APP; + primarySignature[0] = '\0'; } else if (!strcmp(primarySignature, secondarySignature)) { // Both types have the same preferred app, there is // no point in testing it twice. @@ -2596,37 +2593,80 @@ BRoster::_TranslateType(const char* mimeType, BMimeType* appMeta, } } + // We will use this BMessage "signatures" to hold all supporting apps + // so we can iterator over them in the preferred order. We include + // the supporting apps in such a way that the configured preferred + // applications for the MIME type are in front of other supporting + // applications for the sub and the super type respectively. + const char* kSigField = "applications"; + BMessage signatures; + if (error == B_OK && primarySignature[0] != '\0') + error = signatures.AddString(kSigField, primarySignature); + + BMessage supportingSignatures; + if (error == B_OK + && type.GetSupportingApps(&supportingSignatures) == B_OK) { + int32 subCount; + if (supportingSignatures.FindInt32("be:sub", &subCount) != B_OK) + subCount = 0; + // Add all signatures with direct support for the sub-type + const char* supportingType; + for (int32 i = 0; error == B_OK && i < subCount + && supportingSignatures.FindString(kSigField, i, + &supportingType) == B_OK; i++) { + // don't add the signature if it's the preferred app already. + if (strcmp(primarySignature, supportingType) != 0) + error = signatures.AddString(kSigField, supportingType); + } + // Add the preferred type of the super type here before adding + // the other types supporting the super type. + if (error == B_OK && secondarySignature[0] != '\0') + error = signatures.AddString(kSigField, secondarySignature); + // Add all signatures with support for the super-type + for (int32 i = subCount; error == B_OK + && supportingSignatures.FindString(kSigField, i, + &supportingType) == B_OK; i++) { + // don't add the signature if it's the preferred app already. + if (strcmp(secondarySignature, supportingType) != 0) + error = signatures.AddString(kSigField, supportingType); + } + } else { + // Failed to get supporting apps, just add the preferred apps. + if (error == B_OK) + error = signatures.AddString(kSigField, secondarySignature); + } + if (error != B_OK) return error; - // see if we can find the application and if it's valid, try - // both preferred app signatures, if available (from type and - // super type) + // Set an error in case we can't resolve a single supporting app. + error = B_LAUNCH_FAILED_NO_PREFERRED_APP; - status_t primaryError = B_OK; - - for (int32 tries = 0; tries < 2; tries++) { - const char* signature = tries == 0 - ? primarySignature : secondarySignature; + // See if we can find a good application that is valid from the messege. + const char* signature; + for (int32 i = 0; + signatures.FindString(kSigField, i, &signature) == B_OK; i++) { if (signature[0] == '\0') continue; error = appMeta->SetTo(signature); - // check, whether the signature is installed and has an app hint + // Check, whether the signature is installed and has an app hint bool appFound = false; if (error == B_OK && appMeta->GetAppHint(appRef) == B_OK) { - // resolve symbolic links, if necessary + // Resolve symbolic links, if necessary BEntry entry; if (entry.SetTo(appRef, true) == B_OK && entry.IsFile() && entry.GetRef(appRef) == B_OK) { appFound = true; - } else - appMeta->SetAppHint(NULL); // bad app hint -- remove it + } else { + // Bad app hint -- remove it + appMeta->SetAppHint(NULL); + } } // In case there is no app hint or it is invalid, we need to query for - // the app + // the app. if (error == B_OK && !appFound) error = query_for_app(appMeta->Type(), appRef); if (error == B_OK) @@ -2635,12 +2675,7 @@ BRoster::_TranslateType(const char* mimeType, BMimeType* appMeta, if (error == B_OK) error = can_app_be_used(appRef); - if (error != B_OK) { - if (tries == 0) - primaryError = error; - else if (primarySignature[0]) - error = primaryError; - } else + if (error == B_OK) break; }