Restore winxp

This commit is contained in:
Fedor 2019-03-12 19:33:28 +03:00
parent 277045c132
commit 3e27fff9b4
83 changed files with 2661 additions and 418 deletions

View File

@ -4,6 +4,7 @@
ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
ac_add_options --enable-jemalloc
ac_add_options --enable-require-all-d3dc-versions
if [ -f /c/builds/gapi.data ]; then
_gapi_keyfile=c:/builds/gapi.data

View File

@ -6,6 +6,7 @@ ac_add_options --enable-debug
ac_add_options --enable-dmd
ac_add_options --enable-profiling # needed for --enable-dmd to work on Windows
ac_add_options --enable-verify-mar
ac_add_options --enable-require-all-d3dc-versions
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1

View File

@ -57,6 +57,9 @@ DEFINES += -DMOZ_ANGLE_RENDERER=$(MOZ_ANGLE_RENDERER)
ifdef MOZ_D3DCOMPILER_VISTA_DLL
DEFINES += -DMOZ_D3DCOMPILER_VISTA_DLL=$(MOZ_D3DCOMPILER_VISTA_DLL)
endif
ifdef MOZ_D3DCOMPILER_XP_DLL
DEFINES += -DMOZ_D3DCOMPILER_XP_DLL=$(MOZ_D3DCOMPILER_XP_DLL)
endif
endif
DEFINES += -DMOZ_CHILD_PROCESS_NAME=$(MOZ_CHILD_PROCESS_NAME)

View File

@ -574,6 +574,10 @@
#ifdef MOZ_D3DCOMPILER_VISTA_DLL
@BINPATH@/@MOZ_D3DCOMPILER_VISTA_DLL@
#endif
#ifdef MOZ_D3DCOMPILER_XP_DLL
@BINPATH@/@MOZ_D3DCOMPILER_XP_DLL@
#endif
#endif # MOZ_ANGLE_RENDERER
; [Browser Chrome Files]

View File

@ -43,10 +43,10 @@
#ifdef HAVE_64BIT_BUILD
!define HAVE_64BIT_BUILD
!define ARCH "x64"
!define MinSupportedVer "Microsoft Windows 7 x64"
!define MinSupportedVer "Microsoft Windows XP x64"
#else
!define ARCH "x86"
!define MinSupportedVer "Microsoft Windows 7"
!define MinSupportedVer "Microsoft Windows XP"
#endif
!define MinSupportedCPU "SSE2"

View File

@ -1043,7 +1043,7 @@ Function .onInit
System::Call "kernel32::IsProcessorFeaturePresent(i 10)i .R7"
; Windows NT 6.0 and lower are not supported on any architecture.
${Unless} ${AtLeastWin7}
${Unless} ${AtLeastWinXP}
${If} "$R7" == "0"
strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_CPU_MSG)"
${Else}

View File

@ -33,12 +33,6 @@ NSDISTMODE = copy
include $(topsrcdir)/config/config.mk
ifeq ($(OS_ARCH),WINNT)
# Rebuild firefox.exe if the manifest changes - it's included by splash.rc.
# (this dependency should really be just for firefox.exe, not other targets)
EXTRA_DEPS += $(PROGRAM).manifest
endif
PROGRAMS_DEST = $(DIST)/bin
include $(topsrcdir)/config/rules.mk

View File

@ -6,8 +6,6 @@
#include <windows.h>
#include "nsNativeAppSupportWin.h"
1 24 "palemoon.exe.manifest"
IDI_APPICON ICON FIREFOX_ICO
IDI_DOCUMENT ICON DOCUMENT_ICO
IDI_APPLICATION ICON FIREFOX_ICO

View File

@ -186,6 +186,10 @@
#ifdef MOZ_D3DCOMPILER_VISTA_DLL
@BINPATH@/@MOZ_D3DCOMPILER_VISTA_DLL@
#endif
#ifdef MOZ_D3DCOMPILER_XP_DLL
@BINPATH@/@MOZ_D3DCOMPILER_XP_DLL@
#endif
#endif # MOZ_ANGLE_RENDERER
; [Browser Chrome Files]

View File

@ -43,10 +43,10 @@
#ifdef HAVE_64BIT_BUILD
!define HAVE_64BIT_BUILD
!define ARCH "x64"
!define MinSupportedVer "Microsoft Windows 7 x64"
!define MinSupportedVer "Microsoft Windows XP x64"
#else
!define ARCH "x86"
!define MinSupportedVer "Microsoft Windows 7"
!define MinSupportedVer "Microsoft Windows XP"
#endif
!define MinSupportedCPU "SSE2"

View File

@ -1043,7 +1043,7 @@ Function .onInit
System::Call "kernel32::IsProcessorFeaturePresent(i 10)i .R7"
; Windows NT 6.0 and lower are not supported on any architecture.
${Unless} ${AtLeastWin7}
${Unless} ${AtLeastWinXP}
${If} "$R7" == "0"
strCpy $R7 "$(WARN_MIN_SUPPORTED_OSVER_CPU_MSG)"
${Else}

View File

@ -219,6 +219,7 @@ def old_configure_options(*options):
'--enable-readline',
'--enable-reflow-perf',
'--enable-release',
'--enable-require-all-d3dc-versions',
'--enable-safe-browsing',
'--enable-sandbox',
'--enable-signmar',

View File

@ -194,9 +194,9 @@ def valid_ucrt_sdk_dir(windows_sdk_dir, windows_sdk_dir_env):
# contain the Universal CRT SDK. When the main SDK is 8.1, there
# is, however, supposed to be a reduced install of the SDK 10
# with the UCRT.
if version != 'include':
sdks[d] = Version(version), sdk
continue
#if version != 'include':
sdks[d] = Version(version), sdk
continue
if d == windows_sdk_dir_env:
# When WINDOWSSDKDIR is set in the environment and we can't find the
# Universal CRT SDK, chances are this is a start-shell-msvc*.bat

View File

@ -576,9 +576,16 @@ DecoderDoctorDocumentWatcher::SynthesizeAnalysis()
// going through expected decoders from most to least desirable.
#if defined(XP_WIN)
if (!formatsRequiringWMF.IsEmpty()) {
DD_INFO("DecoderDoctorDocumentWatcher[%p, doc=%p]::SynthesizeAnalysis() - unplayable formats: %s -> Cannot play media because WMF was not found",
this, mDocument, NS_ConvertUTF16toUTF8(formatsRequiringWMF).get());
ReportAnalysis(mDocument, sMediaWMFNeeded, false, formatsRequiringWMF);
if (IsVistaOrLater()) {
DD_INFO("DecoderDoctorDocumentWatcher[%p, doc=%p]::SynthesizeAnalysis() - unplayable formats: %s -> Cannot play media because WMF was not found",
this, mDocument, NS_ConvertUTF16toUTF8(formatsRequiringWMF).get());
ReportAnalysis(mDocument, sMediaWMFNeeded, false, formatsRequiringWMF);
} else {
DD_INFO("DecoderDoctorDocumentWatcher[%p, doc=%p]::SynthesizeAnalysis() - unplayable formats: %s -> Cannot play media before Windows Vista",
this, mDocument, NS_ConvertUTF16toUTF8(formatsRequiringWMF).get());
ReportAnalysis(mDocument, sMediaUnsupportedBeforeWindowsVista,
false, formatsRequiringWMF);
}
return;
}
#endif

View File

