Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 364986 Details for
Bug 493722
www-client/firefox-24.2.0 version bump and KDE integration
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
mozilla-kde-24.1.1.patch
mozilla-kde-24.1.1.patch (text/plain), 130.51 KB, created by
Andreas Sturmlechner
on 2013-12-09 07:03:55 UTC
(
hide
)
Description:
mozilla-kde-24.1.1.patch
Filename:
MIME Type:
Creator:
Andreas Sturmlechner
Created:
2013-12-09 07:03:55 UTC
Size:
130.51 KB
patch
obsolete
>Description: Add KDE integration to Firefox (toolkit parts) >Author: Wolfgang Rosenauer <wolfgang@rosenauer.org> >Author: Lubos Lunak <lunak@suse.com> >Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=140751 > https://bugzilla.novell.com/show_bug.cgi?id=170055 > >diff --git a/modules/libpref/src/Makefile.in b/modules/libpref/src/Makefile.in >--- a/modules/libpref/src/Makefile.in >+++ b/modules/libpref/src/Makefile.in >@@ -49,14 +49,15 @@ endif > # Optimizer bug with GCC 3.2.2 on OS/2 > ifeq ($(OS_ARCH), OS2) > nsPrefService.$(OBJ_SUFFIX): nsPrefService.cpp > $(REPORT_BUILD) > @$(MAKE_DEPS_AUTO_CXX) > $(ELOG) $(CCC) $(OUTOPTION)$@ -c $(COMPILE_CXXFLAGS:-O2=-O1) $(_VPATH_SRCS) > endif > >+LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre > > greprefs.js: $(grepref_files) > $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $^ > $@ > > libs:: greprefs.js > $(INSTALL) $^ $(DIST)/bin/ >diff --git a/modules/libpref/src/Preferences.cpp b/modules/libpref/src/Preferences.cpp >--- a/modules/libpref/src/Preferences.cpp >+++ b/modules/libpref/src/Preferences.cpp >@@ -23,16 +23,17 @@ > #include "nsIStringEnumerator.h" > #include "nsIZipReader.h" > #include "nsPrefBranch.h" > #include "nsXPIDLString.h" > #include "nsCRT.h" > #include "nsCOMArray.h" > #include "nsXPCOMCID.h" > #include "nsAutoPtr.h" >+#include "nsKDEUtils.h" > > #include "nsQuickSort.h" > #include "pldhash.h" > > #include "prefapi.h" > #include "prefread.h" > #include "prefapi_private_data.h" > >@@ -972,16 +973,34 @@ pref_LoadPrefsInDir(nsIFile* aDir, char > > static nsresult pref_LoadPrefsInDirList(const char *listId) > { > nsresult rv; > nsCOMPtr<nsIProperties> dirSvc(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv)); > if (NS_FAILED(rv)) > return rv; > >+ // make sure we load these special files after all the others >+ static const char* specialFiles[] = { >+#if defined(XP_UNIX) >+ "" >+#endif >+ }; >+ >+ if (nsKDEUtils::kdeSession()) { >+ for(int i = 0; >+ i < NS_ARRAY_LENGTH(specialFiles); >+ ++i ) { >+ if (*specialFiles[ i ] == '\0') { >+ specialFiles[ i ] = "kde.js"; >+ break; >+ } >+ } >+ } >+ > nsCOMPtr<nsISimpleEnumerator> list; > dirSvc->Get(listId, > NS_GET_IID(nsISimpleEnumerator), > getter_AddRefs(list)); > if (!list) > return NS_OK; > > bool hasMore; >@@ -997,17 +1016,17 @@ static nsresult pref_LoadPrefsInDirList( > > nsAutoCString leaf; > path->GetNativeLeafName(leaf); > > // Do we care if a file provided by this process fails to load? > if (Substring(leaf, leaf.Length() - 4).Equals(NS_LITERAL_CSTRING(".xpi"))) > ReadExtensionPrefs(path); > else >- pref_LoadPrefsInDir(path, nullptr, 0); >+ pref_LoadPrefsInDir(path, specialFiles, NS_ARRAY_LENGTH(specialFiles)); > } > return NS_OK; > } > > static nsresult pref_ReadPrefFromJar(nsZipArchive* jarReader, const char *name) > { > nsZipItemPtr<char> manifest(jarReader, name, true); > NS_ENSURE_TRUE(manifest.Buffer(), NS_ERROR_NOT_AVAILABLE); >@@ -1101,28 +1120,40 @@ static nsresult pref_InitInitialObjects( > /* these pref file names should not be used: we process them after all other application pref files for backwards compatibility */ > static const char* specialFiles[] = { > #if defined(XP_MACOSX) > "macprefs.js" > #elif defined(XP_WIN) > "winpref.js" > #elif defined(XP_UNIX) > "unix.js" >+ , "" // placeholder for KDE (empty is otherwise harmless) > #if defined(VMS) > , "openvms.js" > #elif defined(_AIX) > , "aix.js" > #endif > #elif defined(XP_OS2) > "os2pref.js" > #elif defined(XP_BEOS) > "beos.js" > #endif > }; > >+ if(nsKDEUtils::kdeSession()) { // TODO what if some setup actually requires the helper? >+ for(int i = 0; >+ i < NS_ARRAY_LENGTH(specialFiles); >+ ++i ) { >+ if( *specialFiles[ i ] == '\0' ) { >+ specialFiles[ i ] = "kde.js"; >+ break; >+ } >+ } >+ } >+ > rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles, ArrayLength(specialFiles)); > if (NS_FAILED(rv)) > NS_WARNING("Error parsing application default preferences."); > > // Load jar:$app/omni.jar!/defaults/preferences/*.js > // or jar:$gre/omni.jar!/defaults/preferences/*.js. > nsRefPtr<nsZipArchive> appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP); > // GetReader(mozilla::Omnijar::APP) returns null when $app == $gre, in which >diff --git a/python/mozbuild/mozpack/chrome/flags.py b/python/mozbuild/mozpack/chrome/flags.py >--- a/python/mozbuild/mozpack/chrome/flags.py >+++ b/python/mozbuild/mozpack/chrome/flags.py >@@ -208,16 +208,17 @@ class Flags(OrderedDict): > 'platformversion': VersionFlag, > 'contentaccessible': Flag, > 'os': StringFlag, > 'osversion': VersionFlag, > 'abi': StringFlag, > 'platform': Flag, > 'xpcnativewrappers': Flag, > 'tablet': Flag, >+ 'desktop': StringFlag, > } > RE = re.compile(r'([!<>=]+)') > > def __init__(self, *flags): > ''' > Initialize a set of flags given in string form. > flags = Flags('contentaccessible=yes', 'appversion>=3.5') > ''' >diff --git a/python/mozbuild/mozpack/chrome/manifest.py b/python/mozbuild/mozpack/chrome/manifest.py >--- a/python/mozbuild/mozpack/chrome/manifest.py >+++ b/python/mozbuild/mozpack/chrome/manifest.py >@@ -30,16 +30,17 @@ class ManifestEntry(object): > allowed_flags = [ > 'application', > 'platformversion', > 'os', > 'osversion', > 'abi', > 'xpcnativewrappers', > 'tablet', >+ 'desktop', > ] > > def __init__(self, base, *flags): > ''' > Initialize a manifest entry with the given base path and flags. > ''' > self.base = base > self.flags = Flags(*flags) >diff --git a/toolkit/components/downloads/Makefile.in b/toolkit/components/downloads/Makefile.in >--- a/toolkit/components/downloads/Makefile.in >+++ b/toolkit/components/downloads/Makefile.in >@@ -23,9 +23,11 @@ ifndef MOZ_SUITE > DISABLED_EXTRA_COMPONENTS = \ > nsDownloadManagerUI.js \ > nsDownloadManagerUI.manifest \ > $(NULL) > endif > > include $(topsrcdir)/config/rules.mk > >+LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre >+ > CXXFLAGS += $(TK_CFLAGS) >diff --git a/toolkit/components/downloads/nsDownloadManager.cpp b/toolkit/components/downloads/nsDownloadManager.cpp >--- a/toolkit/components/downloads/nsDownloadManager.cpp >+++ b/toolkit/components/downloads/nsDownloadManager.cpp >@@ -38,16 +38,20 @@ > > #ifdef XP_WIN > #include <shlobj.h> > #ifdef DOWNLOAD_SCANNER > #include "nsDownloadScanner.h" > #endif > #endif > >+#if defined(XP_UNIX) && !defined(XP_MACOSX) >+#include "nsKDEUtils.h" >+#endif >+ > #ifdef XP_MACOSX > #include <CoreFoundation/CoreFoundation.h> > #endif > > #ifdef MOZ_WIDGET_ANDROID > #include "AndroidBridge.h" > #endif > >@@ -2609,16 +2613,25 @@ nsDownload::SetState(DownloadState aStat > nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID)); > > // Master pref to control this function. > bool showTaskbarAlert = true; > if (pref) > pref->GetBoolPref(PREF_BDM_SHOWALERTONCOMPLETE, &showTaskbarAlert); > > if (showTaskbarAlert) { >+ if( nsKDEUtils::kdeSupport()) { >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "DOWNLOADFINISHED" )); >+ nsAutoString displayName; >+ GetDisplayName( displayName ); >+ command.AppendElement( nsAutoCString( ToNewUTF8String( displayName ))); >+ nsKDEUtils::command( command ); >+ } else { >+ // begin non-KDE block > int32_t alertInterval = 2000; > if (pref) > pref->GetIntPref(PREF_BDM_SHOWALERTINTERVAL, &alertInterval); > > int64_t alertIntervalUSec = alertInterval * PR_USEC_PER_MSEC; > int64_t goat = PR_Now() - mStartTime; > showTaskbarAlert = goat > alertIntervalUSec; > >@@ -2645,19 +2658,20 @@ nsDownload::SetState(DownloadState aStat > // retention policy, there's no reason to make the text clickable > // because if it is, they'll click open the download manager and > // the items they downloaded will have been removed. > alerts->ShowAlertNotification( > NS_LITERAL_STRING(DOWNLOAD_MANAGER_ALERT_ICON), title, > message, !removeWhenDone, > mPrivate ? NS_LITERAL_STRING("private") : NS_LITERAL_STRING("non-private"), > mDownloadManager, EmptyString(), NS_LITERAL_STRING("auto"), EmptyString()); >- } >+ } > } > } >+ } > > #if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_ANDROID) || defined(MOZ_WIDGET_GTK2) > nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(mTarget); > nsCOMPtr<nsIFile> file; > nsAutoString path; > > if (fileURL && > NS_SUCCEEDED(fileURL->GetFile(getter_AddRefs(file))) && >diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn >--- a/toolkit/content/jar.mn >+++ b/toolkit/content/jar.mn >@@ -50,29 +50,33 @@ toolkit.jar: > content/global/viewZoomOverlay.js (viewZoomOverlay.js) > *+ content/global/bindings/autocomplete.xml (widgets/autocomplete.xml) > content/global/bindings/browser.xml (widgets/browser.xml) > content/global/bindings/button.xml (widgets/button.xml) > content/global/bindings/checkbox.xml (widgets/checkbox.xml) > content/global/bindings/colorpicker.xml (widgets/colorpicker.xml) > content/global/bindings/datetimepicker.xml (widgets/datetimepicker.xml) > *+ content/global/bindings/dialog.xml (widgets/dialog.xml) >+*+ content/global/bindings/dialog-kde.xml (widgets/dialog-kde.xml) >+% override chrome://global/content/bindings/dialog.xml chrome://global/content/bindings/dialog-kde.xml desktop=kde > content/global/bindings/editor.xml (widgets/editor.xml) > content/global/bindings/expander.xml (widgets/expander.xml) > * content/global/bindings/filefield.xml (widgets/filefield.xml) > *+ content/global/bindings/findbar.xml (widgets/findbar.xml) > content/global/bindings/general.xml (widgets/general.xml) > content/global/bindings/groupbox.xml (widgets/groupbox.xml) > *+ content/global/bindings/listbox.xml (widgets/listbox.xml) > content/global/bindings/menu.xml (widgets/menu.xml) > content/global/bindings/menulist.xml (widgets/menulist.xml) > content/global/bindings/notification.xml (widgets/notification.xml) > content/global/bindings/numberbox.xml (widgets/numberbox.xml) > content/global/bindings/popup.xml (widgets/popup.xml) > *+ content/global/bindings/preferences.xml (widgets/preferences.xml) >+*+ content/global/bindings/preferences-kde.xml (widgets/preferences-kde.xml) >+% override chrome://global/content/bindings/preferences.xml chrome://global/content/bindings/preferences-kde.xml desktop=kde > content/global/bindings/progressmeter.xml (widgets/progressmeter.xml) > content/global/bindings/radio.xml (widgets/radio.xml) > content/global/bindings/remote-browser.xml (widgets/remote-browser.xml) > content/global/bindings/resizer.xml (widgets/resizer.xml) > content/global/bindings/richlistbox.xml (widgets/richlistbox.xml) > content/global/bindings/scale.xml (widgets/scale.xml) > content/global/bindings/scrollbar.xml (widgets/scrollbar.xml) > content/global/bindings/scrollbox.xml (widgets/scrollbox.xml) >diff --git a/toolkit/content/widgets/dialog-kde.xml b/toolkit/content/widgets/dialog-kde.xml >new file mode 100644 >--- /dev/null >+++ b/toolkit/content/widgets/dialog-kde.xml >@@ -0,0 +1,451 @@ >+<?xml version="1.0"?> >+<!-- This Source Code Form is subject to the terms of the Mozilla Public >+ - License, v. 2.0. If a copy of the MPL was not distributed with this >+ - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> >+ >+ >+<bindings id="dialogBindings" >+ xmlns="http://www.mozilla.org/xbl" >+ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" >+ xmlns:xbl="http://www.mozilla.org/xbl"> >+ >+ <binding id="dialog" extends="chrome://global/content/bindings/general.xml#root-element"> >+ <resources> >+ <stylesheet src="chrome://global/skin/dialog.css"/> >+ </resources> >+ <content> >+ <xul:vbox class="box-inherit dialog-content-box" flex="1"> >+ <children/> >+ </xul:vbox> >+ >+ <xul:hbox class="dialog-button-box" anonid="buttons" >+ xbl:inherits="pack=buttonpack,align=buttonalign,dir=buttondir,orient=buttonorient" >+#ifdef XP_UNIX_GNOME >+ > >+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="help" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> >+ <xul:spacer anonid="spacer" flex="1"/> >+ <xul:button dlgtype="cancel" class="dialog-button"/> >+ <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/> >+#elif XP_UNIX >+ pack="end"> >+ <xul:button dlgtype="help" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> >+ <xul:spacer anonid="spacer" flex="1" hidden="true"/> >+ <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/> >+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="cancel" class="dialog-button"/> >+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> >+#else >+ pack="end"> >+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> >+ <xul:spacer anonid="spacer" flex="1" hidden="true"/> >+ <xul:button dlgtype="accept" class="dialog-button" xbl:inherits="disabled=buttondisabledaccept"/> >+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="cancel" class="dialog-button"/> >+ <xul:button dlgtype="help" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> >+#endif >+ </xul:hbox> >+ </content> >+ >+ <implementation> >+ <field name="_mStrBundle">null</field> >+ <field name="_closeHandler">(function(event) { >+ if (!document.documentElement.cancelDialog()) >+ event.preventDefault(); >+ })</field> >+ >+ <property name="buttons" >+ onget="return this.getAttribute('buttons');" >+ onset="this._configureButtons(val); return val;"/> >+ >+ <property name="defaultButton"> >+ <getter> >+ <![CDATA[ >+ if (this.hasAttribute("defaultButton")) >+ return this.getAttribute("defaultButton"); >+ else // default to the accept button >+ return "accept"; >+ ]]> >+ </getter> >+ <setter> >+ <![CDATA[ >+ this._setDefaultButton(val); >+ return val; >+ ]]> >+ </setter> >+ </property> >+ >+ <method name="acceptDialog"> >+ <body> >+ <![CDATA[ >+ return this._doButtonCommand("accept"); >+ ]]> >+ </body> >+ </method> >+ >+ <method name="cancelDialog"> >+ <body> >+ <![CDATA[ >+ return this._doButtonCommand("cancel"); >+ ]]> >+ </body> >+ </method> >+ >+ <method name="getButton"> >+ <parameter name="aDlgType"/> >+ <body> >+ <![CDATA[ >+ return this._buttons[aDlgType]; >+ ]]> >+ </body> >+ </method> >+ >+ <method name="moveToAlertPosition"> >+ <body> >+ <![CDATA[ >+ // hack. we need this so the window has something like its final size >+ if (window.outerWidth == 1) { >+ dump("Trying to position a sizeless window; caller should have called sizeToContent() or sizeTo(). See bug 75649.\n"); >+ sizeToContent(); >+ } >+ >+ var xOffset = (opener.outerWidth - window.outerWidth) / 2; >+ var yOffset = opener.outerHeight / 5; >+ >+ var newX = opener.screenX + xOffset; >+ var newY = opener.screenY + yOffset; >+ >+ // ensure the window is fully onscreen (if smaller than the screen) >+ if (newX < screen.availLeft) >+ newX = screen.availLeft + 20; >+ if ((newX + window.outerWidth) > (screen.availLeft + screen.availWidth)) >+ newX = (screen.availLeft + screen.availWidth) - window.outerWidth - 20; >+ >+ if (newY < screen.availTop) >+ newY = screen.availTop + 20; >+ if ((newY + window.outerHeight) > (screen.availTop + screen.availHeight)) >+ newY = (screen.availTop + screen.availHeight) - window.outerHeight - 60; >+ >+ window.moveTo( newX, newY ); >+ ]]> >+ </body> >+ </method> >+ >+ <method name="centerWindowOnScreen"> >+ <body> >+ <![CDATA[ >+ var xOffset = screen.availWidth/2 - window.outerWidth/2; >+ var yOffset = screen.availHeight/2 - window.outerHeight/2; //(opener.outerHeight *2)/10; >+ >+ xOffset = xOffset > 0 ? xOffset : 0; >+ yOffset = yOffset > 0 ? yOffset : 0; >+ window.moveTo(xOffset, yOffset); >+ ]]> >+ </body> >+ </method> >+ >+ <constructor> >+ <![CDATA[ >+ this._configureButtons(this.buttons); >+ >+ // listen for when window is closed via native close buttons >+ window.addEventListener("close", this._closeHandler, false); >+ >+ // for things that we need to initialize after onload fires >+ window.addEventListener("load", this.postLoadInit, false); >+ >+ window.moveToAlertPosition = this.moveToAlertPosition; >+ window.centerWindowOnScreen = this.centerWindowOnScreen; >+ ]]> >+ </constructor> >+ >+ <method name="postLoadInit"> >+ <parameter name="aEvent"/> >+ <body> >+ <![CDATA[ >+ function focusInit() { >+ const dialog = document.documentElement; >+ const defaultButton = dialog.getButton(dialog.defaultButton); >+ // give focus to the first focusable element in the dialog >+ if (!document.commandDispatcher.focusedElement) { >+ document.commandDispatcher.advanceFocusIntoSubtree(dialog); >+ >+ var focusedElt = document.commandDispatcher.focusedElement; >+ if (focusedElt) { >+ var initialFocusedElt = focusedElt; >+ while (focusedElt.localName == "tab" || >+ focusedElt.getAttribute("noinitialfocus") == "true") { >+ document.commandDispatcher.advanceFocusIntoSubtree(focusedElt); >+ focusedElt = document.commandDispatcher.focusedElement; >+ if (focusedElt == initialFocusedElt) >+ break; >+ } >+ >+ if (initialFocusedElt.localName == "tab") { >+ if (focusedElt.hasAttribute("dlgtype")) { >+ // We don't want to focus on anonymous OK, Cancel, etc. buttons, >+ // so return focus to the tab itself >+ initialFocusedElt.focus(); >+ } >+ } >+#ifndef XP_MACOSX >+ else if (focusedElt.hasAttribute("dlgtype") && focusedElt != defaultButton) { >+ defaultButton.focus(); >+ } >+#endif >+ } >+ } >+ >+ try { >+ if (defaultButton) >+ window.notifyDefaultButtonLoaded(defaultButton); >+ } catch (e) { } >+ } >+ >+ // Give focus after onload completes, see bug 103197. >+ setTimeout(focusInit, 0); >+ ]]> >+ </body> >+ </method> >+ >+ <property name="mStrBundle"> >+ <getter> >+ <![CDATA[ >+ if (!this._mStrBundle) { >+ // need to create string bundle manually instead of using <xul:stringbundle/> >+ // see bug 63370 for details >+ this._mStrBundle = Components.classes["@mozilla.org/intl/stringbundle;1"] >+ .getService(Components.interfaces.nsIStringBundleService) >+ .createBundle("chrome://global/locale/dialog.properties"); >+ } >+ return this._mStrBundle; >+ ]]></getter> >+ </property> >+ >+ <method name="_configureButtons"> >+ <parameter name="aButtons"/> >+ <body> >+ <![CDATA[ >+ // by default, get all the anonymous button elements >+ var buttons = {}; >+ this._buttons = buttons; >+ buttons.accept = document.getAnonymousElementByAttribute(this, "dlgtype", "accept"); >+ buttons.cancel = document.getAnonymousElementByAttribute(this, "dlgtype", "cancel"); >+ buttons.extra1 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra1"); >+ buttons.extra2 = document.getAnonymousElementByAttribute(this, "dlgtype", "extra2"); >+ buttons.help = document.getAnonymousElementByAttribute(this, "dlgtype", "help"); >+ buttons.disclosure = document.getAnonymousElementByAttribute(this, "dlgtype", "disclosure"); >+ >+ // look for any overriding explicit button elements >+ var exBtns = this.getElementsByAttribute("dlgtype", "*"); >+ var dlgtype; >+ var i; >+ for (i = 0; i < exBtns.length; ++i) { >+ dlgtype = exBtns[i].getAttribute("dlgtype"); >+ buttons[dlgtype].hidden = true; // hide the anonymous button >+ buttons[dlgtype] = exBtns[i]; >+ } >+ >+ // add the label and oncommand handler to each button >+ for (dlgtype in buttons) { >+ var button = buttons[dlgtype]; >+ button.addEventListener("command", this._handleButtonCommand, true); >+ >+ // don't override custom labels with pre-defined labels on explicit buttons >+ if (!button.hasAttribute("label")) { >+ // dialog attributes override the default labels in dialog.properties >+ if (this.hasAttribute("buttonlabel"+dlgtype)) { >+ button.setAttribute("label", this.getAttribute("buttonlabel"+dlgtype)); >+ if (this.hasAttribute("buttonaccesskey"+dlgtype)) >+ button.setAttribute("accesskey", this.getAttribute("buttonaccesskey"+dlgtype)); >+ } else if (dlgtype != "extra1" && dlgtype != "extra2") { >+ button.setAttribute("label", this.mStrBundle.GetStringFromName("button-"+dlgtype)); >+ var accessKey = this.mStrBundle.GetStringFromName("accesskey-"+dlgtype); >+ if (accessKey) >+ button.setAttribute("accesskey", accessKey); >+ } >+ } >+ // allow specifying alternate icons in the dialog header >+ if (!button.hasAttribute("icon")) { >+ // if there's an icon specified, use that >+ if (this.hasAttribute("buttonicon"+dlgtype)) >+ button.setAttribute("icon", this.getAttribute("buttonicon"+dlgtype)); >+ // otherwise set defaults >+ else >+ switch (dlgtype) { >+ case "accept": >+ button.setAttribute("icon","accept"); >+ break; >+ case "cancel": >+ button.setAttribute("icon","cancel"); >+ break; >+ case "disclosure": >+ button.setAttribute("icon","properties"); >+ break; >+ case "help": >+ button.setAttribute("icon","help"); >+ break; >+ default: >+ break; >+ } >+ } >+ } >+ >+ // ensure that hitting enter triggers the default button command >+ this.defaultButton = this.defaultButton; >+ >+ // if there is a special button configuration, use it >+ if (aButtons) { >+ // expect a comma delimited list of dlgtype values >+ var list = aButtons.split(","); >+ >+ // mark shown dlgtypes as true >+ var shown = { accept: false, cancel: false, help: false, >+ disclosure: false, extra1: false, extra2: false }; >+ for (i = 0; i < list.length; ++i) >+ shown[list[i].replace(/ /g, "")] = true; >+ >+ // hide/show the buttons we want >+ for (dlgtype in buttons) >+ buttons[dlgtype].hidden = !shown[dlgtype]; >+ >+#ifdef XP_WIN >+# show the spacer on Windows only when the extra2 button is present >+ var spacer = document.getAnonymousElementByAttribute(this, "anonid", "spacer"); >+ spacer.removeAttribute("hidden"); >+ spacer.setAttribute("flex", shown["extra2"]?"1":"0"); >+#endif >+ >+ } >+ ]]> >+ </body> >+ </method> >+ >+ <method name="_setDefaultButton"> >+ <parameter name="aNewDefault"/> >+ <body> >+ <![CDATA[ >+ // remove the default attribute from the previous default button, if any >+ var oldDefaultButton = this.getButton(this.defaultButton); >+ if (oldDefaultButton) >+ oldDefaultButton.removeAttribute("default"); >+ >+ var newDefaultButton = this.getButton(aNewDefault); >+ if (newDefaultButton) { >+ this.setAttribute("defaultButton", aNewDefault); >+ newDefaultButton.setAttribute("default", "true"); >+ } >+ else { >+ this.setAttribute("defaultButton", "none"); >+ if (aNewDefault != "none") >+ dump("invalid new default button: " + aNewDefault + ", assuming: none\n"); >+ } >+ ]]> >+ </body> >+ </method> >+ >+ <method name="_handleButtonCommand"> >+ <parameter name="aEvent"/> >+ <body> >+ <![CDATA[ >+ return document.documentElement._doButtonCommand( >+ aEvent.target.getAttribute("dlgtype")); >+ ]]> >+ </body> >+ </method> >+ >+ <method name="_doButtonCommand"> >+ <parameter name="aDlgType"/> >+ <body> >+ <![CDATA[ >+ var button = this.getButton(aDlgType); >+ if (!button.disabled) { >+ var noCancel = this._fireButtonEvent(aDlgType); >+ if (noCancel) { >+ if (aDlgType == "accept" || aDlgType == "cancel") >+ window.close(); >+ } >+ return noCancel; >+ } >+ return true; >+ ]]> >+ </body> >+ </method> >+ >+ <method name="_fireButtonEvent"> >+ <parameter name="aDlgType"/> >+ <body> >+ <![CDATA[ >+ var event = document.createEvent("Events"); >+ event.initEvent("dialog"+aDlgType, true, true); >+ >+ // handle dom event handlers >+ var noCancel = this.dispatchEvent(event); >+ >+ // handle any xml attribute event handlers >+ var handler = this.getAttribute("ondialog"+aDlgType); >+ if (handler != "") { >+ var fn = new Function("event", handler); >+ var returned = fn(event); >+ if (returned == false) >+ noCancel = false; >+ } >+ >+ return noCancel; >+ ]]> >+ </body> >+ </method> >+ >+ <method name="_hitEnter"> >+ <parameter name="evt"/> >+ <body> >+ <![CDATA[ >+ if (evt.defaultPrevented) >+ return; >+ >+ var btn = this.getButton(this.defaultButton); >+ if (btn) >+ this._doButtonCommand(this.defaultButton); >+ ]]> >+ </body> >+ </method> >+ >+ </implementation> >+ >+ <handlers> >+ <handler event="keypress" keycode="VK_ENTER" >+ group="system" action="this._hitEnter(event);"/> >+ <handler event="keypress" keycode="VK_RETURN" >+ group="system" action="this._hitEnter(event);"/> >+ <handler event="keypress" keycode="VK_ESCAPE" group="system"> >+ if (!event.defaultPrevented) >+ this.cancelDialog(); >+ </handler> >+#ifdef XP_MACOSX >+ <handler event="keypress" key="." modifiers="meta" phase="capturing" action="this.cancelDialog();"/> >+#else >+ <handler event="focus" phase="capturing"> >+ var btn = this.getButton(this.defaultButton); >+ if (btn) >+ btn.setAttribute("default", event.originalTarget == btn || !(event.originalTarget instanceof Components.interfaces.nsIDOMXULButtonElement)); >+ </handler> >+#endif >+ </handlers> >+ >+ </binding> >+ >+ <binding id="dialogheader"> >+ <resources> >+ <stylesheet src="chrome://global/skin/dialog.css"/> >+ </resources> >+ <content> >+ <xul:label class="dialogheader-title" xbl:inherits="value=title,crop" crop="right" flex="1"/> >+ <xul:label class="dialogheader-description" xbl:inherits="value=description"/> >+ </content> >+ </binding> >+ >+</bindings> >diff --git a/toolkit/content/widgets/preferences-kde.xml b/toolkit/content/widgets/preferences-kde.xml >new file mode 100644 >--- /dev/null >+++ b/toolkit/content/widgets/preferences-kde.xml >@@ -0,0 +1,1339 @@ >+<?xml version="1.0"?> >+ >+<!DOCTYPE bindings [ >+ <!ENTITY % preferencesDTD SYSTEM "chrome://global/locale/preferences.dtd"> >+ %preferencesDTD; >+ <!ENTITY % globalKeysDTD SYSTEM "chrome://global/locale/globalKeys.dtd"> >+ %globalKeysDTD; >+]> >+ >+<bindings id="preferencesBindings" >+ xmlns="http://www.mozilla.org/xbl" >+ xmlns:xbl="http://www.mozilla.org/xbl" >+ xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> >+ >+# >+# = Preferences Window Framework >+# >+# The syntax for use looks something like: >+# >+# <prefwindow> >+# <prefpane id="prefPaneA"> >+# <preferences> >+# <preference id="preference1" name="app.preference1" type="bool" onchange="foo();"/> >+# <preference id="preference2" name="app.preference2" type="bool" useDefault="true"/> >+# </preferences> >+# <checkbox label="Preference" preference="preference1"/> >+# </prefpane> >+# </prefwindow> >+# >+ >+ <binding id="preferences"> >+ <implementation implements="nsIObserver"> >+ <method name="observe"> >+ <parameter name="aSubject"/> >+ <parameter name="aTopic"/> >+ <parameter name="aData"/> >+ <body> >+ <![CDATA[ >+ for (var i = 0; i < this.childNodes.length; ++i) { >+ var preference = this.childNodes[i]; >+ if (preference.name == aData) { >+ preference.value = preference.valueFromPreferences; >+ } >+ } >+ ]]> >+ </body> >+ </method> >+ >+ <method name="fireChangedEvent"> >+ <parameter name="aPreference"/> >+ <body> >+ <![CDATA[ >+ // Value changed, synthesize an event >+ try { >+ var event = document.createEvent("Events"); >+ event.initEvent("change", true, true); >+ aPreference.dispatchEvent(event); >+ } >+ catch (e) { >+ Components.utils.reportError(e); >+ } >+ ]]> >+ </body> >+ </method> >+ >+ <field name="service"> >+ Components.classes["@mozilla.org/preferences-service;1"] >+ .getService(Components.interfaces.nsIPrefService); >+ </field> >+ <field name="rootBranch"> >+ Components.classes["@mozilla.org/preferences-service;1"] >+ .getService(Components.interfaces.nsIPrefBranch); >+ </field> >+ <field name="defaultBranch"> >+ this.service.getDefaultBranch(""); >+ </field> >+ <field name="rootBranchInternal"> >+ Components.classes["@mozilla.org/preferences-service;1"] >+ .getService(Components.interfaces.nsIPrefBranchInternal); >+ </field> >+ <property name="type" readonly="true"> >+ <getter> >+ <![CDATA[ >+ return document.documentElement.type || ""; >+ ]]> >+ </getter> >+ </property> >+ <property name="instantApply" readonly="true"> >+ <getter> >+ <![CDATA[ >+ var doc = document.documentElement; >+ return this.type == "child" ? doc.instantApply >+ : doc.instantApply || this.rootBranch.getBoolPref("browser.preferences.instantApply"); >+ ]]> >+ </getter> >+ </property> >+ </implementation> >+ </binding> >+ >+ <binding id="preference"> >+ <implementation> >+ <constructor> >+ <![CDATA[ >+ // if the element has been inserted without the name attribute set, >+ // we have nothing to do here >+ if (!this.name) >+ return; >+ >+ this.preferences.rootBranchInternal >+ .addObserver(this.name, this.preferences, false); >+ // In non-instant apply mode, we must try and use the last saved state >+ // from any previous opens of a child dialog instead of the value from >+ // preferences, to pick up any edits a user may have made. >+ if (this.preferences.type == "child" && >+ !this.instantApply && window.opener) { >+ var pdoc = window.opener.document; >+ >+ // Try to find a preference element for the same preference. >+ var preference = null; >+ var parentPreferences = pdoc.getElementsByTagName("preferences"); >+ for (var k = 0; (k < parentPreferences.length && !preference); ++k) { >+ var parentPrefs = parentPreferences[k] >+ .getElementsByAttribute("name", this.name); >+ for (var l = 0; (l < parentPrefs.length && !preference); ++l) { >+ if (parentPrefs[l].localName == "preference") >+ preference = parentPrefs[l]; >+ } >+ } >+ this._setValue(preference ? preference.value >+ : this.valueFromPreferences, false); >+ } >+ else >+ this._setValue(this.valueFromPreferences, false); >+ ]]> >+ </constructor> >+ <destructor> >+ this.preferences.rootBranchInternal >+ .removeObserver(this.name, this.preferences); >+ </destructor> >+ >+ <property name="instantApply"> >+ <getter> >+ return this.getAttribute("instantApply") == "true" || this.preferences.instantApply; >+ </getter> >+ </property> >+ >+ <property name="preferences" onget="return this.parentNode"/> >+ <property name="name" onget="return this.getAttribute('name');"> >+ <setter> >+ if (val == this.name) >+ return val; >+ >+ this.preferences.rootBranchInternal >+ .removeObserver(this.name, this.preferences); >+ this.setAttribute('name', val); >+ this.preferences.rootBranchInternal >+ .addObserver(val, this.preferences, false); >+ >+ return val; >+ </setter> >+ </property> >+ <property name="type" onget="return this.getAttribute('type');" >+ onset="this.setAttribute('type', val); return val;"/> >+ <property name="inverted" onget="return this.getAttribute('inverted') == 'true';" >+ onset="this.setAttribute('inverted', val); return val;"/> >+ <property name="readonly" onget="return this.getAttribute('readonly') == 'true';" >+ onset="this.setAttribute('readonly', val); return val;"/> >+ >+ <field name="_value">null</field> >+ <method name="_setValue"> >+ <parameter name="aValue"/> >+ <parameter name="aUpdate"/> >+ <body> >+ <![CDATA[ >+ if (aUpdate && this.value !== aValue) { >+ this._value = aValue; >+ if (this.instantApply) >+ this.valueFromPreferences = aValue; >+ this.preferences.fireChangedEvent(this); >+ } >+ else if (!aUpdate) { >+ this._value = aValue; >+ this.updateElements(); >+ } >+ return aValue; >+ ]]> >+ </body> >+ </method> >+ <property name="value" onget="return this._value" onset="return this._setValue(val, true);"/> >+ >+ <property name="locked"> >+ <getter> >+ return this.preferences.rootBranch.prefIsLocked(this.name); >+ </getter> >+ </property> >+ >+ <property name="disabled"> >+ <getter> >+ return this.getAttribute("disabled") == "true"; >+ </getter> >+ <setter> >+ <![CDATA[ >+ if (val) >+ this.setAttribute("disabled", "true"); >+ else >+ this.removeAttribute("disabled"); >+ >+ if (!this.id) >+ return val; >+ >+ var elements = document.getElementsByAttribute("preference", this.id); >+ for (var i = 0; i < elements.length; ++i) { >+ elements[i].disabled = val; >+ >+ var labels = document.getElementsByAttribute("control", elements[i].id); >+ for (var j = 0; j < labels.length; ++j) >+ labels[j].disabled = val; >+ } >+ >+ return val; >+ ]]> >+ </setter> >+ </property> >+ >+ <property name="tabIndex"> >+ <getter> >+ return parseInt(this.getAttribute("tabindex")); >+ </getter> >+ <setter> >+ <![CDATA[ >+ if (val) >+ this.setAttribute("tabindex", val); >+ else >+ this.removeAttribute("tabindex"); >+ >+ if (!this.id) >+ return val; >+ >+ var elements = document.getElementsByAttribute("preference", this.id); >+ for (var i = 0; i < elements.length; ++i) { >+ elements[i].tabIndex = val; >+ >+ var labels = document.getElementsByAttribute("control", elements[i].id); >+ for (var j = 0; j < labels.length; ++j) >+ labels[j].tabIndex = val; >+ } >+ >+ return val; >+ ]]> >+ </setter> >+ </property> >+ >+ <property name="hasUserValue"> >+ <getter> >+ <![CDATA[ >+ return this.preferences.rootBranch.prefHasUserValue(this.name) && >+ this.value !== undefined; >+ ]]> >+ </getter> >+ </property> >+ >+ <method name="reset"> >+ <body> >+ // defer reset until preference update >+ this.value = undefined; >+ </body> >+ </method> >+ >+ <field name="_useDefault">false</field> >+ <property name="defaultValue"> >+ <getter> >+ <![CDATA[ >+ this._useDefault = true; >+ var val = this.valueFromPreferences; >+ this._useDefault = false; >+ return val; >+ ]]> >+ </getter> >+ </property> >+ >+ <property name="_branch"> >+ <getter> >+ return this._useDefault ? this.preferences.defaultBranch : this.preferences.rootBranch; >+ </getter> >+ </property> >+ >+ <field name="batching">false</field> >+ >+ <method name="_reportUnknownType"> >+ <body> >+ <![CDATA[ >+ var consoleService = Components.classes["@mozilla.org/consoleservice;1"] >+ .getService(Components.interfaces.nsIConsoleService); >+ var msg = "<preference> with id='" + this.id + "' and name='" + >+ this.name + "' has unknown type '" + this.type + "'."; >+ consoleService.logStringMessage(msg); >+ ]]> >+ </body> >+ </method> >+ >+ <property name="valueFromPreferences"> >+ <getter> >+ <![CDATA[ >+ try { >+ // Force a resync of value with preferences. >+ switch (this.type) { >+ case "int": >+ return this._branch.getIntPref(this.name); >+ case "bool": >+ var val = this._branch.getBoolPref(this.name); >+ return this.inverted ? !val : val; >+ case "wstring": >+ return this._branch >+ .getComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString) >+ .data; >+ case "string": >+ case "unichar": >+ return this._branch >+ .getComplexValue(this.name, Components.interfaces.nsISupportsString) >+ .data; >+ case "fontname": >+ var family = this._branch >+ .getComplexValue(this.name, Components.interfaces.nsISupportsString) >+ .data; >+ var fontEnumerator = Components.classes["@mozilla.org/gfx/fontenumerator;1"] >+ .createInstance(Components.interfaces.nsIFontEnumerator); >+ return fontEnumerator.getStandardFamilyName(family); >+ case "file": >+ var f = this._branch >+ .getComplexValue(this.name, Components.interfaces.nsILocalFile); >+ return f; >+ default: >+ this._reportUnknownType(); >+ } >+ } >+ catch (e) { } >+ return null; >+ ]]> >+ </getter> >+ <setter> >+ <![CDATA[ >+ // Exit early if nothing to do. >+ if (this.readonly || this.valueFromPreferences == val) >+ return val; >+ >+ // The special value undefined means 'reset preference to default'. >+ if (val === undefined) { >+ this.preferences.rootBranch.clearUserPref(this.name); >+ return val; >+ } >+ >+ // Force a resync of preferences with value. >+ switch (this.type) { >+ case "int": >+ this.preferences.rootBranch.setIntPref(this.name, val); >+ break; >+ case "bool": >+ this.preferences.rootBranch.setBoolPref(this.name, this.inverted ? !val : val); >+ break; >+ case "wstring": >+ var pls = Components.classes["@mozilla.org/pref-localizedstring;1"] >+ .createInstance(Components.interfaces.nsIPrefLocalizedString); >+ pls.data = val; >+ this.preferences.rootBranch >+ .setComplexValue(this.name, Components.interfaces.nsIPrefLocalizedString, pls); >+ break; >+ case "string": >+ case "unichar": >+ case "fontname": >+ var iss = Components.classes["@mozilla.org/supports-string;1"] >+ .createInstance(Components.interfaces.nsISupportsString); >+ iss.data = val; >+ this.preferences.rootBranch >+ .setComplexValue(this.name, Components.interfaces.nsISupportsString, iss); >+ break; >+ case "file": >+ var lf; >+ if (typeof(val) == "string") { >+ lf = Components.classes["@mozilla.org/file/local;1"] >+ .createInstance(Components.interfaces.nsILocalFile); >+ lf.persistentDescriptor = val; >+ if (!lf.exists()) >+ lf.initWithPath(val); >+ } >+ else >+ lf = val.QueryInterface(Components.interfaces.nsILocalFile); >+ this.preferences.rootBranch >+ .setComplexValue(this.name, Components.interfaces.nsILocalFile, lf); >+ break; >+ default: >+ this._reportUnknownType(); >+ } >+ if (!this.batching) >+ this.preferences.service.savePrefFile(null); >+ return val; >+ ]]> >+ </setter> >+ </property> >+ >+ <method name="setElementValue"> >+ <parameter name="aElement"/> >+ <body> >+ <![CDATA[ >+ if (this.locked) >+ aElement.disabled = true; >+ >+ if (!this.isElementEditable(aElement)) >+ return; >+ >+ var rv = undefined; >+ if (aElement.hasAttribute("onsyncfrompreference")) { >+ // Value changed, synthesize an event >+ try { >+ var event = document.createEvent("Events"); >+ event.initEvent("syncfrompreference", true, true); >+ var f = new Function ("event", >+ aElement.getAttribute("onsyncfrompreference")); >+ rv = f.call(aElement, event); >+ } >+ catch (e) { >+ Components.utils.reportError(e); >+ } >+ } >+ var val = rv !== undefined ? rv : (this.instantApply ? this.valueFromPreferences : this.value); >+ // if the preference is marked for reset, show default value in UI >+ if (val === undefined) >+ val = this.defaultValue; >+ >+ /** >+ * Initialize a UI element property with a value. Handles the case >+ * where an element has not yet had a XBL binding attached for it and >+ * the property setter does not yet exist by setting the same attribute >+ * on the XUL element using DOM apis and assuming the element's >+ * constructor or property getters appropriately handle this state. >+ */ >+ function setValue(element, attribute, value) { >+ if (attribute in element) >+ element[attribute] = value; >+ else >+ element.setAttribute(attribute, value); >+ } >+ if (aElement.localName == "checkbox" || >+ aElement.localName == "listitem") >+ setValue(aElement, "checked", val); >+ else if (aElement.localName == "colorpicker") >+ setValue(aElement, "color", val); >+ else if (aElement.localName == "textbox") { >+ // XXXmano Bug 303998: Avoid a caret placement issue if either the >+ // preference observer or its setter calls updateElements as a result >+ // of the input event handler. >+ if (aElement.value !== val) >+ setValue(aElement, "value", val); >+ } >+ else >+ setValue(aElement, "value", val); >+ ]]> >+ </body> >+ </method> >+ >+ <method name="getElementValue"> >+ <parameter name="aElement"/> >+ <body> >+ <![CDATA[ >+ if (aElement.hasAttribute("onsynctopreference")) { >+ // Value changed, synthesize an event >+ try { >+ var event = document.createEvent("Events"); >+ event.initEvent("synctopreference", true, true); >+ var f = new Function ("event", >+ aElement.getAttribute("onsynctopreference")); >+ var rv = f.call(aElement, event); >+ if (rv !== undefined) >+ return rv; >+ } >+ catch (e) { >+ Components.utils.reportError(e); >+ } >+ } >+ >+ /** >+ * Read the value of an attribute from an element, assuming the >+ * attribute is a property on the element's node API. If the property >+ * is not present in the API, then assume its value is contained in >+ * an attribute, as is the case before a binding has been attached. >+ */ >+ function getValue(element, attribute) { >+ if (attribute in element) >+ return element[attribute]; >+ return element.getAttribute(attribute); >+ } >+ if (aElement.localName == "checkbox" || >+ aElement.localName == "listitem") >+ var value = getValue(aElement, "checked"); >+ else if (aElement.localName == "colorpicker") >+ value = getValue(aElement, "color"); >+ else >+ value = getValue(aElement, "value"); >+ >+ switch (this.type) { >+ case "int": >+ return parseInt(value, 10) || 0; >+ case "bool": >+ return typeof(value) == "boolean" ? value : value == "true"; >+ } >+ return value; >+ ]]> >+ </body> >+ </method> >+ >+ <method name="isElementEditable"> >+ <parameter name="aElement"/> >+ <body> >+ <![CDATA[ >+ switch (aElement.localName) { >+ case "checkbox": >+ case "colorpicker": >+ case "radiogroup": >+ case "textbox": >+ case "listitem": >+ case "listbox": >+ case "menulist": >+ return true; >+ } >+ return aElement.getAttribute("preference-editable") == "true"; >+ ]]> >+ </body> >+ </method> >+ >+ <method name="updateElements"> >+ <body> >+ <![CDATA[ >+ if (!this.id) >+ return; >+ >+ // This "change" event handler tracks changes made to preferences by >+ // sources other than the user in this window. >+ var elements = document.getElementsByAttribute("preference", this.id); >+ for (var i = 0; i < elements.length; ++i) >+ this.setElementValue(elements[i]); >+ ]]> >+ </body> >+ </method> >+ </implementation> >+ >+ <handlers> >+ <handler event="change"> >+ this.updateElements(); >+ </handler> >+ </handlers> >+ </binding> >+ >+ <binding id="prefwindow" >+ extends="chrome://global/content/bindings/dialog.xml#dialog"> >+ <resources> >+ <stylesheet src="chrome://global/skin/preferences.css"/> >+ </resources> >+ <content dlgbuttons="accept,cancel" persist="lastSelected screenX screenY" >+ closebuttonlabel="&preferencesCloseButton.label;" >+ closebuttonaccesskey="&preferencesCloseButton.accesskey;" >+ role="dialog" >+#ifdef XP_WIN >+ title="&preferencesDefaultTitleWin.title;"> >+#else >+ title="&preferencesDefaultTitleMac.title;"> >+#endif >+ <xul:windowdragbox orient="vertical"> >+ <xul:radiogroup anonid="selector" orient="horizontal" class="paneSelector chromeclass-toolbar" >+ role="listbox"/> <!-- Expose to accessibility APIs as a listbox --> >+ </xul:windowdragbox> >+ <xul:hbox flex="1" class="paneDeckContainer"> >+ <xul:deck anonid="paneDeck" flex="1"> >+ <children includes="prefpane"/> >+ </xul:deck> >+ </xul:hbox> >+ <xul:hbox anonid="dlg-buttons" class="prefWindow-dlgbuttons" >+#ifdef XP_UNIX_GNOME >+ > >+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/> >+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> >+ <xul:spacer anonid="spacer" flex="1"/> >+ <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/> >+ <xul:button dlgtype="accept" class="dialog-button" icon="accept"/> >+#elif XP_UNIX >+ pack="end"> >+ <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/> >+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> >+ <xul:spacer anonid="spacer" flex="1"/> >+ <xul:button dlgtype="accept" class="dialog-button" icon="accept"/> >+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/> >+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> >+#else >+ pack="end"> >+ <xul:button dlgtype="extra2" class="dialog-button" hidden="true"/> >+ <xul:spacer anonid="spacer" flex="1"/> >+ <xul:button dlgtype="accept" class="dialog-button" icon="accept"/> >+ <xul:button dlgtype="extra1" class="dialog-button" hidden="true"/> >+ <xul:button dlgtype="cancel" class="dialog-button" icon="cancel"/> >+ <xul:button dlgtype="help" class="dialog-button" hidden="true" icon="help"/> >+ <xul:button dlgtype="disclosure" class="dialog-button" hidden="true"/> >+#endif >+ </xul:hbox> >+ <xul:hbox> >+ <children/> >+ </xul:hbox> >+ </content> >+ <implementation implements="nsITimerCallback"> >+ <constructor> >+ <![CDATA[ >+ if (this.type != "child") { >+ var psvc = Components.classes["@mozilla.org/preferences-service;1"] >+ .getService(Components.interfaces.nsIPrefBranch); >+ this.instantApply = psvc.getBoolPref("browser.preferences.instantApply"); >+ if (this.instantApply) { >+ var docElt = document.documentElement; >+ var acceptButton = docElt.getButton("accept"); >+ acceptButton.hidden = true; >+ var cancelButton = docElt.getButton("cancel"); >+#ifdef XP_MACOSX >+ // no buttons on Mac except Help >+ cancelButton.hidden = true; >+ // Also, don't fire onDialogAccept on enter >+ acceptButton.disabled = true; >+#else >+ // morph the Cancel button into the Close button >+ cancelButton.setAttribute ("icon", "close"); >+ cancelButton.label = docElt.getAttribute("closebuttonlabel"); >+ cancelButton.accesskey = docElt.getAttribute("closebuttonaccesskey"); >+#endif >+ } >+ } >+ this.setAttribute("animated", this._shouldAnimate ? "true" : "false"); >+ var panes = this.preferencePanes; >+ >+ var lastPane = null; >+ if (this.lastSelected) { >+ lastPane = document.getElementById(this.lastSelected); >+ if (!lastPane) { >+ this.lastSelected = ""; >+ } >+ } >+ >+ var paneToLoad; >+ if ("arguments" in window && window.arguments[0] && document.getElementById(window.arguments[0]) && document.getElementById(window.arguments[0]).nodeName == "prefpane") { >+ paneToLoad = document.getElementById(window.arguments[0]); >+ this.lastSelected = paneToLoad.id; >+ } >+ else if (lastPane) >+ paneToLoad = lastPane; >+ else >+ paneToLoad = panes[0]; >+ >+ for (var i = 0; i < panes.length; ++i) { >+ this._makePaneButton(panes[i]); >+ if (panes[i].loaded) { >+ // Inline pane content, fire load event to force initialization. >+ this._fireEvent("paneload", panes[i]); >+ } >+ } >+ this.showPane(paneToLoad); >+ >+ if (panes.length == 1) >+ this._selector.setAttribute("collapsed", "true"); >+ ]]> >+ </constructor> >+ >+ <destructor> >+ <![CDATA[ >+ // Release timers to avoid reference cycles. >+ if (this._animateTimer) { >+ this._animateTimer.cancel(); >+ this._animateTimer = null; >+ } >+ if (this._fadeTimer) { >+ this._fadeTimer.cancel(); >+ this._fadeTimer = null; >+ } >+ ]]> >+ </destructor> >+ >+ <field name="instantApply">false</field> >+ >+ <property name="preferencePanes" >+ onget="return this.getElementsByTagName('prefpane');"/> >+ >+ <property name="type" onget="return this.getAttribute('type');"/> >+ <property name="_paneDeck" >+ onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'paneDeck');"/> >+ <property name="_paneDeckContainer" >+ onget="return document.getAnonymousElementByAttribute(this, 'class', 'paneDeckContainer');"/> >+ <property name="_selector" >+ onget="return document.getAnonymousElementByAttribute(this, 'anonid', 'selector');"/> >+ <property name="lastSelected" >+ onget="return this.getAttribute('lastSelected');"> >+ <setter> >+ this.setAttribute("lastSelected", val); >+ document.persist(this.id, "lastSelected"); >+ return val; >+ </setter> >+ </property> >+ <property name="currentPane" >+ onset="return this._currentPane = val;"> >+ <getter> >+ if (!this._currentPane) >+ this._currentPane = this.preferencePanes[0]; >+ >+ return this._currentPane; >+ </getter> >+ </property> >+ <field name="_currentPane">null</field> >+ >+ >+ <method name="_makePaneButton"> >+ <parameter name="aPaneElement"/> >+ <body> >+ <![CDATA[ >+ var radio = document.createElement("radio"); >+ radio.setAttribute("pane", aPaneElement.id); >+ radio.setAttribute("label", aPaneElement.label); >+ // Expose preference group choice to accessibility APIs as an unchecked list item >+ // The parent group is exposed to accessibility APIs as a list >+ if (aPaneElement.image) >+ radio.setAttribute("src", aPaneElement.image); >+ radio.style.listStyleImage = aPaneElement.style.listStyleImage; >+ this._selector.appendChild(radio); >+ return radio; >+ ]]> >+ </body> >+ </method> >+ >+ <method name="showPane"> >+ <parameter name="aPaneElement"/> >+ <body> >+ <![CDATA[ >+ if (!aPaneElement) >+ return; >+ >+ this._selector.selectedItem = document.getAnonymousElementByAttribute(this, "pane", aPaneElement.id); >+ if (!aPaneElement.loaded) { >+ function OverlayLoadObserver(aPane) >+ { >+ this._pane = aPane; >+ } >+ OverlayLoadObserver.prototype = { >+ _outer: this, >+ observe: function (aSubject, aTopic, aData) >+ { >+ this._pane.loaded = true; >+ this._outer._fireEvent("paneload", this._pane); >+ this._outer._selectPane(this._pane); >+ } >+ }; >+ >+ var obs = new OverlayLoadObserver(aPaneElement); >+ document.loadOverlay(aPaneElement.src, obs); >+ } >+ else >+ this._selectPane(aPaneElement); >+ ]]> >+ </body> >+ </method> >+ >+ <method name="_fireEvent"> >+ <parameter name="aEventName"/> >+ <parameter name="aTarget"/> >+ <body> >+ <![CDATA[ >+ // Panel loaded, synthesize a load event. >+ try { >+ var event = document.createEvent("Events"); >+ event.initEvent(aEventName, true, true); >+ var cancel = !aTarget.dispatchEvent(event); >+ if (aTarget.hasAttribute("on" + aEventName)) { >+ var fn = new Function ("event", aTarget.getAttribute("on" + aEventName)); >+ var rv = fn.call(aTarget, event); >+ if (rv == false) >+ cancel = true; >+ } >+ return !cancel; >+ } >+ catch (e) { >+ Components.utils.reportError(e); >+ } >+ return false; >+ ]]> >+ </body> >+ </method> >+ >+ <field name="_initialized">false</field> >+ <method name="_selectPane"> >+ <parameter name="aPaneElement"/> >+ <body> >+ <![CDATA[ >+#ifdef XP_MACOSX >+ var paneTitle = aPaneElement.label; >+ if (paneTitle != "") >+ document.title = paneTitle; >+#endif >+ var helpButton = document.documentElement.getButton("help"); >+ if (aPaneElement.helpTopic) >+ helpButton.hidden = false; >+ else >+ helpButton.hidden = true; >+ >+ // Find this pane's index in the deck and set the deck's >+ // selectedIndex to that value to switch to it. >+ var prefpanes = this.preferencePanes; >+ for (var i = 0; i < prefpanes.length; ++i) { >+ if (prefpanes[i] == aPaneElement) { >+ this._paneDeck.selectedIndex = i; >+ >+ if (this.type != "child") { >+ if (aPaneElement.hasAttribute("flex") && this._shouldAnimate && >+ prefpanes.length > 1) >+ aPaneElement.removeAttribute("flex"); >+ // Calling sizeToContent after the first prefpane is loaded >+ // will size the windows contents so style information is >+ // available to calculate correct sizing. >+ if (!this._initialized && prefpanes.length > 1) { >+ if (this._shouldAnimate) >+ this.style.minHeight = 0; >+ window.sizeToContent(); >+ } >+ >+ var oldPane = this.lastSelected ? document.getElementById(this.lastSelected) : this.preferencePanes[0]; >+ oldPane.selected = !(aPaneElement.selected = true); >+ this.lastSelected = aPaneElement.id; >+ this.currentPane = aPaneElement; >+ this._initialized = true; >+ >+ // Only animate if we've switched between prefpanes >+ if (this._shouldAnimate && oldPane.id != aPaneElement.id) { >+ aPaneElement.style.opacity = 0.0; >+ this.animate(oldPane, aPaneElement); >+ } >+ else if (!this._shouldAnimate && prefpanes.length > 1) { >+ var targetHeight = parseInt(window.getComputedStyle(this._paneDeckContainer, "").height); >+ var verticalPadding = parseInt(window.getComputedStyle(aPaneElement, "").paddingTop); >+ verticalPadding += parseInt(window.getComputedStyle(aPaneElement, "").paddingBottom); >+ if (aPaneElement.contentHeight > targetHeight - verticalPadding) { >+ // To workaround the bottom border of a groupbox from being >+ // cutoff an hbox with a class of bottomBox may enclose it. >+ // This needs to include its padding to resize properly. >+ // See bug 394433 >+ var bottomPadding = 0; >+ var bottomBox = aPaneElement.getElementsByAttribute("class", "bottomBox")[0]; >+ if (bottomBox) >+ bottomPadding = parseInt(window.getComputedStyle(bottomBox, "").paddingBottom); >+ window.innerHeight += bottomPadding + verticalPadding + aPaneElement.contentHeight - targetHeight; >+ } >+ >+ // XXX rstrong - extend the contents of the prefpane to >+ // prevent elements from being cutoff (see bug 349098). >+ if (aPaneElement.contentHeight + verticalPadding < targetHeight) >+ aPaneElement._content.style.height = targetHeight - verticalPadding + "px"; >+ } >+ } >+ break; >+ } >+ } >+ ]]> >+ </body> >+ </method> >+ >+ <property name="_shouldAnimate"> >+ <getter> >+ <![CDATA[ >+ var psvc = Components.classes["@mozilla.org/preferences-service;1"] >+ .getService(Components.interfaces.nsIPrefBranch); >+#ifdef XP_MACOSX >+ var animate = true; >+#else >+ var animate = false; >+#endif >+ try { >+ animate = psvc.getBoolPref("browser.preferences.animateFadeIn"); >+ } >+ catch (e) { } >+ return animate; >+ ]]> >+ </getter> >+ </property> >+ >+ <method name="animate"> >+ <parameter name="aOldPane"/> >+ <parameter name="aNewPane"/> >+ <body> >+ <![CDATA[ >+ // if we are already resizing, use currentHeight >+ var oldHeight = this._currentHeight ? this._currentHeight : aOldPane.contentHeight; >+ >+ this._multiplier = aNewPane.contentHeight > oldHeight ? 1 : -1; >+ var sizeDelta = Math.abs(oldHeight - aNewPane.contentHeight); >+ this._animateRemainder = sizeDelta % this._animateIncrement; >+ >+ this._setUpAnimationTimer(oldHeight); >+ ]]> >+ </body> >+ </method> >+ >+ <property name="_sizeIncrement"> >+ <getter> >+ <![CDATA[ >+ var lastSelectedPane = document.getElementById(this.lastSelected); >+ var increment = this._animateIncrement * this._multiplier; >+ var newHeight = this._currentHeight + increment; >+ if ((this._multiplier > 0 && this._currentHeight >= lastSelectedPane.contentHeight) || >+ (this._multiplier < 0 && this._currentHeight <= lastSelectedPane.contentHeight)) >+ return 0; >+ >+ if ((this._multiplier > 0 && newHeight > lastSelectedPane.contentHeight) || >+ (this._multiplier < 0 && newHeight < lastSelectedPane.contentHeight)) >+ increment = this._animateRemainder * this._multiplier; >+ return increment; >+ ]]> >+ </getter> >+ </property> >+ >+ <method name="notify"> >+ <parameter name="aTimer"/> >+ <body> >+ <![CDATA[ >+ if (!document) >+ aTimer.cancel(); >+ >+ if (aTimer == this._animateTimer) { >+ var increment = this._sizeIncrement; >+ if (increment != 0) { >+ window.innerHeight += increment; >+ this._currentHeight += increment; >+ } >+ else { >+ aTimer.cancel(); >+ this._setUpFadeTimer(); >+ } >+ } else if (aTimer == this._fadeTimer) { >+ var elt = document.getElementById(this.lastSelected); >+ var newOpacity = parseFloat(window.getComputedStyle(elt, "").opacity) + this._fadeIncrement; >+ if (newOpacity < 1.0) >+ elt.style.opacity = newOpacity; >+ else { >+ aTimer.cancel(); >+ elt.style.opacity = 1.0; >+ } >+ } >+ ]]> >+ </body> >+ </method> >+ >+ <method name="_setUpAnimationTimer"> >+ <parameter name="aStartHeight"/> >+ <body> >+ <![CDATA[ >+ if (!this._animateTimer) >+ this._animateTimer = Components.classes["@mozilla.org/timer;1"] >+ .createInstance(Components.interfaces.nsITimer); >+ else >+ this._animateTimer.cancel(); >+ this._currentHeight = aStartHeight; >+ >+ this._animateTimer.initWithCallback(this, this._animateDelay, >+ Components.interfaces.nsITimer.TYPE_REPEATING_SLACK); >+ ]]> >+ </body> >+ </method> >+ >+ <method name="_setUpFadeTimer"> >+ <body> >+ <![CDATA[ >+ if (!this._fadeTimer) >+ this._fadeTimer = Components.classes["@mozilla.org/timer;1"] >+ .createInstance(Components.interfaces.nsITimer); >+ else >+ this._fadeTimer.cancel(); >+ >+ this._fadeTimer.initWithCallback(this, this._fadeDelay, >+ Components.interfaces.nsITimer.TYPE_REPEATING_SLACK); >+ ]]> >+ </body> >+ </method> >+ >+ <field name="_animateTimer">null</field> >+ <field name="_fadeTimer">null</field> >+ <field name="_animateDelay">15</field> >+ <field name="_animateIncrement">40</field> >+ <field name="_fadeDelay">5</field> >+ <field name="_fadeIncrement">0.40</field> >+ <field name="_animateRemainder">0</field> >+ <field name="_currentHeight">0</field> >+ <field name="_multiplier">0</field> >+ >+ <method name="addPane"> >+ <parameter name="aPaneElement"/> >+ <body> >+ <![CDATA[ >+ this.appendChild(aPaneElement); >+ >+ // Set up pane button >+ this._makePaneButton(aPaneElement); >+ ]]> >+ </body> >+ </method> >+ >+ <method name="openSubDialog"> >+ <parameter name="aURL"/> >+ <parameter name="aFeatures"/> >+ <parameter name="aParams"/> >+ <body> >+ return openDialog(aURL, "", "modal,centerscreen,resizable=no" + (aFeatures != "" ? ("," + aFeatures) : ""), aParams); >+ </body> >+ </method> >+ >+ <method name="openWindow"> >+ <parameter name="aWindowType"/> >+ <parameter name="aURL"/> >+ <parameter name="aFeatures"/> >+ <parameter name="aParams"/> >+ <body> >+ <![CDATA[ >+ var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] >+ .getService(Components.interfaces.nsIWindowMediator); >+ var win = aWindowType ? wm.getMostRecentWindow(aWindowType) : null; >+ if (win) { >+ if ("initWithParams" in win) >+ win.initWithParams(aParams); >+ win.focus(); >+ } >+ else { >+ var features = "resizable,dialog=no,centerscreen" + (aFeatures != "" ? ("," + aFeatures) : ""); >+ var parentWindow = (this.instantApply || !window.opener || window.opener.closed) ? window : window.opener; >+ win = parentWindow.openDialog(aURL, "_blank", features, aParams); >+ } >+ return win; >+ ]]> >+ </body> >+ </method> >+ </implementation> >+ <handlers> >+ <handler event="dialogaccept"> >+ <![CDATA[ >+ if (!this._fireEvent("beforeaccept", this)) >+ return; >+ >+ if (this.type == "child" && window.opener) { >+ var psvc = Components.classes["@mozilla.org/preferences-service;1"] >+ .getService(Components.interfaces.nsIPrefBranch); >+ var instantApply = psvc.getBoolPref("browser.preferences.instantApply"); >+ if (instantApply) { >+ var panes = this.preferencePanes; >+ for (var i = 0; i < panes.length; ++i) >+ panes[i].writePreferences(true); >+ } >+ else { >+ // Clone all the preferences elements from the child document and >+ // insert them into the pane collection of the parent. >+ var pdoc = window.opener.document; >+ if (pdoc.documentElement.localName == "prefwindow") { >+ var currentPane = pdoc.documentElement.currentPane; >+ var id = window.location.href + "#childprefs"; >+ var childPrefs = pdoc.getElementById(id); >+ if (!childPrefs) { >+ var childPrefs = pdoc.createElement("preferences"); >+ currentPane.appendChild(childPrefs); >+ childPrefs.id = id; >+ } >+ var panes = this.preferencePanes; >+ for (var i = 0; i < panes.length; ++i) { >+ var preferences = panes[i].preferences; >+ for (var j = 0; j < preferences.length; ++j) { >+ // Try to find a preference element for the same preference. >+ var preference = null; >+ var parentPreferences = pdoc.getElementsByTagName("preferences"); >+ for (var k = 0; (k < parentPreferences.length && !preference); ++k) { >+ var parentPrefs = parentPreferences[k] >+ .getElementsByAttribute("name", preferences[j].name); >+ for (var l = 0; (l < parentPrefs.length && !preference); ++l) { >+ if (parentPrefs[l].localName == "preference") >+ preference = parentPrefs[l]; >+ } >+ } >+ if (!preference) { >+ // No matching preference in the parent window. >+ preference = pdoc.createElement("preference"); >+ childPrefs.appendChild(preference); >+ preference.name = preferences[j].name; >+ preference.type = preferences[j].type; >+ preference.inverted = preferences[j].inverted; >+ preference.readonly = preferences[j].readonly; >+ preference.disabled = preferences[j].disabled; >+ } >+ preference.value = preferences[j].value; >+ } >+ } >+ } >+ } >+ } >+ else { >+ var panes = this.preferencePanes; >+ for (var i = 0; i < panes.length; ++i) >+ panes[i].writePreferences(false); >+ >+ var psvc = Components.classes["@mozilla.org/preferences-service;1"] >+ .getService(Components.interfaces.nsIPrefService); >+ psvc.savePrefFile(null); >+ } >+ ]]> >+ </handler> >+ <handler event="command"> >+ if (event.originalTarget.hasAttribute("pane")) { >+ var pane = document.getElementById(event.originalTarget.getAttribute("pane")); >+ this.showPane(pane); >+ } >+ </handler> >+ >+ <handler event="keypress" key="&windowClose.key;" modifiers="accel" phase="capturing"> >+ <![CDATA[ >+ if (this.instantApply) >+ window.close(); >+ event.stopPropagation(); >+ event.preventDefault(); >+ ]]> >+ </handler> >+ >+ <handler event="keypress" >+#ifdef XP_MACOSX >+ key="&openHelpMac.commandkey;" modifiers="accel" >+#else >+ keycode="&openHelp.commandkey;" >+#endif >+ phase="capturing"> >+ <![CDATA[ >+ var helpButton = this.getButton("help"); >+ if (helpButton.disabled || helpButton.hidden) >+ return; >+ this._fireEvent("dialoghelp", this); >+ event.stopPropagation(); >+ event.preventDefault(); >+ ]]> >+ </handler> >+ </handlers> >+ </binding> >+ >+ <binding id="prefpane"> >+ <resources> >+ <stylesheet src="chrome://global/skin/preferences.css"/> >+ </resources> >+ <content> >+ <xul:vbox class="content-box" xbl:inherits="flex"> >+ <children/> >+ </xul:vbox> >+ </content> >+ <implementation> >+ <method name="writePreferences"> >+ <parameter name="aFlushToDisk"/> >+ <body> >+ <![CDATA[ >+ // Write all values to preferences. >+ var preferences = this.preferences; >+ for (var i = 0; i < preferences.length; ++i) { >+ var preference = preferences[i]; >+ preference.batching = true; >+ preference.valueFromPreferences = preference.value; >+ preference.batching = false; >+ } >+ if (aFlushToDisk) { >+ var psvc = Components.classes["@mozilla.org/preferences-service;1"] >+ .getService(Components.interfaces.nsIPrefService); >+ psvc.savePrefFile(null); >+ } >+ ]]> >+ </body> >+ </method> >+ >+ <property name="src" >+ onget="return this.getAttribute('src');" >+ onset="this.setAttribute('src', val); return val;"/> >+ <property name="selected" >+ onget="return this.getAttribute('selected') == 'true';" >+ onset="this.setAttribute('selected', val); return val;"/> >+ <property name="image" >+ onget="return this.getAttribute('image');" >+ onset="this.setAttribute('image', val); return val;"/> >+ <property name="label" >+ onget="return this.getAttribute('label');" >+ onset="this.setAttribute('label', val); return val;"/> >+ >+ <property name="preferenceElements" >+ onget="return this.getElementsByAttribute('preference', '*');"/> >+ <property name="preferences" >+ onget="return this.getElementsByTagName('preference');"/> >+ >+ <property name="helpTopic"> >+ <getter> >+ <![CDATA[ >+ // if there are tabs, and the selected tab provides a helpTopic, return that >+ var box = this.getElementsByTagName("tabbox"); >+ if (box[0]) { >+ var tab = box[0].selectedTab; >+ if (tab && tab.hasAttribute("helpTopic")) >+ return tab.getAttribute("helpTopic"); >+ } >+ >+ // otherwise, return the helpTopic of the current panel >+ return this.getAttribute("helpTopic"); >+ ]]> >+ </getter> >+ </property> >+ >+ <field name="_loaded">false</field> >+ <property name="loaded" >+ onget="return !this.src ? true : this._loaded;" >+ onset="this._loaded = val; return val;"/> >+ >+ <method name="preferenceForElement"> >+ <parameter name="aElement"/> >+ <body> >+ return document.getElementById(aElement.getAttribute("preference")); >+ </body> >+ </method> >+ >+ <method name="getPreferenceElement"> >+ <parameter name="aStartElement"/> >+ <body> >+ <![CDATA[ >+ var temp = aStartElement; >+ while (temp && temp.nodeType == Node.ELEMENT_NODE && >+ !temp.hasAttribute("preference")) >+ temp = temp.parentNode; >+ return temp.nodeType == Node.ELEMENT_NODE ? temp : aStartElement; >+ ]]> >+ </body> >+ </method> >+ >+ <method name="userChangedValue"> >+ <parameter name="aElement"/> >+ <body> >+ <![CDATA[ >+ var element = this.getPreferenceElement(aElement); >+ if (element.hasAttribute("preference")) { >+ var preference = document.getElementById(element.getAttribute("preference")); >+ var prefVal = preference.getElementValue(element); >+ preference.value = prefVal; >+ } >+ ]]> >+ </body> >+ </method> >+ >+ <property name="contentHeight"> >+ <getter> >+ var targetHeight = parseInt(window.getComputedStyle(this._content, "").height); >+ targetHeight += parseInt(window.getComputedStyle(this._content, "").marginTop); >+ targetHeight += parseInt(window.getComputedStyle(this._content, "").marginBottom); >+ return targetHeight; >+ </getter> >+ </property> >+ <field name="_content"> >+ document.getAnonymousElementByAttribute(this, "class", "content-box"); >+ </field> >+ </implementation> >+ <handlers> >+ <handler event="command"> >+ // This "command" event handler tracks changes made to preferences by >+ // the user in this window. >+ if (event.sourceEvent) >+ event = event.sourceEvent; >+ this.userChangedValue(event.target); >+ </handler> >+ <handler event="select"> >+ // This "select" event handler tracks changes made to colorpicker >+ // preferences by the user in this window. >+ if (event.target.localName == "colorpicker") >+ this.userChangedValue(event.target); >+ </handler> >+ <handler event="change"> >+ // This "change" event handler tracks changes made to preferences by >+ // the user in this window. >+ this.userChangedValue(event.target); >+ </handler> >+ <handler event="input"> >+ // This "input" event handler tracks changes made to preferences by >+ // the user in this window. >+ this.userChangedValue(event.target); >+ </handler> >+ <handler event="paneload"> >+ <![CDATA[ >+ // Initialize all values from preferences. >+ var elements = this.preferenceElements; >+ for (var i = 0; i < elements.length; ++i) { >+ try { >+ var preference = this.preferenceForElement(elements[i]); >+ preference.setElementValue(elements[i]); >+ } >+ catch (e) { >+ dump("*** No preference found for " + elements[i].getAttribute("preference") + "\n"); >+ } >+ } >+ ]]> >+ </handler> >+ </handlers> >+ </binding> >+ >+ <binding id="panebutton" extends="chrome://global/content/bindings/radio.xml#radio"> >+ <resources> >+ <stylesheet src="chrome://global/skin/preferences.css"/> >+ </resources> >+ <content> >+ <xul:image class="paneButtonIcon" xbl:inherits="src"/> >+ <xul:label class="paneButtonLabel" xbl:inherits="value=label"/> >+ </content> >+ <implementation implements="nsIAccessible"> >+ <property name="accessibleType" readonly="true"> >+ <getter> >+ <![CDATA[ >+ return Components.interfaces.nsIAccessibleProvider.XULListitem; >+ ]]> >+ </getter> >+ </property> >+ </implementation> >+ </binding> >+ >+</bindings> >+ >+# -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- >+# This Source Code Form is subject to the terms of the Mozilla Public >+# License, v. 2.0. If a copy of the MPL was not distributed with this >+# file, You can obtain one at http://mozilla.org/MPL/2.0/. >+ >+# >+# This is PrefWindow 6. The Code Could Well Be Ready, Are You? >+# >+# Historical References: >+# PrefWindow V (February 1, 2003) >+# PrefWindow IV (April 24, 2000) >+# PrefWindow III (January 6, 2000) >+# PrefWindow II (???) >+# PrefWindow I (June 4, 1999) >+# >diff --git a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp >--- a/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp >+++ b/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp >@@ -14,16 +14,18 @@ > #include "prenv.h" > #include "nsPrintfCString.h" > #include "nsNetUtil.h" > #include "nsISupportsPrimitives.h" > #include "nsIGSettingsService.h" > #include "nsInterfaceHashtable.h" > #include "mozilla/Attributes.h" > #include "nsIURI.h" >+#include "nsVoidArray.h" >+#include "nsKDEUtils.h" > > class nsUnixSystemProxySettings MOZ_FINAL : public nsISystemProxySettings { > public: > NS_DECL_ISUPPORTS > NS_DECL_NSISYSTEMPROXYSETTINGS > > nsUnixSystemProxySettings() {} > nsresult Init(); >@@ -35,16 +37,17 @@ private: > nsCOMPtr<nsIGSettingsService> mGSettings; > nsCOMPtr<nsIGSettingsCollection> mProxySettings; > nsInterfaceHashtable<nsCStringHashKey, nsIGSettingsCollection> mSchemeProxySettings; > bool IsProxyMode(const char* aMode); > nsresult SetProxyResultFromGConf(const char* aKeyBase, const char* aType, nsACString& aResult); > nsresult GetProxyFromGConf(const nsACString& aScheme, const nsACString& aHost, int32_t aPort, nsACString& aResult); > nsresult GetProxyFromGSettings(const nsACString& aScheme, const nsACString& aHost, int32_t aPort, nsACString& aResult); > nsresult SetProxyResultFromGSettings(const char* aKeyBase, const char* aType, nsACString& aResult); >+ nsresult GetProxyFromKDE(const nsACString& aScheme, const nsACString& aHost, PRInt32 aPort, nsACString& aResult); > }; > > NS_IMPL_ISUPPORTS1(nsUnixSystemProxySettings, nsISystemProxySettings) > > NS_IMETHODIMP > nsUnixSystemProxySettings::GetMainThreadOnly(bool *aMainThreadOnly) > { > // dbus prevents us from being threadsafe, but this routine should not block anyhow >@@ -496,16 +499,19 @@ nsUnixSystemProxySettings::GetProxyFromG > > nsresult > nsUnixSystemProxySettings::GetProxyForURI(const nsACString & aSpec, > const nsACString & aScheme, > const nsACString & aHost, > const int32_t aPort, > nsACString & aResult) > { >+ if (nsKDEUtils::kdeSupport()) >+ return GetProxyFromKDE(aScheme, aHost, aPort, aResult); >+ > if (mProxySettings) { > nsresult rv = GetProxyFromGSettings(aScheme, aHost, aPort, aResult); > if (NS_SUCCEEDED(rv)) > return rv; > } > if (mGConf) > return GetProxyFromGConf(aScheme, aHost, aPort, aResult); > >@@ -531,8 +537,34 @@ static const mozilla::Module::ContractID > > static const mozilla::Module kUnixProxyModule = { > mozilla::Module::kVersion, > kUnixProxyCIDs, > kUnixProxyContracts > }; > > NSMODULE_DEFN(nsUnixProxyModule) = &kUnixProxyModule; >+ >+nsresult >+nsUnixSystemProxySettings::GetProxyFromKDE(const nsACString& aScheme, >+ const nsACString& aHost, >+ PRInt32 aPort, >+ nsACString& aResult) >+{ >+ nsAutoCString url; >+ url = aScheme; >+ url += "://"; >+ url += aHost; >+ if( aPort >= 0 ) >+ { >+ url += ":"; >+ url += nsPrintfCString("%d", aPort); >+ } >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "GETPROXY" )); >+ command.AppendElement( url ); >+ nsTArray<nsCString> result; >+ if( !nsKDEUtils::command( command, &result ) || result.Length() != 1 ) >+ return NS_ERROR_FAILURE; >+ aResult = result[0]; >+ return NS_OK; >+} >+ >diff --git a/toolkit/xre/moz.build b/toolkit/xre/moz.build >--- a/toolkit/xre/moz.build >+++ b/toolkit/xre/moz.build >@@ -38,18 +38,20 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'qt > 'nsNativeAppSupportQt.cpp', > 'nsQAppInstance.cpp', > ] > elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'os2': > CPP_SOURCES += [ > 'nsNativeAppSupportOS2.cpp', > ] > elif CONFIG['MOZ_ENABLE_GTK']: >+ EXPORTS += ['nsKDEUtils.h'] > CPP_SOURCES += [ > 'nsNativeAppSupportUnix.cpp', >+ 'nsKDEUtils.cpp' > ] > else: > CPP_SOURCES += [ > 'nsNativeAppSupportDefault.cpp', > ] > > if CONFIG['MOZ_X11']: > CPP_SOURCES += [ >diff --git a/toolkit/xre/nsKDEUtils.cpp b/toolkit/xre/nsKDEUtils.cpp >new file mode 100644 >--- /dev/null >+++ b/toolkit/xre/nsKDEUtils.cpp >@@ -0,0 +1,339 @@ >+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ >+/* This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#include "nsKDEUtils.h" >+#include "nsIWidget.h" >+#include "nsISupportsPrimitives.h" >+#include "nsIMutableArray.h" >+#include "nsComponentManagerUtils.h" >+#include "nsArrayUtils.h" >+ >+#include <gtk/gtk.h> >+ >+#include <limits.h> >+#include <stdio.h> >+#include <sys/wait.h> >+#include <sys/resource.h> >+#include <unistd.h> >+#include <X11/Xlib.h> >+ >+//#define DEBUG_KDE >+#ifdef DEBUG_KDE >+#define KMOZILLAHELPER "kmozillahelper" >+#else >+// not need for lib64, it's a binary >+#define KMOZILLAHELPER "/usr/lib/mozilla/kmozillahelper" >+#endif >+ >+#define KMOZILLAHELPER_VERSION 6 >+#define MAKE_STR2( n ) #n >+#define MAKE_STR( n ) MAKE_STR2( n ) >+ >+static bool getKdeSession() >+ { >+ Display* dpy = XOpenDisplay( NULL ); >+ if( dpy == NULL ) >+ return false; >+ Atom kde_full_session = XInternAtom( dpy, "KDE_FULL_SESSION", True ); >+ bool kde = false; >+ if( kde_full_session != None ) >+ { >+ int cnt; >+ if( Atom* props = XListProperties( dpy, DefaultRootWindow( dpy ), &cnt )) >+ { >+ for( int i = 0; >+ i < cnt; >+ ++i ) >+ { >+ if( props[ i ] == kde_full_session ) >+ { >+ kde = true; >+#ifdef DEBUG_KDE >+ fprintf( stderr, "KDE SESSION %d\n", kde ); >+#endif >+ break; >+ } >+ } >+ XFree( props ); >+ } >+ } >+ XCloseDisplay( dpy ); >+ return kde; >+ } >+ >+static bool getKdeSupport() >+ { >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "CHECK" )); >+ command.AppendElement( NS_LITERAL_CSTRING( MAKE_STR( KMOZILLAHELPER_VERSION ))); >+ bool kde = nsKDEUtils::command( command ); >+#ifdef DEBUG_KDE >+ fprintf( stderr, "KDE RUNNING %d\n", kde ); >+#endif >+ return kde; >+ } >+ >+nsKDEUtils::nsKDEUtils() >+ : commandFile( NULL ) >+ , replyFile( NULL ) >+ { >+ } >+ >+nsKDEUtils::~nsKDEUtils() >+ { >+// closeHelper(); not actually useful, exiting will close the fd too >+ } >+ >+nsKDEUtils* nsKDEUtils::self() >+ { >+ static nsKDEUtils s; >+ return &s; >+ } >+ >+static bool helperRunning = false; >+static bool helperFailed = false; >+ >+bool nsKDEUtils::kdeSession() >+ { >+ static bool session = getKdeSession(); >+ return session; >+ } >+ >+bool nsKDEUtils::kdeSupport() >+ { >+ static bool support = kdeSession() && getKdeSupport(); >+ return support && helperRunning; >+ } >+ >+struct nsKDECommandData >+ { >+ FILE* file; >+ nsTArray<nsCString>* output; >+ GMainLoop* loop; >+ bool success; >+ }; >+ >+static gboolean kdeReadFunc( GIOChannel*, GIOCondition, gpointer data ) >+ { >+ nsKDECommandData* p = static_cast< nsKDECommandData* >( data ); >+ char buf[ 8192 ]; // TODO big enough >+ bool command_done = false; >+ bool command_failed = false; >+ while( !command_done && !command_failed && fgets( buf, 8192, p->file ) != NULL ) >+ { // TODO what if the kernel splits a line into two chunks? >+//#ifdef DEBUG_KDE >+// fprintf( stderr, "READ: %s %d\n", buf, feof( p->file )); >+//#endif >+ if( char* eol = strchr( buf, '\n' )) >+ *eol = '\0'; >+ command_done = ( strcmp( buf, "\\1" ) == 0 ); >+ command_failed = ( strcmp( buf, "\\0" ) == 0 ); >+ nsAutoCString line( buf ); >+ line.ReplaceSubstring( "\\n", "\n" ); >+ line.ReplaceSubstring( "\\" "\\", "\\" ); // \\ -> \ , i.e. unescape >+ if( p->output && !( command_done || command_failed )) >+ p->output->AppendElement( nsCString( buf )); // TODO utf8? >+ } >+ bool quit = false; >+ if( feof( p->file ) || command_failed ) >+ { >+ quit = true; >+ p->success = false; >+ } >+ if( command_done ) >+ { // reading one reply finished >+ quit = true; >+ p->success = true; >+ } >+ if( quit ) >+ { >+ if( p->loop ) >+ g_main_loop_quit( p->loop ); >+ return FALSE; >+ } >+ return TRUE; >+ } >+ >+bool nsKDEUtils::command( const nsTArray<nsCString>& command, nsTArray<nsCString>* output ) >+ { >+ return self()->internalCommand( command, NULL, false, output ); >+ } >+ >+bool nsKDEUtils::command( nsIArray* command, nsIArray** output) >+ { >+ nsTArray<nsCString> in; >+ PRUint32 length; >+ command->GetLength( &length ); >+ for ( PRUint32 i = 0; i < length; i++ ) >+ { >+ nsCOMPtr<nsISupportsCString> str = do_QueryElementAt( command, i ); >+ if( str ) >+ { >+ nsAutoCString s; >+ str->GetData( s ); >+ in.AppendElement( s ); >+ } >+ } >+ >+ nsTArray<nsCString> out; >+ bool ret = self()->internalCommand( in, NULL, false, &out ); >+ >+ if ( !output ) return ret; >+ >+ nsCOMPtr<nsIMutableArray> result = do_CreateInstance( NS_ARRAY_CONTRACTID ); >+ if ( !result ) return false; >+ >+ for ( PRUint32 i = 0; i < out.Length(); i++ ) >+ { >+ nsCOMPtr<nsISupportsCString> rstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); >+ if ( !rstr ) return false; >+ >+ rstr->SetData( out[i] ); >+ result->AppendElement( rstr, false ); >+ } >+ >+ NS_ADDREF( *output = result); >+ return ret; >+ } >+ >+ >+bool nsKDEUtils::commandBlockUi( const nsTArray<nsCString>& command, const GtkWindow* parent, nsTArray<nsCString>* output ) >+ { >+ return self()->internalCommand( command, parent, true, output ); >+ } >+ >+bool nsKDEUtils::internalCommand( const nsTArray<nsCString>& command, const GtkWindow* parent, bool blockUi, >+ nsTArray<nsCString>* output ) >+ { >+ if( !startHelper()) >+ return false; >+ feedCommand( command ); >+ // do not store the data in 'this' but in extra structure, just in case there >+ // is reentrancy (can there be? the event loop is re-entered) >+ nsKDECommandData data; >+ data.file = replyFile; >+ data.output = output; >+ data.success = false; >+ if( blockUi ) >+ { >+ data.loop = g_main_loop_new( NULL, FALSE ); >+ GtkWidget* window = gtk_window_new( GTK_WINDOW_TOPLEVEL ); >+ if( parent && parent->group ) >+ gtk_window_group_add_window( parent->group, GTK_WINDOW( window )); >+ gtk_widget_realize( window ); >+ gtk_widget_set_sensitive( window, TRUE ); >+ gtk_grab_add( window ); >+ GIOChannel* channel = g_io_channel_unix_new( fileno( data.file )); >+ g_io_add_watch( channel, static_cast< GIOCondition >( G_IO_IN | G_IO_ERR | G_IO_HUP ), kdeReadFunc, &data ); >+ g_io_channel_unref( channel ); >+ g_main_loop_run( data.loop ); >+ g_main_loop_unref( data.loop ); >+ gtk_grab_remove( window ); >+ gtk_widget_destroy( window ); >+ } >+ else >+ { >+ data.loop = NULL; >+ while( kdeReadFunc( NULL, static_cast< GIOCondition >( 0 ), &data )) >+ ; >+ } >+ return data.success; >+ } >+ >+bool nsKDEUtils::startHelper() >+ { >+ if( helperRunning ) >+ return true; >+ if( helperFailed ) >+ return false; >+ helperFailed = true; >+ int fdcommand[ 2 ]; >+ int fdreply[ 2 ]; >+ if( pipe( fdcommand ) < 0 ) >+ return false; >+ if( pipe( fdreply ) < 0 ) >+ { >+ close( fdcommand[ 0 ] ); >+ close( fdcommand[ 1 ] ); >+ return false; >+ } >+ char* args[ 2 ] = { const_cast< char* >( KMOZILLAHELPER ), NULL }; >+ switch( fork()) >+ { >+ case -1: >+ { >+ close( fdcommand[ 0 ] ); >+ close( fdcommand[ 1 ] ); >+ close( fdreply[ 0 ] ); >+ close( fdreply[ 1 ] ); >+ return false; >+ } >+ case 0: // child >+ { >+ if( dup2( fdcommand[ 0 ], STDIN_FILENO ) < 0 ) >+ _exit( 1 ); >+ if( dup2( fdreply[ 1 ], STDOUT_FILENO ) < 0 ) >+ _exit( 1 ); >+ int maxfd = 1024; // close all other fds >+ struct rlimit rl; >+ if( getrlimit( RLIMIT_NOFILE, &rl ) == 0 ) >+ maxfd = rl.rlim_max; >+ for( int i = 3; >+ i < maxfd; >+ ++i ) >+ close( i ); >+#ifdef DEBUG_KDE >+ execvp( KMOZILLAHELPER, args ); >+#else >+ execv( KMOZILLAHELPER, args ); >+#endif >+ _exit( 1 ); // failed >+ } >+ default: // parent >+ { >+ commandFile = fdopen( fdcommand[ 1 ], "w" ); >+ replyFile = fdopen( fdreply[ 0 ], "r" ); >+ close( fdcommand[ 0 ] ); >+ close( fdreply[ 1 ] ); >+ if( commandFile == NULL || replyFile == NULL ) >+ { >+ closeHelper(); >+ return false; >+ } >+ // ok, helper ready, getKdeRunning() will check if it works >+ } >+ } >+ helperFailed = false; >+ helperRunning = true; >+ return true; >+ } >+ >+void nsKDEUtils::closeHelper() >+ { >+ if( commandFile != NULL ) >+ fclose( commandFile ); // this will also make the helper quit >+ if( replyFile != NULL ) >+ fclose( replyFile ); >+ helperRunning = false; >+ } >+ >+void nsKDEUtils::feedCommand( const nsTArray<nsCString>& command ) >+ { >+ for( int i = 0; >+ i < command.Length(); >+ ++i ) >+ { >+ nsCString line = command[ i ]; >+ line.ReplaceSubstring( "\\", "\\" "\\" ); // \ -> \\ , i.e. escape >+ line.ReplaceSubstring( "\n", "\\n" ); >+#ifdef DEBUG_KDE >+ fprintf( stderr, "COMM: %s\n", line.get()); >+#endif >+ fputs( line.get(), commandFile ); >+ fputs( "\n", commandFile ); >+ } >+ fputs( "\\E\n", commandFile ); // done as \E, so it cannot happen in normal data >+ fflush( commandFile ); >+ } >diff --git a/toolkit/xre/nsKDEUtils.h b/toolkit/xre/nsKDEUtils.h >new file mode 100644 >--- /dev/null >+++ b/toolkit/xre/nsKDEUtils.h >@@ -0,0 +1,48 @@ >+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ >+/* This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#ifndef nsKDEUtils_h__ >+#define nsKDEUtils_h__ >+ >+#include "nsStringGlue.h" >+#include "nsTArray.h" >+#include <stdio.h> >+ >+typedef struct _GtkWindow GtkWindow; >+ >+class nsIArray; >+ >+class NS_EXPORT nsKDEUtils >+ { >+ public: >+ /* Returns true if running inside a KDE session (regardless of whether there is KDE >+ support available for Firefox). This should be used e.g. when determining >+ dialog button order but not for code that requires the KDE support. */ >+ static bool kdeSession(); >+ /* Returns true if running inside a KDE session and KDE support is available >+ for Firefox. This should be used everywhere where the external helper is needed. */ >+ static bool kdeSupport(); >+ /* Executes the given helper command, returns true if helper returned success. */ >+ static bool command( const nsTArray<nsCString>& command, nsTArray<nsCString>* output = NULL ); >+ static bool command( nsIArray* command, nsIArray** output = NULL ); >+ /* Like command(), but additionally blocks the parent widget like if there was >+ a modal dialog shown and enters the event loop (i.e. there are still paint updates, >+ this is for commands that take long). */ >+ static bool commandBlockUi( const nsTArray<nsCString>& command, const GtkWindow* parent, nsTArray<nsCString>* output = NULL ); >+ >+ private: >+ nsKDEUtils(); >+ ~nsKDEUtils(); >+ static nsKDEUtils* self(); >+ bool startHelper(); >+ void closeHelper(); >+ void feedCommand( const nsTArray<nsCString>& command ); >+ bool internalCommand( const nsTArray<nsCString>& command, const GtkWindow* parent, bool isParent, >+ nsTArray<nsCString>* output ); >+ FILE* commandFile; >+ FILE* replyFile; >+ }; >+ >+#endif // nsKDEUtils >diff --git a/uriloader/exthandler/Makefile.in b/uriloader/exthandler/Makefile.in >--- a/uriloader/exthandler/Makefile.in >+++ b/uriloader/exthandler/Makefile.in >@@ -86,9 +86,10 @@ EXTRA_COMPONENTS = \ > # we don't want the shared lib, but we want to force the creation of a static lib. > FORCE_STATIC_LIB = 1 > include $(topsrcdir)/config/config.mk > include $(topsrcdir)/ipc/chromium/chromium-config.mk > include $(topsrcdir)/config/rules.mk > > ifneq (,$(filter qt gtk2 gtk3, $(MOZ_WIDGET_TOOLKIT))) > CXXFLAGS += $(TK_CFLAGS) $(MOZ_DBUS_GLIB_CFLAGS) >+LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre > endif >diff --git a/uriloader/exthandler/moz.build b/uriloader/exthandler/moz.build >--- a/uriloader/exthandler/moz.build >+++ b/uriloader/exthandler/moz.build >@@ -68,16 +68,18 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco > pass > else: > CPP_SOURCES += [ > 'nsOSHelperAppService.cpp', > ] > > if CONFIG['MOZ_ENABLE_GTK']: > CPP_SOURCES += [ >+ 'nsCommonRegistry.cpp', >+ 'nsKDERegistry.cpp', > 'nsGNOMERegistry.cpp', > 'nsMIMEInfoUnix.cpp', > ] > elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'android': > CPP_SOURCES += [ > 'nsMIMEInfoAndroid.cpp', > 'nsAndroidHandlerApp.cpp', > 'nsExternalSharingAppService.cpp', >diff --git a/uriloader/exthandler/unix/nsCommonRegistry.cpp b/uriloader/exthandler/unix/nsCommonRegistry.cpp >new file mode 100644 >--- /dev/null >+++ b/uriloader/exthandler/unix/nsCommonRegistry.cpp >@@ -0,0 +1,54 @@ >+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ >+/* This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#include "nsCommonRegistry.h" >+ >+#include "nsGNOMERegistry.h" >+#include "nsKDERegistry.h" >+#include "nsString.h" >+#include "nsVoidArray.h" >+#include "nsKDEUtils.h" >+ >+/* static */ bool >+nsCommonRegistry::HandlerExists(const char *aProtocolScheme) >+{ >+ if( nsKDEUtils::kdeSupport()) >+ return nsKDERegistry::HandlerExists( aProtocolScheme ); >+ return nsGNOMERegistry::HandlerExists( aProtocolScheme ); >+} >+ >+/* static */ nsresult >+nsCommonRegistry::LoadURL(nsIURI *aURL) >+{ >+ if( nsKDEUtils::kdeSupport()) >+ return nsKDERegistry::LoadURL( aURL ); >+ return nsGNOMERegistry::LoadURL( aURL ); >+} >+ >+/* static */ void >+nsCommonRegistry::GetAppDescForScheme(const nsACString& aScheme, >+ nsAString& aDesc) >+{ >+ if( nsKDEUtils::kdeSupport()) >+ return nsKDERegistry::GetAppDescForScheme( aScheme, aDesc ); >+ return nsGNOMERegistry::GetAppDescForScheme( aScheme, aDesc ); >+} >+ >+ >+/* static */ already_AddRefed<nsMIMEInfoBase> >+nsCommonRegistry::GetFromExtension(const nsACString& aFileExt) >+{ >+ if( nsKDEUtils::kdeSupport()) >+ return nsKDERegistry::GetFromExtension( aFileExt ); >+ return nsGNOMERegistry::GetFromExtension( aFileExt ); >+} >+ >+/* static */ already_AddRefed<nsMIMEInfoBase> >+nsCommonRegistry::GetFromType(const nsACString& aMIMEType) >+{ >+ if( nsKDEUtils::kdeSupport()) >+ return nsKDERegistry::GetFromType( aMIMEType ); >+ return nsGNOMERegistry::GetFromType( aMIMEType ); >+} >diff --git a/uriloader/exthandler/unix/nsCommonRegistry.h b/uriloader/exthandler/unix/nsCommonRegistry.h >new file mode 100644 >--- /dev/null >+++ b/uriloader/exthandler/unix/nsCommonRegistry.h >@@ -0,0 +1,23 @@ >+/* This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#include "nsIURI.h" >+#include "nsCOMPtr.h" >+ >+class nsMIMEInfoBase; >+ >+class nsCommonRegistry >+{ >+ public: >+ static bool HandlerExists(const char *aProtocolScheme); >+ >+ static nsresult LoadURL(nsIURI *aURL); >+ >+ static void GetAppDescForScheme(const nsACString& aScheme, >+ nsAString& aDesc); >+ >+ static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt); >+ >+ static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType); >+}; >diff --git a/uriloader/exthandler/unix/nsKDERegistry.cpp b/uriloader/exthandler/unix/nsKDERegistry.cpp >new file mode 100644 >--- /dev/null >+++ b/uriloader/exthandler/unix/nsKDERegistry.cpp >@@ -0,0 +1,88 @@ >+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ >+/* This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#include "nsKDERegistry.h" >+#include "prlink.h" >+#include "prmem.h" >+#include "nsString.h" >+#include "nsILocalFile.h" >+#include "nsMIMEInfoUnix.h" >+#include "nsAutoPtr.h" >+#include "nsKDEUtils.h" >+ >+/* static */ bool >+nsKDERegistry::HandlerExists(const char *aProtocolScheme) >+{ >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "HANDLEREXISTS" )); >+ command.AppendElement( nsAutoCString( aProtocolScheme )); >+ return nsKDEUtils::command( command ); >+} >+ >+/* static */ nsresult >+nsKDERegistry::LoadURL(nsIURI *aURL) >+{ >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "OPEN" )); >+ nsCString url; >+ aURL->GetSpec( url ); >+ command.AppendElement( url ); >+ bool rv = nsKDEUtils::command( command ); >+ if (!rv) >+ return NS_ERROR_FAILURE; >+ >+ return NS_OK; >+} >+ >+/* static */ void >+nsKDERegistry::GetAppDescForScheme(const nsACString& aScheme, >+ nsAString& aDesc) >+{ >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "GETAPPDESCFORSCHEME" )); >+ command.AppendElement( aScheme ); >+ nsTArray<nsCString> output; >+ if( nsKDEUtils::command( command, &output ) && output.Length() == 1 ) >+ CopyUTF8toUTF16( output[ 0 ], aDesc ); >+} >+ >+ >+/* static */ already_AddRefed<nsMIMEInfoBase> >+nsKDERegistry::GetFromExtension(const nsACString& aFileExt) >+{ >+ NS_ASSERTION(aFileExt[0] != '.', "aFileExt shouldn't start with a dot"); >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "GETFROMEXTENSION" )); >+ command.AppendElement( aFileExt ); >+ return GetFromHelper( command ); >+} >+ >+/* static */ already_AddRefed<nsMIMEInfoBase> >+nsKDERegistry::GetFromType(const nsACString& aMIMEType) >+{ >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "GETFROMTYPE" )); >+ command.AppendElement( aMIMEType ); >+ return GetFromHelper( command ); >+} >+ >+/* static */ already_AddRefed<nsMIMEInfoBase> >+nsKDERegistry::GetFromHelper(const nsTArray<nsCString>& command) >+{ >+ nsTArray<nsCString> output; >+ if( nsKDEUtils::command( command, &output ) && output.Length() == 3 ) >+ { >+ nsCString mimetype = output[ 0 ]; >+ nsRefPtr<nsMIMEInfoUnix> mimeInfo = new nsMIMEInfoUnix( mimetype ); >+ NS_ENSURE_TRUE(mimeInfo, nullptr); >+ nsCString description = output[ 1 ]; >+ mimeInfo->SetDescription(NS_ConvertUTF8toUTF16(description)); >+ nsCString handlerAppName = output[ 2 ]; >+ mimeInfo->SetDefaultDescription(NS_ConvertUTF8toUTF16(handlerAppName)); >+ mimeInfo->SetPreferredAction(nsIMIMEInfo::useSystemDefault); >+ return mimeInfo.forget(); >+ } >+ return nullptr; >+} >diff --git a/uriloader/exthandler/unix/nsKDERegistry.h b/uriloader/exthandler/unix/nsKDERegistry.h >new file mode 100644 >--- /dev/null >+++ b/uriloader/exthandler/unix/nsKDERegistry.h >@@ -0,0 +1,29 @@ >+/* This Source Code Form is subject to the terms of the Mozilla Public >+ * License, v. 2.0. If a copy of the MPL was not distributed with this >+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ >+ >+#include "nsIURI.h" >+#include "nsCOMPtr.h" >+#include "nsTArray.h" >+ >+class nsMIMEInfoBase; >+class nsAutoCString; >+class nsCString; >+ >+class nsKDERegistry >+{ >+ public: >+ static bool HandlerExists(const char *aProtocolScheme); >+ >+ static nsresult LoadURL(nsIURI *aURL); >+ >+ static void GetAppDescForScheme(const nsACString& aScheme, >+ nsAString& aDesc); >+ >+ static already_AddRefed<nsMIMEInfoBase> GetFromExtension(const nsACString& aFileExt); >+ >+ static already_AddRefed<nsMIMEInfoBase> GetFromType(const nsACString& aMIMEType); >+ private: >+ static already_AddRefed<nsMIMEInfoBase> GetFromHelper(const nsTArray<nsCString>& command); >+ >+}; >diff --git a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp >--- a/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp >+++ b/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp >@@ -16,30 +16,33 @@ > #include <QString> > #if (MOZ_ENABLE_CONTENTACTION) > #include <contentaction/contentaction.h> > #include "nsContentHandlerApp.h" > #endif > #endif > > #include "nsMIMEInfoUnix.h" >-#include "nsGNOMERegistry.h" >+#include "nsCommonRegistry.h" > #include "nsIGIOService.h" > #include "nsNetCID.h" > #include "nsIIOService.h" > #include "nsIGnomeVFSService.h" > #include "nsAutoPtr.h" > #ifdef MOZ_ENABLE_DBUS > #include "nsDBusHandlerApp.h" > #endif >+#if defined(XP_UNIX) && !defined(XP_MACOSX) >+#include "nsKDEUtils.h" >+#endif > > nsresult > nsMIMEInfoUnix::LoadUriInternal(nsIURI * aURI) > { >- nsresult rv = nsGNOMERegistry::LoadURL(aURI); >+ nsresult rv = nsCommonRegistry::LoadURL(aURI); > > #if (MOZ_PLATFORM_MAEMO == 5) && defined (MOZ_ENABLE_GNOMEVFS) > if (NS_FAILED(rv)){ > HildonURIAction *action = hildon_uri_get_default_action(mSchemeOrType.get(), nullptr); > if (action) { > nsAutoCString spec; > aURI->GetAsciiSpec(spec); > if (hildon_uri_open(spec.get(), action, nullptr)) >@@ -67,22 +70,22 @@ nsMIMEInfoUnix::GetHasDefaultHandler(boo > { > // if mDefaultApplication is set, it means the application has been set from > // either /etc/mailcap or ${HOME}/.mailcap, in which case we don't want to > // give the GNOME answer. > if (mDefaultApplication) > return nsMIMEInfoImpl::GetHasDefaultHandler(_retval); > > *_retval = false; >- nsRefPtr<nsMIMEInfoBase> mimeInfo = nsGNOMERegistry::GetFromType(mSchemeOrType); >+ nsRefPtr<nsMIMEInfoBase> mimeInfo = nsCommonRegistry::GetFromType(mSchemeOrType); > if (!mimeInfo) { > nsAutoCString ext; > nsresult rv = GetPrimaryExtension(ext); > if (NS_SUCCEEDED(rv)) { >- mimeInfo = nsGNOMERegistry::GetFromExtension(ext); >+ mimeInfo = nsCommonRegistry::GetFromExtension(ext); > } > } > if (mimeInfo) > *_retval = true; > > if (*_retval) > return NS_OK; > >@@ -130,16 +133,33 @@ nsMIMEInfoUnix::LaunchDefaultWithFile(ns > ContentAction::Action::defaultActionForFile(uri, QString(mSchemeOrType.get())); > if (action.isValid()) { > action.trigger(); > return NS_OK; > } > return NS_ERROR_FAILURE; > #endif > >+ if( nsKDEUtils::kdeSupport()) { >+ bool supports; >+ if( NS_SUCCEEDED( GetHasDefaultHandler( &supports )) && supports ) { >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "OPEN" )); >+ command.AppendElement( nativePath ); >+ command.AppendElement( NS_LITERAL_CSTRING( "MIMETYPE" )); >+ command.AppendElement( mSchemeOrType ); >+ if( nsKDEUtils::command( command )) >+ return NS_OK; >+ } >+ if (!mDefaultApplication) >+ return NS_ERROR_FILE_NOT_FOUND; >+ >+ return LaunchWithIProcess(mDefaultApplication, nativePath); >+ } >+ > nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); > nsAutoCString uriSpec; > if (giovfs) { > // nsGIOMimeApp->Launch wants a URI string instead of local file > nsresult rv; > nsCOMPtr<nsIIOService> ioservice = do_GetService(NS_IOSERVICE_CONTRACTID, &rv); > NS_ENSURE_SUCCESS(rv, rv); > nsCOMPtr<nsIURI> uri; >@@ -157,17 +177,17 @@ nsMIMEInfoUnix::LaunchDefaultWithFile(ns > /* Fallback to GnomeVFS */ > nsCOMPtr<nsIGnomeVFSMimeApp> app; > if (NS_SUCCEEDED(gnomevfs->GetAppForMimeType(mSchemeOrType, getter_AddRefs(app))) && app) > return app->Launch(nativePath); > } > > // If we haven't got an app we try to get a valid one by searching for the > // extension mapped type >- nsRefPtr<nsMIMEInfoBase> mimeInfo = nsGNOMERegistry::GetFromExtension(nativePath); >+ nsRefPtr<nsMIMEInfoBase> mimeInfo = nsCommonRegistry::GetFromExtension(nativePath); > if (mimeInfo) { > nsAutoCString type; > mimeInfo->GetType(type); > if (giovfs) { > nsCOMPtr<nsIGIOMimeApp> app; > if (NS_SUCCEEDED(giovfs->GetAppForMimeType(type, getter_AddRefs(app))) && app) > return app->Launch(uriSpec); > } else if (gnomevfs) { >diff --git a/uriloader/exthandler/unix/nsOSHelperAppService.cpp b/uriloader/exthandler/unix/nsOSHelperAppService.cpp >--- a/uriloader/exthandler/unix/nsOSHelperAppService.cpp >+++ b/uriloader/exthandler/unix/nsOSHelperAppService.cpp >@@ -10,17 +10,17 @@ > #if defined(MOZ_ENABLE_CONTENTACTION) > #include <contentaction/contentaction.h> > #include <QString> > #endif > > #include "nsOSHelperAppService.h" > #include "nsMIMEInfoUnix.h" > #ifdef MOZ_WIDGET_GTK >-#include "nsGNOMERegistry.h" >+#include "nsCommonRegistry.h" > #endif > #include "nsISupports.h" > #include "nsString.h" > #include "nsReadableUtils.h" > #include "nsUnicharUtils.h" > #include "nsXPIDLString.h" > #include "nsIURL.h" > #include "nsIFileStreams.h" >@@ -1157,29 +1157,29 @@ nsresult nsOSHelperAppService::OSProtoco > ContentAction::Action::defaultActionForScheme(QString(aProtocolScheme) + ':'); > > if (action.isValid()) > *aHandlerExists = true; > #endif > > #ifdef MOZ_WIDGET_GTK > // Check the GConf registry for a protocol handler >- *aHandlerExists = nsGNOMERegistry::HandlerExists(aProtocolScheme); >+ *aHandlerExists = nsCommonRegistry::HandlerExists(aProtocolScheme); > #if (MOZ_PLATFORM_MAEMO == 5) && defined (MOZ_ENABLE_GNOMEVFS) > *aHandlerExists = nsMIMEInfoUnix::HandlerExists(aProtocolScheme); > #endif > #endif > > return NS_OK; > } > > NS_IMETHODIMP nsOSHelperAppService::GetApplicationDescription(const nsACString& aScheme, nsAString& _retval) > { > #ifdef MOZ_WIDGET_GTK >- nsGNOMERegistry::GetAppDescForScheme(aScheme, _retval); >+ nsCommonRegistry::GetAppDescForScheme(aScheme, _retval); > return _retval.IsEmpty() ? NS_ERROR_NOT_AVAILABLE : NS_OK; > #else > return NS_ERROR_NOT_AVAILABLE; > #endif > } > > nsresult nsOSHelperAppService::GetFileTokenForPath(const PRUnichar * platformAppPath, nsIFile ** aFile) > { >@@ -1266,17 +1266,17 @@ nsOSHelperAppService::GetFromExtension(c > mime_types_description, > true); > > if (NS_FAILED(rv) || majorType.IsEmpty()) { > > #ifdef MOZ_WIDGET_GTK > LOG(("Looking in GNOME registry\n")); > nsRefPtr<nsMIMEInfoBase> gnomeInfo = >- nsGNOMERegistry::GetFromExtension(aFileExt); >+ nsCommonRegistry::GetFromExtension(aFileExt); > if (gnomeInfo) { > LOG(("Got MIMEInfo from GNOME registry\n")); > return gnomeInfo.forget(); > } > #endif > > rv = LookUpTypeAndDescription(NS_ConvertUTF8toUTF16(aFileExt), > majorType, >@@ -1389,17 +1389,17 @@ nsOSHelperAppService::GetFromType(const > #ifdef MOZ_WIDGET_GTK > nsRefPtr<nsMIMEInfoBase> gnomeInfo; > if (handler.IsEmpty()) { > // No useful data yet. Check the GNOME registry. Unfortunately, newer > // GNOME versions no longer have type-to-extension mappings, so we might > // get back a MIMEInfo without any extensions set. In that case we'll have > // to look in our mime.types files for the extensions. > LOG(("Looking in GNOME registry\n")); >- gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType); >+ gnomeInfo = nsCommonRegistry::GetFromType(aMIMEType); > if (gnomeInfo && gnomeInfo->HasExtensions()) { > LOG(("Got MIMEInfo from GNOME registry, and it has extensions set\n")); > return gnomeInfo.forget(); > } > } > #endif > > // Now look up our extensions >diff --git a/widget/gtk2/Makefile.in b/widget/gtk2/Makefile.in >--- a/widget/gtk2/Makefile.in >+++ b/widget/gtk2/Makefile.in >@@ -67,11 +67,14 @@ DEFINES += -DCAIRO_GFX -DMOZ_APP_NAME=' > > INCLUDES += \ > -I$(srcdir)/../xpwidgets \ > -I$(srcdir)/../shared \ > -I$(topsrcdir)/layout/generic \ > -I$(topsrcdir)/layout/xul/base/src \ > -I$(topsrcdir)/other-licenses/atk-1.0 \ > $(NULL) >+ >+LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre >+ > ifdef MOZ_X11 > INCLUDES += -I$(srcdir)/../shared/x11 > endif >diff --git a/widget/gtk2/nsFilePicker.cpp b/widget/gtk2/nsFilePicker.cpp >--- a/widget/gtk2/nsFilePicker.cpp >+++ b/widget/gtk2/nsFilePicker.cpp >@@ -1,31 +1,33 @@ > /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ > /* This Source Code Form is subject to the terms of the Mozilla Public > * License, v. 2.0. If a copy of the MPL was not distributed with this > * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ > > #include "mozilla/Util.h" > > #include <gtk/gtk.h> >+#include <gdk/gdkx.h> > > #include "nsIFileURL.h" > #include "nsIURI.h" > #include "nsIWidget.h" > #include "nsIFile.h" > #include "nsIStringBundle.h" > > #include "nsArrayEnumerator.h" > #include "nsMemory.h" > #include "nsEnumeratorUtils.h" > #include "nsNetUtil.h" > #include "nsReadableUtils.h" > #include "mozcontainer.h" > > #include "nsFilePicker.h" >+#include "nsKDEUtils.h" > > #if (MOZ_PLATFORM_MAEMO == 5) > #include <hildon-fm-2/hildon/hildon-file-chooser-dialog.h> > #endif > > using namespace mozilla; > > #define MAX_PREVIEW_SIZE 180 >@@ -242,17 +244,19 @@ nsFilePicker::AppendFilters(int32_t aFil > return nsBaseFilePicker::AppendFilters(aFilterMask); > } > > NS_IMETHODIMP > nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter) > { > if (aFilter.EqualsLiteral("..apps")) { > // No platform specific thing we can do here, really.... >- return NS_OK; >+ // Unless it's KDE. >+ if( mMode != modeOpen || !nsKDEUtils::kdeSupport()) >+ return NS_OK; > } > > nsAutoCString filter, name; > CopyUTF16toUTF8(aFilter, filter); > CopyUTF16toUTF8(aTitle, name); > > mFilters.AppendElement(filter); > mFilterNames.AppendElement(name); >@@ -366,16 +370,32 @@ nsFilePicker::Show(int16_t *aReturn) > > NS_IMETHODIMP > nsFilePicker::Open(nsIFilePickerShownCallback *aCallback) > { > // Can't show two dialogs concurrently with the same filepicker > if (mRunning) > return NS_ERROR_NOT_AVAILABLE; > >+ // KDE file picker is not handled via callback >+ if( nsKDEUtils::kdeSupport()) { >+ int16_t result; >+ mCallback = aCallback; >+ mRunning = true; >+ kdeFileDialog(&result); >+ if (mCallback) { >+ mCallback->Done(result); >+ mCallback = nullptr; >+ } else { >+ mResult = result; >+ } >+ mRunning = false; >+ return NS_OK; >+ } >+ > nsXPIDLCString title; > title.Adopt(ToNewUTF8String(mTitle)); > > GtkWindow *parent_widget = > GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)); > > GtkFileChooserAction action = GetGtkFileChooserAction(mMode); > const gchar *accept_button = (action == GTK_FILE_CHOOSER_ACTION_SAVE) >@@ -567,8 +587,235 @@ nsFilePicker::Done(GtkWidget* file_choos > if (mCallback) { > mCallback->Done(result); > mCallback = nullptr; > } else { > mResult = result; > } > NS_RELEASE_THIS(); > } >+ >+nsCString nsFilePicker::kdeMakeFilter( int index ) >+ { >+ nsCString buf = mFilters[ index ]; >+ for( PRUint32 i = 0; >+ i < buf.Length(); >+ ++i ) >+ if( buf[ i ] == ';' ) // KDE separates just using spaces >+ buf.SetCharAt( ' ', i ); >+ if (!mFilterNames[index].IsEmpty()) >+ { >+ buf += "|"; >+ buf += mFilterNames[index].get(); >+ } >+ return buf; >+ } >+ >+static PRInt32 windowToXid( nsIWidget* widget ) >+ { >+ GtkWindow *parent_widget = GTK_WINDOW(widget->GetNativeData(NS_NATIVE_SHELLWIDGET)); >+ GdkWindow* gdk_window = gtk_widget_get_window( gtk_widget_get_toplevel( GTK_WIDGET( parent_widget ))); >+ return GDK_WINDOW_XID( gdk_window ); >+ } >+ >+NS_IMETHODIMP nsFilePicker::kdeFileDialog(PRInt16 *aReturn) >+ { >+ NS_ENSURE_ARG_POINTER(aReturn); >+ >+ if( mMode == modeOpen && mFilters.Length() == 1 && mFilters[ 0 ].EqualsLiteral( "..apps" )) >+ return kdeAppsDialog( aReturn ); >+ >+ nsXPIDLCString title; >+ title.Adopt(ToNewUTF8String(mTitle)); >+ >+ const char* arg = NULL; >+ if( mAllowURLs ) >+ { >+ switch( mMode ) >+ { >+ case nsIFilePicker::modeOpen: >+ case nsIFilePicker::modeOpenMultiple: >+ arg = "GETOPENURL"; >+ break; >+ case nsIFilePicker::modeSave: >+ arg = "GETSAVEURL"; >+ break; >+ case nsIFilePicker::modeGetFolder: >+ arg = "GETDIRECTORYURL"; >+ break; >+ } >+ } >+ else >+ { >+ switch( mMode ) >+ { >+ case nsIFilePicker::modeOpen: >+ case nsIFilePicker::modeOpenMultiple: >+ arg = "GETOPENFILENAME"; >+ break; >+ case nsIFilePicker::modeSave: >+ arg = "GETSAVEFILENAME"; >+ break; >+ case nsIFilePicker::modeGetFolder: >+ arg = "GETDIRECTORYFILENAME"; >+ break; >+ } >+ } >+ >+ nsAutoCString directory; >+ if (mDisplayDirectory) { >+ mDisplayDirectory->GetNativePath(directory); >+ } else if (mPrevDisplayDirectory) { >+ mPrevDisplayDirectory->GetNativePath(directory); >+ } >+ >+ nsAutoCString startdir; >+ if (!directory.IsEmpty()) { >+ startdir = directory; >+ } >+ if (mMode == nsIFilePicker::modeSave) { >+ if( !startdir.IsEmpty()) >+ { >+ startdir += "/"; >+ startdir += ToNewUTF8String(mDefault); >+ } >+ else >+ startdir = ToNewUTF8String(mDefault); >+ } >+ if( startdir.IsEmpty()) >+ startdir = "."; >+ >+ nsAutoCString filters; >+ PRInt32 count = mFilters.Length(); >+ if( count == 0 ) //just in case >+ filters = "*"; >+ else >+ { >+ filters = kdeMakeFilter( 0 ); >+ for (PRInt32 i = 1; i < count; ++i) >+ { >+ filters += "\n"; >+ filters += kdeMakeFilter( i ); >+ } >+ } >+ >+ nsTArray<nsCString> command; >+ command.AppendElement( nsAutoCString( arg )); >+ command.AppendElement( startdir ); >+ if( mMode != nsIFilePicker::modeGetFolder ) >+ { >+ command.AppendElement( filters ); >+ nsAutoCString selected; >+ selected.AppendInt( mSelectedType ); >+ command.AppendElement( selected ); >+ } >+ command.AppendElement( title ); >+ if( mMode == nsIFilePicker::modeOpenMultiple ) >+ command.AppendElement( NS_LITERAL_CSTRING( "MULTIPLE" )); >+ if( PRInt32 xid = windowToXid( mParentWidget )) >+ { >+ command.AppendElement( NS_LITERAL_CSTRING( "PARENT" )); >+ nsAutoCString parent; >+ parent.AppendInt( xid ); >+ command.AppendElement( parent ); >+ } >+ >+ nsTArray<nsCString> output; >+ if( nsKDEUtils::commandBlockUi( command, GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)), &output )) >+ { >+ *aReturn = nsIFilePicker::returnOK; >+ mFiles.Clear(); >+ if( mMode != nsIFilePicker::modeGetFolder ) >+ { >+ mSelectedType = atoi( output[ 0 ].get()); >+ output.RemoveElementAt( 0 ); >+ } >+ if (mMode == nsIFilePicker::modeOpenMultiple) >+ { >+ mFileURL.Truncate(); >+ PRUint32 count = output.Length(); >+ for( PRUint32 i = 0; >+ i < count; >+ ++i ) >+ { >+ nsCOMPtr<nsIFile> localfile; >+ nsresult rv = NS_NewNativeLocalFile( output[ i ], >+ PR_FALSE, >+ getter_AddRefs(localfile)); >+ if (NS_SUCCEEDED(rv)) >+ mFiles.AppendObject(localfile); >+ } >+ } >+ else >+ { >+ if( output.Length() == 0 ) >+ mFileURL = nsCString(); >+ else if( mAllowURLs ) >+ mFileURL = output[ 0 ]; >+ else // GetFile() actually requires it to be url even for local files :-/ >+ { >+ mFileURL = nsCString( "file://" ); >+ mFileURL.Append( output[ 0 ] ); >+ } >+ } >+ // Remember last used directory. >+ nsCOMPtr<nsIFile> file; >+ GetFile(getter_AddRefs(file)); >+ if (file) { >+ nsCOMPtr<nsIFile> dir; >+ file->GetParent(getter_AddRefs(dir)); >+ nsCOMPtr<nsIFile> localDir(do_QueryInterface(dir)); >+ if (localDir) { >+ localDir.swap(mPrevDisplayDirectory); >+ } >+ } >+ if (mMode == nsIFilePicker::modeSave) >+ { >+ nsCOMPtr<nsIFile> file; >+ GetFile(getter_AddRefs(file)); >+ if (file) >+ { >+ bool exists = false; >+ file->Exists(&exists); >+ if (exists) // TODO do overwrite check in the helper app >+ *aReturn = nsIFilePicker::returnReplace; >+ } >+ } >+ } >+ else >+ { >+ *aReturn = nsIFilePicker::returnCancel; >+ } >+ return NS_OK; >+ } >+ >+ >+NS_IMETHODIMP nsFilePicker::kdeAppsDialog(PRInt16 *aReturn) >+ { >+ NS_ENSURE_ARG_POINTER(aReturn); >+ >+ nsXPIDLCString title; >+ title.Adopt(ToNewUTF8String(mTitle)); >+ >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING( "APPSDIALOG" )); >+ command.AppendElement( title ); >+ if( PRInt32 xid = windowToXid( mParentWidget )) >+ { >+ command.AppendElement( NS_LITERAL_CSTRING( "PARENT" )); >+ nsAutoCString parent; >+ parent.AppendInt( xid ); >+ command.AppendElement( parent ); >+ } >+ >+ nsTArray<nsCString> output; >+ if( nsKDEUtils::commandBlockUi( command, GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)), &output )) >+ { >+ *aReturn = nsIFilePicker::returnOK; >+ mFileURL = output.Length() > 0 ? output[ 0 ] : nsCString(); >+ } >+ else >+ { >+ *aReturn = nsIFilePicker::returnCancel; >+ } >+ return NS_OK; >+ } >+ >diff --git a/widget/gtk2/nsFilePicker.h b/widget/gtk2/nsFilePicker.h >--- a/widget/gtk2/nsFilePicker.h >+++ b/widget/gtk2/nsFilePicker.h >@@ -67,11 +67,17 @@ protected: > nsString mDefault; > nsString mDefaultExtension; > > nsTArray<nsCString> mFilters; > nsTArray<nsCString> mFilterNames; > > private: > static nsIFile *mPrevDisplayDirectory; >+ >+ bool kdeRunning(); >+ bool getKdeRunning(); >+ NS_IMETHODIMP kdeFileDialog(PRInt16 *aReturn); >+ NS_IMETHODIMP kdeAppsDialog(PRInt16 *aReturn); >+ nsCString kdeMakeFilter( int index ); > }; > > #endif >diff --git a/xpcom/components/Makefile.in b/xpcom/components/Makefile.in >--- a/xpcom/components/Makefile.in >+++ b/xpcom/components/Makefile.in >@@ -28,9 +28,10 @@ LOCAL_INCLUDES = \ > FORCE_STATIC_LIB = 1 > > include $(topsrcdir)/config/rules.mk > > DEFINES += -D_IMPL_NS_COM > > ifdef MOZ_WIDGET_GTK > CXXFLAGS += $(TK_CFLAGS) >+LOCAL_INCLUDES += -I$(topsrcdir)/toolkit/xre > endif >diff --git a/xpcom/components/ManifestParser.cpp b/xpcom/components/ManifestParser.cpp >--- a/xpcom/components/ManifestParser.cpp >+++ b/xpcom/components/ManifestParser.cpp >@@ -30,16 +30,17 @@ > #include "nsTextFormatter.h" > #include "nsVersionComparator.h" > #include "nsXPCOMCIDInternal.h" > > #include "nsIConsoleService.h" > #include "nsIScriptError.h" > #include "nsIXULAppInfo.h" > #include "nsIXULRuntime.h" >+#include "nsKDEUtils.h" > > using namespace mozilla; > > struct ManifestDirective > { > const char* directive; > int argc; > >@@ -397,16 +398,17 @@ ParseManifest(NSLocationType type, FileL > NS_NAMED_LITERAL_STRING(kPlatform, "platform"); > NS_NAMED_LITERAL_STRING(kContentAccessible, "contentaccessible"); > NS_NAMED_LITERAL_STRING(kApplication, "application"); > NS_NAMED_LITERAL_STRING(kAppVersion, "appversion"); > NS_NAMED_LITERAL_STRING(kGeckoVersion, "platformversion"); > NS_NAMED_LITERAL_STRING(kOs, "os"); > NS_NAMED_LITERAL_STRING(kOsVersion, "osversion"); > NS_NAMED_LITERAL_STRING(kABI, "abi"); >+ NS_NAMED_LITERAL_STRING(kDesktop, "desktop"); > #if defined(MOZ_WIDGET_ANDROID) > NS_NAMED_LITERAL_STRING(kTablet, "tablet"); > #endif > > // Obsolete > NS_NAMED_LITERAL_STRING(kXPCNativeWrappers, "xpcnativewrappers"); > > nsAutoString appID; >@@ -444,41 +446,46 @@ ParseManifest(NSLocationType type, FileL > CopyUTF8toUTF16(s, abi); > abi.Insert(PRUnichar('_'), 0); > abi.Insert(osTarget, 0); > } > } > } > > nsAutoString osVersion; >+ nsAutoString desktop; > #if defined(XP_WIN) > OSVERSIONINFO info = { sizeof(OSVERSIONINFO) }; > if (GetVersionEx(&info)) { > nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(), > info.dwMajorVersion, > info.dwMinorVersion); > } >+ desktop = NS_LITERAL_STRING("win"); > #elif defined(MOZ_WIDGET_COCOA) > SInt32 majorVersion, minorVersion; > if ((Gestalt(gestaltSystemVersionMajor, &majorVersion) == noErr) && > (Gestalt(gestaltSystemVersionMinor, &minorVersion) == noErr)) { > nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(), > majorVersion, > minorVersion); > } >+ desktop = NS_LITERAL_STRING("macosx"); > #elif defined(MOZ_WIDGET_GTK) > nsTextFormatter::ssprintf(osVersion, NS_LITERAL_STRING("%ld.%ld").get(), > gtk_major_version, > gtk_minor_version); >+ desktop = nsKDEUtils::kdeSession() ? NS_LITERAL_STRING("kde") : NS_LITERAL_STRING("gnome"); > #elif defined(MOZ_WIDGET_ANDROID) > bool isTablet = false; > if (mozilla::AndroidBridge::Bridge()) { > mozilla::AndroidBridge::Bridge()->GetStaticStringField("android/os/Build$VERSION", "RELEASE", osVersion); > isTablet = mozilla::AndroidBridge::Bridge()->IsTablet(); > } >+ desktop = NS_LITERAL_STRING("android"); > #endif > > // Because contracts must be registered after CIDs, we save and process them > // at the end. > nsTArray<CachedDirective> contracts; > > char *token; > char *newline = buf; >@@ -560,24 +567,26 @@ ParseManifest(NSLocationType type, FileL > TriState stOsVersion = eUnspecified; > TriState stOs = eUnspecified; > TriState stABI = eUnspecified; > #if defined(MOZ_WIDGET_ANDROID) > TriState stTablet = eUnspecified; > #endif > bool platform = false; > bool contentAccessible = false; >+ TriState stDesktop = eUnspecified; > > while (NULL != (token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && ok) { > ToLowerCase(token); > NS_ConvertASCIItoUTF16 wtoken(token); > > if (CheckStringFlag(kApplication, wtoken, appID, stApp) || > CheckStringFlag(kOs, wtoken, osTarget, stOs) || > CheckStringFlag(kABI, wtoken, abi, stABI) || >+ CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) || > CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) || > CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion) || > CheckVersionFlag(kGeckoVersion, wtoken, geckoVersion, stGeckoVersion)) > continue; > > #if defined(MOZ_WIDGET_ANDROID) > bool tablet = false; > if (CheckFlag(kTablet, wtoken, tablet)) { >@@ -606,16 +615,17 @@ ParseManifest(NSLocationType type, FileL > } > > if (!ok || > stApp == eBad || > stAppVersion == eBad || > stGeckoVersion == eBad || > stOs == eBad || > stOsVersion == eBad || >+ stDesktop == eBad || > #ifdef MOZ_WIDGET_ANDROID > stTablet == eBad || > #endif > stABI == eBad) > continue; > > if (directive->regfunc) { > if (GeckoProcessType_Default != XRE_GetProcessType()) >diff --git a/xpcom/io/Makefile.in b/xpcom/io/Makefile.in >--- a/xpcom/io/Makefile.in >+++ b/xpcom/io/Makefile.in >@@ -43,17 +43,17 @@ include $(topsrcdir)/ipc/chromium/chromi > DEFINES += -D_IMPL_NS_COM > > ifeq ($(OS_ARCH),Linux) > ifneq (,$(findstring lib64,$(libdir))) > DEFINES += -DHAVE_USR_LIB64_DIR > endif > endif > >-LOCAL_INCLUDES += -I.. >+LOCAL_INCLUDES += -I.. -I$(topsrcdir)/toolkit/xre > > ifeq ($(MOZ_PLATFORM_MAEMO),5) > CFLAGS += $(MOZ_DBUS_CFLAGS) > CXXFLAGS += $(MOZ_DBUS_CFLAGS) > endif > > ifdef MOZ_PLATFORM_MAEMO > CFLAGS += $(MOZ_PLATFORM_MAEMO_CFLAGS) $(MOZ_QT_CFLAGS) >diff --git a/xpcom/io/nsLocalFileUnix.cpp b/xpcom/io/nsLocalFileUnix.cpp >--- a/xpcom/io/nsLocalFileUnix.cpp >+++ b/xpcom/io/nsLocalFileUnix.cpp >@@ -50,16 +50,17 @@ > #include "prproces.h" > #include "nsIDirectoryEnumerator.h" > #include "nsISimpleEnumerator.h" > #include "private/pprio.h" > > #ifdef MOZ_WIDGET_GTK > #include "nsIGIOService.h" > #include "nsIGnomeVFSService.h" >+#include "nsKDEUtils.h" > #endif > > #ifdef MOZ_WIDGET_COCOA > #include <Carbon/Carbon.h> > #include "CocoaFileUtils.h" > #include "prmem.h" > #include "plbase64.h" > >@@ -1753,44 +1754,51 @@ nsLocalFile::SetPersistentDescriptor(con > return InitWithNativePath(aPersistentDescriptor); > #endif > } > > NS_IMETHODIMP > nsLocalFile::Reveal() > { > #ifdef MOZ_WIDGET_GTK >- nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); >- nsCOMPtr<nsIGnomeVFSService> gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID); >- if (!giovfs && !gnomevfs) >- return NS_ERROR_FAILURE; >- >+ nsAutoCString url; > bool isDirectory; > if (NS_FAILED(IsDirectory(&isDirectory))) > return NS_ERROR_FAILURE; > > if (isDirectory) { >- if (giovfs) >- return giovfs->ShowURIForInput(mPath); >- else >- /* Fallback to GnomeVFS */ >- return gnomevfs->ShowURIForInput(mPath); >+ url = mPath; > } else { > nsCOMPtr<nsIFile> parentDir; > nsAutoCString dirPath; > if (NS_FAILED(GetParent(getter_AddRefs(parentDir)))) > return NS_ERROR_FAILURE; > if (NS_FAILED(parentDir->GetNativePath(dirPath))) > return NS_ERROR_FAILURE; > >- if (giovfs) >- return giovfs->ShowURIForInput(dirPath); >- else >- return gnomevfs->ShowURIForInput(dirPath); >+ url = dirPath; > } >+ >+ if(nsKDEUtils::kdeSupport()) { >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING("REVEAL") ); >+ command.AppendElement( mPath ); >+ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; >+ } >+ >+ nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); >+ nsCOMPtr<nsIGnomeVFSService> gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID); >+ if (!giovfs && !gnomevfs) >+ return NS_ERROR_FAILURE; >+ >+ if (giovfs) >+ return giovfs->ShowURIForInput(url); >+ else >+ return gnomevfs->ShowURIForInput(url); >+ > #elif defined(MOZ_WIDGET_COCOA) > CFURLRef url; > if (NS_SUCCEEDED(GetCFURL(&url))) { > nsresult rv = CocoaFileUtils::RevealFileInFinder(url); > ::CFRelease(url); > return rv; > } > return NS_ERROR_FAILURE; >@@ -1816,16 +1824,23 @@ nsLocalFile::Launch() > > if (nullptr == connection) > return NS_ERROR_FAILURE; > > if (hildon_mime_open_file(connection, mPath.get()) != kHILDON_SUCCESS) > return NS_ERROR_FAILURE; > return NS_OK; > #else >+ if( nsKDEUtils::kdeSupport()) { >+ nsTArray<nsCString> command; >+ command.AppendElement( NS_LITERAL_CSTRING("OPEN") ); >+ command.AppendElement( mPath ); >+ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; >+ } >+ > nsCOMPtr<nsIGIOService> giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); > nsCOMPtr<nsIGnomeVFSService> gnomevfs = do_GetService(NS_GNOMEVFSSERVICE_CONTRACTID); > if (giovfs) { > return giovfs->ShowURIForInput(mPath); > } else if (gnomevfs) { > /* GnomeVFS fallback */ > return gnomevfs->ShowURIForInput(mPath); > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 493722
:
364982
|
364984
| 364986 |
364988
|
364992