@ -1841,18 +1841,20 @@ MediaManager::GetNonE10sParent()
MediaManager::StartupInit()
{
#ifdef WIN32
// Bug 1107702 - Some Windows versions fail in GetAdaptersInfo (and others)
// if the first(?) call occurs after the process size is over 2GB (kb/2588507).
// Attempt to 'prime' the pump by making a call at startup.
unsigned long out_buf_len = sizeof(IP_ADAPTER_INFO);
PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *) moz_xmalloc(out_buf_len);
if (GetAdaptersInfo(pAdapterInfo, &out_buf_len) == ERROR_BUFFER_OVERFLOW) {
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *) moz_xmalloc(out_buf_len);
GetAdaptersInfo(pAdapterInfo, &out_buf_len);
}
if (pAdapterInfo) {
free(pAdapterInfo);
if (IsVistaOrLater() && !IsWin8OrLater()) {
// Bug 1107702 - Older Windows fail in GetAdaptersInfo (and others) if the
// first(?) call occurs after the process size is over 2GB (kb/2588507).
// Attempt to 'prime' the pump by making a call at startup.
unsigned long out_buf_len = sizeof(IP_ADAPTER_INFO);
PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *) moz_xmalloc(out_buf_len);
if (GetAdaptersInfo(pAdapterInfo, &out_buf_len) == ERROR_BUFFER_OVERFLOW) {
free(pAdapterInfo);
pAdapterInfo = (IP_ADAPTER_INFO *) moz_xmalloc(out_buf_len);
GetAdaptersInfo(pAdapterInfo, &out_buf_len);
}
if (pAdapterInfo) {
free(pAdapterInfo);
}
}
#endif
}
@ -2078,11 +2080,19 @@ MediaManager::GetUserMedia(nsPIDOMWindowInner* aWindow,
case MediaSourceEnum::Application:
case MediaSourceEnum::Window:
// Deny screensharing request if support is disabled, or
// the requesting document is not from a host on the whitelist
// the requesting document is not from a host on the whitelist, or
// we're on WinXP until proved that it works
if (!Preferences::GetBool(((videoType == MediaSourceEnum::Browser)?
"media.getusermedia.browser.enabled" :
"media.getusermedia.screensharing.enabled"),
false) ||
#if defined(XP_WIN)
(
// Allow tab sharing for all platforms including XP
(videoType != MediaSourceEnum::Browser) &&
!Preferences::GetBool("media.getusermedia.screensharing.allow_on_old_platforms",
false) && !IsVistaOrLater()) ||
#endif
(!privileged && !HostIsHttps(*docURI))) {
RefPtr<MediaStreamError> error =
new MediaStreamError(aWindow,

View File

@ -140,12 +140,26 @@ MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem,
aOutMessage = NS_LITERAL_CSTRING("Adobe EME disabled");
return MediaKeySystemStatus::Cdm_disabled;
}
#ifdef XP_WIN
// Win Vista and later only.
if (!IsVistaOrLater()) {
aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Adobe EME");
return MediaKeySystemStatus::Cdm_not_supported;
}
#endif
return EnsureCDMInstalled(aKeySystem, aOutMessage);
}
}
if (IsWidevineKeySystem(aKeySystem)) {
if (Preferences::GetBool("media.gmp-widevinecdm.visible", false)) {
#ifdef XP_WIN
// Win Vista and later only.
if (!IsVistaOrLater()) {
aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Widevine EME");
return MediaKeySystemStatus::Cdm_not_supported;
}
#endif
if (!Preferences::GetBool("media.gmp-widevinecdm.enabled", false)) {
aOutMessage = NS_LITERAL_CSTRING("Widevine EME disabled");
return MediaKeySystemStatus::Cdm_disabled;

View File

@ -1521,6 +1521,11 @@ TEST(GeckoMediaPlugins, GMPPluginVoucher) {
#if defined(XP_WIN)
TEST(GeckoMediaPlugins, GMPOutputProtection) {
// Output Protection is not available pre-Vista.
if (!IsVistaOrLater()) {
return;
}
RefPtr<GMPStorageTest> runner = new GMPStorageTest();
runner->DoTest(&GMPStorageTest::TestOutputProtection);
}

View File

@ -44,6 +44,10 @@
#include "MP4Decoder.h"
#include "mozilla/dom/RemoteVideoDecoder.h"
#ifdef XP_WIN
#include "mozilla/WindowsVersion.h"
#endif
#include "mp4_demuxer/H264.h"
namespace mozilla {
@ -360,7 +364,16 @@ PDMFactory::CreatePDMs()
}
#endif
#ifdef XP_WIN
if (MediaPrefs::PDMWMFEnabled()) {
if (MediaPrefs::PDMWMFEnabled() && IsVistaOrLater() && !IsWin7AndPre2000Compatible()) {
// *Only* use WMF on Vista and later, as if Firefox is run in Windows 95
// compatibility mode on Windows 7 (it does happen!) we may crash trying
// to startup WMF. So we need to detect the OS version here, as in
// compatibility mode IsVistaOrLater() and friends behave as if we're on
// the emulated version of Windows. See bug 1279171.
// Additionally, we don't want to start the RemoteDecoderModule if we
// expect it's not going to work (i.e. on Windows older than Vista).
// IsWin7AndPre2000Compatible() uses GetVersionEx as the user specified OS version can
// be reflected when compatibility mode is in effect.
m = new WMFDecoderModule();
RefPtr<PlatformDecoderModule> remote = new dom::RemoteDecoderModule(m);
StartupPDM(remote);

View File

@ -7,6 +7,18 @@
#ifndef WMF_H_
#define WMF_H_
#if WINVER < _WIN32_WINNT_WIN7
#error \
You must include WMF.h before including mozilla headers, \
otherwise mozconfig.h will be included \
and that sets WINVER to WinXP, \
which makes Windows Media Foundation unavailable.
#endif
#pragma push_macro("WINVER")
#undef WINVER
#define WINVER _WIN32_WINNT_WIN7
#include <windows.h>
#include <mfapi.h>
#include <mfidl.h>
@ -23,7 +35,7 @@
#include <codecapi.h>
// The Windows headers helpfully declare min and max macros, which don't
// compile in the presence of std::min and std::max and unified builds.
// compile in the prescence of std::min and std::max and unified builds.
// So undef them here.
#ifdef min
#undef min
@ -85,4 +97,8 @@ HRESULT MFCreateDXGISurfaceBuffer(REFIID riid,
} // end namespace wmf
} // end namespace mozilla
#pragma pop_macro("WINVER")
#endif

View File

@ -205,17 +205,31 @@ LoadDLLs()
HRESULT
MFStartup()
{
if (!IsVistaOrLater() || IsWin7AndPre2000Compatible()) {
// *Only* use WMF on Vista and later, as if Firefox is run in Windows 95
// compatibility mode on Windows 7 (it does happen!) we may crash trying
// to startup WMF. So we need to detect the OS version here, as in
// compatibility mode IsVistaOrLater() and friends behave as if we're on
// the emulated version of Windows. See bug 1279171.
// Using GetVersionEx API which takes compatibility mode into account.
return E_FAIL;
}
HRESULT hr = LoadDLLs();
if (FAILED(hr)) {
return hr;
}
const int MF_VISTA_VERSION = (0x0001 << 16 | MF_API_VERSION);
const int MF_WIN7_VERSION = (0x0002 << 16 | MF_API_VERSION);
// decltype is unusable for functions having default parameters
DECL_FUNCTION_PTR(MFStartup, ULONG, DWORD);
ENSURE_FUNCTION_PTR_(MFStartup, Mfplat.dll)
return MFStartupPtr(MF_WIN7_VERSION, MFSTARTUP_FULL);
if (!IsWin7OrLater())
return MFStartupPtr(MF_VISTA_VERSION, MFSTARTUP_FULL);
else
return MFStartupPtr(MF_WIN7_VERSION, MFSTARTUP_FULL);
}
HRESULT

View File

@ -268,7 +268,11 @@ MediaEngineWebRTC::EnumerateVideoDevices(dom::MediaSourceEnum aMediaSource,
bool
MediaEngineWebRTC::SupportsDuplex()
{
#ifndef XP_WIN
return mFullDuplex;
#else
return IsVistaOrLater() && mFullDuplex;
#endif
}
void

View File

@ -110,10 +110,12 @@ ScaledFontDWrite::ScaledFontDWrite(IDWriteFontFace *aFontFace, Float aSize,
, mUseEmbeddedBitmap(aUseEmbeddedBitmap)
, mForceGDIMode(aForceGDIMode)
{
#ifdef USE_SKIA
mStyle = SkFontStyle(aStyle->weight,
DWriteFontStretchFromStretch(aStyle->stretch),
aStyle->style == NS_FONT_STYLE_NORMAL ?
SkFontStyle::kUpright_Slant : SkFontStyle::kItalic_Slant);
#endif
}
already_AddRefed<Path>

View File

@ -9,6 +9,10 @@ ifdef MOZ_D3DCOMPILER_VISTA_DLL_PATH
cp -fp "$(MOZ_D3DCOMPILER_VISTA_DLL_PATH)" "$(DIST)/bin"
endif
ifdef MOZ_D3DCOMPILER_XP_CAB
expand '$(MOZ_D3DCOMPILER_XP_CAB)' -F:$(MOZ_D3DCOMPILER_XP_DLL) '$(DIST)/bin'
endif
endif
include $(topsrcdir)/config/rules.mk

View File

@ -138,6 +138,9 @@ if CONFIG['GNU_CXX']:
'-Wno-shadow-local',
]
if CONFIG['MOZ_DIRECTX_SDK_PATH'] and not CONFIG['MOZ_HAS_WINSDK_WITH_D3D']:
LOCAL_INCLUDES += ['%' + '%s/include/' % CONFIG['MOZ_DIRECTX_SDK_PATH']]
DEFINES['_CRT_SECURE_NO_DEPRECATE'] = True
DEFINES['_HAS_EXCEPTIONS'] = 0

View File

@ -36,7 +36,6 @@
* Carl D. Worth <cworth@cworth.org>
* Mathias Hasselmann <mathias.hasselmann@gmx.de>
* Behdad Esfahbod <behdad@behdad.org>
* Mark Straver <moonchild@palemoon.org>
*/
#ifndef CAIRO_MUTEX_IMPL_PRIVATE_H
@ -179,24 +178,24 @@
#elif defined(_WIN32) /******************************************************/
#define WIN32_LEAN_AND_MEAN
/* We require Windows 7 features */
#if !defined(WINVER) || (WINVER < 0x0601)
# define WINVER 0x0601
/* We require Windows 2000 features such as ETO_PDY */
#if !defined(WINVER) || (WINVER < 0x0500)
# define WINVER 0x0500
#endif
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0601)
# define _WIN32_WINNT 0x0601
#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0500)
# define _WIN32_WINNT 0x0500
#endif
# include <windows.h>
typedef SRWLOCK cairo_mutex_impl_t;
typedef CRITICAL_SECTION cairo_mutex_impl_t;
# define CAIRO_MUTEX_IMPL_WIN32 1
# define CAIRO_MUTEX_IMPL_LOCK(mutex) AcquireSRWLockExclusive (&(mutex))
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) ReleaseSRWLockExclusive (&(mutex))
# define CAIRO_MUTEX_IMPL_INIT(mutex) InitializeSRWLock (&(mutex))
# define CAIRO_MUTEX_IMPL_FINI(mutex) CAIRO_MUTEX_IMPL_NOOP
# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER SRWLOCK_INIT
# define CAIRO_MUTEX_IMPL_LOCK(mutex) EnterCriticalSection (&(mutex))
# define CAIRO_MUTEX_IMPL_UNLOCK(mutex) LeaveCriticalSection (&(mutex))
# define CAIRO_MUTEX_IMPL_INIT(mutex) InitializeCriticalSection (&(mutex))
# define CAIRO_MUTEX_IMPL_FINI(mutex) DeleteCriticalSection (&(mutex))
# define CAIRO_MUTEX_IMPL_NIL_INITIALIZER { NULL, 0, 0, NULL, NULL, 0 }
#elif defined __OS2__ /******************************************************/

View File

@ -150,6 +150,8 @@ FINAL_LIBRARY = 'xul'
if CONFIG['MOZ_D3DCOMPILER_VISTA_DLL']:
DEFINES['MOZ_D3DCOMPILER_VISTA_DLL'] = CONFIG['MOZ_D3DCOMPILER_VISTA_DLL']
if CONFIG['MOZ_D3DCOMPILER_XP_DLL']:
DEFINES['MOZ_D3DCOMPILER_XP_DLL'] = CONFIG['MOZ_D3DCOMPILER_XP_DLL']
CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
CXXFLAGS += CONFIG['TK_CFLAGS']

View File

@ -461,7 +461,8 @@ gfxGDIFont::FillLogFont(LOGFONTW& aLogFont, gfxFloat aSize,
weight = mNeedsBold ? 700 : fe->Weight();
}
fe->FillLogFont(&aLogFont, weight, aSize);
fe->FillLogFont(&aLogFont, weight, aSize,
(mAntialiasOption == kAntialiasSubpixel) ? true : false);
// If GDI synthetic italic is wanted, force the lfItalic field to true
if (aUseGDIFakeItalic) {

View File

@ -37,6 +37,11 @@ using namespace mozilla;
#define ROUND(x) floor((x) + 0.5)
#ifndef CLEARTYPE_QUALITY
#define CLEARTYPE_QUALITY 5
#endif
#define LOG_FONTLIST(args) MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \
LogLevel::Debug, args)
#define LOG_FONTLIST_ENABLED() MOZ_LOG_TEST( \
@ -217,7 +222,16 @@ GDIFontEntry::IsSymbolFont()
gfxFont *
GDIFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle, bool aNeedsBold)
{
return new gfxGDIFont(this, aFontStyle, aNeedsBold);
bool isXP = !IsVistaOrLater();
bool useClearType = isXP && !aFontStyle->systemFont &&
(gfxWindowsPlatform::GetPlatform()->UseClearTypeAlways() ||
(mIsDataUserFont &&
gfxWindowsPlatform::GetPlatform()->UseClearTypeForDownloadableFonts()));
return new gfxGDIFont(this, aFontStyle, aNeedsBold,
(useClearType ? gfxFont::kAntialiasSubpixel
: gfxFont::kAntialiasDefault));
}
nsresult
@ -249,7 +263,8 @@ GDIFontEntry::CopyFontTable(uint32_t aTableTag, nsTArray<uint8_t>& aBuffer)
void
GDIFontEntry::FillLogFont(LOGFONTW *aLogFont,
uint16_t aWeight, gfxFloat aSize)
uint16_t aWeight, gfxFloat aSize,
bool aUseCleartype)
{
memcpy(aLogFont, &mLogFont, sizeof(LOGFONTW));
@ -275,6 +290,8 @@ GDIFontEntry::FillLogFont(LOGFONTW *aLogFont,
if (mIsDataUserFont) {
aLogFont->lfItalic = 0;
}
aLogFont->lfQuality = (aUseCleartype ? CLEARTYPE_QUALITY : DEFAULT_QUALITY);
}
#define MISSING_GLYPH 0x1F // glyph index returned for missing characters
@ -860,8 +877,15 @@ gfxGDIFontList::MakePlatformFont(const nsAString& aFontName,
gfxWindowsFontType(isCFF ? GFX_FONT_TYPE_PS_OPENTYPE : GFX_FONT_TYPE_TRUETYPE) /*type*/,
aStyle, w, aStretch, winUserFontData, false);
if (fe) {
fe->mIsDataUserFont = true;
if (!fe)
return fe;
fe->mIsDataUserFont = true;
// Uniscribe doesn't place CFF fonts loaded privately
// via AddFontMemResourceEx on XP/Vista
if (isCFF && !IsWin7OrLater()) {
fe->mForceGDI = true;
}
return fe;

View File

@ -112,7 +112,8 @@ public:
virtual bool IsSymbolFont();
void FillLogFont(LOGFONTW *aLogFont, uint16_t aWeight, gfxFloat aSize);
void FillLogFont(LOGFONTW *aLogFont, uint16_t aWeight, gfxFloat aSize,
bool aUseCleartype);
static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics,
DWORD fontType)

View File

@ -145,6 +145,9 @@ public:
NS_IMPL_ISUPPORTS(GfxD2DVramReporter, nsIMemoryReporter)
#define GFX_USE_CLEARTYPE_ALWAYS "gfx.font_rendering.cleartype.always_use_for_content"
#define GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE "gfx.font_rendering.cleartype.use_for_downloadable_fonts"
#define GFX_CLEARTYPE_PARAMS "gfx.font_rendering.cleartype_params."
#define GFX_CLEARTYPE_PARAMS_GAMMA "gfx.font_rendering.cleartype_params.gamma"
#define GFX_CLEARTYPE_PARAMS_CONTRAST "gfx.font_rendering.cleartype_params.enhanced_contrast"
@ -190,6 +193,10 @@ public:
HMODULE gdi32Handle;
PFND3DKMTQS queryD3DKMTStatistics = nullptr;
// GPU memory reporting is not available before Windows 7
if (!IsWin7OrLater())
return NS_OK;
if ((gdi32Handle = LoadLibrary(TEXT("gdi32.dll"))))
queryD3DKMTStatistics = (PFND3DKMTQS)GetProcAddress(gdi32Handle, "D3DKMTQueryStatistics");
@ -312,6 +319,9 @@ NS_IMPL_ISUPPORTS(D3DSharedTexturesReporter, nsIMemoryReporter)
gfxWindowsPlatform::gfxWindowsPlatform()
: mRenderMode(RENDER_GDI)
{
mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
mUseClearTypeAlways = UNINITIALIZED_VALUE;
/*
* Initialize COM
*/
@ -391,6 +401,10 @@ gfxWindowsPlatform::CanUseHardwareVideoDecoding()
bool
gfxWindowsPlatform::InitDWriteSupport()
{
if (!IsVistaOrLater()) {
return false;
}
// DWrite is only supported on Windows 7 with the platform update and higher.
// We check this by seeing if D2D1 support is available.
if (!Factory::SupportsD2D1()) {
@ -972,6 +986,26 @@ gfxWindowsPlatform::GetPlatformCMSOutputProfile(void* &mem, size_t &mem_size)
#endif // _WIN32
}
bool
gfxWindowsPlatform::UseClearTypeForDownloadableFonts()
{
if (mUseClearTypeForDownloadableFonts == UNINITIALIZED_VALUE) {
mUseClearTypeForDownloadableFonts = Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE, true);
}
return mUseClearTypeForDownloadableFonts;
}
bool
gfxWindowsPlatform::UseClearTypeAlways()
{
if (mUseClearTypeAlways == UNINITIALIZED_VALUE) {
mUseClearTypeAlways = Preferences::GetBool(GFX_USE_CLEARTYPE_ALWAYS, false);
}
return mUseClearTypeAlways;
}
void
gfxWindowsPlatform::GetDLLVersion(char16ptr_t aDLLPath, nsAString& aVersion)
{
@ -1115,7 +1149,14 @@ gfxWindowsPlatform::FontsPrefsChanged(const char *aPref)
gfxPlatform::FontsPrefsChanged(aPref);
if (aPref && !strncmp(GFX_CLEARTYPE_PARAMS, aPref, strlen(GFX_CLEARTYPE_PARAMS))) {
if (!aPref) {
mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
mUseClearTypeAlways = UNINITIALIZED_VALUE;
} else if (!strcmp(GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE, aPref)) {
mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
} else if (!strcmp(GFX_USE_CLEARTYPE_ALWAYS, aPref)) {
mUseClearTypeAlways = UNINITIALIZED_VALUE;
} else if (!strncmp(GFX_CLEARTYPE_PARAMS, aPref, strlen(GFX_CLEARTYPE_PARAMS))) {
SetupClearTypeParams();
} else {
clearTextFontCaches = false;
@ -1363,13 +1404,17 @@ gfxWindowsPlatform::InitializeD3D9Config()
return;
}
d3d9.SetDefaultFromPref(
gfxPrefs::GetLayersAllowD3D9FallbackPrefName(),
true,
gfxPrefs::GetLayersAllowD3D9FallbackPrefDefault());
if (!IsVistaOrLater()) {
d3d9.EnableByDefault();
} else {
d3d9.SetDefaultFromPref(
gfxPrefs::GetLayersAllowD3D9FallbackPrefName(),
true,
gfxPrefs::GetLayersAllowD3D9FallbackPrefDefault());
if (!d3d9.IsEnabled() && gfxPrefs::LayersPreferD3D9()) {
d3d9.UserEnable("Direct3D9 enabled via layers.prefer-d3d9");
if (!d3d9.IsEnabled() && gfxPrefs::LayersPreferD3D9()) {
d3d9.UserEnable("Direct3D9 enabled via layers.prefer-d3d9");
}
}
nsCString message;
@ -1517,6 +1562,11 @@ gfxWindowsPlatform::InitializeD2DConfig()
NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_D3D11_COMP"));
return;
}
if (!IsVistaOrLater()) {
d2d1.DisableByDefault(FeatureStatus::Unavailable, "Direct2D is not available on Windows XP",
NS_LITERAL_CSTRING("FEATURE_FAILURE_D2D_XP"));
return;
}
d2d1.SetDefaultFromPref(
gfxPrefs::GetDirect2DDisabledPrefName(),
@ -1605,12 +1655,14 @@ gfxWindowsPlatform::InitGPUProcessSupport()
"Not using GPU Process since D3D11 is unavailable",
NS_LITERAL_CSTRING("FEATURE_FAILURE_NO_D3D11"));
} else if (!IsWin7SP1OrLater()) {
// On Windows 7 Pre-SP1, DXGI 1.2 is not available and remote presentation
// for D3D11 will not work. Rather than take a regression and use D3D9, we
// revert back to in-process rendering.
// For Windows XP, we simply don't care enough to support this
// configuration. On Windows Vista and 7 Pre-SP1, DXGI 1.2 is not
// available and remote presentation for D3D11 will not work. Rather
// than take a regression and use D3D9, we revert back to in-process
// rendering.
gpuProc.Disable(
FeatureStatus::Unavailable,
"Windows 7 Pre-SP1 cannot use the GPU process",
"Windows XP, Vista, and 7 Pre-SP1 cannot use the GPU process",
NS_LITERAL_CSTRING("FEATURE_FAILURE_OLD_WINDOWS"));
} else if (!IsWin8OrLater()) {
// Windows 7 SP1 can have DXGI 1.2 only via the Platform Update, so we
@ -1633,6 +1685,10 @@ gfxWindowsPlatform::InitGPUProcessSupport()
bool
gfxWindowsPlatform::DwmCompositionEnabled()
{
if (!IsVistaOrLater()) {
return false;
}
MOZ_ASSERT(WinUtils::dwmIsCompositionEnabledPtr);
BOOL dwmEnabled = false;

View File

@ -183,6 +183,11 @@ public:
mozilla::gfx::BackendType GetContentBackendFor(mozilla::layers::LayersBackend aLayers) override;
// ClearType is not always enabled even when available (e.g. Windows XP)
// if either of these prefs are enabled and apply, use ClearType rendering
bool UseClearTypeForDownloadableFonts();
bool UseClearTypeAlways();
static void GetDLLVersion(char16ptr_t aDLLPath, nsAString& aVersion);
// returns ClearType tuning information for each display
@ -239,6 +244,9 @@ protected:
protected:
RenderMode mRenderMode;
int8_t mUseClearTypeForDownloadableFonts;
int8_t mUseClearTypeAlways;
private:
void Init();
void InitAcceleration() override;

View File

@ -5,20 +5,45 @@
#include "Hal.h"
#include "HalImpl.h"
#include "nsITimer.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/battery/Constants.h"
#include "nsComponentManagerUtils.h"
#include <windows.h>
#include "mozilla/WindowsVersion.h"
using namespace mozilla::dom::battery;
namespace mozilla {
namespace hal_impl {
static nsCOMPtr<nsITimer> sUpdateTimer;
/* Power Event API is Vista or later */
static decltype(RegisterPowerSettingNotification)* sRegisterPowerSettingNotification = nullptr;
static decltype(UnregisterPowerSettingNotification)* sUnregisterPowerSettingNotification = nullptr;
static HPOWERNOTIFY sPowerHandle = nullptr;
static HPOWERNOTIFY sCapacityHandle = nullptr;
static HWND sHWnd = nullptr;
static void
UpdateHandler(nsITimer* aTimer, void* aClosure) {
NS_ASSERTION(!IsVistaOrLater(),
"We shouldn't call this function for Vista or later version!");
static hal::BatteryInformation sLastInfo;
hal::BatteryInformation currentInfo;
hal_impl::GetCurrentBatteryInformation(&currentInfo);
if (sLastInfo.level() != currentInfo.level() ||
sLastInfo.charging() != currentInfo.charging() ||
sLastInfo.remainingTime() != currentInfo.remainingTime()) {
hal::NotifyBatteryChange(currentInfo);
sLastInfo = currentInfo;
}
}
static
LRESULT CALLBACK
BatteryWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
@ -38,56 +63,94 @@ BatteryWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
void
EnableBatteryNotifications()
{
// Create custom window to watch battery event
// If we can get Gecko's window handle, this is unnecessary.
if (IsVistaOrLater()) {
// RegisterPowerSettingNotification is from Vista or later.
// Use this API if available.
HMODULE hUser32 = GetModuleHandleW(L"USER32.DLL");
if (!sRegisterPowerSettingNotification)
sRegisterPowerSettingNotification = (decltype(RegisterPowerSettingNotification)*)
GetProcAddress(hUser32, "RegisterPowerSettingNotification");
if (!sUnregisterPowerSettingNotification)
sUnregisterPowerSettingNotification = (decltype(UnregisterPowerSettingNotification)*)
GetProcAddress(hUser32, "UnregisterPowerSettingNotification");
if (sHWnd == nullptr) {
WNDCLASSW wc;
HMODULE hSelf = GetModuleHandle(nullptr);
if (!GetClassInfoW(hSelf, L"MozillaBatteryClass", &wc)) {
ZeroMemory(&wc, sizeof(WNDCLASSW));
wc.hInstance = hSelf;
wc.lpfnWndProc = BatteryWindowProc;
wc.lpszClassName = L"MozillaBatteryClass";
RegisterClassW(&wc);
if (!sRegisterPowerSettingNotification ||
!sUnregisterPowerSettingNotification) {
NS_ASSERTION(false, "Canot find PowerSettingNotification functions.");
return;
}
sHWnd = CreateWindowW(L"MozillaBatteryClass", L"Battery Watcher",
0, 0, 0, 0, 0,
nullptr, nullptr, hSelf, nullptr);
}
// Create custom window to watch battery event
// If we can get Gecko's window handle, this is unnecessary.
if (sHWnd == nullptr) {
return;
}
if (sHWnd == nullptr) {
WNDCLASSW wc;
HMODULE hSelf = GetModuleHandle(nullptr);
sPowerHandle =
RegisterPowerSettingNotification(sHWnd,
&GUID_ACDC_POWER_SOURCE,
DEVICE_NOTIFY_WINDOW_HANDLE);
sCapacityHandle =
RegisterPowerSettingNotification(sHWnd,
&GUID_BATTERY_PERCENTAGE_REMAINING,
DEVICE_NOTIFY_WINDOW_HANDLE);
if (!GetClassInfoW(hSelf, L"MozillaBatteryClass", &wc)) {
ZeroMemory(&wc, sizeof(WNDCLASSW));
wc.hInstance = hSelf;
wc.lpfnWndProc = BatteryWindowProc;
wc.lpszClassName = L"MozillaBatteryClass";
RegisterClassW(&wc);
}
sHWnd = CreateWindowW(L"MozillaBatteryClass", L"Battery Watcher",
0, 0, 0, 0, 0,
nullptr, nullptr, hSelf, nullptr);
}
if (sHWnd == nullptr) {
return;
}
sPowerHandle =
sRegisterPowerSettingNotification(sHWnd,
&GUID_ACDC_POWER_SOURCE,
DEVICE_NOTIFY_WINDOW_HANDLE);
sCapacityHandle =
sRegisterPowerSettingNotification(sHWnd,
&GUID_BATTERY_PERCENTAGE_REMAINING,
DEVICE_NOTIFY_WINDOW_HANDLE);
} else
{
// for Windows XP. If we remove Windows XP support,
// we should remove timer-based power notification
sUpdateTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
if (sUpdateTimer) {
sUpdateTimer->InitWithFuncCallback(UpdateHandler,
nullptr,
Preferences::GetInt("dom.battery.timer",
30000 /* 30s */),
nsITimer::TYPE_REPEATING_SLACK);
}
}
}
void
DisableBatteryNotifications()
{
if (sPowerHandle) {
UnregisterPowerSettingNotification(sPowerHandle);
sPowerHandle = nullptr;
}
if (IsVistaOrLater()) {
if (sPowerHandle) {
sUnregisterPowerSettingNotification(sPowerHandle);
sPowerHandle = nullptr;
}
if (sCapacityHandle) {
UnregisterPowerSettingNotification(sCapacityHandle);
sCapacityHandle = nullptr;
}
if (sCapacityHandle) {
sUnregisterPowerSettingNotification(sCapacityHandle);
sCapacityHandle = nullptr;
}
if (sHWnd) {
DestroyWindow(sHWnd);
sHWnd = nullptr;
if (sHWnd) {
DestroyWindow(sHWnd);
sHWnd = nullptr;
}
} else
{
if (sUpdateTimer) {
sUpdateTimer->Cancel();
sUpdateTimer = nullptr;
}
}
}

View File

@ -29,6 +29,11 @@
#include "nsContentSecurityManager.h"
#include "nsContentUtils.h"
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0600
// we need windows.h to read out registry information...
#include <windows.h>
#include <shellapi.h>
@ -411,27 +416,41 @@ nsIconChannel::GetStockHIcon(nsIMozIconURI* aIconURI,
{
nsresult rv = NS_OK;
uint32_t desiredImageSize;
aIconURI->GetImageSize(&desiredImageSize);
nsAutoCString stockIcon;
aIconURI->GetStockIcon(stockIcon);
// We can only do this on Vista or above
HMODULE hShellDLL = ::LoadLibraryW(L"shell32.dll");
decltype(SHGetStockIconInfo)* pSHGetStockIconInfo =
(decltype(SHGetStockIconInfo)*) ::GetProcAddress(hShellDLL,
"SHGetStockIconInfo");
SHSTOCKICONID stockIconID = GetStockIconIDForName(stockIcon);
if (stockIconID == SIID_INVALID) {
return NS_ERROR_NOT_AVAILABLE;
if (pSHGetStockIconInfo) {
uint32_t desiredImageSize;
aIconURI->GetImageSize(&desiredImageSize);
nsAutoCString stockIcon;
aIconURI->GetStockIcon(stockIcon);
SHSTOCKICONID stockIconID = GetStockIconIDForName(stockIcon);
if (stockIconID == SIID_INVALID) {
return NS_ERROR_NOT_AVAILABLE;
}
UINT infoFlags = SHGSI_ICON;
infoFlags |= GetSizeInfoFlag(desiredImageSize);
SHSTOCKICONINFO sii = {0};
sii.cbSize = sizeof(sii);
HRESULT hr = pSHGetStockIconInfo(stockIconID, infoFlags, &sii);
if (SUCCEEDED(hr)) {
*hIcon = sii.hIcon;
} else {
rv = NS_ERROR_FAILURE;
}
} else {
rv = NS_ERROR_NOT_AVAILABLE;
}
UINT infoFlags = SHGSI_ICON;
infoFlags |= GetSizeInfoFlag(desiredImageSize);
SHSTOCKICONINFO sii = {0};
sii.cbSize = sizeof(sii);
HRESULT hr = SHGetStockIconInfo(stockIconID, infoFlags, &sii);
if (SUCCEEDED(hr)) {
*hIcon = sii.hIcon;
} else {
rv = NS_ERROR_FAILURE;
if (hShellDLL) {
::FreeLibrary(hShellDLL);
}
return rv;

View File

@ -297,34 +297,43 @@ bool LaunchApp(const std::wstring& cmdline,
startup_info.wShowWindow = start_hidden ? SW_HIDE : SW_SHOW;
LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList = NULL;
// Don't even bother trying pre-Vista...
if (mozilla::IsVistaOrLater()) {
// setup our handle array first - if we end up with no handles that can
// be inherited we can avoid trying to do the ThreadAttributeList dance...
HANDLE handlesToInherit[2];
int handleCount = 0;
HANDLE stdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE stdErr = ::GetStdHandle(STD_ERROR_HANDLE);
// setup our handle array first - if we end up with no handles that can
// be inherited we can avoid trying to do the ThreadAttributeList dance...
HANDLE handlesToInherit[2];
int handleCount = 0;
HANDLE stdOut = ::GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE stdErr = ::GetStdHandle(STD_ERROR_HANDLE);
if (IsInheritableHandle(stdOut))
handlesToInherit[handleCount++] = stdOut;
if (stdErr != stdOut && IsInheritableHandle(stdErr))
handlesToInherit[handleCount++] = stdErr;
if (IsInheritableHandle(stdOut))
handlesToInherit[handleCount++] = stdOut;
if (stdErr != stdOut && IsInheritableHandle(stdErr))
handlesToInherit[handleCount++] = stdErr;
if (handleCount) {
lpAttributeList = CreateThreadAttributeList(handlesToInherit, handleCount);
if (lpAttributeList) {
// it's safe to inherit handles, so arrange for that...
startup_info.cb = sizeof(startup_info_ex);
startup_info.dwFlags |= STARTF_USESTDHANDLES;
startup_info.hStdOutput = stdOut;
startup_info.hStdError = stdErr;
startup_info.hStdInput = INVALID_HANDLE_VALUE;
startup_info_ex.lpAttributeList = lpAttributeList;
dwCreationFlags |= EXTENDED_STARTUPINFO_PRESENT;
bInheritHandles = TRUE;
if (handleCount) {
lpAttributeList = CreateThreadAttributeList(handlesToInherit, handleCount);
if (lpAttributeList) {
// it's safe to inherit handles, so arrange for that...
startup_info.cb = sizeof(startup_info_ex);
startup_info.dwFlags |= STARTF_USESTDHANDLES;
startup_info.hStdOutput = stdOut;
startup_info.hStdError = stdErr;
startup_info.hStdInput = INVALID_HANDLE_VALUE;
startup_info_ex.lpAttributeList = lpAttributeList;
dwCreationFlags |= EXTENDED_STARTUPINFO_PRESENT;
bInheritHandles = TRUE;
}
}
} else if (PR_GetEnv("MOZ_WIN_INHERIT_STD_HANDLES_PRE_VISTA")) {
// Even if we can't limit what gets inherited, we sometimes want to inherit
// stdout/err for testing purposes.
startup_info.dwFlags |= STARTF_USESTDHANDLES;
startup_info.hStdOutput = ::GetStdHandle(STD_OUTPUT_HANDLE);
startup_info.hStdError = ::GetStdHandle(STD_ERROR_HANDLE);
startup_info.hStdInput = INVALID_HANDLE_VALUE;
bInheritHandles = TRUE;
}
PROCESS_INFORMATION process_info;
BOOL createdOK = CreateProcess(NULL,
const_cast<wchar_t*>(cmdline.c_str()), NULL, NULL,

View File

@ -1034,7 +1034,7 @@ MessageChannel::WaitForSyncNotify(bool aHandleWindowsMessages)
MOZ_ASSERT(gUIThreadId, "InitUIThread was not called!");
#if defined(ACCESSIBILITY)
if (mFlags & REQUIRE_A11Y_REENTRY) {
if (IsVistaOrLater() && (mFlags & REQUIRE_A11Y_REENTRY)) {
MOZ_ASSERT(!(mFlags & REQUIRE_DEFERRED_MESSAGE_PROTECTION));
return WaitForSyncNotifyWithA11yReentry();
}

View File

@ -44,6 +44,13 @@ MainThreadRuntime::MainThreadRuntime()
return;
}
// Windows XP doesn't support setting of the COM exception policy, so we'll
// just stop here in that case.
if (!IsVistaOrLater()) {
mInitResult = S_OK;
return;
}
// We are required to initialize security in order to configure global options.
mInitResult = InitializeSecurity();
MOZ_ASSERT(SUCCEEDED(mInitResult));
@ -60,8 +67,11 @@ MainThreadRuntime::MainThreadRuntime()
return;
}
// Use the strictest policy available.
ULONG_PTR exceptionSetting = COMGLB_EXCEPTION_DONOT_HANDLE_ANY;
// Windows 7 has a policy that is even more strict. We should use that one
// whenever possible.
ULONG_PTR exceptionSetting = IsWin7OrLater() ?
COMGLB_EXCEPTION_DONOT_HANDLE_ANY :
COMGLB_EXCEPTION_DONOT_HANDLE;
mInitResult = globalOpts->Set(COMGLB_EXCEPTION_HANDLING, exceptionSetting);
MOZ_ASSERT(SUCCEEDED(mInitResult));
}

View File

@ -39,7 +39,7 @@ mozilla::Atomic<AutoEnterOOMUnsafeRegion*> AutoEnterOOMUnsafeRegion::owner_;
namespace oom {
JS_PUBLIC_DATA(uint32_t) targetThread = 0;
MOZ_THREAD_LOCAL(uint32_t) threadType;
JS_PUBLIC_DATA(MOZ_THREAD_LOCAL(uint32_t)) threadType;
JS_PUBLIC_DATA(uint64_t) maxAllocations = UINT64_MAX;
JS_PUBLIC_DATA(uint64_t) counter = 0;
JS_PUBLIC_DATA(bool) failAlways = true;

View File

@ -143,7 +143,7 @@ MOZ_TOOL_VARIABLES
dnl Special win32 checks
dnl ========================================================
WINVER=601
WINVER=502
case "$target" in
*-mingw*)
@ -206,6 +206,10 @@ case "$target" in
# -Zc:sizedDealloc- disables C++14 global sized deallocation (see bug 1160146)
CXXFLAGS="$CXXFLAGS -Zc:sizedDealloc-"
# Disable C++11 thread-safe statics due to crashes on XP (bug 1204752)
# See https://connect.microsoft.com/VisualStudio/feedback/details/1789709/visual-c-2015-runtime-broken-on-windows-server-2003-c-11-magic-statics
CXXFLAGS="$CXXFLAGS -Zc:threadSafeInit-"
;;
esac
AC_SUBST(MSVS_VERSION)
@ -717,7 +721,11 @@ case "$target" in
IMPORT_LIB_SUFFIX=lib
MKSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
MKCSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
WIN32_SUBSYSTEM_VERSION=6.01
dnl Set subsystem version.
WIN32_SUBSYSTEM_VERSION=5.01
if test "$CPU_ARCH" = "x86_64"; then
WIN32_SUBSYSTEM_VERSION=5.02
fi
WIN32_CONSOLE_EXE_LDFLAGS=-SUBSYSTEM:CONSOLE,$WIN32_SUBSYSTEM_VERSION
WIN32_GUI_EXE_LDFLAGS=-SUBSYSTEM:WINDOWS,$WIN32_SUBSYSTEM_VERSION
DSO_LDOPTS=-SUBSYSTEM:WINDOWS,$WIN32_SUBSYSTEM_VERSION

View File

@ -28,34 +28,342 @@
_InterlockedIncrement((volatile long*)(addend))
#endif
// Windows XP and Server 2003 don't support condition variables natively. The
// NativeImports class is responsible for detecting native support and
// retrieving the appropriate function pointers. It gets instantiated once,
// using a static initializer.
class ConditionVariableNativeImports
{
public:
ConditionVariableNativeImports() {
HMODULE kernel32_dll = GetModuleHandle("kernel32.dll");
MOZ_RELEASE_ASSERT(kernel32_dll != NULL);
#define LOAD_SYMBOL(symbol) loadSymbol(kernel32_dll, #symbol, symbol)
supported_ = LOAD_SYMBOL(InitializeConditionVariable) &&
LOAD_SYMBOL(WakeConditionVariable) &&
LOAD_SYMBOL(WakeAllConditionVariable) &&
LOAD_SYMBOL(SleepConditionVariableCS);
#undef LOAD_SYMBOL
}
inline bool supported() const {
return supported_;
}
void(WINAPI* InitializeConditionVariable)(CONDITION_VARIABLE* ConditionVariable);
void(WINAPI* WakeAllConditionVariable)(PCONDITION_VARIABLE ConditionVariable);
void(WINAPI* WakeConditionVariable)(CONDITION_VARIABLE* ConditionVariable);
BOOL(WINAPI* SleepConditionVariableCS)(CONDITION_VARIABLE* ConditionVariable,
CRITICAL_SECTION* CriticalSection,
DWORD dwMilliseconds);
private:
template <typename T>
inline bool loadSymbol(HMODULE module, const char* name, T& fn) {
FARPROC ptr = GetProcAddress(module, name);
if (!ptr)
return false;
fn = reinterpret_cast<T>(ptr);
return true;
}
bool supported_;
};
static ConditionVariableNativeImports sNativeImports;
// Wrapper for native condition variable APIs.
struct ConditionVariableNative
{
inline void initialize() {
sNativeImports.InitializeConditionVariable(&cv_);
}
inline void destroy() {
// Native condition variables don't require cleanup.
}
inline void notify_one() { sNativeImports.WakeConditionVariable(&cv_); }
inline void notify_all() { sNativeImports.WakeAllConditionVariable(&cv_); }
inline bool wait(CRITICAL_SECTION* cs, DWORD msec) {
return sNativeImports.SleepConditionVariableCS(&cv_, cs, msec);
}
private:
CONDITION_VARIABLE cv_;
};
// Fallback condition variable support for Windows XP and Server 2003. Given the
// difficulty of testing on these antiquated platforms and their rapidly
// diminishing market share, this implementation trades performance for
// predictable behavior.
struct ConditionVariableFallback
{
static const uint32_t WAKEUP_MODE_NONE = 0;
static const uint32_t WAKEUP_MODE_ONE = 0x40000000;
static const uint32_t WAKEUP_MODE_ALL = 0x80000000;
static const uint32_t WAKEUP_MODE_MASK = WAKEUP_MODE_ONE | WAKEUP_MODE_ALL;
static const uint32_t SLEEPERS_COUNT_MASK = ~WAKEUP_MODE_MASK;
void initialize()
{
// Initialize the state variable to 0 sleepers, no wakeup.
sleepersCountAndWakeupMode_ = 0 | WAKEUP_MODE_NONE;
// Create a semaphore that prevents threads from entering sleep,
// or waking other threads while a wakeup is ongoing.
sleepWakeupSemaphore_ = CreateSemaphoreW(NULL, 1, 1, NULL);
MOZ_RELEASE_ASSERT(sleepWakeupSemaphore_);
// Use an auto-reset event for waking up a single sleeper.
wakeOneEvent_ = CreateEventW(NULL, FALSE, FALSE, NULL);
MOZ_RELEASE_ASSERT(wakeOneEvent_);
// Use a manual-reset event for waking up all sleepers.
wakeAllEvent_ = CreateEventW(NULL, TRUE, FALSE, NULL);
MOZ_RELEASE_ASSERT(wakeAllEvent_);
}
void destroy()
{
BOOL r;
MOZ_RELEASE_ASSERT(sleepersCountAndWakeupMode_ == (0 | WAKEUP_MODE_NONE));
r = CloseHandle(sleepWakeupSemaphore_);
MOZ_RELEASE_ASSERT(r);
r = CloseHandle(wakeOneEvent_);
MOZ_RELEASE_ASSERT(r);
r = CloseHandle(wakeAllEvent_);
MOZ_RELEASE_ASSERT(r);
}
private:
void wakeup(uint32_t wakeupMode, HANDLE wakeEvent)
{
// Ensure that only one thread at a time can wake up others.
BOOL result = WaitForSingleObject(sleepWakeupSemaphore_, INFINITE);
MOZ_RELEASE_ASSERT(result == WAIT_OBJECT_0);
// Atomically set the wakeup mode and retrieve the number of sleepers.
uint32_t wcwm = InterlockedExchangeAdd(&sleepersCountAndWakeupMode_,
wakeupMode);
uint32_t sleepersCount = wcwm & SLEEPERS_COUNT_MASK;
MOZ_RELEASE_ASSERT((wcwm & WAKEUP_MODE_MASK) == WAKEUP_MODE_NONE);
if (sleepersCount > 0) {
// If there are any sleepers, set the wake event. The (last) woken
// up thread is responsible for releasing the semaphore.
BOOL success = SetEvent(wakeEvent);
MOZ_RELEASE_ASSERT(success);
} else {
// If there are no sleepers, set the wakeup mode back to 'none'
// and release the semaphore ourselves.
sleepersCountAndWakeupMode_ = 0 | WAKEUP_MODE_NONE;
BOOL success = ReleaseSemaphore(sleepWakeupSemaphore_, 1, NULL);
MOZ_RELEASE_ASSERT(success);
}
}
public:
void notify_one() { wakeup(WAKEUP_MODE_ONE, wakeOneEvent_); }
void notify_all() { wakeup(WAKEUP_MODE_ALL, wakeAllEvent_); }
bool wait(CRITICAL_SECTION* userLock, DWORD msec)
{
// Make sure that we can't enter sleep when there are other threads
// that still need to wake up on either of the wake events being set.
DWORD result = WaitForSingleObject(sleepWakeupSemaphore_, INFINITE);
MOZ_RELEASE_ASSERT(result == WAIT_OBJECT_0);
// Register ourselves as a sleeper. Use an atomic operation, because
// if another thread times out at the same time, it will decrement the
// sleepers count without acquiring the semaphore.
uint32_t wcwm = InterlockedIncrement(&sleepersCountAndWakeupMode_);
MOZ_RELEASE_ASSERT((wcwm & WAKEUP_MODE_MASK) == WAKEUP_MODE_NONE);
// Now that that this thread has been enlisted as a sleeper, it is safe
// again for other threads to do a wakeup.
BOOL success = ReleaseSemaphore(sleepWakeupSemaphore_, 1, NULL);
MOZ_RELEASE_ASSERT(success);
// Release the caller's mutex.
LeaveCriticalSection(userLock);
// Wait for either event to become signaled, which happens when
// notify_one() or notify_all() is called, or for a timeout.
HANDLE handles[2] = { wakeOneEvent_, wakeAllEvent_ };
DWORD waitResult = WaitForMultipleObjects(2, handles, FALSE, msec);
MOZ_RELEASE_ASSERT(waitResult == WAIT_OBJECT_0 ||
waitResult == WAIT_OBJECT_0 + 1 ||
(waitResult == WAIT_TIMEOUT && msec != INFINITE));
// Atomically decrease the sleepers count and retrieve the wakeup mode
// and new sleepers count.
// If the wait returned because wakeOneEvent_ was set, we are certain
// that the wakeup mode will be WAKEUP_MODE_ONE. In that case,
// atomically reset the wakeup mode to 'none', because if another
// thread's sleep times out at same time and it finds that it was the
// last sleeper, it decides whether or not to reset the wakeOneEvent_
// based on the current wakeup mode.
uint32_t sub;
if (waitResult == WAIT_OBJECT_0)
sub = 1 | WAKEUP_MODE_ONE;
else
sub = 1;
// Note that InterlockedExchangeAdd returns the old value, but it's
// easier to work with the new value.
wcwm = InterlockedExchangeAdd(&sleepersCountAndWakeupMode_, -sub) - sub;
uint32_t wakeupMode = wcwm & WAKEUP_MODE_MASK;
uint32_t sleepersCount = wcwm & SLEEPERS_COUNT_MASK;
bool releaseSleepWakeupSemaphore = false;
if (waitResult == WAIT_OBJECT_0) {
// The wake-one event is an auto-reset event so if we're woken by
// it, it should already have been reset. We also already removed
// the WAKEUP_MODE_ONE bit so the wakeup mode should now be 'none'
// again.
MOZ_RELEASE_ASSERT(wakeupMode == WAKEUP_MODE_NONE);
// The signaling thread has acquired the enter-wakeup semaphore and
// expects the woken (this) thread to release it again.
releaseSleepWakeupSemaphore = true;
} else if (waitResult == WAIT_TIMEOUT && wakeupMode == WAKEUP_MODE_ONE &&
sleepersCount == 0) {
// In theory a race condition is possible where the last sleeper
// times out right at the moment that another thread signals it.
// If that just happened we now have a dangling signal event and
// mode, but no threads to be woken up by it, and we need to clean
// that up.
BOOL success = ResetEvent(wakeOneEvent_);
MOZ_RELEASE_ASSERT(success);
// This is safe - we are certain there are no other sleepers that
// could wake up right now, and the semaphore ensures that no
// non-sleeping threads are messing with
// sleepersCountAndWakeupMode_.
sleepersCountAndWakeupMode_ = 0 | WAKEUP_MODE_NONE;
// The signaling thread has acquired the sleep-wakeup semaphore and
// expects the woken thread to release it. But since there are no
// sleeping threads left this thread will do it instead.
releaseSleepWakeupSemaphore = true;
} else if (wakeupMode == WAKEUP_MODE_ALL && sleepersCount == 0) {
// If this was the last thread waking up in response to a
// notify_all, clear the wakeup mode and reset the wake-all event.
// A race condition similar to the case described above could
// occur, so waitResult could be WAIT_TIMEOUT, but that doesn't
// matter for the actions that need to be taken.
MOZ_RELEASE_ASSERT(waitResult = WAIT_OBJECT_0 + 1 ||
waitResult == WAIT_TIMEOUT);
BOOL success = ResetEvent(wakeAllEvent_);
MOZ_RELEASE_ASSERT(success);
sleepersCountAndWakeupMode_ = 0 | WAKEUP_MODE_NONE;
// The broadcasting thread has acquired the enter-wakeup semaphore
// and expects the last thread that wakes up to release it.
releaseSleepWakeupSemaphore = true;
} else if ((waitResult == WAIT_TIMEOUT && msec != INFINITE) ||
(waitResult == WAIT_OBJECT_0 + 1 &&
wakeupMode == WAKEUP_MODE_ALL)) {
// Either:
// * The wait timed out but found no active notify_one or notify_all
// the moment it decreased the wait count.
// * A notify_all woke up this thread but there are more threads
// that need to be woken up by the wake-all event.
// These are ordinary conditions in which we don't have to do
// anything.
} else {
MOZ_CRASH("invalid wakeup condition");
}
// Release the enter-wakeup semaphore if the wakeup condition requires
// us to do it.
if (releaseSleepWakeupSemaphore) {
BOOL success = ReleaseSemaphore(sleepWakeupSemaphore_, 1, NULL);
MOZ_RELEASE_ASSERT(success);
}
// Reacquire the user mutex.
EnterCriticalSection(userLock);
// Return true if woken up, false when timed out.
if (waitResult == WAIT_TIMEOUT) {
SetLastError(ERROR_TIMEOUT);
return false;
}
return true;
}
private:
uint32_t sleepersCountAndWakeupMode_;
HANDLE sleepWakeupSemaphore_;
HANDLE wakeOneEvent_;
HANDLE wakeAllEvent_;
};
struct js::ConditionVariable::PlatformData
{
CONDITION_VARIABLE cv_;
union
{
ConditionVariableNative native;
ConditionVariableFallback fallback;
};
};
js::ConditionVariable::ConditionVariable()
{
InitializeConditionVariable(&platformData()->cv_);
if (sNativeImports.supported())
platformData()->native.initialize();
else
platformData()->fallback.initialize();
}
void
js::ConditionVariable::notify_one()
{
WakeConditionVariable(&platformData()->cv_);
if (sNativeImports.supported())
platformData()->native.notify_one();
else
platformData()->fallback.notify_one();
}
void
js::ConditionVariable::notify_all()
{
WakeAllConditionVariable(&platformData()->cv_);
if (sNativeImports.supported())
platformData()->native.notify_all();
else
platformData()->fallback.notify_all();
}
void
js::ConditionVariable::wait(UniqueLock<Mutex>& lock)
{
SRWLOCK* srwlock = &lock.lock.platformData()->lock;
bool r = SleepConditionVariableSRW(&platformData()->cv_, srwlock, INFINITE, 0);
CRITICAL_SECTION* cs = &lock.lock.platformData()->criticalSection;
bool r;
if (sNativeImports.supported())
r = platformData()->native.wait(cs, INFINITE);
else
r = platformData()->fallback.wait(cs, INFINITE);
MOZ_RELEASE_ASSERT(r);
}
@ -70,7 +378,7 @@ js::CVStatus
js::ConditionVariable::wait_for(UniqueLock<Mutex>& lock,
const mozilla::TimeDuration& rel_time)
{
SRWLOCK* srwlock = &lock.lock.platformData()->lock;
CRITICAL_SECTION* cs = &lock.lock.platformData()->criticalSection;
// Note that DWORD is unsigned, so we have to be careful to clamp at 0.
// If rel_time is Forever, then ToMilliseconds is +inf, which evaluates as
@ -82,7 +390,11 @@ js::ConditionVariable::wait_for(UniqueLock<Mutex>& lock,
? INFINITE
: static_cast<DWORD>(msecd);
BOOL r = SleepConditionVariableSRW(&platformData()->cv_, srwlock, msec, 0);
BOOL r;
if (sNativeImports.supported())
r = platformData()->native.wait(cs, msec);
else
r = platformData()->fallback.wait(cs, msec);
if (r)
return CVStatus::NoTimeout;
MOZ_RELEASE_ASSERT(GetLastError() == ERROR_TIMEOUT);
@ -91,7 +403,10 @@ js::ConditionVariable::wait_for(UniqueLock<Mutex>& lock,
js::ConditionVariable::~ConditionVariable()
{
// Native condition variables don't require cleanup.
if (sNativeImports.supported())
platformData()->native.destroy();
else
platformData()->fallback.destroy();
}
inline js::ConditionVariable::PlatformData*

View File

@ -13,6 +13,35 @@
#include "threading/Mutex.h"
#include "threading/windows/MutexPlatformData.h"
namespace {
// We build with a toolkit that supports WinXP, so we have to probe
// for modern features at runtime. This is necessary because Vista and
// later automatically allocate and subsequently leak a debug info
// object for each critical section that we allocate unless we tell it
// not to. In order to tell it not to, we need the extra flags field
// provided by the Ex version of InitializeCriticalSection.
struct MutexNativeImports
{
using InitializeCriticalSectionExT = BOOL (WINAPI*)(CRITICAL_SECTION*, DWORD, DWORD);
InitializeCriticalSectionExT InitializeCriticalSectionEx;
MutexNativeImports() {
HMODULE kernel32_dll = GetModuleHandle("kernel32.dll");
MOZ_RELEASE_ASSERT(kernel32_dll != NULL);
InitializeCriticalSectionEx = reinterpret_cast<InitializeCriticalSectionExT>(
GetProcAddress(kernel32_dll, "InitializeCriticalSectionEx"));
}
bool hasInitializeCriticalSectionEx() const {
return InitializeCriticalSectionEx;
}
};
static MutexNativeImports NativeImports;
} // (anonymous namespace)
js::detail::MutexImpl::MutexImpl()
{
AutoEnterOOMUnsafeRegion oom;
@ -20,7 +49,18 @@ js::detail::MutexImpl::MutexImpl()
if (!platformData_)
oom.crash("js::Mutex::Mutex");
InitializeSRWLock(&platformData()->lock);
// This number was adopted from NSPR.
const static DWORD LockSpinCount = 1500;
BOOL r;
if (NativeImports.hasInitializeCriticalSectionEx()) {
r = NativeImports.InitializeCriticalSectionEx(&platformData()->criticalSection,
LockSpinCount,
CRITICAL_SECTION_NO_DEBUG_INFO);
} else {
r = InitializeCriticalSectionAndSpinCount(&platformData()->criticalSection,
LockSpinCount);
}
MOZ_RELEASE_ASSERT(r);
}
js::detail::MutexImpl::~MutexImpl()
@ -28,17 +68,18 @@ js::detail::MutexImpl::~MutexImpl()
if (!platformData_)
return;
DeleteCriticalSection(&platformData()->criticalSection);
js_delete(platformData());
}
void
js::detail::MutexImpl::lock()
{
AcquireSRWLockExclusive(&platformData()->lock);
EnterCriticalSection(&platformData()->criticalSection);
}
void
js::detail::MutexImpl::unlock()
{
ReleaseSRWLockExclusive(&platformData()->lock);
LeaveCriticalSection(&platformData()->criticalSection);
}

View File

@ -13,7 +13,7 @@
struct js::detail::MutexImpl::PlatformData
{
SRWLOCK lock;
CRITICAL_SECTION criticalSection;
};
#endif // platform_win_MutexPlatformData_h

View File

@ -70,6 +70,8 @@ struct OperatingSystemVersionInfo {
// Os version identities used in the -moz-os-version media query.
const OperatingSystemVersionInfo osVersionStrings[] = {
{ LookAndFeel::eOperatingSystemVersion_WindowsXP, L"windows-xp" },
{ LookAndFeel::eOperatingSystemVersion_WindowsVista, L"windows-vista" },
{ LookAndFeel::eOperatingSystemVersion_Windows7, L"windows-win7" },
{ LookAndFeel::eOperatingSystemVersion_Windows8, L"windows-win8" },
{ LookAndFeel::eOperatingSystemVersion_Windows10, L"windows-win10" }

View File

@ -204,6 +204,9 @@
#ifdef MOZ_MEMORY_WINDOWS
/* Some defines from the CRT internal headers that we need here. */
#define _CRT_SPINCOUNT 5000
#define __crtInitCritSecAndSpinCount InitializeCriticalSectionAndSpinCount
#include <io.h>
#include <windows.h>
#include <intrin.h>
@ -592,8 +595,8 @@ void *_mmap(void *addr, size_t length, int prot, int flags,
* issues in some cases.
*/
#if defined(MOZ_MEMORY_WINDOWS)
#define malloc_mutex_t SRWLOCK
#define malloc_spinlock_t SRWLOCK
#define malloc_mutex_t CRITICAL_SECTION
#define malloc_spinlock_t CRITICAL_SECTION
#elif defined(MOZ_MEMORY_DARWIN)
typedef struct {
OSSpinLock lock;
@ -1558,7 +1561,8 @@ static bool
malloc_mutex_init(malloc_mutex_t *mutex)
{
#if defined(MOZ_MEMORY_WINDOWS)
InitializeSRWLock(mutex);
if (! __crtInitCritSecAndSpinCount(mutex, _CRT_SPINCOUNT))
return (true);
#elif defined(MOZ_MEMORY_DARWIN)
mutex->lock = OS_SPINLOCK_INIT;
#elif defined(MOZ_MEMORY_LINUX) && !defined(MOZ_MEMORY_ANDROID)
@ -1587,7 +1591,7 @@ malloc_mutex_lock(malloc_mutex_t *mutex)
{
#if defined(MOZ_MEMORY_WINDOWS)
AcquireSRWLockExclusive(mutex);
EnterCriticalSection(mutex);
#elif defined(MOZ_MEMORY_DARWIN)
OSSpinLockLock(&mutex->lock);
#elif defined(MOZ_MEMORY)
@ -1602,7 +1606,7 @@ malloc_mutex_unlock(malloc_mutex_t *mutex)
{
#if defined(MOZ_MEMORY_WINDOWS)
ReleaseSRWLockExclusive(mutex);
LeaveCriticalSection(mutex);
#elif defined(MOZ_MEMORY_DARWIN)
OSSpinLockUnlock(&mutex->lock);
#elif defined(MOZ_MEMORY)
@ -1619,7 +1623,8 @@ static bool
malloc_spin_init(malloc_spinlock_t *lock)
{
#if defined(MOZ_MEMORY_WINDOWS)
InitializeSRWLock(lock);
if (! __crtInitCritSecAndSpinCount(lock, _CRT_SPINCOUNT))
return (true);
#elif defined(MOZ_MEMORY_DARWIN)
lock->lock = OS_SPINLOCK_INIT;
#elif defined(MOZ_MEMORY_LINUX) && !defined(MOZ_MEMORY_ANDROID)
@ -1646,7 +1651,7 @@ malloc_spin_lock(malloc_spinlock_t *lock)
{
#if defined(MOZ_MEMORY_WINDOWS)
AcquireSRWLockExclusive(lock);
EnterCriticalSection(lock);
#elif defined(MOZ_MEMORY_DARWIN)
OSSpinLockLock(&lock->lock);
#elif defined(MOZ_MEMORY)
@ -1660,7 +1665,7 @@ static inline void
malloc_spin_unlock(malloc_spinlock_t *lock)
{
#if defined(MOZ_MEMORY_WINDOWS)
ReleaseSRWLockExclusive(lock);
LeaveCriticalSection(lock);
#elif defined(MOZ_MEMORY_DARWIN)
OSSpinLockUnlock(&lock->lock);
#elif defined(MOZ_MEMORY)

View File

@ -9,7 +9,20 @@
#ifndef mozilla_ThreadLocal_h
#define mozilla_ThreadLocal_h
#if !defined(XP_WIN)
#if defined(XP_WIN)
// This file will get included in any file that wants to add a profiler mark.
// In order to not bring <windows.h> together we could include windef.h and
// winbase.h which are sufficient to get the prototypes for the Tls* functions.
// # include <windef.h>
// # include <winbase.h>
// Unfortunately, even including these headers causes us to add a bunch of ugly
// stuff to our namespace e.g #define CreateEvent CreateEventW
extern "C" {
__declspec(dllimport) void* __stdcall TlsGetValue(unsigned long);
__declspec(dllimport) int __stdcall TlsSetValue(unsigned long, void*);
__declspec(dllimport) unsigned long __stdcall TlsAlloc();
}
#else
# include <pthread.h>
# include <signal.h>
#endif
@ -31,7 +44,7 @@ typedef sig_atomic_t sig_safe_t;
namespace detail {
#if defined(HAVE_THREAD_TLS_KEYWORD) || defined(XP_WIN) || defined(XP_MACOSX)
#if defined(HAVE_THREAD_TLS_KEYWORD)
#define MOZ_HAS_THREAD_LOCAL
#endif
@ -78,7 +91,11 @@ template<typename T>
class ThreadLocal
{
#ifndef MOZ_HAS_THREAD_LOCAL
#if defined(XP_WIN)
typedef unsigned long key_t;
#else
typedef pthread_key_t key_t;
#endif
// Integral types narrower than void* must be extended to avoid
// warnings from valgrind on some platforms. This helper type
@ -144,7 +161,12 @@ ThreadLocal<T>::init()
return true;
#else
if (!initialized()) {
#ifdef XP_WIN
mKey = TlsAlloc();
mInited = mKey != 0xFFFFFFFFUL; // TLS_OUT_OF_INDEXES
#else
mInited = !pthread_key_create(&mKey, nullptr);
#endif
}
return mInited;
#endif
@ -159,7 +181,11 @@ ThreadLocal<T>::get() const
#else
MOZ_ASSERT(initialized());
void* h;
#ifdef XP_WIN
h = TlsGetValue(mKey);
#else
h = pthread_getspecific(mKey);
#endif
return static_cast<T>(reinterpret_cast<typename Helper<T>::Type>(h));
#endif
}
@ -173,7 +199,11 @@ ThreadLocal<T>::set(const T aValue)
#else
MOZ_ASSERT(initialized());
void* h = reinterpret_cast<void*>(static_cast<typename Helper<T>::Type>(aValue));
#ifdef XP_WIN
bool succeeded = TlsSetValue(mKey, h);
#else
bool succeeded = !pthread_setspecific(mKey, h);
#endif
if (!succeeded) {
MOZ_CRASH();
}
@ -181,11 +211,7 @@ ThreadLocal<T>::set(const T aValue)
}
#ifdef MOZ_HAS_THREAD_LOCAL
#if defined(XP_WIN) || defined(XP_MACOSX)
#define MOZ_THREAD_LOCAL(TYPE) thread_local mozilla::detail::ThreadLocal<TYPE>
#else
#define MOZ_THREAD_LOCAL(TYPE) __thread mozilla::detail::ThreadLocal<TYPE>
#endif
#else
#define MOZ_THREAD_LOCAL(TYPE) mozilla::detail::ThreadLocal<TYPE>
#endif

View File

@ -156,6 +156,41 @@ IsNotWin7PreRTM()
IsWindowsBuildOrLater(7600);
}
MOZ_ALWAYS_INLINE bool
IsWin7AndPre2000Compatible() {
/*
* See Bug 1279171.
* We'd like to avoid using WMF on specific OS version when compatibility
* mode is in effect. The purpose of this function is to check if FF runs on
* Win7 OS with application compatibility mode being set to 95/98/ME.
* Those compatibility mode options (95/98/ME) can only display and
* be selected for 32-bit application.
* If the compatibility mode is in effect, the GetVersionEx function will
* report the OS as it identifies itself, which may not be the OS that is
* installed.
* Note : 1) We only target for Win7 build number greater than 7600.
* 2) GetVersionEx may be altered or unavailable for release after
* Win8.1. Set pragma to avoid build warning as error.
*/
bool isWin7 = IsNotWin7PreRTM() && !IsWin8OrLater();
if (!isWin7) {
return false;
}
OSVERSIONINFOEX info;
ZeroMemory(&info, sizeof(OSVERSIONINFOEX));
info.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
#pragma warning(push)
#pragma warning(disable:4996)
bool success = GetVersionEx((LPOSVERSIONINFO) &info);
#pragma warning(pop)
if (!success) {
return false;
}
return info.dwMajorVersion < 5;
}
} // namespace mozilla
#endif /* mozilla_WindowsVersion_h */

View File

@ -156,8 +156,41 @@ static CRITICAL_SECTION sTimeStampLock;
// Kept in [mt]
static ULONGLONG sFaultIntoleranceCheckpoint = 0;
// Used only when GetTickCount64 is not available on the platform.
// Last result of GetTickCount call.
//
// Kept in [ms]
static DWORD sLastGTCResult = 0;
// Higher part of the 64-bit value of MozGetTickCount64,
// incremented atomically.
static DWORD sLastGTCRollover = 0;
namespace mozilla {
typedef ULONGLONG (WINAPI* GetTickCount64_t)();
static GetTickCount64_t sGetTickCount64 = nullptr;
// Function protecting GetTickCount result from rolling over,
// result is in [ms]
static ULONGLONG WINAPI
MozGetTickCount64()
{
DWORD GTC = ::GetTickCount();
// Cheaper then CMPXCHG8B
AutoCriticalSection lock(&sTimeStampLock);
// Pull the rollover counter forward only if new value of GTC goes way
// down under the last saved result
if ((sLastGTCResult > GTC) && ((sLastGTCResult - GTC) > (1UL << 30))) {
++sLastGTCRollover;
}
sLastGTCResult = GTC;
return ULONGLONG(sLastGTCRollover) << 32 | sLastGTCResult;
}
// Result is in [mt]
static inline ULONGLONG
PerformanceCounter()
@ -322,7 +355,7 @@ TimeStampValue::CheckQPC(const TimeStampValue& aOther) const
if (duration < sHardFailureLimit) {
// Interval between the two time stamps is very short, consider
// QPC as unstable and record a failure.
uint64_t now = ms2mt(GetTickCount64());
uint64_t now = ms2mt(sGetTickCount64());
AutoCriticalSection lock(&sTimeStampLock);
@ -452,6 +485,16 @@ TimeStamp::Startup()
gInitialized = true;
HMODULE kernelDLL = GetModuleHandleW(L"kernel32.dll");
sGetTickCount64 = reinterpret_cast<GetTickCount64_t>(
GetProcAddress(kernelDLL, "GetTickCount64"));
if (!sGetTickCount64) {
// If the platform does not support the GetTickCount64 (Windows XP doesn't),
// then use our fallback implementation based on GetTickCount.
sGetTickCount64 = MozGetTickCount64;
}
InitializeCriticalSectionAndSpinCount(&sTimeStampLock, kLockSpinCount);
sHasStableTSC = HasStableTSC();
@ -490,7 +533,7 @@ TimeStamp::Now(bool aHighResolution)
// Both values are in [mt] units.
ULONGLONG QPC = useQPC ? PerformanceCounter() : uint64_t(0);
ULONGLONG GTC = ms2mt(GetTickCount64());
ULONGLONG GTC = ms2mt(sGetTickCount64());
return TimeStamp(TimeStampValue(GTC, QPC, useQPC));
}

View File

@ -161,7 +161,7 @@ dnl ========================================================
dnl Special win32 checks
dnl ========================================================
WINVER=601
WINVER=502
case "$target" in
*-mingw*)
@ -215,6 +215,10 @@ case "$target" in
# -Zc:sizedDealloc- disables C++14 global sized deallocation (see bug 1160146)
CXXFLAGS="$CXXFLAGS -Zc:sizedDealloc-"
# Disable C++11 thread-safe statics due to crashes on XP (bug 1204752)
# See https://connect.microsoft.com/VisualStudio/feedback/details/1789709/visual-c-2015-runtime-broken-on-windows-server-2003-c-11-magic-statics
CXXFLAGS="$CXXFLAGS -Zc:threadSafeInit-"
# C4752: We explicitly use AVX instructions in only some libs, not global
# This is a pointless "helpful warning" to use /arch:AVX which we don't want.
@ -947,7 +951,11 @@ case "$target" in
IMPORT_LIB_SUFFIX=lib
MKSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
MKCSHLIB='$(LD) -NOLOGO -DLL -OUT:$@ -PDB:$(LINK_PDBFILE) $(DSO_LDOPTS)'
WIN32_SUBSYSTEM_VERSION=6.01
dnl Set subsystem version.
WIN32_SUBSYSTEM_VERSION=5.01
if test "$CPU_ARCH" = "x86_64"; then
WIN32_SUBSYSTEM_VERSION=5.02
fi
WIN32_CONSOLE_EXE_LDFLAGS=-SUBSYSTEM:CONSOLE,$WIN32_SUBSYSTEM_VERSION
WIN32_GUI_EXE_LDFLAGS=-SUBSYSTEM:WINDOWS,$WIN32_SUBSYSTEM_VERSION
DSO_LDOPTS=-SUBSYSTEM:WINDOWS,$WIN32_SUBSYSTEM_VERSION
@ -3192,6 +3200,9 @@ MOZ_D3D_CPU_SUFFIX=
MOZ_HAS_WINSDK_WITH_D3D=
MOZ_D3DCOMPILER_VISTA_DLL=
MOZ_D3DCOMPILER_VISTA_DLL_PATH=
MOZ_DIRECTX_SDK_PATH=
MOZ_D3DCOMPILER_XP_DLL=
MOZ_D3DCOMPILER_XP_CAB=
if test "$COMPILE_ENVIRONMENT" ; then
case "$target_os" in
@ -3210,6 +3221,11 @@ x86_64)
;;
esac
MOZ_ARG_ENABLE_BOOL(require-all-d3dc-versions,
[ --enable-require-all-d3dc-versions Require all versions of the D3D compiler needed for supported Windows systems.],
MOZ_REQUIRE_ALL_D3DCS=1,
MOZ_REQUIRE_ALL_D3DCS=)
# This is potentially set in external mozconfig files; if it's set,
# then the build exposes the "webgl" context name, which is reserved
# for conformant implementations.
@ -3267,19 +3283,85 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
MOZ_CHECK_HEADER(d3d10.h, MOZ_HAS_WINSDK_WITH_D3D=1)
fi
######################################
# Find _43 for use by XP.
# Get the SDK path from the registry.
# First try to get the June 2010 SDK
MOZ_DIRECTX_SDK_REG_KEY=`reg query 'HKLM\Software\Microsoft\DirectX' //s | grep 'Microsoft DirectX SDK (June 2010)' | head -n 1`
if test -z "$MOZ_DIRECTX_SDK_REG_KEY" ; then
# Otherwise just take whatever comes first
MOZ_DIRECTX_SDK_REG_KEY=`reg query 'HKLM\Software\Microsoft\DirectX' //s | grep 'Microsoft DirectX SDK' | head -n 1`
fi
MOZ_DIRECTX_SDK_PATH=`reg query "$MOZ_DIRECTX_SDK_REG_KEY" //v InstallPath | grep REG_SZ | sed 's/.*\([[a-zA-Z]]\)\\:\\\\/\\1\\:\\\\/' | sed 's,\\\\,/,g'`
if test -n "$MOZ_DIRECTX_SDK_PATH" &&
test -f "$MOZ_DIRECTX_SDK_PATH"/lib/$MOZ_D3D_CPU_SUFFIX/dxguid.lib ; then
AC_MSG_RESULT([Found DirectX SDK via registry, using $MOZ_DIRECTX_SDK_PATH])
else
AC_MSG_RESULT([DirectX SDK not found.])
MOZ_DIRECTX_SDK_PATH=
fi
# Check that our DirectX SDK is acceptable.
if test -n "$MOZ_DIRECTX_SDK_PATH"; then
if test -n "`echo $MOZ_DIRECTX_SDK_REG_KEY | grep 'February 2010'`" ; then
AC_MSG_RESULT([Found the February 2010 DirectX SDK, which is unacceptable to ANGLE.])
MOZ_DIRECTX_SDK_PATH=
fi
fi
if test -n "$MOZ_DIRECTX_SDK_PATH"; then
# Find a D3D compiler DLL in the DirectX SDK, if we didn't find one already.
# Get the SDK numeric version (e.g. 43) by looking at the dependencies of d3dx9.lib
MOZ_D3DX9_VERSION=`dumpbin //headers "$MOZ_DIRECTX_SDK_PATH"/lib/$MOZ_D3D_CPU_SUFFIX/d3dx9.lib | egrep d3dx9_[[0-9]][[0-9]]\.dll | head -n1 | sed 's/.*\([[0-9]][[0-9]]\).*/\\1/g'`
if test -n "$MOZ_D3DX9_VERSION" ; then
MOZ_D3DCOMPILER_XP_CAB=`find "$MOZ_DIRECTX_SDK_PATH"/Redist -name *D3DCompiler_${MOZ_D3DX9_VERSION}_${MOZ_D3D_CPU_SUFFIX}.cab | head -n1`
if test -n "$MOZ_D3DCOMPILER_XP_CAB"; then
MOZ_D3DCOMPILER_XP_DLL=D3DCompiler_$MOZ_D3DX9_VERSION.dll
else
AC_MSG_RESULT([Couldn't find a CAB containing the D3D compiler DLL.])
AC_MSG_ERROR([DirectX SDK at "$MOZ_DIRECTX_SDK_PATH" appears broken.])
MOZ_DIRECTX_SDK_PATH=
fi
else
AC_MSG_RESULT([Couldn't determine the D3DX9 version for the DirectX SDK.])
MOZ_DIRECTX_SDK_PATH=
fi
else
AC_MSG_RESULT([Couldn't find an acceptable DirectX SDK for ANGLE, needed for d3dcompiler_43.])
fi
######################################
# Check that we found what we needed.
MOZ_FOUND_A_D3D_COMPILER=
MOZ_FOUND_BOTH_D3D_COMPILERS=1
if test -n "$MOZ_D3DCOMPILER_VISTA_DLL"; then
MOZ_FOUND_A_D3D_COMPILER=1
AC_MSG_RESULT([Found d3dcompiler DLL for Vista+: $MOZ_D3DCOMPILER_VISTA_DLL])
else
MOZ_FOUND_BOTH_D3D_COMPILERS=
fi
if test -n "$MOZ_D3DCOMPILER_XP_DLL"; then
MOZ_FOUND_A_D3D_COMPILER=1
AC_MSG_RESULT([Found d3dcompiler DLL for XP: $MOZ_D3DCOMPILER_XP_DLL])
else
MOZ_FOUND_BOTH_D3D_COMPILERS=
fi
if test -z "$CROSS_COMPILE"; then
if test -z "MOZ_FOUND_A_D3D_COMPILER"; then
AC_MSG_ERROR([Couldn't find an acceptable D3D compiler DLL.])
fi
if test -n "$MOZ_REQUIRE_ALL_D3DCS" -a -z "$MOZ_FOUND_BOTH_D3D_COMPILERS"; then
AC_MSG_ERROR([Both D3D compilers _43 and _46+ are required by --enable-require-d3d-compilers.])
AC_MSG_ERROR([ Install Windows SDK 8.0+, as well as DirectX SDK (June 2010 version or newer), or reconfigure without this flag.])
fi
fi
fi # MOZ_ANGLE_RENDERER
@ -5062,6 +5144,9 @@ AC_SUBST(MOZ_D3D_CPU_SUFFIX)
AC_SUBST(MOZ_HAS_WINSDK_WITH_D3D)
AC_SUBST(MOZ_D3DCOMPILER_VISTA_DLL)
AC_SUBST(MOZ_D3DCOMPILER_VISTA_DLL_PATH)
AC_SUBST(MOZ_DIRECTX_SDK_PATH)
AC_SUBST(MOZ_D3DCOMPILER_XP_DLL)
AC_SUBST(MOZ_D3DCOMPILER_XP_CAB)
AC_SUBST(MOZ_ANDROID_APPLICATION_CLASS)
AC_SUBST(MOZ_ANDROID_BROWSER_INTENT_CLASS)

View File

@ -21,10 +21,6 @@
#include "nsIFaviconService.h"
#endif // MOZ_PLACES
#ifdef XP_WIN
#include <shellapi.h>
#endif
using namespace mozilla;
using mozilla::dom::ContentChild;
@ -157,12 +153,23 @@ bool nsAlertsService::ShouldShowAlert()
bool result = true;
#ifdef XP_WIN
QUERY_USER_NOTIFICATION_STATE qstate;
if (SUCCEEDED(SHQueryUserNotificationState(&qstate))) {
if (qstate != QUNS_ACCEPTS_NOTIFICATIONS) {
result = false;
HMODULE shellDLL = ::LoadLibraryW(L"shell32.dll");
if (!shellDLL)
return result;
SHQueryUserNotificationStatePtr pSHQueryUserNotificationState =
(SHQueryUserNotificationStatePtr) ::GetProcAddress(shellDLL, "SHQueryUserNotificationState");
if (pSHQueryUserNotificationState) {
MOZ_QUERY_USER_NOTIFICATION_STATE qstate;
if (SUCCEEDED(pSHQueryUserNotificationState(&qstate))) {
if (qstate != QUNS_ACCEPTS_NOTIFICATIONS) {
result = false;
}
}
}
::FreeLibrary(shellDLL);
#endif
return result;

View File

@ -10,6 +10,23 @@
#include "nsCOMPtr.h"
#include "nsXULAlerts.h"
#ifdef XP_WIN
typedef enum tagMOZ_QUERY_USER_NOTIFICATION_STATE {
QUNS_NOT_PRESENT = 1,
QUNS_BUSY = 2,
QUNS_RUNNING_D3D_FULL_SCREEN = 3,
QUNS_PRESENTATION_MODE = 4,
QUNS_ACCEPTS_NOTIFICATIONS = 5,
QUNS_QUIET_TIME = 6,
QUNS_IMMERSIVE = 7
} MOZ_QUERY_USER_NOTIFICATION_STATE;
extern "C" {
// This function is Windows Vista or later
typedef HRESULT (__stdcall *SHQueryUserNotificationStatePtr)(MOZ_QUERY_USER_NOTIFICATION_STATE *pquns);
}
#endif // defined(XP_WIN)
class nsAlertsService : public nsIAlertsService,
public nsIAlertsDoNotDisturb
{

View File

@ -16,6 +16,26 @@ EXTRA_DEPS += symverscript
endif
endif
ifdef MOZ_WEBRTC
ifeq (WINNT,$(OS_TARGET))
ifndef MOZ_HAS_WINSDK_WITH_D3D
OS_LDFLAGS += \
-LIBPATH:'$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_D3D_CPU_SUFFIX)' \
$(NULL)
endif
endif
endif
ifdef MOZ_WEBRTC
ifeq (WINNT,$(OS_TARGET))
ifndef MOZ_HAS_WINSDK_WITH_D3D
OS_LDFLAGS += \
-LIBPATH:'$(MOZ_DIRECTX_SDK_PATH)/lib/$(MOZ_D3D_CPU_SUFFIX)' \
$(NULL)
endif
endif
endif
# Generate GDB pretty printer-autoload files only on Linux. OSX's GDB is
# too old to support Python pretty-printers; if this changes, we could make
# this 'ifdef GNU_CC'.

View File

@ -5108,7 +5108,7 @@
${EndIf}
; Windows NT 6.0 (Vista/Server 2008) and lower are not supported.
${Unless} ${AtLeastWin7}
${Unless} ${AtLeastWinXP}
MessageBox MB_OK|MB_ICONSTOP "$R9"
; Nothing initialized so no need to call OnEndCommon
Quit

View File

@ -351,7 +351,9 @@ popupnotificationcontent {
width: 20px;
}
@media (-moz-os-version: windows-win7) {
@media (-moz-os-version: windows-xp),
(-moz-os-version: windows-vista),
(-moz-os-version: windows-win7) {
.close-icon {
-moz-image-region: rect(0, 16px, 16px, 0);
}
@ -385,7 +387,9 @@ popupnotificationcontent {
-moz-image-region: rect(0, 120px, 40px, 80px);
}
@media (-moz-os-version: windows-win7) {
@media (-moz-os-version: windows-xp),
(-moz-os-version: windows-vista),
(-moz-os-version: windows-win7) {
.close-icon {
-moz-image-region: rect(0, 32px, 32px, 0);
}

View File

@ -99,6 +99,7 @@
#include <intrin.h>
#include <math.h>
#include "cairo/cairo-features.h"
#include "mozilla/WindowsVersion.h"
#include "mozilla/mscom/MainThreadRuntime.h"
#include "mozilla/widget/AudioSession.h"
@ -2823,7 +2824,10 @@ XREMain::XRE_mainInit(bool* aExitFlag)
// manual font file I/O on _all_ system fonts. To avoid this, load the
// dwrite library and create a factory as early as possible so that the
// FntCache service is ready by the time it's needed.
CreateThread(nullptr, 0, &InitDwriteBG, nullptr, 0, nullptr);
if (IsVistaOrLater()) {
CreateThread(nullptr, 0, &InitDwriteBG, nullptr, 0, nullptr);
}
}
#endif
@ -4211,7 +4215,7 @@ enum {
kE10sDisabledForAddons = 7,
kE10sForceDisabled = 8,
// kE10sDisabledForXPAcceleration = 9, removed in bug 1296353
// kE10sDisabledForOperatingSystem = 10, removed due to xp-eol
kE10sDisabledForOperatingSystem = 10,
};
const char* kAccessibilityLastRunDatePref = "accessibility.lastLoadDate";
@ -4247,6 +4251,18 @@ MultiprocessBlockPolicy() {
}
#if defined(XP_WIN)
/**
* Avoids enabling e10s for Windows XP users on the release channel.
*/
if (!IsVistaOrLater()) {
nsAdoptingCString channelName = Preferences::GetDefaultCString("app.update.channel");
if (channelName.EqualsLiteral("release") || channelName.EqualsLiteral("esr")) {
gMultiprocessBlockPolicy = kE10sDisabledForOperatingSystem;
return gMultiprocessBlockPolicy;
}
}
bool disabledForA11y = false;
/**
* Avoids enabling e10s if accessibility has recently loaded. Performs the

View File

@ -24,7 +24,6 @@
#ifdef XP_WIN
#include <process.h>
#include <shobjidl.h>
#include "mozilla/ipc/WindowsMessageLoop.h"
#endif
@ -108,6 +107,10 @@ using mozilla::startup::sChildProcessType;
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
#ifdef XP_WIN
static const wchar_t kShellLibraryName[] = L"shell32.dll";
#endif
nsresult
XRE_LockProfileDirectory(nsIFile* aDirectory,
nsISupports* *aLockObject)
@ -231,9 +234,26 @@ XRE_SetProcessType(const char* aProcessTypeString)
void
SetTaskbarGroupId(const nsString& aId)
{
if (FAILED(SetCurrentProcessExplicitAppUserModelID(aId.get()))) {
typedef HRESULT (WINAPI * SetCurrentProcessExplicitAppUserModelIDPtr)(PCWSTR AppID);
SetCurrentProcessExplicitAppUserModelIDPtr funcAppUserModelID = nullptr;
HMODULE hDLL = ::LoadLibraryW(kShellLibraryName);
funcAppUserModelID = (SetCurrentProcessExplicitAppUserModelIDPtr)
GetProcAddress(hDLL, "SetCurrentProcessExplicitAppUserModelID");
if (!funcAppUserModelID) {
::FreeLibrary(hDLL);
return;
}
if (FAILED(funcAppUserModelID(aId.get()))) {
NS_WARNING("SetCurrentProcessExplicitAppUserModelID failed for child process.");
}
if (hDLL)
::FreeLibrary(hDLL);
}
#endif

View File

@ -37,6 +37,10 @@
#include "gfxConfig.h"
#include "DriverCrashGuard.h"
#if defined(MOZ_CRASHREPORTER)
#include "nsExceptionHandler.h"
#endif
using namespace mozilla::widget;
using namespace mozilla;
using mozilla::MutexAutoLock;
@ -248,7 +252,13 @@ RemovePrefForDriverVersion()
static OperatingSystem
BlacklistOSToOperatingSystem(const nsAString& os)
{
if (os.EqualsLiteral("WINNT 6.1"))
if (os.EqualsLiteral("WINNT 5.1"))
return OperatingSystem::WindowsXP;
else if (os.EqualsLiteral("WINNT 5.2"))
return OperatingSystem::WindowsServer2003;
else if (os.EqualsLiteral("WINNT 6.0"))
return OperatingSystem::WindowsVista;
else if (os.EqualsLiteral("WINNT 6.1"))
return OperatingSystem::Windows7;
else if (os.EqualsLiteral("WINNT 6.2"))
return OperatingSystem::Windows8;

View File

@ -450,7 +450,9 @@ public:
* Operating system versions.
*/
enum OperatingSystemVersion {
eOperatingSystemVersion_Windows7 = 2,
eOperatingSystemVersion_WindowsXP = 0,
eOperatingSystemVersion_WindowsVista,
eOperatingSystemVersion_Windows7,
eOperatingSystemVersion_Windows8,
eOperatingSystemVersion_Windows10,
eOperatingSystemVersion_Unknown

View File

@ -235,6 +235,9 @@ ParseIDFromDeviceID(const nsAString &key, const char *prefix, int length)
// based on http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
enum {
kWindowsUnknown = 0,
kWindowsXP = 0x50001,
kWindowsServer2003 = 0x50002,
kWindowsVista = 0x60000,
kWindows7 = 0x60001,
kWindows8 = 0x60002,
kWindows8_1 = 0x60003,
@ -725,6 +728,12 @@ static OperatingSystem
WindowsVersionToOperatingSystem(int32_t aWindowsVersion)
{
switch(aWindowsVersion) {
case kWindowsXP:
return OperatingSystem::WindowsXP;
case kWindowsServer2003:
return OperatingSystem::WindowsServer2003;
case kWindowsVista:
return OperatingSystem::WindowsVista;
case kWindows7:
return OperatingSystem::Windows7;
case kWindows8:
@ -753,6 +762,11 @@ GfxInfo::GetGfxDriverInfo()
/*
* NVIDIA entries
*/
APPEND_TO_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP,
(nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
DRIVER_LESS_THAN_OR_EQUAL, V(6,14,11,8745), "FEATURE_FAILURE_NV_XP", "nVidia driver > 187.45" );
/*
* The last 5 digit of the NVIDIA driver version maps to the version that
* NVIDIA uses. The minor version (15, 16, 17) corresponds roughtly to the
@ -763,17 +777,33 @@ GfxInfo::GetGfxDriverInfo()
* 187.45 (late October 2009) and earlier contain a bug which can cause us
* to crash on shutdown.
*/
APPEND_TO_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista,
(nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
DRIVER_LESS_THAN_OR_EQUAL, V(8,15,11,8745),
"FEATURE_FAILURE_NV_VISTA_15", "nVidia driver > 187.45" );
APPEND_TO_DRIVER_BLOCKLIST(OperatingSystem::Windows7,
(nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
DRIVER_LESS_THAN_OR_EQUAL, V(8,15,11,8745),
"FEATURE_FAILURE_NV_W7_15", "nVidia driver > 187.45" );
APPEND_TO_DRIVER_BLOCKLIST_RANGE(OperatingSystem::WindowsVista,
(nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
DRIVER_BETWEEN_INCLUSIVE_START, V(8,16,10,0000), V(8,16,11,8745),
"FEATURE_FAILURE_NV_VISTA_16", "nVidia driver > 187.45" );
APPEND_TO_DRIVER_BLOCKLIST_RANGE(OperatingSystem::Windows7,
(nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
DRIVER_BETWEEN_INCLUSIVE_START, V(8,16,10,0000), V(8,16,11,8745),
"FEATURE_FAILURE_NV_W7_16", "nVidia driver > 187.45" );
// Telemetry doesn't show any driver in this range so it might not even be required.
APPEND_TO_DRIVER_BLOCKLIST_RANGE(OperatingSystem::WindowsVista,
(nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
DRIVER_BETWEEN_INCLUSIVE_START, V(8,17,10,0000), V(8,17,11,8745),
"FEATURE_FAILURE_NV_VISTA_17", "nVidia driver > 187.45" );
// Telemetry doesn't show any driver in this range so it might not even be required.
APPEND_TO_DRIVER_BLOCKLIST_RANGE(OperatingSystem::Windows7,
(nsAString&) GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), GfxDriverInfo::allDevices,
GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
@ -871,6 +901,13 @@ GfxInfo::GetGfxDriverInfo()
nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION, \
DRIVER_BUILD_ID_LESS_THAN, driverVer, ruleId )
IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::WindowsVista, IntelGMA500, 1006, "FEATURE_FAILURE_594877_1");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::WindowsVista, IntelGMA900, GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_594877_2");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::WindowsVista, IntelGMA950, 1504, "FEATURE_FAILURE_594877_3");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::WindowsVista, IntelGMA3150, 2124, "FEATURE_FAILURE_594877_4");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::WindowsVista, IntelGMAX3000, 1666, "FEATURE_FAILURE_594877_5");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::WindowsVista, IntelHDGraphicsToSandyBridge, 2202, "FEATURE_FAILURE_594877_6");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7, IntelGMA500, 2026, "FEATURE_FAILURE_594877_7");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7, IntelGMA900, GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_594877_8");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST_D2D(OperatingSystem::Windows7, IntelGMA950, 1930, "FEATURE_FAILURE_594877_9");
@ -887,6 +924,31 @@ GfxInfo::GetGfxDriverInfo()
nsIGfxInfo::FEATURE_DIRECT2D, nsIGfxInfo::FEATURE_BLOCKED_DEVICE,
DRIVER_LESS_THAN, GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_1180379");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMA500, V(3,0,20,3200), "FEATURE_FAILURE_INTEL_1");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMA900, V(6,14,10,4764), "FEATURE_FAILURE_INTEL_2");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMA950, V(6,14,10,4926), "FEATURE_FAILURE_INTEL_3");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMA3150, V(6,14,10,5134), "FEATURE_FAILURE_INTEL_4");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMAX3000, V(6,14,10,5218), "FEATURE_FAILURE_INTEL_5");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelGMAX4500HD, V(6,14,10,4969), "FEATURE_FAILURE_INTEL_6");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsXP, IntelHDGraphicsToSandyBridge, V(6,14,10,4969), "FEATURE_FAILURE_INTEL_7");
// StrechRect seems to suffer from precision issues which leads to artifacting
// during content drawing starting with at least version 6.14.10.5082
// and going until 6.14.10.5218. See bug 919454 and bug 949275 for more info.
APPEND_TO_DRIVER_BLOCKLIST_RANGE(OperatingSystem::WindowsXP,
const_cast<nsAString&>(GfxDriverInfo::GetDeviceVendor(VendorIntel)),
const_cast<GfxDeviceFamily*>(GfxDriverInfo::GetDeviceFamily(IntelGMAX4500HD)),
GfxDriverInfo::allFeatures, nsIGfxInfo::FEATURE_BLOCKED_DRIVER_VERSION,
DRIVER_BETWEEN_EXCLUSIVE, V(6,14,10,5076), V(6,14,10,5218), "FEATURE_FAILURE_INTEL_8", "6.14.10.5218");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista, IntelGMA500, V(3,0,20,3200), "FEATURE_FAILURE_INTEL_9");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista, IntelGMA900, GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_INTEL_10");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista, IntelGMA950, V(7,14,10,1504), "FEATURE_FAILURE_INTEL_11");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista, IntelGMA3150, V(7,14,10,1910), "FEATURE_FAILURE_INTEL_12");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista, IntelGMAX3000, V(7,15,10,1666), "FEATURE_FAILURE_INTEL_13");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista, IntelGMAX4500HD, V(7,15,10,1666), "FEATURE_FAILURE_INTEL_14");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::WindowsVista, IntelHDGraphicsToSandyBridge, V(7,15,10,1666), "FEATURE_FAILURE_INTEL_15");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::Windows7, IntelGMA500, V(5,0,0,2026), "FEATURE_FAILURE_INTEL_16");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::Windows7, IntelGMA900, GfxDriverInfo::allDriverVersions, "FEATURE_FAILURE_INTEL_17");
IMPLEMENT_INTEL_DRIVER_BLOCKLIST(OperatingSystem::Windows7, IntelGMA950, V(8,15,10,1930), "FEATURE_FAILURE_INTEL_18");
@ -1144,6 +1206,23 @@ GfxInfo::GetFeatureStatusImpl(int32_t aFeature,
return NS_OK;
}
// special-case the WinXP test slaves: they have out-of-date drivers, but we still want to
// whitelist them, actually we do know that this combination of device and driver version
// works well.
if (mWindowsVersion == kWindowsXP &&
adapterVendorID.Equals(GfxDriverInfo::GetDeviceVendor(VendorNVIDIA), nsCaseInsensitiveStringComparator()) &&
adapterDeviceID.LowerCaseEqualsLiteral("0x0861") && // GeForce 9400
driverVersion == V(6,14,11,7756))
{
*aStatus = FEATURE_STATUS_OK;
return NS_OK;
}
// Windows Server 2003 should be just like Windows XP for present purpose, but still has a different version number.
// OTOH Windows Server 2008 R1 and R2 already have the same version numbers as Vista and Seven respectively
if (os == OperatingSystem::WindowsServer2003)
os = OperatingSystem::WindowsXP;
if (mHasDriverVersionMismatch) {
*aStatus = nsIGfxInfo::FEATURE_BLOCKED_MISMATCHED_VERSION;
return NS_OK;

View File

@ -1360,6 +1360,34 @@ NativeKey::InitWithKeyChar()
break;
}
if (!CanComputeVirtualKeyCodeFromScanCode()) {
// The right control key and the right alt key are extended keys.
// Therefore, we never get VK_RCONTRL and VK_RMENU for the result of
// MapVirtualKeyEx() on WinXP or WinServer2003.
//
// If VK_SHIFT, VK_CONTROL or VK_MENU key message is caused by well
// known scan code, we should decide it as Right key. Otherwise,
// decide it as Left key.
switch (mOriginalVirtualKeyCode) {
case VK_CONTROL:
mVirtualKeyCode =
mIsExtended && mScanCode == 0x1D ? VK_RCONTROL : VK_LCONTROL;
break;
case VK_MENU:
mVirtualKeyCode =
mIsExtended && mScanCode == 0x38 ? VK_RMENU : VK_LMENU;
break;
case VK_SHIFT:
// Neither left shift nor right shift is an extended key,
// let's use VK_LSHIFT for unknown mapping.
mVirtualKeyCode = VK_LSHIFT;
break;
default:
MOZ_CRASH("Unsupported mOriginalVirtualKeyCode");
}
break;
}
NS_ASSERTION(!mVirtualKeyCode,
"mVirtualKeyCode has been computed already");
@ -1416,6 +1444,11 @@ NativeKey::InitWithKeyChar()
// scancode, we cannot compute virtual keycode. I.e., with such
// applications, we cannot generate proper KeyboardEvent.code value.
// We cannot compute the virtual key code from WM_CHAR message on WinXP
// if it's caused by an extended key.
if (!CanComputeVirtualKeyCodeFromScanCode()) {
break;
}
mVirtualKeyCode = mOriginalVirtualKeyCode =
ComputeVirtualKeyCodeFromScanCodeEx();
NS_ASSERTION(mVirtualKeyCode, "Failed to compute virtual keycode");
@ -1833,6 +1866,18 @@ NativeKey::GetKeyLocation() const
}
}
bool
NativeKey::CanComputeVirtualKeyCodeFromScanCode() const
{
// Vista or later supports ScanCodeEx.
if (IsVistaOrLater()) {
return true;
}
// Otherwise, MapVirtualKeyEx() can compute virtual keycode only with
// non-extended key.
return !mIsExtended;
}
uint8_t
NativeKey::ComputeVirtualKeyCodeFromScanCode() const
{
@ -1846,6 +1891,12 @@ NativeKey::ComputeVirtualKeyCodeFromScanCodeEx() const
// MapVirtualKeyEx() has been improved for supporting extended keys since
// Vista. When we call it for mapping a scancode of an extended key and
// a virtual keycode, we need to add 0xE000 to the scancode.
// On the other hand, neither WinXP nor WinServer2003 doesn't support 0xE000.
// Therefore, we have no way to get virtual keycode from scan code of
// extended keys.
if (NS_WARN_IF(!CanComputeVirtualKeyCodeFromScanCode())) {
return 0;
}
return static_cast<uint8_t>(
::MapVirtualKeyEx(GetScanCodeWithExtendedFlag(), MAPVK_VSC_TO_VK_EX,
mKeyboardLayout));
@ -1856,7 +1907,8 @@ NativeKey::ComputeScanCodeExFromVirtualKeyCode(UINT aVirtualKeyCode) const
{
return static_cast<uint16_t>(
::MapVirtualKeyEx(aVirtualKeyCode,
MAPVK_VK_TO_VSC_EX,
IsVistaOrLater() ? MAPVK_VK_TO_VSC_EX :
MAPVK_VK_TO_VSC,
mKeyboardLayout));
}
@ -4176,7 +4228,8 @@ KeyboardLayout::LoadLayout(HKL aLayout)
if (MOZ_LOG_TEST(sKeyboardLayoutLogger, LogLevel::Verbose)) {
static const UINT kExtendedScanCode[] = { 0x0000, 0xE000 };
static const UINT kMapType = MAPVK_VSC_TO_VK_EX;
static const UINT kMapType =
IsVistaOrLater() ? MAPVK_VSC_TO_VK_EX : MAPVK_VSC_TO_VK;
MOZ_LOG(sKeyboardLayoutLogger, LogLevel::Verbose,
("Logging virtual keycode values for scancode (0x%p)...",
mKeyboardLayout));
@ -4188,6 +4241,11 @@ KeyboardLayout::LoadLayout(HKL aLayout)
MOZ_LOG(sKeyboardLayoutLogger, LogLevel::Verbose,
("0x%04X, %s", scanCode, kVirtualKeyName[virtualKeyCode]));
}
// XP and Server 2003 don't support 0xE0 prefix of the scancode.
// Therefore, we don't need to continue on them.
if (!IsVistaOrLater()) {
break;
}
}
}
}

View File

@ -559,6 +559,11 @@ private:
*/
bool GetFollowingCharMessage(MSG& aCharMsg);
/**
* Whether the key event can compute virtual keycode from the scancode value.
*/
bool CanComputeVirtualKeyCodeFromScanCode() const;
/**
* Wraps MapVirtualKeyEx() with MAPVK_VSC_TO_VK.
*/

View File

@ -5764,7 +5764,8 @@ TSFTextStore::Initialize()
return;
}
bool enableTsf = Preferences::GetBool(kPrefNameEnableTSF, false);
bool enableTsf =
IsVistaOrLater() && Preferences::GetBool(kPrefNameEnableTSF, false);
MOZ_LOG(sTextStoreLog, LogLevel::Info,
(" TSFTextStore::Initialize(), TSF is %s",
enableTsf ? "enabled" : "disabled"));

View File

@ -28,9 +28,7 @@
#include "mozilla/Telemetry.h"
// Defined in dwmapi in a header that needs a higher numbered _WINNT #define
#ifndef DWM_SIT_DISPLAYFRAME
#define DWM_SIT_DISPLAYFRAME 0x1
#endif
namespace mozilla {
namespace widget {

View File

@ -992,7 +992,10 @@ MouseScrollHandler::SystemSettings::InitScrollChars()
&mScrollChars, 0)) {
MOZ_LOG(gMouseScrollLog, LogLevel::Info,
("MouseScroll::SystemSettings::InitScrollChars(): ::SystemParametersInfo("
"SPI_GETWHEELSCROLLCHARS) failed, this is unexpected on Vista or later"));
"SPI_GETWHEELSCROLLCHARS) failed, %s",
IsVistaOrLater() ?
"this is unexpected on Vista or later" :
"but on XP or earlier, this is not a problem"));
// XXX Should we use DefaultScrollChars()?
mScrollChars = 1;
}
@ -1078,7 +1081,7 @@ bool
MouseScrollHandler::SystemSettings::IsOverridingSystemScrollSpeedAllowed()
{
return mScrollLines == DefaultScrollLines() &&
mScrollChars == DefaultScrollChars();
(!IsVistaOrLater() || mScrollChars == DefaultScrollChars());
}
/******************************************************************************

View File

@ -34,6 +34,8 @@
#include <propkey.h>
#include <shellapi.h>
const wchar_t kShellLibraryName[] = L"shell32.dll";
static NS_DEFINE_CID(kJumpListBuilderCID, NS_WIN_JUMPLISTBUILDER_CID);
namespace {
@ -75,14 +77,30 @@ SetWindowAppUserModelProp(mozIDOMWindow *aParent,
if (!toplevelHWND)
return NS_ERROR_INVALID_ARG;
RefPtr<IPropertyStore> pPropStore;
if (FAILED(SHGetPropertyStoreForWindow(toplevelHWND, IID_IPropertyStore,
getter_AddRefs(pPropStore)))) {
typedef HRESULT (WINAPI * SHGetPropertyStoreForWindowPtr)
(HWND hwnd, REFIID riid, void** ppv);
SHGetPropertyStoreForWindowPtr funcGetProStore = nullptr;
HMODULE hDLL = ::LoadLibraryW(kShellLibraryName);
funcGetProStore = (SHGetPropertyStoreForWindowPtr)
GetProcAddress(hDLL, "SHGetPropertyStoreForWindow");
if (!funcGetProStore) {
FreeLibrary(hDLL);
return NS_ERROR_NO_INTERFACE;
}
IPropertyStore* pPropStore;
if (FAILED(funcGetProStore(toplevelHWND,
IID_PPV_ARGS(&pPropStore)))) {
FreeLibrary(hDLL);
return NS_ERROR_INVALID_ARG;
}
PROPVARIANT pv;
if (FAILED(InitPropVariantFromString(aIdentifier.get(), &pv))) {
pPropStore->Release();
FreeLibrary(hDLL);
return NS_ERROR_UNEXPECTED;
}
@ -93,6 +111,8 @@ SetWindowAppUserModelProp(mozIDOMWindow *aParent,
}
PropVariantClear(&pv);
pPropStore->Release();
FreeLibrary(hDLL);
return rv;
}
@ -319,18 +339,40 @@ WinTaskbar::GetDefaultGroupId(nsAString & aDefaultGroupId) {
// (static) Called from AppShell
bool
WinTaskbar::RegisterAppUserModelID() {
if (!IsWin7OrLater())
return false;
SetCurrentProcessExplicitAppUserModelIDPtr funcAppUserModelID = nullptr;
bool retVal = false;
nsAutoString uid;
if (!GetAppUserModelID(uid))
return false;
return SUCCEEDED(SetCurrentProcessExplicitAppUserModelID(uid.get()));
HMODULE hDLL = ::LoadLibraryW(kShellLibraryName);
funcAppUserModelID = (SetCurrentProcessExplicitAppUserModelIDPtr)
GetProcAddress(hDLL, "SetCurrentProcessExplicitAppUserModelID");
if (!funcAppUserModelID) {
::FreeLibrary(hDLL);
return false;
}
if (SUCCEEDED(funcAppUserModelID(uid.get())))
retVal = true;
if (hDLL)
::FreeLibrary(hDLL);
return retVal;
}
NS_IMETHODIMP
WinTaskbar::GetAvailable(bool *aAvailable) {
// ITaskbarList4::HrInit() may fail with shell extensions like blackbox
// installed. Initialize early to return available=false in those cases.
*aAvailable = Initialize();
*aAvailable = IsWin7OrLater() && Initialize();
return NS_OK;
}

View File

@ -462,7 +462,7 @@ static NtTestAlertPtr sNtTestAlert = nullptr;
void
WinUtils::Initialize()
{
if (!sDwmDll) {
if (!sDwmDll && IsVistaOrLater()) {
sDwmDll = ::LoadLibraryW(kDwmLibraryName);
if (sDwmDll) {
@ -601,7 +601,7 @@ WinUtils::SystemScaleFactor()
return systemScale;
}
#if WINVER < 0x603
#ifndef WM_DPICHANGED
typedef enum {
MDT_EFFECTIVE_DPI = 0,
MDT_ANGULAR_DPI = 1,
@ -628,14 +628,16 @@ GETPROCESSDPIAWARENESSPROC sGetProcessDpiAwareness;
static bool
SlowIsPerMonitorDPIAware()
{
// Intentionally leak the handle.
HMODULE shcore =
LoadLibraryEx(L"shcore", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (shcore) {
sGetDpiForMonitor =
(GETDPIFORMONITORPROC) GetProcAddress(shcore, "GetDpiForMonitor");
sGetProcessDpiAwareness =
(GETPROCESSDPIAWARENESSPROC) GetProcAddress(shcore, "GetProcessDpiAwareness");
if (IsVistaOrLater()) {
// Intentionally leak the handle.
HMODULE shcore =
LoadLibraryEx(L"shcore", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (shcore) {
sGetDpiForMonitor =
(GETDPIFORMONITORPROC) GetProcAddress(shcore, "GetDpiForMonitor");
sGetProcessDpiAwareness =
(GETPROCESSDPIAWARENESSPROC) GetProcAddress(shcore, "GetProcessDpiAwareness");
}
}
PROCESS_DPI_AWARENESS dpiAwareness;
return sGetDpiForMonitor && sGetProcessDpiAwareness &&
@ -758,7 +760,7 @@ static DWORD
GetWaitFlags()
{
DWORD result = MWMO_INPUTAVAILABLE;
if (XRE_IsContentProcess()) {
if (IsVistaOrLater() && XRE_IsContentProcess()) {
result |= MWMO_ALERTABLE;
}
return result;
@ -1138,8 +1140,7 @@ WinUtils::GetIsMouseFromTouch(EventMessage aEventMessage)
const uint32_t MOZ_T_I_SIGNATURE = TABLET_INK_TOUCH | TABLET_INK_SIGNATURE;
const uint32_t MOZ_T_I_CHECK_TCH = TABLET_INK_TOUCH | TABLET_INK_CHECK;
return ((aEventMessage == eMouseMove || aEventMessage == eMouseDown ||
aEventMessage == eMouseUp || aEventMessage == eMouseAuxClick ||
aEventMessage == eMouseDoubleClick) &&
aEventMessage == eMouseUp || aEventMessage == eMouseDoubleClick) &&
(GetMessageExtraInfo() & MOZ_T_I_SIGNATURE) == MOZ_T_I_CHECK_TCH);
}
@ -1877,7 +1878,7 @@ WinUtils::IsTouchDeviceSupportPresent()
uint32_t
WinUtils::GetMaxTouchPoints()
{
if (IsTouchDeviceSupportPresent()) {
if (IsWin7OrLater() && IsTouchDeviceSupportPresent()) {
return GetSystemMetrics(SM_MAXIMUMTOUCHES);
}
return 0;
@ -1892,6 +1893,11 @@ typedef DWORD (WINAPI * GetFinalPathNameByHandlePtr)(HANDLE hFile,
bool
WinUtils::ResolveJunctionPointsAndSymLinks(std::wstring& aPath)
{
// Users folder was introduced with Vista.
if (!IsVistaOrLater()) {
return true;
}
wchar_t path[MAX_PATH] = { 0 };
nsAutoHandle handle(
@ -2019,19 +2025,21 @@ WinUtils::GetAppInitDLLs(nsAString& aOutput)
}
nsAutoRegKey key(hkey);
LONG status;
const wchar_t kLoadAppInitDLLs[] = L"LoadAppInit_DLLs";
DWORD loadAppInitDLLs = 0;
DWORD loadAppInitDLLsLen = sizeof(loadAppInitDLLs);
status = RegQueryValueExW(hkey, kLoadAppInitDLLs, nullptr,
nullptr, (LPBYTE)&loadAppInitDLLs,
&loadAppInitDLLsLen);
if (status != ERROR_SUCCESS) {
return false;
}
if (!loadAppInitDLLs) {
// If loadAppInitDLLs is zero then AppInit_DLLs is disabled.
// In this case we'll return true along with an empty output string.
return true;
if (IsVistaOrLater()) {
const wchar_t kLoadAppInitDLLs[] = L"LoadAppInit_DLLs";
DWORD loadAppInitDLLs = 0;
DWORD loadAppInitDLLsLen = sizeof(loadAppInitDLLs);
status = RegQueryValueExW(hkey, kLoadAppInitDLLs, nullptr,
nullptr, (LPBYTE)&loadAppInitDLLs,
&loadAppInitDLLsLen);
if (status != ERROR_SUCCESS) {
return false;
}
if (!loadAppInitDLLs) {
// If loadAppInitDLLs is zero then AppInit_DLLs is disabled.
// In this case we'll return true along with an empty output string.
return true;
}
}
DWORD numBytes = 0;
const wchar_t kAppInitDLLs[] = L"AppInit_DLLs";

View File

@ -5,8 +5,7 @@
#include <windows.h>
#include <winsdkver.h>
#include <wrl.h>
#include "mozwrlbase.h"
#include "nsServiceManagerUtils.h"
#include "WindowsUIUtils.h"

View File

@ -0,0 +1,77 @@
/* -*- Mode: C++; tab-width: 4; 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/. */
#pragma once
/*
* Includes <wrl.h> and it's children. Defines imports needed by
* corewrappers.h in the case where windows.h has already been
* included w/WINVER < 0x600. Also ups WINVER/_WIN32_WINNT prior
* to including wrl.h. Mozilla's build currently has WINVER set to
* 0x502 for XP support.
*/
#if _WIN32_WINNT < 0x600
#include <windows.h>
VOID
WINAPI
ReleaseSRWLockExclusive(
_Inout_ PSRWLOCK SRWLock
);
VOID
WINAPI
ReleaseSRWLockShared(
_Inout_ PSRWLOCK SRWLock
);
BOOL
WINAPI
InitializeCriticalSectionEx(
_Out_ LPCRITICAL_SECTION lpCriticalSection,
_In_ DWORD dwSpinCount,
_In_ DWORD Flags
);
VOID
WINAPI
InitializeSRWLock(
_Out_ PSRWLOCK SRWLock
);
VOID
WINAPI
AcquireSRWLockExclusive(
_Inout_ PSRWLOCK SRWLock
);
BOOLEAN
WINAPI
TryAcquireSRWLockExclusive(
_Inout_ PSRWLOCK SRWLock
);
BOOLEAN
WINAPI
TryAcquireSRWLockShared(
_Inout_ PSRWLOCK SRWLock
);
VOID
WINAPI
AcquireSRWLockShared(
_Inout_ PSRWLOCK SRWLock
);
#undef WINVER
#undef _WIN32_WINNT
#define WINVER 0x600
#define _WIN32_WINNT 0x600
#endif // _WIN32_WINNT < 0x600
#include <wrl.h>

View File

@ -1261,7 +1261,8 @@ nsDataObj :: GetFileContentsInternetShortcut ( FORMATETC& aFE, STGMEDIUM& aSTG )
const char *shortcutFormatStr;
int totalLen;
nsCString path;
if (!Preferences::GetBool(kShellIconPref, true)) {
if (!Preferences::GetBool(kShellIconPref, true) ||
!IsVistaOrLater()) {
shortcutFormatStr = "[InternetShortcut]\r\nURL=%s\r\n";
const int formatLen = strlen(shortcutFormatStr) - 2; // don't include %s
totalLen = formatLen + asciiUrl.Length(); // don't include null character

View File

@ -28,6 +28,7 @@
#include "nsPIDOMWindow.h"
#include "GeckoProfiler.h"
using mozilla::IsVistaOrLater;
using mozilla::IsWin8OrLater;
using mozilla::MakeUnique;
using mozilla::mscom::EnsureMTA;
@ -218,6 +219,191 @@ STDMETHODIMP nsFilePicker::QueryInterface(REFIID refiid, void** ppvResult)
return E_NOINTERFACE;
}
/*
* XP picker callbacks
*/
// Show - Display the file dialog
int CALLBACK
BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
if (uMsg == BFFM_INITIALIZED)
{
char16_t * filePath = (char16_t *) lpData;
if (filePath)
::SendMessageW(hwnd, BFFM_SETSELECTIONW,
TRUE /* true because lpData is a path string */,
lpData);
}
return 0;
}
static void
EnsureWindowVisible(HWND hwnd)
{
// Obtain the monitor which has the largest area of intersection
// with the window, or nullptr if there is no intersection.
HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONULL);
if (!monitor) {
// The window is not visible, we should reposition it to the same place as its parent
HWND parentHwnd = GetParent(hwnd);
RECT parentRect;
GetWindowRect(parentHwnd, &parentRect);
SetWindowPos(hwnd, nullptr, parentRect.left, parentRect.top, 0, 0,
SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER);
}
}
// Callback hook which will ensure that the window is visible. Currently
// only in use on os <= XP.
UINT_PTR CALLBACK
nsFilePicker::FilePickerHook(HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
switch(msg) {
case WM_NOTIFY:
{
LPOFNOTIFYW lpofn = (LPOFNOTIFYW) lParam;
if (!lpofn || !lpofn->lpOFN) {
return 0;
}
if (CDN_INITDONE == lpofn->hdr.code) {
// The Window will be automatically moved to the last position after
// CDN_INITDONE. We post a message to ensure the window will be visible
// so it will be done after the automatic last position window move.
PostMessage(hwnd, MOZ_WM_ENSUREVISIBLE, 0, 0);
}
}
break;
case MOZ_WM_ENSUREVISIBLE:
EnsureWindowVisible(GetParent(hwnd));
break;
case WM_INITDIALOG:
{
OPENFILENAMEW* pofn = reinterpret_cast<OPENFILENAMEW*>(lParam);
SetProp(hwnd, kDialogPtrProp, (HANDLE)pofn->lCustData);
nsFilePicker* picker = reinterpret_cast<nsFilePicker*>(pofn->lCustData);
if (picker) {
picker->SetDialogHandle(hwnd);
SetTimer(hwnd, kDialogTimerID, kDialogTimerTimeout, nullptr);
}
}
break;
case WM_TIMER:
{
// Check to see if our parent has been torn down, if so, we close too.
if (wParam == kDialogTimerID) {
nsFilePicker* picker =
reinterpret_cast<nsFilePicker*>(GetProp(hwnd, kDialogPtrProp));
if (picker && picker->ClosePickerIfNeeded(true)) {
KillTimer(hwnd, kDialogTimerID);
}
}
}
break;
}
return 0;
}
// Callback hook which will dynamically allocate a buffer large enough
// for the file picker dialog. Currently only in use on os <= XP.
UINT_PTR CALLBACK
nsFilePicker::MultiFilePickerHook(HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam)
{
switch (msg) {
case WM_INITDIALOG:
{
// Finds the child drop down of a File Picker dialog and sets the
// maximum amount of text it can hold when typed in manually.
// A wParam of 0 mean 0x7FFFFFFE characters.
HWND comboBox = FindWindowEx(GetParent(hwnd), nullptr,
L"ComboBoxEx32", nullptr );
if(comboBox)
SendMessage(comboBox, CB_LIMITTEXT, 0, 0);
// Store our nsFilePicker ptr for future use
OPENFILENAMEW* pofn = reinterpret_cast<OPENFILENAMEW*>(lParam);
SetProp(hwnd, kDialogPtrProp, (HANDLE)pofn->lCustData);
nsFilePicker* picker =
reinterpret_cast<nsFilePicker*>(pofn->lCustData);
if (picker) {
picker->SetDialogHandle(hwnd);
SetTimer(hwnd, kDialogTimerID, kDialogTimerTimeout, nullptr);
}
}
break;
case WM_NOTIFY:
{
LPOFNOTIFYW lpofn = (LPOFNOTIFYW) lParam;
if (!lpofn || !lpofn->lpOFN) {
return 0;
}
// CDN_SELCHANGE is sent when the selection in the list box of the file
// selection dialog changes
if (lpofn->hdr.code == CDN_SELCHANGE) {
HWND parentHWND = GetParent(hwnd);
// Get the required size for the selected files buffer
UINT newBufLength = 0;
int requiredBufLength = CommDlg_OpenSave_GetSpecW(parentHWND,
nullptr, 0);
if(requiredBufLength >= 0)
newBufLength += requiredBufLength;
else
newBufLength += MAX_PATH;
// If the user selects multiple files, the buffer contains the
// current directory followed by the file names of the selected
// files. So make room for the directory path. If the user
// selects a single file, it is no harm to add extra space.
requiredBufLength = CommDlg_OpenSave_GetFolderPathW(parentHWND,
nullptr, 0);
if(requiredBufLength >= 0)
newBufLength += requiredBufLength;
else
newBufLength += MAX_PATH;
// Check if lpstrFile and nMaxFile are large enough
if (newBufLength > lpofn->lpOFN->nMaxFile) {
if (lpofn->lpOFN->lpstrFile)
delete[] lpofn->lpOFN->lpstrFile;
// We allocate FILE_BUFFER_SIZE more bytes than is needed so that
// if the user selects a file and holds down shift and down to
// select additional items, we will not continuously reallocate
newBufLength += FILE_BUFFER_SIZE;
wchar_t* filesBuffer = new wchar_t[newBufLength];
ZeroMemory(filesBuffer, newBufLength * sizeof(wchar_t));
lpofn->lpOFN->lpstrFile = filesBuffer;
lpofn->lpOFN->nMaxFile = newBufLength;
}
}
}
break;
case WM_TIMER:
{
// Check to see if our parent has been torn down, if so, we close too.
if (wParam == kDialogTimerID) {
nsFilePicker* picker =
reinterpret_cast<nsFilePicker*>(GetProp(hwnd, kDialogPtrProp));
if (picker && picker->ClosePickerIfNeeded(true)) {
KillTimer(hwnd, kDialogTimerID);
}
}
}
break;
}
return FilePickerHook(hwnd, msg, wParam, lParam);
}
/*
* Vista+ callbacks
@ -290,18 +476,25 @@ nsFilePicker::OnOverwrite(IFileDialog *pfd,
*/
bool
nsFilePicker::ClosePickerIfNeeded()
nsFilePicker::ClosePickerIfNeeded(bool aIsXPDialog)
{
if (!mParentWidget || !mDlgWnd)
return false;
nsWindow *win = static_cast<nsWindow *>(mParentWidget.get());
if (IsWindow(mDlgWnd) && IsWindowVisible(mDlgWnd) && win->DestroyCalled()) {
// Note, the xp callbacks hand us an inner window, so we have to step up
// one to get the actual dialog.
HWND dlgWnd;
if (aIsXPDialog)
dlgWnd = GetParent(mDlgWnd);
else
dlgWnd = mDlgWnd;
if (IsWindow(dlgWnd) && IsWindowVisible(dlgWnd) && win->DestroyCalled()) {
wchar_t className[64];
// Make sure we have the right window
if (GetClassNameW(mDlgWnd, className, mozilla::ArrayLength(className)) &&
if (GetClassNameW(dlgWnd, className, mozilla::ArrayLength(className)) &&
!wcscmp(className, L"#32770") &&
DestroyWindow(mDlgWnd)) {
DestroyWindow(dlgWnd)) {
mDlgWnd = nullptr;
return true;
}
@ -313,7 +506,7 @@ void
nsFilePicker::PickerCallbackTimerFunc(nsITimer *aTimer, void *aCtx)
{
nsFilePicker* picker = (nsFilePicker*)aCtx;
if (picker->ClosePickerIfNeeded()) {
if (picker->ClosePickerIfNeeded(false)) {
aTimer->Cancel();
}
}
@ -330,15 +523,62 @@ nsFilePicker::SetDialogHandle(HWND aWnd)
* Folder picker invocation
*/
// Open the older XP style folder picker dialog. We end up in this call
// on XP systems or when platform is built without the longhorn SDK.
bool
nsFilePicker::ShowXPFolderPicker(const nsString& aInitialDir)
{
bool result = false;
auto dirBuffer = MakeUnique<wchar_t[]>(FILE_BUFFER_SIZE);
wcsncpy(dirBuffer.get(), aInitialDir.get(), FILE_BUFFER_SIZE);
dirBuffer[FILE_BUFFER_SIZE-1] = '\0';
AutoDestroyTmpWindow adtw((HWND)(mParentWidget.get() ?
mParentWidget->GetNativeData(NS_NATIVE_TMP_WINDOW) : nullptr));
BROWSEINFOW browserInfo = {0};
browserInfo.pidlRoot = nullptr;
browserInfo.pszDisplayName = dirBuffer.get();
browserInfo.lpszTitle = mTitle.get();
browserInfo.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
browserInfo.hwndOwner = adtw.get();
browserInfo.iImage = 0;
browserInfo.lParam = reinterpret_cast<LPARAM>(this);
if (!aInitialDir.IsEmpty()) {
// the dialog is modal so that |initialDir.get()| will be valid in
// BrowserCallbackProc. Thus, we don't need to clone it.
browserInfo.lParam = (LPARAM) aInitialDir.get();
browserInfo.lpfn = &BrowseCallbackProc;
} else {
browserInfo.lParam = 0;
browserInfo.lpfn = nullptr;
}
LPITEMIDLIST list = ::SHBrowseForFolderW(&browserInfo);
if (list) {
result = ::SHGetPathFromIDListW(list, dirBuffer.get());
if (result)
mUnicodeFile.Assign(static_cast<const wchar_t*>(dirBuffer.get()));
// free PIDL
CoTaskMemFree(list);
}
return result;
}
/*
* Show a folder picker.
*
* Show a folder picker post Windows XP
*
* @param aInitialDir The initial directory, the last used directory will be
* used if left blank.
* @param aWasInitError Out parameter will hold true if there was an error
* before the folder picker is shown.
* @return true if a file was selected successfully.
*/
bool
nsFilePicker::ShowFolderPicker(const nsString& aInitialDir)
nsFilePicker::ShowFolderPicker(const nsString& aInitialDir, bool &aWasInitError)
{
if (!IsWin8OrLater()) {
// Some Windows 7 users are experiencing a race condition when some dlls
@ -353,8 +593,10 @@ nsFilePicker::ShowFolderPicker(const nsString& aInitialDir)
if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC,
IID_IFileOpenDialog,
getter_AddRefs(dialog)))) {
aWasInitError = true;
return false;
}
aWasInitError = false;
// hook up event callbacks
dialog->Advise(this, &mFDECookie);
@ -416,15 +658,233 @@ nsFilePicker::ShowFolderPicker(const nsString& aInitialDir)
* File open and save picker invocation
*/
/* static */ bool
nsFilePicker::GetFileNameWrapper(OPENFILENAMEW* ofn, PickerType aType)
{
MOZ_SEH_TRY {
if (aType == PICKER_TYPE_OPEN)
return ::GetOpenFileNameW(ofn);
else if (aType == PICKER_TYPE_SAVE)
return ::GetSaveFileNameW(ofn);
} MOZ_SEH_EXCEPT(true) {
NS_ERROR("nsFilePicker GetFileName win32 call generated an exception! This is bad!");
}
return false;
}
bool
nsFilePicker::FilePickerWrapper(OPENFILENAMEW* ofn, PickerType aType)
{
if (!ofn)
return false;
AutoWidgetPickerState awps(mParentWidget);
return GetFileNameWrapper(ofn, aType);
}
bool
nsFilePicker::ShowXPFilePicker(const nsString& aInitialDir)
{
OPENFILENAMEW ofn = {0};
ofn.lStructSize = sizeof(ofn);
nsString filterBuffer = mFilterList;
auto fileBuffer = MakeUnique<wchar_t[]>(FILE_BUFFER_SIZE);
wcsncpy(fileBuffer.get(), mDefaultFilePath.get(), FILE_BUFFER_SIZE);
fileBuffer[FILE_BUFFER_SIZE-1] = '\0'; // null terminate in case copy truncated
if (!aInitialDir.IsEmpty()) {
ofn.lpstrInitialDir = aInitialDir.get();
}
AutoDestroyTmpWindow adtw((HWND) (mParentWidget.get() ?
mParentWidget->GetNativeData(NS_NATIVE_TMP_WINDOW) : nullptr));
ofn.lpstrTitle = (LPCWSTR)mTitle.get();
ofn.lpstrFilter = (LPCWSTR)filterBuffer.get();
ofn.nFilterIndex = mSelectedType;
ofn.lpstrFile = fileBuffer.get();
ofn.nMaxFile = FILE_BUFFER_SIZE;
ofn.hwndOwner = adtw.get();
ofn.lCustData = reinterpret_cast<LPARAM>(this);
ofn.Flags = OFN_SHAREAWARE | OFN_LONGNAMES | OFN_OVERWRITEPROMPT |
OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_ENABLESIZING |
OFN_EXPLORER;
// Windows Vista and up won't allow you to use the new looking dialogs with
// a hook procedure. The hook procedure fixes a problem on XP dialogs for
// file picker visibility. Vista and up automatically ensures the file
// picker is always visible.
if (!IsVistaOrLater()) {
ofn.lpfnHook = FilePickerHook;
ofn.Flags |= OFN_ENABLEHOOK;
}
// Handle add to recent docs settings
if (IsPrivacyModeEnabled() || !mAddToRecentDocs) {
ofn.Flags |= OFN_DONTADDTORECENT;
}
NS_NAMED_LITERAL_STRING(htmExt, "html");
if (!mDefaultExtension.IsEmpty()) {
ofn.lpstrDefExt = mDefaultExtension.get();
} else if (IsDefaultPathHtml()) {
// Get file extension from suggested filename to detect if we are
// saving an html file.
// This is supposed to append ".htm" if user doesn't supply an
// extension but the behavior is sort of weird:
// - Often appends ".html" even if you have an extension
// - It obeys your extension if you put quotes around name
ofn.lpstrDefExt = htmExt.get();
}
// When possible, instead of using OFN_NOCHANGEDIR to ensure the current
// working directory will not change from this call, we will retrieve the
// current working directory before the call and restore it after the
// call. This flag causes problems on Windows XP for paths that are
// selected like C:test.txt where the user is currently at C:\somepath
// In which case expected result should be C:\somepath\test.txt
AutoRestoreWorkingPath restoreWorkingPath;
// If we can't get the current working directory, the best case is to
// use the OFN_NOCHANGEDIR flag
if (!restoreWorkingPath.HasWorkingPath()) {
ofn.Flags |= OFN_NOCHANGEDIR;
}
bool result = false;
switch(mMode) {
case modeOpen:
// FILE MUST EXIST!
ofn.Flags |= OFN_FILEMUSTEXIST;
result = FilePickerWrapper(&ofn, PICKER_TYPE_OPEN);
break;
case modeOpenMultiple:
ofn.Flags |= OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT;
// The hook set here ensures that the buffer returned will always be
// large enough to hold all selected files. The hook may modify the
// value of ofn.lpstrFile and deallocate the old buffer that it pointed
// to (fileBuffer). The hook assumes that the passed in value is heap
// allocated and that the returned value should be freed by the caller.
// If the hook changes the buffer, it will deallocate the old buffer.
// This fix would be nice to have in Vista and up, but it would force
// the file picker to use the old style dialogs because hooks are not
// allowed in the new file picker UI. We need to eventually move to
// the new Common File Dialogs for Vista and up.
if (!IsVistaOrLater()) {
ofn.lpfnHook = MultiFilePickerHook;
fileBuffer.release();
result = FilePickerWrapper(&ofn, PICKER_TYPE_OPEN);
fileBuffer.reset(ofn.lpstrFile);
} else {
result = FilePickerWrapper(&ofn, PICKER_TYPE_OPEN);
}
break;
case modeSave:
{
ofn.Flags |= OFN_NOREADONLYRETURN;
// Don't follow shortcuts when saving a shortcut, this can be used
// to trick users (bug 271732)
if (IsDefaultPathLink())
ofn.Flags |= OFN_NODEREFERENCELINKS;
result = FilePickerWrapper(&ofn, PICKER_TYPE_SAVE);
if (!result) {
// Error, find out what kind.
if (GetLastError() == ERROR_INVALID_PARAMETER ||
CommDlgExtendedError() == FNERR_INVALIDFILENAME) {
// Probably the default file name is too long or contains illegal
// characters. Try again, without a starting file name.
ofn.lpstrFile[0] = L'\0';
result = FilePickerWrapper(&ofn, PICKER_TYPE_SAVE);
}
}
}
break;
default:
NS_NOTREACHED("unsupported file picker mode");
return false;
}
if (!result)
return false;
// Remember what filter type the user selected
mSelectedType = (int16_t)ofn.nFilterIndex;
// Single file selection, we're done
if (mMode != modeOpenMultiple) {
GetQualifiedPath(fileBuffer.get(), mUnicodeFile);
return true;
}
// Set user-selected location of file or directory. From msdn's "Open and
// Save As Dialog Boxes" section:
// If you specify OFN_EXPLORER, the directory and file name strings are '\0'
// separated, with an extra '\0' character after the last file name. This
// format enables the Explorer-style dialog boxes to return long file names
// that include spaces.
wchar_t *current = fileBuffer.get();
nsAutoString dirName(current);
// Sometimes dirName contains a trailing slash and sometimes it doesn't:
if (current[dirName.Length() - 1] != '\\')
dirName.Append((char16_t)'\\');
while (current && *current && *(current + wcslen(current) + 1)) {
current = current + wcslen(current) + 1;
nsCOMPtr<nsIFile> file = do_CreateInstance("@mozilla.org/file/local;1");
NS_ENSURE_TRUE(file, false);
// Only prepend the directory if the path specified is a relative path
nsAutoString path;
if (PathIsRelativeW(current)) {
path = dirName + nsDependentString(current);
} else {
path = current;
}
nsAutoString canonicalizedPath;
GetQualifiedPath(path.get(), canonicalizedPath);
if (NS_FAILED(file->InitWithPath(canonicalizedPath)) ||
!mFiles.AppendObject(file))
return false;
}
// Handle the case where the user selected just one file. From msdn: If you
// specify OFN_ALLOWMULTISELECT and the user selects only one file the
// lpstrFile string does not have a separator between the path and file name.
if (current && *current && (current == fileBuffer.get())) {
nsCOMPtr<nsIFile> file = do_CreateInstance("@mozilla.org/file/local;1");
NS_ENSURE_TRUE(file, false);
nsAutoString canonicalizedPath;
GetQualifiedPath(current, canonicalizedPath);
if (NS_FAILED(file->InitWithPath(canonicalizedPath)) ||
!mFiles.AppendObject(file))
return false;
}
return true;
}
/*
* Show a file picker.
*
* Show a file picker post Windows XP
*
* @param aInitialDir The initial directory, the last used directory will be
* used if left blank.
* @param aWasInitError Out parameter will hold true if there was an error
* before the file picker is shown.
* @return true if a file was selected successfully.
*/
bool
nsFilePicker::ShowFilePicker(const nsString& aInitialDir)
nsFilePicker::ShowFilePicker(const nsString& aInitialDir, bool &aWasInitError)
{
PROFILER_LABEL_FUNC(js::ProfileEntry::Category::OTHER);
@ -442,15 +902,18 @@ nsFilePicker::ShowFilePicker(const nsString& aInitialDir)
if (FAILED(CoCreateInstance(CLSID_FileOpenDialog, nullptr, CLSCTX_INPROC,
IID_IFileOpenDialog,
getter_AddRefs(dialog)))) {
aWasInitError = true;
return false;
}
} else {
if (FAILED(CoCreateInstance(CLSID_FileSaveDialog, nullptr, CLSCTX_INPROC,
IID_IFileSaveDialog,
getter_AddRefs(dialog)))) {
aWasInitError = true;
return false;
}
}
aWasInitError = false;
// hook up event callbacks
dialog->Advise(this, &mFDECookie);
@ -617,11 +1080,22 @@ nsFilePicker::ShowW(int16_t *aReturnVal)
// with our context set temporarily to system-dpi-aware
WinUtils::AutoSystemDpiAware dpiAwareness;
bool result = false;
// Launch the XP file/folder picker on XP and as a fallback on Vista+.
// The CoCreateInstance call to CLSID_FileOpenDialog fails with "(0x80040111)
// ClassFactory cannot supply requested class" when the checkbox for
// Disable Visual Themes is on in the compatability tab within the shortcut
// properties.
bool result = false, wasInitError = true;
if (mMode == modeGetFolder) {
result = ShowFolderPicker(initialDir);
if (IsVistaOrLater())
result = ShowFolderPicker(initialDir, wasInitError);
if (!result && wasInitError)
result = ShowXPFolderPicker(initialDir);
} else {
result = ShowFilePicker(initialDir);
if (IsVistaOrLater())
result = ShowFilePicker(initialDir, wasInitError);
if (!result && wasInitError)
result = ShowXPFilePicker(initialDir);
}
// exit, and return returnCancel in aReturnVal
@ -773,10 +1247,48 @@ nsFilePicker::InitNative(nsIWidget *aParent,
mTitle.Assign(aTitle);
}
void
nsFilePicker::GetQualifiedPath(const wchar_t *aInPath, nsString &aOutPath)
{
// Prefer a qualified path over a non qualified path.
// Things like c:file.txt would be accepted in Win XP but would later
// fail to open from the download manager.
wchar_t qualifiedFileBuffer[MAX_PATH];
if (PathSearchAndQualifyW(aInPath, qualifiedFileBuffer, MAX_PATH)) {
aOutPath.Assign(qualifiedFileBuffer);
} else {
aOutPath.Assign(aInPath);
}
}
void
nsFilePicker::AppendXPFilter(const nsAString& aTitle, const nsAString& aFilter)
{
mFilterList.Append(aTitle);
mFilterList.Append(char16_t('\0'));
if (aFilter.EqualsLiteral("..apps"))
mFilterList.AppendLiteral("*.exe;*.com");
else
{
nsAutoString filter(aFilter);
filter.StripWhitespace();
if (filter.EqualsLiteral("*"))
filter.AppendLiteral(".*");
mFilterList.Append(filter);
}
mFilterList.Append(char16_t('\0'));
}
NS_IMETHODIMP
nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter)
{
mComFilterList.Append(aTitle, aFilter);
if (IsVistaOrLater()) {
mComFilterList.Append(aTitle, aFilter);
} else {
AppendXPFilter(aTitle, aFilter);
}
return NS_OK;
}

View File

@ -9,6 +9,17 @@
#include <windows.h>
// For Vista IFileDialog interfaces which aren't exposed
// unless _WIN32_WINNT >= _WIN32_WINNT_LONGHORN.
#if _WIN32_WINNT < _WIN32_WINNT_LONGHORN
#define _WIN32_WINNT_bak _WIN32_WINNT
#undef _WIN32_WINNT
#define _WIN32_WINNT _WIN32_WINNT_LONGHORN
#define _WIN32_IE_bak _WIN32_IE
#undef _WIN32_IE
#define _WIN32_IE _WIN32_IE_IE70
#endif
#include "nsIFile.h"
#include "nsITimer.h"
#include "nsISimpleEnumerator.h"
@ -76,19 +87,32 @@ public:
HRESULT STDMETHODCALLTYPE OnOverwrite(IFileDialog *pfd, IShellItem *psi, FDE_OVERWRITE_RESPONSE *pResponse);
protected:
enum PickerType {
PICKER_TYPE_OPEN,
PICKER_TYPE_SAVE,
};
/* method from nsBaseFilePicker */
virtual void InitNative(nsIWidget *aParent,
const nsAString& aTitle);
static void GetQualifiedPath(const wchar_t *aInPath, nsString &aOutPath);
void GetFilterListArray(nsString& aFilterList);
bool ShowFolderPicker(const nsString& aInitialDir);
bool ShowFilePicker(const nsString& aInitialDir);
static bool GetFileNameWrapper(OPENFILENAMEW* ofn, PickerType aType);
bool FilePickerWrapper(OPENFILENAMEW* ofn, PickerType aType);
bool ShowXPFolderPicker(const nsString& aInitialDir);
bool ShowXPFilePicker(const nsString& aInitialDir);
bool ShowFolderPicker(const nsString& aInitialDir, bool &aWasInitError);
bool ShowFilePicker(const nsString& aInitialDir, bool &aWasInitError);
void AppendXPFilter(const nsAString& aTitle, const nsAString& aFilter);
void RememberLastUsedDirectory();
bool IsPrivacyModeEnabled();
bool IsDefaultPathLink();
bool IsDefaultPathHtml();
void SetDialogHandle(HWND aWnd);
bool ClosePickerIfNeeded();
bool ClosePickerIfNeeded(bool aIsXPDialog);
static void PickerCallbackTimerFunc(nsITimer *aTimer, void *aPicker);
static UINT_PTR CALLBACK MultiFilePickerHook(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
static UINT_PTR CALLBACK FilePickerHook(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
nsCOMPtr<nsILoadContext> mLoadContext;
nsCOMPtr<nsIWidget> mParentWidget;
@ -130,4 +154,11 @@ protected:
DWORD mFDECookie;
};
#if defined(_WIN32_WINNT_bak)
#undef _WIN32_WINNT
#define _WIN32_WINNT _WIN32_WINNT_bak
#undef _WIN32_IE
#define _WIN32_IE _WIN32_IE_bak
#endif
#endif // nsFilePicker_h__

View File

@ -31,8 +31,12 @@ nsLookAndFeel::GetOperatingSystemVersion()
version = eOperatingSystemVersion_Windows10;
} else if (IsWin8OrLater()) {
version = eOperatingSystemVersion_Windows8;
} else {
} else if (IsWin7OrLater()) {
version = eOperatingSystemVersion_Windows7;
} else if (IsVistaOrLater()) {
version = eOperatingSystemVersion_WindowsVista;
} else {
version = eOperatingSystemVersion_WindowsXP;
}
return version;
@ -176,7 +180,8 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
idx = COLOR_HIGHLIGHT;
break;
case eColorID__moz_menubarhovertext:
if (!IsAppThemed()) {
if (!IsVistaOrLater() || !IsAppThemed())
{
idx = nsUXThemeData::sFlatMenus ?
COLOR_HIGHLIGHTTEXT :
COLOR_MENUTEXT;
@ -184,7 +189,8 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
}
// Fall through
case eColorID__moz_menuhovertext:
if (IsAppThemed()) {
if (IsVistaOrLater() && IsAppThemed())
{
res = ::GetColorFromTheme(eUXMenu,
MENU_POPUPITEM, MPI_HOT, TMT_TEXTCOLOR, aColor);
if (NS_SUCCEEDED(res))
@ -276,7 +282,7 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
aColor = NS_RGB(0, 0, 0);
return NS_OK;
case eColorID__moz_win_mediatext:
if (IsAppThemed()) {
if (IsVistaOrLater() && IsAppThemed()) {
res = ::GetColorFromTheme(eUXMediaToolbar,
TP_BUTTON, TS_NORMAL, TMT_TEXTCOLOR, aColor);
if (NS_SUCCEEDED(res))
@ -286,7 +292,8 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor &aColor)
idx = COLOR_WINDOWTEXT;
break;
case eColorID__moz_win_communicationstext:
if (IsAppThemed()) {
if (IsVistaOrLater() && IsAppThemed())
{
res = ::GetColorFromTheme(eUXCommunicationsToolbar,
TP_BUTTON, TS_NORMAL, TMT_TEXTCOLOR, aColor);
if (NS_SUCCEEDED(res))

View File

@ -29,6 +29,18 @@
#ifndef SM_SYSTEMDOCKED
#define SM_CONVERTIBLESLATEMODE 0x00002003
#define SM_SYSTEMDOCKED 0x00002004
typedef enum _AR_STATE
{
AR_ENABLED = 0x0,
AR_DISABLED = 0x1,
AR_SUPPRESSED = 0x2,
AR_REMOTESESSION = 0x4,
AR_MULTIMON = 0x8,
AR_NOSENSOR = 0x10,
AR_NOT_SUPPORTED = 0x20,
AR_DOCKED = 0x40,
AR_LAPTOP = 0x80
} AR_STATE, *PAR_STATE;
#endif
class nsLookAndFeel: public nsXPLookAndFeel {

View File

@ -40,6 +40,7 @@
#include "nsUXThemeConstants.h"
#include <algorithm>
using mozilla::IsVistaOrLater;
using namespace mozilla;
using namespace mozilla::gfx;
using namespace mozilla::widget;
@ -302,6 +303,10 @@ DrawThemeBGRTLAware(HANDLE aTheme, HDC aHdc, int aPart, int aState,
* aero basic max 0 2 1 2
* aero basic close 1 2 1 2
*
* xp theme min 0 2 0 2
* xp theme max 0 2 1 2
* xp theme close 1 2 2 2
*
* 'cold' button padding - generic button padding, should
* be handled in css.
* left top right bottom
@ -312,11 +317,16 @@ DrawThemeBGRTLAware(HANDLE aTheme, HDC aHdc, int aPart, int aState,
* aero basic min 0 0 1 0
* aero basic max 1 0 0 0
* aero basic close 0 0 0 0
*
* xp theme min 0 0 1 0
* xp theme max 1 0 0 0
* xp theme close 0 0 0 0
*/
enum CaptionDesktopTheme {
CAPTION_CLASSIC = 0,
CAPTION_BASIC,
CAPTION_XPTHEME,
};
enum CaptionButton {
@ -350,6 +360,8 @@ AddPaddingRect(LayoutDeviceIntSize* aSize, CaptionButton button) {
RECT offset;
if (!IsAppThemed())
offset = buttonData[CAPTION_CLASSIC].hotPadding[button];
else if (!IsVistaOrLater())
offset = buttonData[CAPTION_XPTHEME].hotPadding[button];
else
offset = buttonData[CAPTION_BASIC].hotPadding[button];
aSize->width += offset.left + offset.right;
@ -363,6 +375,8 @@ OffsetBackgroundRect(RECT& rect, CaptionButton button) {
RECT offset;
if (!IsAppThemed())
offset = buttonData[CAPTION_CLASSIC].hotPadding[button];
else if (!IsVistaOrLater())
offset = buttonData[CAPTION_XPTHEME].hotPadding[button];
else
offset = buttonData[CAPTION_BASIC].hotPadding[button];
rect.left += offset.left;
@ -407,7 +421,9 @@ OffsetBackgroundRect(RECT& rect, CaptionButton button) {
static const double kProgressDeterminateTimeSpan = 3.0;
static const double kProgressIndeterminateTimeSpan = 5.0;
// The width of the overlay used to animate the horizontal progress bar (Vista and later).
static const int32_t kProgressHorizontalOverlaySize = 120;
static const int32_t kProgressHorizontalVistaOverlaySize = 120;
// The width of the overlay used for the horizontal indeterminate progress bars on XP.
static const int32_t kProgressHorizontalXPOverlaySize = 55;
// The height of the overlay used to animate the vertical progress bar (Vista and later).
static const int32_t kProgressVerticalOverlaySize = 45;
// The height of the overlay used for the vertical indeterminate progress bar (Vista and later).
@ -421,8 +437,18 @@ static const int32_t kProgressClassicOverlaySize = 40;
*/
static int32_t
GetProgressOverlayStyle(bool aIsVertical)
{
return aIsVertical ? PP_MOVEOVERLAYVERT : PP_MOVEOVERLAY;
{
if (aIsVertical) {
if (IsVistaOrLater()) {
return PP_MOVEOVERLAYVERT;
}
return PP_CHUNKVERT;
} else {
if (IsVistaOrLater()) {
return PP_MOVEOVERLAY;
}
return PP_CHUNK;
}
}
/*
@ -433,11 +459,14 @@ GetProgressOverlayStyle(bool aIsVertical)
static int32_t
GetProgressOverlaySize(bool aIsVertical, bool aIsIndeterminate)
{
if (aIsVertical) {
return aIsIndeterminate ? kProgressVerticalIndeterminateOverlaySize
: kProgressVerticalOverlaySize;
if (IsVistaOrLater()) {
if (aIsVertical) {
return aIsIndeterminate ? kProgressVerticalIndeterminateOverlaySize
: kProgressVerticalOverlaySize;
}
return kProgressHorizontalVistaOverlaySize;
}
return kProgressHorizontalOverlaySize;
return kProgressHorizontalXPOverlaySize;
}
/*
@ -526,6 +555,87 @@ nsNativeThemeWin::CalculateProgressOverlayRect(nsIFrame* aFrame,
return overlayRect;
}
/*
* DrawChunkProgressMeter - renders an xp style chunked progress meter. Called
* by DrawProgressMeter.
*
* @param aTheme progress theme handle
* @param aHdc hdc returned by gfxWindowsNativeDrawing
* @param aPart the PP_X progress part
* @param aState the theme state
* @param aFrame the elements frame
* @param aWidgetRect bounding rect for the widget
* @param aClipRect dirty rect that needs drawing.
* @param aAppUnits app units per device pixel
* @param aIsIndeterm is an indeterminate progress?
* @param aIsVertical render a vertical progress?
* @param aIsRtl direction is rtl
*/
static void
DrawChunkProgressMeter(HTHEME aTheme, HDC aHdc, int aPart,
int aState, nsIFrame* aFrame, RECT* aWidgetRect,
RECT* aClipRect, gfxFloat aAppUnits, bool aIsIndeterm,
bool aIsVertical, bool aIsRtl)
{
NS_ASSERTION(aTheme, "Bad theme.");
NS_ASSERTION(aHdc, "Bad hdc.");
NS_ASSERTION(aWidgetRect, "Bad rect.");
NS_ASSERTION(aClipRect, "Bad clip rect.");
NS_ASSERTION(aFrame, "Bad frame.");
// For horizontal meters, the theme lib paints the right graphic but doesn't
// paint the chunks, so we do that manually. For vertical meters, the theme
// library draws everything correctly.
if (aIsVertical) {
DrawThemeBackground(aTheme, aHdc, aPart, aState, aWidgetRect, aClipRect);
return;
}
// query for the proper chunk metrics
int chunkSize, spaceSize;
if (FAILED(GetThemeMetric(aTheme, aHdc, aPart, aState,
TMT_PROGRESSCHUNKSIZE, &chunkSize)) ||
FAILED(GetThemeMetric(aTheme, aHdc, aPart, aState,
TMT_PROGRESSSPACESIZE, &spaceSize))) {
DrawThemeBackground(aTheme, aHdc, aPart, aState, aWidgetRect, aClipRect);
return;
}
// render chunks
if (!aIsRtl || aIsIndeterm) {
for (int chunk = aWidgetRect->left; chunk <= aWidgetRect->right;
chunk += (chunkSize+spaceSize)) {
if (!aIsIndeterm && ((chunk + chunkSize) > aWidgetRect->right)) {
// aWidgetRect->right represents the end of the meter. Partial blocks
// don't get rendered with one exception, so exit here if we don't have
// a full chunk to draw.
// The above is true *except* when the meter is at 100% fill, in which
// case Windows renders any remaining partial block. Query the parent
// frame to find out if we're at 100%.
if (!IsProgressMeterFilled(aFrame)) {
break;
}
}
RECT bounds =
{ chunk, aWidgetRect->top, chunk + chunkSize, aWidgetRect->bottom };
DrawThemeBackground(aTheme, aHdc, aPart, aState, &bounds, aClipRect);
}
} else {
// rtl needs to grow in the opposite direction to look right.
for (int chunk = aWidgetRect->right; chunk >= aWidgetRect->left;
chunk -= (chunkSize+spaceSize)) {
if ((chunk - chunkSize) < aWidgetRect->left) {
if (!IsProgressMeterFilled(aFrame)) {
break;
}
}
RECT bounds =
{ chunk - chunkSize, aWidgetRect->top, chunk, aWidgetRect->bottom };
DrawThemeBackground(aTheme, aHdc, aPart, aState, &bounds, aClipRect);
}
}
}
/*
* DrawProgressMeter - render an appropriate progress meter based on progress
* meter style, orientation, and os. Note, this does not render the underlying
@ -545,7 +655,8 @@ void
nsNativeThemeWin::DrawThemedProgressMeter(nsIFrame* aFrame, int aWidgetType,
HANDLE aTheme, HDC aHdc,
int aPart, int aState,
RECT* aWidgetRect, RECT* aClipRect)
RECT* aWidgetRect, RECT* aClipRect,
gfxFloat aAppUnits)
{
if (!aFrame || !aTheme || !aHdc)
return;
@ -556,6 +667,12 @@ nsNativeThemeWin::DrawThemedProgressMeter(nsIFrame* aFrame, int aWidgetType,
RECT adjWidgetRect, adjClipRect;
adjWidgetRect = *aWidgetRect;
adjClipRect = *aClipRect;
if (!IsVistaOrLater()) {
// Adjust clipping out by one pixel. XP progress meters are inset,
// Vista+ are not.
InflateRect(&adjWidgetRect, 1, 1);
InflateRect(&adjClipRect, 1, 1);
}
nsIFrame* parentFrame = aFrame->GetParent();
if (!parentFrame) {
@ -570,13 +687,20 @@ nsNativeThemeWin::DrawThemedProgressMeter(nsIFrame* aFrame, int aWidgetType,
bool indeterminate = IsIndeterminateProgress(parentFrame, eventStates);
bool animate = indeterminate;
// Vista and up progress meter is fill style, rendered here. We render
// the pulse overlay in the follow up section below.
DrawThemeBackground(aTheme, aHdc, aPart, aState,
&adjWidgetRect, &adjClipRect);
if (!IsProgressMeterFilled(aFrame)) {
animate = true;
}
if (IsVistaOrLater()) {
// Vista and up progress meter is fill style, rendered here. We render
// the pulse overlay in the follow up section below.
DrawThemeBackground(aTheme, aHdc, aPart, aState,
&adjWidgetRect, &adjClipRect);
if (!IsProgressMeterFilled(aFrame)) {
animate = true;
}
} else if (!indeterminate) {
// XP progress meters are 'chunk' style.
DrawChunkProgressMeter(aTheme, aHdc, aPart, aState, aFrame,
&adjWidgetRect, &adjClipRect, aAppUnits,
indeterminate, vertical, IsFrameRTL(aFrame));
}
if (animate) {
// Indeterminate rendering
@ -584,8 +708,14 @@ nsNativeThemeWin::DrawThemedProgressMeter(nsIFrame* aFrame, int aWidgetType,
RECT overlayRect =
CalculateProgressOverlayRect(aFrame, &adjWidgetRect, vertical,
indeterminate, false);
DrawThemeBackground(aTheme, aHdc, overlayPart, aState, &overlayRect,
&adjClipRect);
if (IsVistaOrLater()) {
DrawThemeBackground(aTheme, aHdc, overlayPart, aState, &overlayRect,
&adjClipRect);
} else {
DrawChunkProgressMeter(aTheme, aHdc, overlayPart, aState, aFrame,
&overlayRect, &adjClipRect, aAppUnits,
indeterminate, vertical, IsFrameRTL(aFrame));
}
if (!QueueAnimatedContentForRefresh(aFrame->GetContent(), 60)) {
NS_WARNING("unable to animate progress widget!");
@ -596,6 +726,15 @@ nsNativeThemeWin::DrawThemedProgressMeter(nsIFrame* aFrame, int aWidgetType,
HANDLE
nsNativeThemeWin::GetTheme(uint8_t aWidgetType)
{
if (!IsVistaOrLater()) {
// On XP or earlier, render dropdowns as textfields;
// doing it the right way works fine with the MS themes,
// but breaks on a lot of custom themes (presumably because MS
// apps do the textfield border business as well).
if (aWidgetType == NS_THEME_MENULIST)
aWidgetType = NS_THEME_TEXTFIELD;
}
switch (aWidgetType) {
case NS_THEME_BUTTON:
case NS_THEME_RADIO:
@ -608,7 +747,9 @@ nsNativeThemeWin::GetTheme(uint8_t aWidgetType)
case NS_THEME_FOCUS_OUTLINE:
return nsUXThemeData::GetTheme(eUXEdit);
case NS_THEME_TOOLTIP:
return nsUXThemeData::GetTheme(eUXTooltip);
// XP/2K3 should force a classic treatment of tooltips
return !IsVistaOrLater() ?
nullptr : nsUXThemeData::GetTheme(eUXTooltip);
case NS_THEME_TOOLBOX:
return nsUXThemeData::GetTheme(eUXRebar);
case NS_THEME_WIN_MEDIA_TOOLBOX:
@ -735,6 +876,12 @@ nsresult
nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
int32_t& aPart, int32_t& aState)
{
if (!IsVistaOrLater()) {
// See GetTheme
if (aWidgetType == NS_THEME_MENULIST)
aWidgetType = NS_THEME_TEXTFIELD;
}
switch (aWidgetType) {
case NS_THEME_BUTTON: {
aPart = BP_BUTTON;
@ -807,43 +954,63 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
case NS_THEME_TEXTFIELD_MULTILINE: {
EventStates eventState = GetContentState(aFrame, aWidgetType);
/* Note: the NOSCROLL type has a rounded corner in each corner. The more
* specific HSCROLL, VSCROLL, HVSCROLL types have side and/or top/bottom
* edges rendered as straight horizontal lines with sharp corners to
* accommodate a scrollbar. However, the scrollbar gets rendered on top
* of this for us, so we don't care, and can just use NOSCROLL here.
*/
aPart = TFP_EDITBORDER_NOSCROLL;
if (!aFrame) {
aState = TFS_EDITBORDER_NORMAL;
} else if (IsDisabled(aFrame, eventState)) {
aState = TFS_EDITBORDER_DISABLED;
} else if (IsReadOnly(aFrame)) {
/* no special read-only state */
aState = TFS_EDITBORDER_NORMAL;
} else {
nsIContent* content = aFrame->GetContent();
/* XUL textboxes don't get focused themselves, because they have child
* html:input.. but we can check the XUL focused attributes on them
if (IsVistaOrLater()) {
/* Note: the NOSCROLL type has a rounded corner in each
* corner. The more specific HSCROLL, VSCROLL, HVSCROLL types
* have side and/or top/bottom edges rendered as straight
* horizontal lines with sharp corners to accommodate a
* scrollbar. However, the scrollbar gets rendered on top of
* this for us, so we don't care, and can just use NOSCROLL
* here.
*/
if (content && content->IsXULElement() && IsFocused(aFrame))
aState = TFS_EDITBORDER_FOCUSED;
else if (eventState.HasAtLeastOneOfStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS))
aState = TFS_EDITBORDER_FOCUSED;
else if (eventState.HasState(NS_EVENT_STATE_HOVER))
aState = TFS_EDITBORDER_HOVER;
else
aPart = TFP_EDITBORDER_NOSCROLL;
if (!aFrame) {
aState = TFS_EDITBORDER_NORMAL;
} else if (IsDisabled(aFrame, eventState)) {
aState = TFS_EDITBORDER_DISABLED;
} else if (IsReadOnly(aFrame)) {
/* no special read-only state */
aState = TFS_EDITBORDER_NORMAL;
} else {
nsIContent* content = aFrame->GetContent();
/* XUL textboxes don't get focused themselves, because they have child
* html:input.. but we can check the XUL focused attributes on them
*/
if (content && content->IsXULElement() && IsFocused(aFrame))
aState = TFS_EDITBORDER_FOCUSED;
else if (eventState.HasAtLeastOneOfStates(NS_EVENT_STATE_ACTIVE | NS_EVENT_STATE_FOCUS))
aState = TFS_EDITBORDER_FOCUSED;
else if (eventState.HasState(NS_EVENT_STATE_HOVER))
aState = TFS_EDITBORDER_HOVER;
else
aState = TFS_EDITBORDER_NORMAL;
}
} else {
aPart = TFP_TEXTFIELD;
if (!aFrame)
aState = TS_NORMAL;
else if (IsDisabled(aFrame, eventState))
aState = TS_DISABLED;
else if (IsReadOnly(aFrame))
aState = TFS_READONLY;
else
aState = StandardGetState(aFrame, aWidgetType, true);
}
return NS_OK;
}
case NS_THEME_FOCUS_OUTLINE: {
// XXX the EDITBORDER values don't respect DTBG_OMITCONTENT
aPart = TFP_TEXTFIELD; //TFP_EDITBORDER_NOSCROLL;
aState = TS_FOCUSED; //TFS_EDITBORDER_FOCUSED;
if (IsVistaOrLater()) {
// XXX the EDITBORDER values don't respect DTBG_OMITCONTENT
aPart = TFP_TEXTFIELD; //TFP_EDITBORDER_NOSCROLL;
aState = TS_FOCUSED; //TFS_EDITBORDER_FOCUSED;
} else {
aPart = TFP_TEXTFIELD;
aState = TS_FOCUSED;
}
return NS_OK;
}
case NS_THEME_TOOLTIP: {
@ -867,9 +1034,11 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
nsIFrame* parentFrame = aFrame->GetParent();
if (aWidgetType == NS_THEME_PROGRESSCHUNK_VERTICAL ||
IsVerticalProgress(parentFrame)) {
aPart = PP_FILLVERT;
aPart = IsVistaOrLater() ?
PP_FILLVERT : PP_CHUNKVERT;
} else {
aPart = PP_FILL;
aPart = IsVistaOrLater() ?
PP_FILL : PP_CHUNK;
}
aState = PBBVS_NORMAL;
@ -933,7 +1102,8 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
aState += TS_ACTIVE;
else if (eventState.HasState(NS_EVENT_STATE_HOVER))
aState += TS_HOVER;
else if (parentState.HasState(NS_EVENT_STATE_HOVER))
else if (IsVistaOrLater() &&
parentState.HasState(NS_EVENT_STATE_HOVER))
aState = (aWidgetType - NS_THEME_SCROLLBARBUTTON_UP) + SP_BUTTON_IMPLICIT_HOVER_BASE;
else
aState += TS_NORMAL;
@ -1036,7 +1206,14 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
case NS_THEME_SCROLLBAR:
case NS_THEME_SCROLLBAR_SMALL: {
aState = 0;
aPart = RP_BACKGROUND;
if (IsVistaOrLater()) {
// On vista, they have a part
aPart = RP_BACKGROUND;
} else {
// Otherwise, they don't. (But I bet
// RP_BACKGROUND would work here, too);
aPart = 0;
}
return NS_OK;
}
case NS_THEME_TOOLBAR: {
@ -1161,7 +1338,8 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
aFrame = parentFrame;
EventStates eventState = GetContentState(aFrame, aWidgetType);
aPart = CBP_DROPMARKER_VISTA;
aPart = IsVistaOrLater() ?
CBP_DROPMARKER_VISTA : CBP_DROPMARKER;
// For HTML controls with author styling, we should fall
// back to the old dropmarker style to avoid clashes with
@ -1181,25 +1359,28 @@ nsNativeThemeWin::GetThemePartAndState(nsIFrame* aFrame, uint8_t aWidgetType,
else
isOpen = IsOpenButton(aFrame);
if (isHTML || IsMenuListEditable(aFrame)) {
if (isOpen) {
/* Hover is propagated, but we need to know whether we're hovering
* just the combobox frame, not the dropdown frame. But, we can't get
* that information, since hover is on the content node, and they
* share the same content node. So, instead, we cheat -- if the
* dropdown is open, we always show the hover state. This looks fine
* in practice.
if (IsVistaOrLater()) {
if (isHTML || IsMenuListEditable(aFrame)) {
if (isOpen) {
/* Hover is propagated, but we need to know whether we're
* hovering just the combobox frame, not the dropdown frame.
* But, we can't get that information, since hover is on the
* content node, and they share the same content node. So,
* instead, we cheat -- if the dropdown is open, we always
* show the hover state. This looks fine in practice.
*/
aState = TS_HOVER;
return NS_OK;
}
} else {
/* On Vista, the dropdown indicator on a menulist button in
* chrome is not given a hover effect. When the frame isn't
* isn't HTML content, we cheat and force the dropdown state
* to be normal. (Bug 430434)
*/
aState = TS_HOVER;
aState = TS_NORMAL;
return NS_OK;
}
} else {
/* The dropdown indicator on a menulist button in chrome is not given a
* hover effect. When the frame isn't isn't HTML content, we cheat and
* force the dropdown state to be normal. (Bug 430434)
*/
aState = TS_NORMAL;
return NS_OK;
}
aState = TS_NORMAL;
@ -1703,7 +1884,7 @@ RENDER_AGAIN:
else if (aWidgetType == NS_THEME_PROGRESSCHUNK ||
aWidgetType == NS_THEME_PROGRESSCHUNK_VERTICAL) {
DrawThemedProgressMeter(aFrame, aWidgetType, theme, hdc, part, state,
&widgetRect, &clipRect);
&widgetRect, &clipRect, p2a);
}
else if (aWidgetType == NS_THEME_FOCUS_OUTLINE) {
// Inflate 'widgetRect' with the focus outline size.
@ -1969,39 +2150,41 @@ nsNativeThemeWin::GetWidgetPadding(nsDeviceContext* aContext,
return ok;
}
if (aWidgetType == NS_THEME_NUMBER_INPUT ||
aWidgetType == NS_THEME_TEXTFIELD ||
aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
aWidgetType == NS_THEME_MENULIST)
{
// If we have author-specified padding for these elements, don't do the
// fixups below.
if (aFrame->PresContext()->HasAuthorSpecifiedRules(aFrame, NS_AUTHOR_SPECIFIED_PADDING))
return false;
}
if (IsVistaOrLater()) {
if (aWidgetType == NS_THEME_NUMBER_INPUT ||
aWidgetType == NS_THEME_TEXTFIELD ||
aWidgetType == NS_THEME_TEXTFIELD_MULTILINE ||
aWidgetType == NS_THEME_MENULIST)
{
/* If we have author-specified padding for these elements, don't do the fixups below */
if (aFrame->PresContext()->HasAuthorSpecifiedRules(aFrame, NS_AUTHOR_SPECIFIED_PADDING))
return false;
}
/* textfields need extra pixels on all sides, otherwise they wrap their
* content too tightly. The actual border is drawn 1px inside the specified
* rectangle, so Gecko will end up making the contents look too small.
* Instead, we add 2px padding for the contents and fix this. (Used to be 1px
* added, see bug 430212)
*/
if (aWidgetType == NS_THEME_NUMBER_INPUT ||
aWidgetType == NS_THEME_TEXTFIELD ||
aWidgetType == NS_THEME_TEXTFIELD_MULTILINE) {
aResult->top = aResult->bottom = 2;
aResult->left = aResult->right = 2;
ScaleForFrameDPI(aResult, aFrame);
return ok;
} else if (IsHTMLContent(aFrame) && aWidgetType == NS_THEME_MENULIST) {
/* For content menulist controls, we need an extra pixel so that we have
* room to draw our focus rectangle stuff. Otherwise, the focus rect might
* overlap the control's border.
/* textfields need extra pixels on all sides, otherwise they
* wrap their content too tightly. The actual border is drawn 1px
* inside the specified rectangle, so Gecko will end up making the
* contents look too small. Instead, we add 2px padding for the
* contents and fix this. (Used to be 1px added, see bug 430212)
*/
aResult->top = aResult->bottom = 1;
aResult->left = aResult->right = 1;
ScaleForFrameDPI(aResult, aFrame);
return ok;
if (aWidgetType == NS_THEME_NUMBER_INPUT ||
aWidgetType == NS_THEME_TEXTFIELD ||
aWidgetType == NS_THEME_TEXTFIELD_MULTILINE) {
aResult->top = aResult->bottom = 2;
aResult->left = aResult->right = 2;
ScaleForFrameDPI(aResult, aFrame);
return ok;
} else if (IsHTMLContent(aFrame) && aWidgetType == NS_THEME_MENULIST) {
/* For content menulist controls, we need an extra pixel so
* that we have room to draw our focus rectangle stuff.
* Otherwise, the focus rect might overlap the control's
* border.
*/
aResult->top = aResult->bottom = 1;
aResult->left = aResult->right = 1;
ScaleForFrameDPI(aResult, aFrame);
return ok;
}
}
int32_t right, left, top, bottom;
@ -2066,21 +2249,23 @@ nsNativeThemeWin::GetWidgetOverflow(nsDeviceContext* aContext,
* a border only shows up if the widget is being hovered.
*/
#if 0
/* We explicitly draw dropdown buttons in HTML content 1px bigger up, right,
* and bottom so that they overlap the dropdown's border like they're
* supposed to.
*/
if (aWidgetType == NS_THEME_MENULIST_BUTTON &&
IsHTMLContent(aFrame) &&
!IsWidgetStyled(aFrame->GetParent()->PresContext(),
aFrame->GetParent(),
NS_THEME_MENULIST))
{
int32_t p2a = aContext->AppUnitsPerDevPixel();
/* Note: no overflow on the left */
nsMargin m(p2a, p2a, p2a, 0);
aOverflowRect->Inflate (m);
return true;
if (IsVistaOrLater()) {
/* We explicitly draw dropdown buttons in HTML content 1px bigger
* up, right, and bottom so that they overlap the dropdown's border
* like they're supposed to.
*/
if (aWidgetType == NS_THEME_MENULIST_BUTTON &&
IsHTMLContent(aFrame) &&
!IsWidgetStyled(aFrame->GetParent()->PresContext(),
aFrame->GetParent(),
NS_THEME_MENULIST))
{
int32_t p2a = aContext->AppUnitsPerDevPixel();
/* Note: no overflow on the left */
nsMargin m(p2a, p2a, p2a, 0);
aOverflowRect->Inflate (m);
return true;
}
}
#endif
@ -2204,18 +2389,22 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aF
case NS_THEME_SCALETHUMB_VERTICAL:
{
*aIsOverridable = false;
// On Vista, GetThemePartAndState returns odd values for
// on Vista, GetThemePartAndState returns odd values for
// scale thumbs, so use a hardcoded size instead.
if (aWidgetType == NS_THEME_SCALETHUMB_HORIZONTAL ||
(aWidgetType == NS_THEME_RANGE_THUMB && IsRangeHorizontal(aFrame))) {
aResult->width = 12;
aResult->height = 20;
} else {
aResult->width = 20;
aResult->height = 12;
if (IsVistaOrLater()) {
if (aWidgetType == NS_THEME_SCALETHUMB_HORIZONTAL ||
(aWidgetType == NS_THEME_RANGE_THUMB && IsRangeHorizontal(aFrame))) {
aResult->width = 12;
aResult->height = 20;
}
else {
aResult->width = 20;
aResult->height = 12;
}
ScaleForFrameDPI(aResult, aFrame);
return rv;
}
ScaleForFrameDPI(aResult, aFrame);
return rv;
break;
}
case NS_THEME_SCROLLBAR:
@ -2254,6 +2443,11 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aF
// stores that info in nsUXThemeData.
aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_RESTORE].cx;
aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_RESTORE].cy;
// For XP, subtract 4 from system metrics dimensions.
if (!IsVistaOrLater()) {
aResult->width -= 4;
aResult->height -= 4;
}
AddPaddingRect(aResult, CAPTIONBUTTON_RESTORE);
*aIsOverridable = false;
return rv;
@ -2261,6 +2455,10 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aF
case NS_THEME_WINDOW_BUTTON_MINIMIZE:
aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_MINIMIZE].cx;
aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_MINIMIZE].cy;
if (!IsVistaOrLater()) {
aResult->width -= 4;
aResult->height -= 4;
}
AddPaddingRect(aResult, CAPTIONBUTTON_MINIMIZE);
*aIsOverridable = false;
return rv;
@ -2268,6 +2466,10 @@ nsNativeThemeWin::GetMinimumWidgetSize(nsPresContext* aPresContext, nsIFrame* aF
case NS_THEME_WINDOW_BUTTON_CLOSE:
aResult->width = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_CLOSE].cx;
aResult->height = nsUXThemeData::sCommandButtons[CMDBUTTONIDX_CLOSE].cy;
if (!IsVistaOrLater()) {
aResult->width -= 4;
aResult->height -= 4;
}
AddPaddingRect(aResult, CAPTIONBUTTON_CLOSE);
*aIsOverridable = false;
return rv;
@ -2397,9 +2599,18 @@ nsNativeThemeWin::WidgetStateChanged(nsIFrame* aFrame, uint8_t aWidgetType,
return NS_OK;
}
// On Vista, the scrollbar buttons need to change state when the track has/doesn't have hover
if (!IsVistaOrLater() &&
(aWidgetType == NS_THEME_SCROLLBAR_VERTICAL ||
aWidgetType == NS_THEME_SCROLLBAR_HORIZONTAL)) {
*aShouldRepaint = false;
return NS_OK;
}
// We need to repaint the dropdown arrow in vista HTML combobox controls when
// the control is closed to get rid of the hover effect.
if ((aWidgetType == NS_THEME_MENULIST || aWidgetType == NS_THEME_MENULIST_BUTTON) &&
if (IsVistaOrLater() &&
(aWidgetType == NS_THEME_MENULIST || aWidgetType == NS_THEME_MENULIST_BUTTON) &&
IsHTMLContent(aFrame))
{
*aShouldRepaint = true;

View File

@ -117,7 +117,8 @@ protected:
void DrawThemedProgressMeter(nsIFrame* aFrame, int aWidgetType,
HANDLE aTheme, HDC aHdc,
int aPart, int aState,
RECT* aWidgetRect, RECT* aClipRect);
RECT* aWidgetRect, RECT* aClipRect,
gfxFloat aAppUnits);
private:
TimeStamp mProgressDeterminateTimeStamp;

View File

@ -67,7 +67,7 @@
#define SP_GRIPPERHOR 8
#define SP_GRIPPERVERT 9
// Implicit hover state.
// Vista only; implict hover state.
// BASE + 0 = UP, + 1 = DOWN, etc.
#define SP_BUTTON_IMPLICIT_HOVER_BASE 17

View File

@ -143,8 +143,10 @@ nsUXThemeData::InitTitlebarInfo()
sCommandButtons[3].cx = sCommandButtons[0].cx * 3;
sCommandButtons[3].cy = sCommandButtons[0].cy;
// Trigger a refresh on the next layout.
sTitlebarInfoPopulatedAero = sTitlebarInfoPopulatedThemed = false;
// Use system metrics for pre-vista, otherwise trigger a
// refresh on the next layout.
sTitlebarInfoPopulatedAero = sTitlebarInfoPopulatedThemed =
!IsVistaOrLater();
}
// static
@ -304,7 +306,7 @@ void
nsUXThemeData::UpdateNativeThemeInfo()
{
// Trigger a refresh of themed button metrics if needed
sTitlebarInfoPopulatedThemed = false;
sTitlebarInfoPopulatedThemed = !IsVistaOrLater();
sIsDefaultWindowsTheme = false;
sThemeId = LookAndFeel::eWindowsTheme_Generic;

View File

@ -17,6 +17,155 @@
#include "mozilla/EventForwards.h"
#include "mozilla/TouchEvents.h"
// Desktop builds target apis for 502. Win8 Metro builds target 602.
#if WINVER < 0x0602
DECLARE_HANDLE(HGESTUREINFO);
/*
* Gesture flags - GESTUREINFO.dwFlags
*/
#define GF_BEGIN 0x00000001
#define GF_INERTIA 0x00000002
#define GF_END 0x00000004
/*
* Gesture configuration structure
* - Used in SetGestureConfig and GetGestureConfig
* - Note that any setting not included in either GESTURECONFIG.dwWant or
* GESTURECONFIG.dwBlock will use the parent window's preferences or
* system defaults.
*/
typedef struct tagGESTURECONFIG {
DWORD dwID; // gesture ID
DWORD dwWant; // settings related to gesture ID that are to be turned on
DWORD dwBlock; // settings related to gesture ID that are to be turned off
} GESTURECONFIG, *PGESTURECONFIG;
/*
* Gesture information structure
* - Pass the HGESTUREINFO received in the WM_GESTURE message lParam into the
* GetGestureInfo function to retrieve this information.
* - If cbExtraArgs is non-zero, pass the HGESTUREINFO received in the WM_GESTURE
* message lParam into the GetGestureExtraArgs function to retrieve extended
* argument information.
*/
typedef struct tagGESTUREINFO {
UINT cbSize; // size, in bytes, of this structure (including variable length Args field)
DWORD dwFlags; // see GF_* flags
DWORD dwID; // gesture ID, see GID_* defines
HWND hwndTarget; // handle to window targeted by this gesture
POINTS ptsLocation; // current location of this gesture
DWORD dwInstanceID; // internally used
DWORD dwSequenceID; // internally used
ULONGLONG ullArguments; // arguments for gestures whose arguments fit in 8 BYTES
UINT cbExtraArgs; // size, in bytes, of extra arguments, if any, that accompany this gesture
} GESTUREINFO, *PGESTUREINFO;
typedef GESTUREINFO const * PCGESTUREINFO;
/*
* Gesture notification structure
* - The WM_GESTURENOTIFY message lParam contains a pointer to this structure.
* - The WM_GESTURENOTIFY message notifies a window that gesture recognition is
* in progress and a gesture will be generated if one is recognized under the
* current gesture settings.
*/
typedef struct tagGESTURENOTIFYSTRUCT {
UINT cbSize; // size, in bytes, of this structure
DWORD dwFlags; // unused
HWND hwndTarget; // handle to window targeted by the gesture
POINTS ptsLocation; // starting location
DWORD dwInstanceID; // internally used
} GESTURENOTIFYSTRUCT, *PGESTURENOTIFYSTRUCT;
/*
* Gesture argument helpers
* - Angle should be a double in the range of -2pi to +2pi
* - Argument should be an unsigned 16-bit value
*/
#define GID_ROTATE_ANGLE_TO_ARGUMENT(_arg_) ((USHORT)((((_arg_) + 2.0 * 3.14159265) / (4.0 * 3.14159265)) * 65535.0))
#define GID_ROTATE_ANGLE_FROM_ARGUMENT(_arg_) ((((double)(_arg_) / 65535.0) * 4.0 * 3.14159265) - 2.0 * 3.14159265)
/*
* Gesture configuration flags
*/
#define GC_ALLGESTURES 0x00000001
#define GC_ZOOM 0x00000001
#define GC_PAN 0x00000001
#define GC_PAN_WITH_SINGLE_FINGER_VERTICALLY 0x00000002
#define GC_PAN_WITH_SINGLE_FINGER_HORIZONTALLY 0x00000004
#define GC_PAN_WITH_GUTTER 0x00000008
#define GC_PAN_WITH_INERTIA 0x00000010
#define GC_ROTATE 0x00000001
#define GC_TWOFINGERTAP 0x00000001
#define GC_PRESSANDTAP 0x00000001
/*
* Gesture IDs
*/
#define GID_BEGIN 1
#define GID_END 2
#define GID_ZOOM 3
#define GID_PAN 4
#define GID_ROTATE 5
#define GID_TWOFINGERTAP 6
#define GID_PRESSANDTAP 7
// Maximum number of gestures that can be included
// in a single call to SetGestureConfig / GetGestureConfig
#define GESTURECONFIGMAXCOUNT 256
// If specified, GetGestureConfig returns consolidated configuration
// for the specified window and it's parent window chain
#define GCF_INCLUDE_ANCESTORS 0x00000001
// Window events we need to respond to or receive
#define WM_GESTURE 0x0119
#define WM_GESTURENOTIFY 0x011A
typedef struct _TOUCHINPUT {
LONG x;
LONG y;
HANDLE hSource;
DWORD dwID;
DWORD dwFlags;
DWORD dwMask;
DWORD dwTime;
ULONG_PTR dwExtraInfo;
DWORD cxContact;
DWORD cyContact;
} TOUCHINPUT, *PTOUCHINPUT;
typedef HANDLE HTOUCHINPUT;
#define WM_TOUCH 0x0240
#define TOUCHEVENTF_MOVE 0x0001
#define TOUCHEVENTF_DOWN 0x0002
#define TOUCHEVENTF_UP 0x0004
#define TOUCHEVENTF_INRANGE 0x0008
#define TOUCHEVENTF_PRIMARY 0x0010
#define TOUCHEVENTF_NOCOALESCE 0x0020
#define TOUCHEVENTF_PEN 0x0040
#define TOUCHEVENTF_PALM 0x0080
#define TOUCHINPUTMASKF_TIMEFROMSYSTEM 0x0001
#define TOUCHINPUTMASKF_EXTRAINFO 0x0002
#define TOUCHINPUTMASKF_CONTACTAREA 0x0004
#define TOUCH_COORD_TO_PIXEL(C) (C/100)
#define TWF_FINETOUCH 0x0001
#define TWF_WANTPALM 0x0002
#endif // WINVER < 0x0602
// WM_TABLET_QUERYSYSTEMGESTURESTATUS return values
#define TABLET_ROTATE_GESTURE_ENABLE 0x02000000

View File

@ -266,7 +266,8 @@ LONG nsWindow::sLastMouseDownTime = 0L;
LONG nsWindow::sLastClickCount = 0L;
BYTE nsWindow::sLastMouseButton = 0;
bool nsWindow::sHaveInitializedPrefs = false;
// Trim heap on minimize. (initialized, but still true.)
int nsWindow::sTrimOnMinimize = 2;
TriStateBool nsWindow::sHasBogusPopupsDropShadowOnMultiMonitor = TRI_UNKNOWN;
@ -789,7 +790,7 @@ nsWindow::Create(nsIWidget* aParent,
parent = nullptr;
}
if (!IsWin8OrLater() &&
if (IsVistaOrLater() && !IsWin8OrLater() &&
HasBogusPopupsDropShadowOnMultiMonitor()) {
extendedStyle |= WS_EX_COMPOSITED;
}
@ -914,13 +915,20 @@ nsWindow::Create(nsIWidget* aParent,
mDefaultIMC.Init(this);
IMEHandler::InitInputContext(this, mInputContext);
// Do some initialization work, but only if (a) it hasn't already been done,
// and (b) this is the hidden window (which is conveniently created before
// any visible windows but after the profile has been initialized).
if (!sHaveInitializedPrefs && mWindowType == eWindowType_invisible) {
// If the internal variable set by the config.trim_on_minimize pref has not
// been initialized, and if this is the hidden window (conveniently created
// before any visible windows, and after the profile has been initialized),
// do some initialization work.
if (sTrimOnMinimize == 2 && mWindowType == eWindowType_invisible) {
// Our internal trim prevention logic is effective on 2K/XP at maintaining
// the working set when windows are minimized, but on Vista and up it has
// little to no effect. Since this feature has been the source of numerous
// bugs over the years, disable it (sTrimOnMinimize=1) on Vista and up.
sTrimOnMinimize =
Preferences::GetBool("config.trim_on_minimize",
IsVistaOrLater() ? 1 : 0);
sSwitchKeyboardLayout =
Preferences::GetBool("intl.keyboard.per_window_layout", false);
sHaveInitializedPrefs = true;
}
// Query for command button metric data for rendering the titlebar. We
@ -1646,10 +1654,9 @@ bool nsWindow::IsVisible() const
// XP and Vista visual styles sometimes require window clipping regions to be applied for proper
// transparency. These routines are called on size and move operations.
// XXX this is apparently still needed in Windows 7 and later
void nsWindow::ClearThemeRegion()
{
if (!HasGlass() &&
if (IsVistaOrLater() && !HasGlass() &&
(mWindowType == eWindowType_popup && !IsPopupWithTitleBar() &&
(mPopupType == ePopupTypeTooltip || mPopupType == ePopupTypePanel))) {
SetWindowRgn(mWnd, nullptr, false);
@ -1663,7 +1670,7 @@ void nsWindow::SetThemeRegion()
// so default constants are used for part and state. At some point we might need part and
// state values from nsNativeThemeWin's GetThemePartAndState, but currently windows that
// change shape based on state haven't come up.
if (!HasGlass() &&
if (IsVistaOrLater() && !HasGlass() &&
(mWindowType == eWindowType_popup && !IsPopupWithTitleBar() &&
(mPopupType == ePopupTypeTooltip || mPopupType == ePopupTypePanel))) {
HRGN hRgn = nullptr;
@ -2080,7 +2087,13 @@ nsWindow::SetSizeMode(nsSizeMode aMode)
break;
case nsSizeMode_Minimized :
mode = SW_MINIMIZE;
// Using SW_SHOWMINIMIZED prevents the working set from being trimmed but
// keeps the window active in the tray. So after the window is minimized,
// windows will fire WM_WINDOWPOSCHANGED (OnWindowPosChanged) at which point
// we will do some additional processing to get the active window set right.
// If sTrimOnMinimize is set, we let windows handle minimization normally
// using SW_MINIMIZE.
mode = sTrimOnMinimize ? SW_MINIMIZE : SW_SHOWMINIMIZED;
break;
default :
@ -5818,6 +5831,12 @@ nsWindow::ProcessMessage(UINT msg, WPARAM& wParam, LPARAM& lParam,
case WM_SYSCOMMAND:
{
WPARAM filteredWParam = (wParam &0xFFF0);
// prevent Windows from trimming the working set. bug 76831
if (!sTrimOnMinimize && filteredWParam == SC_MINIMIZE) {
::ShowWindow(mWnd, SW_SHOWMINIMIZED);
result = true;
}
if (mSizeMode == nsSizeMode_Fullscreen &&
filteredWParam == SC_RESTORE &&
GetCurrentShowCmd(mWnd) != SW_SHOWMINIMIZED) {
@ -6435,6 +6454,14 @@ void nsWindow::OnWindowPosChanged(WINDOWPOS* wp)
else
mSizeMode = nsSizeMode_Normal;
// If !sTrimOnMinimize, we minimize windows using SW_SHOWMINIMIZED (See
// SetSizeMode for internal calls, and WM_SYSCOMMAND for external). This
// prevents the working set from being trimmed but keeps the window active.
// After the window is minimized, we need to do some touch up work on the
// active window. (bugs 76831 & 499816)
if (!sTrimOnMinimize && nsSizeMode_Minimized == mSizeMode)
ActivateOtherWindowHelper(mWnd);
#ifdef WINSTATE_DEBUG_OUTPUT
switch (mSizeMode) {
case nsSizeMode_Normal:
@ -6555,6 +6582,31 @@ void nsWindow::OnWindowPosChanged(WINDOWPOS* wp)
}
}
// static
void nsWindow::ActivateOtherWindowHelper(HWND aWnd)
{
// Find the next window that is enabled, visible, and not minimized.
HWND hwndBelow = ::GetNextWindow(aWnd, GW_HWNDNEXT);
while (hwndBelow && (!::IsWindowEnabled(hwndBelow) || !::IsWindowVisible(hwndBelow) ||
::IsIconic(hwndBelow))) {
hwndBelow = ::GetNextWindow(hwndBelow, GW_HWNDNEXT);
}
// Push ourselves to the bottom of the stack, then activate the
// next window.
::SetWindowPos(aWnd, HWND_BOTTOM, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE);
if (hwndBelow)
::SetForegroundWindow(hwndBelow);
// Play the minimize sound while we're here, since that is also
// forgotten when we use SW_SHOWMINIMIZED.
nsCOMPtr<nsISound> sound(do_CreateInstance("@mozilla.org/sound;1"));
if (sound) {
sound->PlaySystemSound(NS_LITERAL_STRING("Minimize"));
}
}
void nsWindow::OnWindowPosChanging(LPWINDOWPOS& info)
{
// Update non-client margins if the frame size is changing, and let the

View File

@ -486,6 +486,7 @@ protected:
bool aIntersectWithExisting) override;
nsIntRegion GetRegionToPaint(bool aForceFullRepaint,
PAINTSTRUCT ps, HDC aDC);
static void ActivateOtherWindowHelper(HWND aWnd);
void ClearCachedResources();
nsIWidgetListener* GetPaintListener();
@ -551,7 +552,7 @@ protected:
static bool sJustGotDeactivate;
static bool sJustGotActivate;
static bool sIsInMouseCapture;
static bool sHaveInitializedPrefs;
static int sTrimOnMinimize;
// Always use the helper method to read this property. See bug 603793.
static TriStateBool sHasBogusPopupsDropShadowOnMultiMonitor;

View File

@ -111,6 +111,7 @@ extern nsresult nsStringInputStreamConstructor(nsISupports*, REFNSIID, void**);
#include "SpecialSystemDirectory.h"
#if defined(XP_WIN)
#include "mozilla/WindowsVersion.h"
#include "nsWindowsRegKey.h"
#endif
@ -583,6 +584,8 @@ NS_InitXPCOM2(nsIServiceManager** aResult,
NS_StartupLocalFile();
StartupSpecialSystemDirectory();
nsDirectoryService::RealInit();
bool value;

View File

@ -20,10 +20,15 @@
#ifdef XP_WIN
#include <windows.h>
#include "mozilla/WindowsVersion.h"
using mozilla::IsVistaOrLater;
#elif defined(XP_MACOSX)
#include <sys/resource.h>
#endif
#include <pratom.h>
#include <prthread.h>
using namespace mozilla;
#ifndef XPCOM_GLUE_AVOID_NSPR
@ -438,7 +443,8 @@ nsThreadPoolNaming::SetThreadPoolName(const nsACString& aPoolName,
nsAutoLowPriorityIO::nsAutoLowPriorityIO()
{
#if defined(XP_WIN)
lowIOPrioritySet = SetThreadPriority(GetCurrentThread(),
lowIOPrioritySet = IsVistaOrLater() &&
SetThreadPriority(GetCurrentThread(),
THREAD_MODE_BACKGROUND_BEGIN);
#elif defined(XP_MACOSX)
oldPriority = getiopolicy_np(IOPOL_TYPE_DISK, IOPOL_SCOPE_THREAD);

View File

@ -12,6 +12,7 @@
#if defined(XP_WIN)
#include <windows.h>
#include <shlobj.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -19,6 +20,9 @@
#include <shlobj.h>
#include <knownfolders.h>
#include <guiddef.h>
#include "mozilla/WindowsVersion.h"
using mozilla::IsWin7OrLater;
#elif defined(XP_UNIX)
@ -47,17 +51,40 @@
#endif
#endif
#ifdef XP_WIN
typedef HRESULT (WINAPI* nsGetKnownFolderPath)(GUID& rfid,
DWORD dwFlags,
HANDLE hToken,
PWSTR* ppszPath);
static nsGetKnownFolderPath gGetKnownFolderPath = nullptr;
#endif
void
StartupSpecialSystemDirectory()
{
#if defined (XP_WIN)
// SHGetKnownFolderPath is only available on Windows Vista
// so that we need to use GetProcAddress to get the pointer.
HMODULE hShell32DLLInst = GetModuleHandleW(L"shell32.dll");
if (hShell32DLLInst) {
gGetKnownFolderPath = (nsGetKnownFolderPath)
GetProcAddress(hShell32DLLInst, "SHGetKnownFolderPath");
}
#endif
}
#if defined (XP_WIN)
static nsresult
GetKnownFolder(GUID* aGuid, nsIFile** aFile)
{
if (!aGuid) {
if (!aGuid || !gGetKnownFolderPath) {
return NS_ERROR_FAILURE;
}
PWSTR path = nullptr;
SHGetKnownFolderPath(*aGuid, 0, nullptr, &path);
gGetKnownFolderPath(*aGuid, 0, nullptr, &path);
if (!path) {
return NS_ERROR_FAILURE;
@ -112,13 +139,19 @@ SHLoadLibraryFromKnownFolder(REFKNOWNFOLDERID aFolderId, DWORD aMode,
}
/*
* Return the default save-to location for the Windows Library passed in
* through aFolderId.
* Check to see if we're on Win7 and up, and if so, returns the default
* save-to location for the Windows Library passed in through aFolderId.
* Otherwise falls back on pre-win7 GetWindowsFolder.
*/
static nsresult
GetLibrarySaveToPath(int aFallbackFolderId, REFKNOWNFOLDERID aFolderId,
nsIFile** aFile)
{
// Skip off checking for library support if the os is Vista or lower.
if (!IsWin7OrLater()) {
return GetWindowsFolder(aFallbackFolderId, aFile);
}
RefPtr<IShellLibrary> shellLib;
RefPtr<IShellItem> savePath;
HRESULT hr =

View File

@ -16,6 +16,9 @@
#include "prenv.h"
#endif
extern void StartupSpecialSystemDirectory();
enum SystemDirectories {
OS_DriveDirectory = 1,
OS_TemporaryDirectory = 2,

View File

@ -7,6 +7,7 @@
#include "mozilla/ArrayUtils.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/UniquePtrExtensions.h"
#include "mozilla/WindowsVersion.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
@ -1974,11 +1975,13 @@ nsLocalFile::CopySingleFile(nsIFile* aSourceFile, nsIFile* aDestParent,
// So we only use COPY_FILE_NO_BUFFERING when we have a remote drive.
int copyOK;
DWORD dwCopyFlags = COPY_FILE_ALLOW_DECRYPTED_DESTINATION;
bool path1Remote, path2Remote;
if (!IsRemoteFilePath(filePath.get(), path1Remote) ||
!IsRemoteFilePath(destPath.get(), path2Remote) ||
path1Remote || path2Remote) {
dwCopyFlags |= COPY_FILE_NO_BUFFERING;
if (IsVistaOrLater()) {
bool path1Remote, path2Remote;
if (!IsRemoteFilePath(filePath.get(), path1Remote) ||
!IsRemoteFilePath(destPath.get(), path2Remote) ||
path1Remote || path2Remote) {
dwCopyFlags |= COPY_FILE_NO_BUFFERING;
}
}
if (FilePreferences::IsBlockedUNCPath(destPath)) {