From 74c6c585ab519e3314bdf6b0fa23d8aa757b78a5 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Fri, 24 Aug 2018 13:21:17 +0200 Subject: Introduce ui.menu.allow_content_scroll When true, overrides the OS convention to prevent scrolling of content when contextual menus are open. This resolves #730. --- widget/windows/nsWindow.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'widget') diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index b2bb59bd3..5ce0117b0 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -366,6 +366,9 @@ static const int32_t kResizableBorderMinSize = 3; // Cached pointer events enabler value, True if pointer events are enabled. static bool gIsPointerEventsEnabled = false; +// Cached scroll outside menu enabler value, True if scrolling is allowed. +static bool gIsScrollingOutsideEnabled = false; + // We should never really try to accelerate windows bigger than this. In some // cases this might lead to no D3D9 acceleration where we could have had it // but D3D9 does not reliably report when it supports bigger windows. 8192 @@ -665,6 +668,10 @@ nsWindow::nsWindow() Preferences::AddBoolVarCache(&gIsPointerEventsEnabled, "dom.w3c_pointer_events.enabled", gIsPointerEventsEnabled); + Preferences::AddBoolVarCache(&gIsScrollingOutsideEnabled, + "ui.menu.allow_content_scroll", + gIsScrollingOutsideEnabled); + } // !sInstanceCount mIdleService = nullptr; @@ -7703,7 +7710,8 @@ nsWindow::DealWithPopups(HWND aWnd, UINT aMessage, break; } } - return consumeRollupEvent; + // Consume event if appropriate unless overridden. + return consumeRollupEvent && !gIsScrollingOutsideEnabled; case WM_ACTIVATEAPP: break; -- cgit v1.2.3 From ab961aeb54335fd07c66de2e3b8c3b6af6f89ea2 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Mon, 3 Sep 2018 10:11:38 +0200 Subject: Remove all C++ Telemetry Accumulation calls. This creates a number of stubs and leaves some surrounding code that may be irrelevant (eg. recorded time stamps, status variables). Stub resolution/removal should be a follow-up to this. --- widget/android/fennec/Telemetry.h | 3 --- widget/windows/nsLookAndFeel.cpp | 3 --- widget/windows/nsWindow.cpp | 6 ------ 3 files changed, 12 deletions(-) (limited to 'widget') diff --git a/widget/android/fennec/Telemetry.h b/widget/android/fennec/Telemetry.h index c72735496..458889ef0 100644 --- a/widget/android/fennec/Telemetry.h +++ b/widget/android/fennec/Telemetry.h @@ -44,7 +44,6 @@ public: AddHistogram(jni::String::Param aName, int32_t aValue) { MOZ_ASSERT(aName); - mozilla::Telemetry::Accumulate(aName->ToCString().get(), aValue); } static void @@ -52,8 +51,6 @@ public: int32_t aValue) { MOZ_ASSERT(aName && aKey); - mozilla::Telemetry::Accumulate(aName->ToCString().get(), - aKey->ToCString(), aValue); } static void diff --git a/widget/windows/nsLookAndFeel.cpp b/widget/windows/nsLookAndFeel.cpp index 97f81abfd..a907622d9 100644 --- a/widget/windows/nsLookAndFeel.cpp +++ b/widget/windows/nsLookAndFeel.cpp @@ -11,7 +11,6 @@ #include "nsUXThemeConstants.h" #include "gfxFont.h" #include "WinUtils.h" -#include "mozilla/Telemetry.h" #include "mozilla/WindowsVersion.h" #include "gfxFontConstants.h" @@ -65,8 +64,6 @@ nsLookAndFeel::nsLookAndFeel() : nsXPLookAndFeel() , mUseAccessibilityTheme(0) { - mozilla::Telemetry::Accumulate(mozilla::Telemetry::TOUCH_ENABLED_DEVICE, - WinUtils::IsTouchDeviceSupportPresent()); } nsLookAndFeel::~nsLookAndFeel() diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 5ce0117b0..122d18686 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -4232,10 +4232,6 @@ nsWindow::DispatchMouseEvent(EventMessage aEventMessage, WPARAM wParam, } if (WinUtils::GetIsMouseFromTouch(aEventMessage)) { - if (aEventMessage == eMouseDown) { - Telemetry::Accumulate(Telemetry::FX_TOUCH_USED, 1); - } - if (mTouchWindow) { // If mTouchWindow is true, then we must have APZ enabled and be // feeding it raw touch events. In that case we don't need to @@ -6750,8 +6746,6 @@ bool nsWindow::OnGesture(WPARAM wParam, LPARAM lParam) bool endFeedback = true; if (mGesture.PanDeltaToPixelScroll(wheelEvent)) { - mozilla::Telemetry::Accumulate(mozilla::Telemetry::SCROLL_INPUT_METHODS, - (uint32_t) ScrollInputMethod::MainThreadTouch); DispatchEvent(&wheelEvent, status); } -- cgit v1.2.3 From 93cae908bcbd063f21d5663a7d3149464af2ad20 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 4 Sep 2018 09:41:24 +0200 Subject: Remove all C++ telemetry autotimers --- widget/nsIdleService.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'widget') diff --git a/widget/nsIdleService.cpp b/widget/nsIdleService.cpp index 6a2833081..a1a2566df 100644 --- a/widget/nsIdleService.cpp +++ b/widget/nsIdleService.cpp @@ -716,9 +716,6 @@ nsIdleService::IdleTimerCallback(void) return; } - // Tell expired listeners they are expired,and find the next timeout - Telemetry::AutoTimer timer; - // We need to initialise the time to the next idle switch. mDeltaToNextIdleSwitchInS = UINT32_MAX; -- cgit v1.2.3 From 6ded94d38cf94a5da8d6a73dfbfca2acb0d719cc Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Tue, 11 Sep 2018 11:55:16 +0200 Subject: Bug 1467363 - Protect access to mTransparentSurface with a lock. --- widget/windows/WinCompositorWidget.cpp | 8 ++++++++ widget/windows/WinCompositorWidget.h | 4 ++++ widget/windows/nsWindowGfx.cpp | 2 ++ 3 files changed, 14 insertions(+) (limited to 'widget') diff --git a/widget/windows/WinCompositorWidget.cpp b/widget/windows/WinCompositorWidget.cpp index f660bd019..99ce67573 100644 --- a/widget/windows/WinCompositorWidget.cpp +++ b/widget/windows/WinCompositorWidget.cpp @@ -22,6 +22,7 @@ using namespace mozilla::gfx; WinCompositorWidget::WinCompositorWidget(const CompositorWidgetInitData& aInitData) : mWidgetKey(aInitData.widgetKey()), mWnd(reinterpret_cast(aInitData.hWnd())), + mTransparentSurfaceLock("mTransparentSurfaceLock"), mTransparencyMode(static_cast(aInitData.transparencyMode())), mMemoryDC(nullptr), mCompositeDC(nullptr), @@ -39,6 +40,7 @@ WinCompositorWidget::WinCompositorWidget(const CompositorWidgetInitData& aInitDa void WinCompositorWidget::OnDestroyWindow() { + MutexAutoLock lock(mTransparentSurfaceLock); mTransparentSurface = nullptr; mMemoryDC = nullptr; } @@ -75,6 +77,8 @@ WinCompositorWidget::GetClientSize() already_AddRefed WinCompositorWidget::StartRemoteDrawing() { + MutexAutoLock lock(mTransparentSurfaceLock); + MOZ_ASSERT(!mCompositeDC); RefPtr surf; @@ -229,6 +233,7 @@ WinCompositorWidget::LeavePresentLock() RefPtr WinCompositorWidget::EnsureTransparentSurface() { + mTransparentSurfaceLock.AssertCurrentThreadOwns(); MOZ_ASSERT(mTransparencyMode == eTransparencyTransparent); IntSize size = GetClientSize().ToUnknownSize(); @@ -245,6 +250,7 @@ WinCompositorWidget::EnsureTransparentSurface() void WinCompositorWidget::CreateTransparentSurface(const gfx::IntSize& aSize) { + mTransparentSurfaceLock.AssertCurrentThreadOwns(); MOZ_ASSERT(!mTransparentSurface && !mMemoryDC); RefPtr surface = new gfxWindowsSurface(aSize, SurfaceFormat::A8R8G8B8_UINT32); mTransparentSurface = surface; @@ -254,6 +260,7 @@ WinCompositorWidget::CreateTransparentSurface(const gfx::IntSize& aSize) void WinCompositorWidget::UpdateTransparency(nsTransparencyMode aMode) { + MutexAutoLock lock(mTransparentSurfaceLock); if (mTransparencyMode == aMode) { return; } @@ -270,6 +277,7 @@ WinCompositorWidget::UpdateTransparency(nsTransparencyMode aMode) void WinCompositorWidget::ClearTransparentWindow() { + MutexAutoLock lock(mTransparentSurfaceLock); if (!mTransparentSurface) { return; } diff --git a/widget/windows/WinCompositorWidget.h b/widget/windows/WinCompositorWidget.h index 9661cab45..1689a8641 100644 --- a/widget/windows/WinCompositorWidget.h +++ b/widget/windows/WinCompositorWidget.h @@ -10,6 +10,7 @@ #include "gfxASurface.h" #include "mozilla/gfx/CriticalSection.h" #include "mozilla/gfx/Point.h" +#include "mozilla/Mutex.h" #include "nsIWidget.h" class nsWindow; @@ -83,6 +84,8 @@ public: return mWnd; } + mozilla::Mutex& GetTransparentSurfaceLock() { return mTransparentSurfaceLock; } + private: HDC GetWindowSurface(); void FreeWindowSurface(HDC dc); @@ -95,6 +98,7 @@ private: gfx::CriticalSection mPresentLock; // Transparency handling. + mozilla::Mutex mTransparentSurfaceLock; nsTransparencyMode mTransparencyMode; RefPtr mTransparentSurface; HDC mMemoryDC; diff --git a/widget/windows/nsWindowGfx.cpp b/widget/windows/nsWindowGfx.cpp index a88631f89..9b303a0f2 100644 --- a/widget/windows/nsWindowGfx.cpp +++ b/widget/windows/nsWindowGfx.cpp @@ -320,6 +320,8 @@ bool nsWindow::OnPaint(HDC aDC, uint32_t aNestingLevel) #if defined(MOZ_XUL) // don't support transparency for non-GDI rendering, for now if (eTransparencyTransparent == mTransparencyMode) { + // This mutex needs to be held when EnsureTransparentSurface is called. + MutexAutoLock lock(mBasicLayersSurface->GetTransparentSurfaceLock()); targetSurface = mBasicLayersSurface->EnsureTransparentSurface(); } #endif -- cgit v1.2.3 From 7214d60a1266d1ddd7ef2be6ae80a04a9a01ee03 Mon Sep 17 00:00:00 2001 From: Mihail Zenkov Date: Thu, 20 Sep 2018 00:13:34 +0300 Subject: Fix timer overflow on converting from sec to msec in idleService --- widget/nsIdleService.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'widget') diff --git a/widget/nsIdleService.cpp b/widget/nsIdleService.cpp index a1a2566df..f9904d39c 100644 --- a/widget/nsIdleService.cpp +++ b/widget/nsIdleService.cpp @@ -46,6 +46,10 @@ using namespace mozilla; // Number of seconds in a day. #define SECONDS_PER_DAY 86400 +// MAX_DELTA_SEC * 1000 should be less than UINT32_MAX to prevent overflow on +// converting from sec to msec +#define MAX_DELTA_SEC (SECONDS_PER_DAY * 10) + static PRLogModuleInfo *sLog = nullptr; #define LOG_TAG "GeckoIdleService" @@ -391,7 +395,7 @@ nsIdleService::GetInstance() nsIdleService::nsIdleService() : mCurrentlySetToTimeoutAt(TimeStamp()), mIdleObserverCount(0), - mDeltaToNextIdleSwitchInS(UINT32_MAX), + mDeltaToNextIdleSwitchInS(MAX_DELTA_SEC), mLastUserInteraction(TimeStamp::Now()) { if (sLog == nullptr) @@ -544,7 +548,7 @@ nsIdleService::ResetIdleTimeOut(uint32_t idleDeltaInMS) // Mark all idle services as non-idle, and calculate the next idle timeout. nsCOMArray notifyList; - mDeltaToNextIdleSwitchInS = UINT32_MAX; + mDeltaToNextIdleSwitchInS = MAX_DELTA_SEC; // Loop through all listeners, and find any that have detected idle. for (uint32_t i = 0; i < mArrayListeners.Length(); i++) { @@ -717,7 +721,7 @@ nsIdleService::IdleTimerCallback(void) } // We need to initialise the time to the next idle switch. - mDeltaToNextIdleSwitchInS = UINT32_MAX; + mDeltaToNextIdleSwitchInS = MAX_DELTA_SEC; // Create list of observers that should be notified. nsCOMArray notifyList; @@ -839,7 +843,7 @@ void nsIdleService::ReconfigureTimer(void) { // Check if either someone is idle, or someone will become idle. - if ((mIdleObserverCount == 0) && UINT32_MAX == mDeltaToNextIdleSwitchInS) { + if ((mIdleObserverCount == 0) && MAX_DELTA_SEC == mDeltaToNextIdleSwitchInS) { // If not, just let any existing timers run to completion // And bail out. MOZ_LOG(sLog, LogLevel::Debug, -- cgit v1.2.3 From e0de8181d9d51cff079f9b54fd6fa276d6aeb094 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Thu, 1 Nov 2018 20:16:11 +0100 Subject: Protect main thread in-process access to WinCompositorWidget transparent surface. --- widget/windows/InProcessWinCompositorWidget.cpp | 25 +++++++++++++++++++++++++ widget/windows/InProcessWinCompositorWidget.h | 4 ++++ 2 files changed, 29 insertions(+) (limited to 'widget') diff --git a/widget/windows/InProcessWinCompositorWidget.cpp b/widget/windows/InProcessWinCompositorWidget.cpp index 685eaf5ca..a11790b32 100644 --- a/widget/windows/InProcessWinCompositorWidget.cpp +++ b/widget/windows/InProcessWinCompositorWidget.cpp @@ -23,6 +23,31 @@ InProcessWinCompositorWidget::InProcessWinCompositorWidget(const CompositorWidge MOZ_ASSERT(mWindow); } +void +InProcessWinCompositorWidget::OnDestroyWindow() +{ + EnterPresentLock(); + WinCompositorWidget::OnDestroyWindow(); + LeavePresentLock(); +} + +void +InProcessWinCompositorWidget::UpdateTransparency(nsTransparencyMode aMode) +{ + EnterPresentLock(); + WinCompositorWidget::UpdateTransparency(aMode); + LeavePresentLock(); +} + +void +InProcessWinCompositorWidget::ClearTransparentWindow() +{ + EnterPresentLock(); + WinCompositorWidget::ClearTransparentWindow(); + LeavePresentLock(); +} + + nsIWidget* InProcessWinCompositorWidget::RealWidget() { diff --git a/widget/windows/InProcessWinCompositorWidget.h b/widget/windows/InProcessWinCompositorWidget.h index 2ce6ba0be..afe5a7f53 100644 --- a/widget/windows/InProcessWinCompositorWidget.h +++ b/widget/windows/InProcessWinCompositorWidget.h @@ -22,6 +22,10 @@ class InProcessWinCompositorWidget final : public WinCompositorWidget public: InProcessWinCompositorWidget(const CompositorWidgetInitData& aInitData, nsWindow* aWindow); + void OnDestroyWindow() override; + void UpdateTransparency(nsTransparencyMode aMode) override; + void ClearTransparentWindow() override; + void ObserveVsync(VsyncObserver* aObserver) override; nsIWidget* RealWidget() override; -- cgit v1.2.3 From 09fec033ec18a5c0eb29815924114016cee32a00 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Fri, 2 Nov 2018 08:33:16 +0100 Subject: Don't allocate PendingAction twice. --- widget/windows/TSFTextStore.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'widget') diff --git a/widget/windows/TSFTextStore.cpp b/widget/windows/TSFTextStore.cpp index 7224126b8..c80de831c 100644 --- a/widget/windows/TSFTextStore.cpp +++ b/widget/windows/TSFTextStore.cpp @@ -4247,14 +4247,14 @@ TSFTextStore::InsertTextAtSelectionInternal(const nsAString& aInsertStr, TS_SELECTION_ACP oldSelection = contentForTSF.Selection().ACP(); if (!mComposition.IsComposing()) { // Use a temporary composition to contain the text - PendingAction* compositionStart = mPendingActions.AppendElement(); + PendingAction* compositionStart = mPendingActions.AppendElements(2); + PendingAction* compositionEnd = compositionStart + 1; compositionStart->mType = PendingAction::COMPOSITION_START; compositionStart->mSelectionStart = oldSelection.acpStart; compositionStart->mSelectionLength = oldSelection.acpEnd - oldSelection.acpStart; compositionStart->mAdjustSelection = false; - PendingAction* compositionEnd = mPendingActions.AppendElement(); compositionEnd->mType = PendingAction::COMPOSITION_END; compositionEnd->mData = aInsertStr; @@ -4455,10 +4455,12 @@ TSFTextStore::RecordCompositionEndAction() } // When only setting selection is necessary, we should append it. if (pendingAction.mAdjustSelection) { + LONG selectionStart = pendingAction.mSelectionStart; + LONG selectionLength = pendingAction.mSelectionLength; PendingAction* setSelection = mPendingActions.AppendElement(); setSelection->mType = PendingAction::SET_SELECTION; - setSelection->mSelectionStart = pendingAction.mSelectionStart; - setSelection->mSelectionLength = pendingAction.mSelectionLength; + setSelection->mSelectionStart = selectionStart; + setSelection->mSelectionLength = selectionLength; setSelection->mSelectionReversed = false; } // Remove the redundant pending composition. -- cgit v1.2.3 From 7504ca8ab4b0a145488f03c51a0f78ffd5682174 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Mon, 26 Nov 2018 16:41:20 +0100 Subject: Remove VR hardware support. This resolves #881 --- widget/nsBaseWidget.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'widget') diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index 909660f71..c6ec3a406 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -73,7 +73,6 @@ #endif #include "gfxConfig.h" #include "mozilla/layers/CompositorSession.h" -#include "VRManagerChild.h" #ifdef DEBUG #include "nsIObserver.h" @@ -366,7 +365,6 @@ nsBaseWidget::OnRenderingDeviceReset() // Update the texture factory identifier. clm->UpdateTextureFactoryIdentifier(identifier); ImageBridgeChild::IdentifyCompositorTextureHost(identifier); - gfx::VRManagerChild::IdentifyTextureHost(identifier); } void @@ -1377,7 +1375,6 @@ void nsBaseWidget::CreateCompositor(int aWidth, int aHeight) // compositors used with ImageBridge and VR (and more generally web content). if (WidgetTypeSupportsAcceleration()) { ImageBridgeChild::IdentifyCompositorTextureHost(textureFactoryIdentifier); - gfx::VRManagerChild::IdentifyTextureHost(textureFactoryIdentifier); } } -- cgit v1.2.3 From 0b6d9a47051be9ef4d064c6f7c60717da91d0bc2 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 7 Feb 2019 14:08:09 +0100 Subject: Handle pasted data of certain types with an odd length. --- widget/windows/nsClipboard.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'widget') diff --git a/widget/windows/nsClipboard.cpp b/widget/windows/nsClipboard.cpp index 0db1dd342..432badeb5 100644 --- a/widget/windows/nsClipboard.cpp +++ b/widget/windows/nsClipboard.cpp @@ -283,16 +283,19 @@ nsresult nsClipboard::GetGlobalData(HGLOBAL aHGBL, void ** aData, uint32_t * aLe { // Allocate a new memory buffer and copy the data from global memory. // Recall that win98 allocates to nearest DWORD boundary. As a safety - // precaution, allocate an extra 2 bytes (but don't report them!) and - // null them out to ensure that all of our strlen calls will succeed. + // precaution, allocate an extra 3 bytes (but don't report them in |aLen|!) + // and null them out to ensure that all of our NS_strlen calls will succeed. + // NS_strlen operates on char16_t, so we need 3 NUL bytes to ensure it finds + // a full NUL char16_t when |*aLen| is odd. nsresult result = NS_ERROR_FAILURE; if (aHGBL != nullptr) { LPSTR lpStr = (LPSTR) GlobalLock(aHGBL); DWORD allocSize = GlobalSize(aHGBL); - char* data = static_cast(malloc(allocSize + sizeof(char16_t))); + char* data = static_cast(malloc(allocSize + 3)); if ( data ) { memcpy ( data, lpStr, allocSize ); - data[allocSize] = data[allocSize + 1] = '\0'; // null terminate for safety + data[allocSize] = data[allocSize + 1] = data[allocSize + 2] = + '\0'; // null terminate for safety GlobalUnlock(aHGBL); *aData = data; -- cgit v1.2.3 From 6992106dc7894fab3f620263e99b4083b36bf9e8 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Thu, 7 Feb 2019 22:06:24 +0100 Subject: Use existing image decoders to handle clipboard BMP data. This gets rid of the old nsImageClipboard widget code in favor of using the nsBMPDecoder in imglib. --- widget/windows/moz.build | 1 - widget/windows/nsClipboard.cpp | 47 +++- widget/windows/nsDataObj.cpp | 126 +++++---- widget/windows/nsImageClipboard.cpp | 497 ------------------------------------ widget/windows/nsImageClipboard.h | 93 ------- widget/windows/nsNativeThemeWin.cpp | 2 + 6 files changed, 120 insertions(+), 646 deletions(-) delete mode 100644 widget/windows/nsImageClipboard.cpp delete mode 100644 widget/windows/nsImageClipboard.h (limited to 'widget') diff --git a/widget/windows/moz.build b/widget/windows/moz.build index 1e7fc4b02..4a449de95 100644 --- a/widget/windows/moz.build +++ b/widget/windows/moz.build @@ -41,7 +41,6 @@ UNIFIED_SOURCES += [ 'nsDataObjCollection.cpp', 'nsDragService.cpp', 'nsIdleServiceWin.cpp', - 'nsImageClipboard.cpp', 'nsLookAndFeel.cpp', 'nsNativeDragSource.cpp', 'nsNativeDragTarget.cpp', diff --git a/widget/windows/nsClipboard.cpp b/widget/windows/nsClipboard.cpp index 432badeb5..c93f351c8 100644 --- a/widget/windows/nsClipboard.cpp +++ b/widget/windows/nsClipboard.cpp @@ -26,7 +26,6 @@ #include "nsReadableUtils.h" #include "nsUnicharUtils.h" #include "nsPrimitiveHelpers.h" -#include "nsImageClipboard.h" #include "nsIWidget.h" #include "nsIComponentManager.h" #include "nsWidgetsCID.h" @@ -36,6 +35,8 @@ #include "nsIOutputStream.h" #include "nsEscape.h" #include "nsIObserverService.h" +#include "nsMimeTypes.h" +#include "imgITools.h" using mozilla::LogLevel; @@ -474,17 +475,45 @@ nsresult nsClipboard::GetNativeDataOffClipboard(IDataObject * aDataObject, UINT if (aMIMEImageFormat) { uint32_t allocLen = 0; - unsigned char * clipboardData; + const char * clipboardData; if (NS_SUCCEEDED(GetGlobalData(stm.hGlobal, (void **)&clipboardData, &allocLen))) { - nsImageFromClipboard converter; - nsIInputStream * inputStream; - converter.GetEncodedImageStream(clipboardData, aMIMEImageFormat, &inputStream); // addrefs for us, don't release - if ( inputStream ) { - *aData = inputStream; - *aLen = sizeof(nsIInputStream*); - result = NS_OK; + nsCOMPtr container; + nsCOMPtr imgTools = do_CreateInstance("@mozilla.org/image/tools;1"); + nsCOMPtr inputStream; + nsresult rv = NS_NewByteInputStream(getter_AddRefs(inputStream), + clipboardData, + allocLen, + NS_ASSIGNMENT_DEPEND); + NS_ENSURE_SUCCESS(rv, rv); + + result = imgTools->DecodeImage(inputStream, + NS_LITERAL_CSTRING(IMAGE_BMP_MS_CLIPBOARD), + getter_AddRefs(container)); + if (NS_FAILED(result)) { + break; } + + nsAutoCString mimeType; + if (strcmp(aMIMEImageFormat, kJPGImageMime) == 0) { + mimeType.Assign(IMAGE_JPEG); + } else { + mimeType.Assign(aMIMEImageFormat); + } + + result = imgTools->EncodeImage(container, mimeType, EmptyString(), + getter_AddRefs(inputStream)); + if (NS_FAILED(result)) { + break; + } + + if (!inputStream) { + result = NS_ERROR_FAILURE; + break; + } + + *aData = inputStream.forget().take(); + *aLen = sizeof(nsIInputStream*); } } break; diff --git a/widget/windows/nsDataObj.cpp b/widget/windows/nsDataObj.cpp index 977a87c08..ee2db7b65 100644 --- a/widget/windows/nsDataObj.cpp +++ b/widget/windows/nsDataObj.cpp @@ -17,7 +17,6 @@ #include "IEnumFE.h" #include "nsPrimitiveHelpers.h" #include "nsXPIDLString.h" -#include "nsImageClipboard.h" #include "nsCRT.h" #include "nsPrintfCString.h" #include "nsIStringBundle.h" @@ -35,6 +34,8 @@ #include "nsIContentPolicy.h" #include "nsContentUtils.h" #include "nsIPrincipal.h" +#include "nsMimeTypes.h" +#include "imgITools.h" #include "WinUtils.h" #include "mozilla/LazyIdleThread.h" @@ -45,6 +46,7 @@ using namespace mozilla; using namespace mozilla::widget; +#define BFH_LENGTH 14 #define DEFAULT_THREAD_TIMEOUT_MS 30000 NS_IMPL_ISUPPORTS(nsDataObj::CStream, nsIStreamListener) @@ -917,20 +919,60 @@ nsDataObj::GetDib(const nsACString& inFlavor, } if ( image ) { - // use the |nsImageToClipboard| helper class to build up a bitmap. We now own - // the bits, and pass them back to the OS in |aSTG|. - nsImageToClipboard converter(image, aFormat.cfFormat == CF_DIBV5); - HANDLE bits = nullptr; - nsresult rv = converter.GetPicture ( &bits ); - if ( NS_SUCCEEDED(rv) && bits ) { - aSTG.hGlobal = bits; - aSTG.tymed = TYMED_HGLOBAL; - result = S_OK; + nsCOMPtr imgTools = do_CreateInstance("@mozilla.org/image/tools;1"); + + nsAutoString options; + if (aFormat.cfFormat == CF_DIBV5) { + options.AppendLiteral("version=5"); + } else { + options.AppendLiteral("version=3"); + } + + nsCOMPtr inputStream; + nsresult rv = imgTools->EncodeImage(image, NS_LITERAL_CSTRING(IMAGE_BMP), + options, getter_AddRefs(inputStream)); + if (NS_FAILED(rv) || !inputStream) { + return E_FAIL; } - } // if we have an image - else + + nsCOMPtr encoder = do_QueryInterface(inputStream); + if (!encoder) { + return E_FAIL; + } + + uint32_t size = 0; + rv = encoder->GetImageBufferUsed(&size); + if (NS_FAILED(rv) || size <= BFH_LENGTH) { + return E_FAIL; + } + + char *src = nullptr; + rv = encoder->GetImageBuffer(&src); + if (NS_FAILED(rv) || !src) { + return E_FAIL; + } + + // We don't want the file header. + src += BFH_LENGTH; + size -= BFH_LENGTH; + + HGLOBAL glob = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, size); + if (!glob) { + DWORD err = ::GetLastError(); + return E_FAIL; + } + + char *dst = (char*) ::GlobalLock(glob); + ::CopyMemory(dst, src, size); + ::GlobalUnlock(glob); + + aSTG.hGlobal = glob; + aSTG.tymed = TYMED_HGLOBAL; + result = S_OK; + } else { NS_WARNING ( "Definitely not an image on clipboard" ); - return result; + } + return result; } @@ -1535,18 +1577,29 @@ HRESULT nsDataObj::DropImage(FORMATETC& aFE, STGMEDIUM& aSTG) if (!image) return E_FAIL; - // Use the clipboard helper class to build up a memory bitmap. - nsImageToClipboard converter(image); - HANDLE bits = nullptr; - rv = converter.GetPicture(&bits); // Clipboard routines return a global handle we own. + nsCOMPtr imgTools = do_CreateInstance("@mozilla.org/image/tools;1"); + nsCOMPtr inputStream; + rv = imgTools->EncodeImage(image, NS_LITERAL_CSTRING(IMAGE_BMP), + NS_LITERAL_STRING("version=3"), + getter_AddRefs(inputStream)); + if (NS_FAILED(rv) || !inputStream) { + return E_FAIL; + } + + nsCOMPtr encoder = do_QueryInterface(inputStream); + if (!encoder) { + return E_FAIL; + } - if (NS_FAILED(rv) || !bits) + uint32_t size = 0; + rv = encoder->GetImageBufferUsed(&size); + if (NS_FAILED(rv)) { return E_FAIL; + } - // We now own these bits! - uint32_t bitmapSize = GlobalSize(bits); - if (!bitmapSize) { - GlobalFree(bits); + char *src = nullptr; + rv = encoder->GetImageBuffer(&src); + if (NS_FAILED(rv) || !src) { return E_FAIL; } @@ -1554,7 +1607,6 @@ HRESULT nsDataObj::DropImage(FORMATETC& aFE, STGMEDIUM& aSTG) nsCOMPtr dropFile; rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(dropFile)); if (!dropFile) { - GlobalFree(bits); return E_FAIL; } @@ -1568,7 +1620,6 @@ HRESULT nsDataObj::DropImage(FORMATETC& aFE, STGMEDIUM& aSTG) dropFile->AppendNative(filename); rv = dropFile->CreateUnique(nsIFile::NORMAL_FILE_TYPE, 0660); if (NS_FAILED(rv)) { - GlobalFree(bits); return E_FAIL; } @@ -1581,33 +1632,16 @@ HRESULT nsDataObj::DropImage(FORMATETC& aFE, STGMEDIUM& aSTG) nsCOMPtr outStream; rv = NS_NewLocalFileOutputStream(getter_AddRefs(outStream), dropFile); if (NS_FAILED(rv)) { - GlobalFree(bits); return E_FAIL; } - char * bm = (char *)GlobalLock(bits); - - BITMAPFILEHEADER fileHdr; - BITMAPINFOHEADER *bmpHdr = (BITMAPINFOHEADER*)bm; - - fileHdr.bfType = ((WORD) ('M' << 8) | 'B'); - fileHdr.bfSize = GlobalSize (bits) + sizeof(fileHdr); - fileHdr.bfReserved1 = 0; - fileHdr.bfReserved2 = 0; - fileHdr.bfOffBits = (DWORD) (sizeof(fileHdr) + bmpHdr->biSize); - - uint32_t writeCount = 0; - if (NS_FAILED(outStream->Write((const char *)&fileHdr, sizeof(fileHdr), &writeCount)) || - NS_FAILED(outStream->Write((const char *)bm, bitmapSize, &writeCount))) - rv = NS_ERROR_FAILURE; + uint32_t written = 0; + rv = outStream->Write(src, size, &written); + if (NS_FAILED(rv) || written != size) { + return E_FAIL; + } outStream->Close(); - - GlobalUnlock(bits); - GlobalFree(bits); - - if (NS_FAILED(rv)) - return E_FAIL; } // Pass the file name back to the drop target so that it can access the file. diff --git a/widget/windows/nsImageClipboard.cpp b/widget/windows/nsImageClipboard.cpp deleted file mode 100644 index fab62eab5..000000000 --- a/widget/windows/nsImageClipboard.cpp +++ /dev/null @@ -1,497 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "nsImageClipboard.h" - -#include "gfxUtils.h" -#include "mozilla/gfx/2D.h" -#include "mozilla/gfx/DataSurfaceHelpers.h" -#include "mozilla/RefPtr.h" -#include "nsITransferable.h" -#include "nsGfxCIID.h" -#include "nsMemory.h" -#include "prmem.h" -#include "imgIEncoder.h" -#include "nsLiteralString.h" -#include "nsComponentManagerUtils.h" - -#define BFH_LENGTH 14 - -using namespace mozilla; -using namespace mozilla::gfx; - -/* Things To Do 11/8/00 - -Check image metrics, can we support them? Do we need to? -Any other render format? HTML? - -*/ - - -// -// nsImageToClipboard ctor -// -// Given an imgIContainer, convert it to a DIB that is ready to go on the win32 clipboard -// -nsImageToClipboard::nsImageToClipboard(imgIContainer* aInImage, bool aWantDIBV5) - : mImage(aInImage) - , mWantDIBV5(aWantDIBV5) -{ - // nothing to do here -} - - -// -// nsImageToClipboard dtor -// -// Clean up after ourselves. We know that we have created the bitmap -// successfully if we still have a pointer to the header. -// -nsImageToClipboard::~nsImageToClipboard() -{ -} - - -// -// GetPicture -// -// Call to get the actual bits that go on the clipboard. If an error -// ocurred during conversion, |outBits| will be null. -// -// NOTE: The caller owns the handle and must delete it with ::GlobalRelease() -// -nsresult -nsImageToClipboard :: GetPicture ( HANDLE* outBits ) -{ - NS_ASSERTION ( outBits, "Bad parameter" ); - - return CreateFromImage ( mImage, outBits ); - -} // GetPicture - - -// -// CalcSize -// -// Computes # of bytes needed by a bitmap with the specified attributes. -// -int32_t -nsImageToClipboard :: CalcSize ( int32_t aHeight, int32_t aColors, WORD aBitsPerPixel, int32_t aSpanBytes ) -{ - int32_t HeaderMem = sizeof(BITMAPINFOHEADER); - - // add size of pallette to header size - if (aBitsPerPixel < 16) - HeaderMem += aColors * sizeof(RGBQUAD); - - if (aHeight < 0) - aHeight = -aHeight; - - return (HeaderMem + (aHeight * aSpanBytes)); -} - - -// -// CalcSpanLength -// -// Computes the span bytes for determining the overall size of the image -// -int32_t -nsImageToClipboard::CalcSpanLength(uint32_t aWidth, uint32_t aBitCount) -{ - int32_t spanBytes = (aWidth * aBitCount) >> 5; - - if ((aWidth * aBitCount) & 0x1F) - spanBytes++; - spanBytes <<= 2; - - return spanBytes; -} - - -// -// CreateFromImage -// -// Do the work to setup the bitmap header and copy the bits out of the -// image. -// -nsresult -nsImageToClipboard::CreateFromImage ( imgIContainer* inImage, HANDLE* outBitmap ) -{ - nsresult rv; - *outBitmap = nullptr; - - RefPtr surface = - inImage->GetFrame(imgIContainer::FRAME_CURRENT, - imgIContainer::FLAG_SYNC_DECODE); - NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE); - - MOZ_ASSERT(surface->GetFormat() == SurfaceFormat::B8G8R8A8 || - surface->GetFormat() == SurfaceFormat::B8G8R8X8); - - RefPtr dataSurface; - if (surface->GetFormat() == SurfaceFormat::B8G8R8A8) { - dataSurface = surface->GetDataSurface(); - } else { - // XXXjwatt Bug 995923 - get rid of this copy and handle B8G8R8X8 - // directly below once bug 995807 is fixed. - dataSurface = gfxUtils:: - CopySurfaceToDataSourceSurfaceWithFormat(surface, - SurfaceFormat::B8G8R8A8); - } - NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE); - - nsCOMPtr encoder = do_CreateInstance("@mozilla.org/image/encoder;2?type=image/bmp", &rv); - NS_ENSURE_SUCCESS(rv, rv); - - uint32_t format; - nsAutoString options; - if (mWantDIBV5) { - options.AppendLiteral("version=5;bpp="); - } else { - options.AppendLiteral("version=3;bpp="); - } - switch (dataSurface->GetFormat()) { - case SurfaceFormat::B8G8R8A8: - format = imgIEncoder::INPUT_FORMAT_HOSTARGB; - options.AppendInt(32); - break; -#if 0 - // XXXjwatt Bug 995923 - fix |format| and reenable once bug 995807 is fixed. - case SurfaceFormat::B8G8R8X8: - format = imgIEncoder::INPUT_FORMAT_RGB; - options.AppendInt(24); - break; -#endif - default: - NS_NOTREACHED("Unexpected surface format"); - return NS_ERROR_INVALID_ARG; - } - - DataSourceSurface::MappedSurface map; - bool mappedOK = dataSurface->Map(DataSourceSurface::MapType::READ, &map); - NS_ENSURE_TRUE(mappedOK, NS_ERROR_FAILURE); - - rv = encoder->InitFromData(map.mData, 0, - dataSurface->GetSize().width, - dataSurface->GetSize().height, - map.mStride, - format, options); - dataSurface->Unmap(); - NS_ENSURE_SUCCESS(rv, rv); - - uint32_t size; - encoder->GetImageBufferUsed(&size); - NS_ENSURE_TRUE(size > BFH_LENGTH, NS_ERROR_FAILURE); - HGLOBAL glob = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE | GMEM_ZEROINIT, - size - BFH_LENGTH); - if (!glob) - return NS_ERROR_OUT_OF_MEMORY; - - char *dst = (char*) ::GlobalLock(glob); - char *src; - rv = encoder->GetImageBuffer(&src); - NS_ENSURE_SUCCESS(rv, rv); - - ::CopyMemory(dst, src + BFH_LENGTH, size - BFH_LENGTH); - ::GlobalUnlock(glob); - - *outBitmap = (HANDLE)glob; - return NS_OK; -} - -nsImageFromClipboard :: nsImageFromClipboard () -{ - // nothing to do here -} - -nsImageFromClipboard :: ~nsImageFromClipboard ( ) -{ -} - -// -// GetEncodedImageStream -// -// Take the raw clipboard image data and convert it to aMIMEFormat in the form of a nsIInputStream -// -nsresult -nsImageFromClipboard ::GetEncodedImageStream (unsigned char * aClipboardData, const char * aMIMEFormat, nsIInputStream** aInputStream ) -{ - NS_ENSURE_ARG_POINTER (aInputStream); - NS_ENSURE_ARG_POINTER (aMIMEFormat); - nsresult rv; - *aInputStream = nullptr; - - // pull the size information out of the BITMAPINFO header and - // initialize the image - BITMAPINFO* header = (BITMAPINFO *) aClipboardData; - int32_t width = header->bmiHeader.biWidth; - int32_t height = header->bmiHeader.biHeight; - // neg. heights mean the Y axis is inverted and we don't handle that case - NS_ENSURE_TRUE(height > 0, NS_ERROR_FAILURE); - - unsigned char * rgbData = new unsigned char[width * height * 3 /* RGB */]; - - if (rgbData) { - BYTE * pGlobal = (BYTE *) aClipboardData; - // Convert the clipboard image into RGB packed pixel data - rv = ConvertColorBitMap((unsigned char *) (pGlobal + header->bmiHeader.biSize), header, rgbData); - // if that succeeded, encode the bitmap as aMIMEFormat data. Don't return early or we risk leaking rgbData - if (NS_SUCCEEDED(rv)) { - nsAutoCString encoderCID(NS_LITERAL_CSTRING("@mozilla.org/image/encoder;2?type=")); - - // Map image/jpg to image/jpeg (which is how the encoder is registered). - if (strcmp(aMIMEFormat, kJPGImageMime) == 0) - encoderCID.AppendLiteral("image/jpeg"); - else - encoderCID.Append(aMIMEFormat); - nsCOMPtr encoder = do_CreateInstance(encoderCID.get(), &rv); - if (NS_SUCCEEDED(rv)){ - rv = encoder->InitFromData(rgbData, 0, width, height, 3 * width /* RGB * # pixels in a row */, - imgIEncoder::INPUT_FORMAT_RGB, EmptyString()); - if (NS_SUCCEEDED(rv)) { - encoder.forget(aInputStream); - } - } - } - delete [] rgbData; - } - else - rv = NS_ERROR_OUT_OF_MEMORY; - - return rv; -} // GetImage - -// -// InvertRows -// -// Take the image data from the clipboard and invert the rows. Modifying aInitialBuffer in place. -// -void -nsImageFromClipboard::InvertRows(unsigned char * aInitialBuffer, uint32_t aSizeOfBuffer, uint32_t aNumBytesPerRow) -{ - if (!aNumBytesPerRow) - return; - - uint32_t numRows = aSizeOfBuffer / aNumBytesPerRow; - unsigned char * row = new unsigned char[aNumBytesPerRow]; - - uint32_t currentRow = 0; - uint32_t lastRow = (numRows - 1) * aNumBytesPerRow; - while (currentRow < lastRow) - { - // store the current row into a temporary buffer - memcpy(row, &aInitialBuffer[currentRow], aNumBytesPerRow); - memcpy(&aInitialBuffer[currentRow], &aInitialBuffer[lastRow], aNumBytesPerRow); - memcpy(&aInitialBuffer[lastRow], row, aNumBytesPerRow); - lastRow -= aNumBytesPerRow; - currentRow += aNumBytesPerRow; - } - - delete[] row; -} - -// -// ConvertColorBitMap -// -// Takes the clipboard bitmap and converts it into a RGB packed pixel values. -// -nsresult -nsImageFromClipboard::ConvertColorBitMap(unsigned char * aInputBuffer, PBITMAPINFO pBitMapInfo, unsigned char * aOutBuffer) -{ - uint8_t bitCount = pBitMapInfo->bmiHeader.biBitCount; - uint32_t imageSize = pBitMapInfo->bmiHeader.biSizeImage; // may be zero for BI_RGB bitmaps which means we need to calculate by hand - uint32_t bytesPerPixel = bitCount / 8; - - if (bitCount <= 4) - bytesPerPixel = 1; - - // rows are DWORD aligned. Calculate how many real bytes are in each row in the bitmap. This number won't - // correspond to biWidth. - uint32_t rowSize = (bitCount * pBitMapInfo->bmiHeader.biWidth + 7) / 8; // +7 to round up - if (rowSize % 4) - rowSize += (4 - (rowSize % 4)); // Pad to DWORD Boundary - - // if our buffer includes a color map, skip over it - if (bitCount <= 8) - { - int32_t bytesToSkip = (pBitMapInfo->bmiHeader.biClrUsed ? pBitMapInfo->bmiHeader.biClrUsed : (1 << bitCount) ) * sizeof(RGBQUAD); - aInputBuffer += bytesToSkip; - } - - bitFields colorMasks; // only used if biCompression == BI_BITFIELDS - - if (pBitMapInfo->bmiHeader.biCompression == BI_BITFIELDS) - { - // color table consists of 3 DWORDS containing the color masks... - colorMasks.red = (*((uint32_t*)&(pBitMapInfo->bmiColors[0]))); - colorMasks.green = (*((uint32_t*)&(pBitMapInfo->bmiColors[1]))); - colorMasks.blue = (*((uint32_t*)&(pBitMapInfo->bmiColors[2]))); - CalcBitShift(&colorMasks); - aInputBuffer += 3 * sizeof(DWORD); - } - else if (pBitMapInfo->bmiHeader.biCompression == BI_RGB && !imageSize) // BI_RGB can have a size of zero which means we figure it out - { - // XXX: note use rowSize here and not biWidth. rowSize accounts for the DWORD padding for each row - imageSize = rowSize * pBitMapInfo->bmiHeader.biHeight; - } - - // The windows clipboard image format inverts the rows - InvertRows(aInputBuffer, imageSize, rowSize); - - if (!pBitMapInfo->bmiHeader.biCompression || pBitMapInfo->bmiHeader.biCompression == BI_BITFIELDS) - { - uint32_t index = 0; - uint32_t writeIndex = 0; - - unsigned char redValue, greenValue, blueValue; - uint8_t colorTableEntry = 0; - int8_t bit; // used for grayscale bitmaps where each bit is a pixel - uint32_t numPixelsLeftInRow = pBitMapInfo->bmiHeader.biWidth; // how many more pixels do we still need to read for the current row - uint32_t pos = 0; - - while (index < imageSize) - { - switch (bitCount) - { - case 1: - for (bit = 7; bit >= 0 && numPixelsLeftInRow; bit--) - { - colorTableEntry = (aInputBuffer[index] >> bit) & 1; - aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbRed; - aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbGreen; - aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbBlue; - numPixelsLeftInRow--; - } - pos += 1; - break; - case 4: - { - // each aInputBuffer[index] entry contains data for two pixels. - // read the first pixel - colorTableEntry = aInputBuffer[index] >> 4; - aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbRed; - aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbGreen; - aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbBlue; - numPixelsLeftInRow--; - - if (numPixelsLeftInRow) // now read the second pixel - { - colorTableEntry = aInputBuffer[index] & 0xF; - aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbRed; - aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbGreen; - aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[colorTableEntry].rgbBlue; - numPixelsLeftInRow--; - } - pos += 1; - } - break; - case 8: - aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[aInputBuffer[index]].rgbRed; - aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[aInputBuffer[index]].rgbGreen; - aOutBuffer[writeIndex++] = pBitMapInfo->bmiColors[aInputBuffer[index]].rgbBlue; - numPixelsLeftInRow--; - pos += 1; - break; - case 16: - { - uint16_t num = 0; - num = (uint8_t) aInputBuffer[index+1]; - num <<= 8; - num |= (uint8_t) aInputBuffer[index]; - - redValue = ((uint32_t) (((float)(num & 0xf800) / 0xf800) * 0xFF0000) & 0xFF0000)>> 16; - greenValue = ((uint32_t)(((float)(num & 0x07E0) / 0x07E0) * 0x00FF00) & 0x00FF00)>> 8; - blueValue = ((uint32_t)(((float)(num & 0x001F) / 0x001F) * 0x0000FF) & 0x0000FF); - - // now we have the right RGB values... - aOutBuffer[writeIndex++] = redValue; - aOutBuffer[writeIndex++] = greenValue; - aOutBuffer[writeIndex++] = blueValue; - numPixelsLeftInRow--; - pos += 2; - } - break; - case 32: - case 24: - if (pBitMapInfo->bmiHeader.biCompression == BI_BITFIELDS) - { - uint32_t val = *((uint32_t*) (aInputBuffer + index) ); - aOutBuffer[writeIndex++] = (val & colorMasks.red) >> colorMasks.redRightShift << colorMasks.redLeftShift; - aOutBuffer[writeIndex++] = (val & colorMasks.green) >> colorMasks.greenRightShift << colorMasks.greenLeftShift; - aOutBuffer[writeIndex++] = (val & colorMasks.blue) >> colorMasks.blueRightShift << colorMasks.blueLeftShift; - numPixelsLeftInRow--; - pos += 4; // we read in 4 bytes of data in order to process this pixel - } - else - { - aOutBuffer[writeIndex++] = aInputBuffer[index+2]; - aOutBuffer[writeIndex++] = aInputBuffer[index+1]; - aOutBuffer[writeIndex++] = aInputBuffer[index]; - numPixelsLeftInRow--; - pos += bytesPerPixel; // 3 bytes for 24 bit data, 4 bytes for 32 bit data (we skip over the 4th byte)... - } - break; - default: - // This is probably the wrong place to check this... - return NS_ERROR_FAILURE; - } - - index += bytesPerPixel; // increment our loop counter - - if (!numPixelsLeftInRow) - { - if (rowSize != pos) - { - // advance index to skip over remaining padding bytes - index += (rowSize - pos); - } - numPixelsLeftInRow = pBitMapInfo->bmiHeader.biWidth; - pos = 0; - } - - } // while we still have bytes to process - } - - return NS_OK; -} - -void nsImageFromClipboard::CalcBitmask(uint32_t aMask, uint8_t& aBegin, uint8_t& aLength) -{ - // find the rightmost 1 - uint8_t pos; - bool started = false; - aBegin = aLength = 0; - for (pos = 0; pos <= 31; pos++) - { - if (!started && (aMask & (1 << pos))) - { - aBegin = pos; - started = true; - } - else if (started && !(aMask & (1 << pos))) - { - aLength = pos - aBegin; - break; - } - } -} - -void nsImageFromClipboard::CalcBitShift(bitFields * aColorMask) -{ - uint8_t begin, length; - // red - CalcBitmask(aColorMask->red, begin, length); - aColorMask->redRightShift = begin; - aColorMask->redLeftShift = 8 - length; - // green - CalcBitmask(aColorMask->green, begin, length); - aColorMask->greenRightShift = begin; - aColorMask->greenLeftShift = 8 - length; - // blue - CalcBitmask(aColorMask->blue, begin, length); - aColorMask->blueRightShift = begin; - aColorMask->blueLeftShift = 8 - length; -} diff --git a/widget/windows/nsImageClipboard.h b/widget/windows/nsImageClipboard.h deleted file mode 100644 index 25b33cc56..000000000 --- a/widget/windows/nsImageClipboard.h +++ /dev/null @@ -1,93 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef nsImageClipboard_h -#define nsImageClipboard_h - -/* Things To Do 11/8/00 - -Check image metrics, can we support them? Do we need to? -Any other render format? HTML? - -*/ - -#include "nsError.h" -#include - -#include "nsCOMPtr.h" -#include "imgIContainer.h" -#include "nsIInputStream.h" - - -// -// nsImageToClipboard -// -// A utility class that takes an imgIContainer and does all the bitmap magic -// to allow us to put it on the clipboard -// -class nsImageToClipboard -{ -public: - nsImageToClipboard(imgIContainer* aInImage, bool aWantDIBV5 = true); - ~nsImageToClipboard(); - - // Call to get the actual bits that go on the clipboard. If |nullptr|, the - // setup operations have failed. - // - // NOTE: The caller owns the handle and must delete it with ::GlobalRelease() - nsresult GetPicture ( HANDLE* outBits ) ; - -private: - - // Computes # of bytes needed by a bitmap with the specified attributes. - int32_t CalcSize(int32_t aHeight, int32_t aColors, WORD aBitsPerPixel, int32_t aSpanBytes); - int32_t CalcSpanLength(uint32_t aWidth, uint32_t aBitCount); - - // Do the work - nsresult CreateFromImage ( imgIContainer* inImage, HANDLE* outBitmap ); - - nsCOMPtr mImage; // the image we're working with - bool mWantDIBV5; - -}; // class nsImageToClipboard - - -struct bitFields { - uint32_t red; - uint32_t green; - uint32_t blue; - uint8_t redLeftShift; - uint8_t redRightShift; - uint8_t greenLeftShift; - uint8_t greenRightShift; - uint8_t blueLeftShift; - uint8_t blueRightShift; -}; - -// -// nsImageFromClipboard -// -// A utility class that takes a DIB from the win32 clipboard and does -// all the bitmap magic to convert it to a PNG or a JPEG in the form of a nsIInputStream -// -class nsImageFromClipboard -{ -public: - nsImageFromClipboard () ; - ~nsImageFromClipboard ( ) ; - - // Retrieve the newly created image - nsresult GetEncodedImageStream (unsigned char * aClipboardData, const char * aMIMEFormat, nsIInputStream** outImage); - -private: - - void InvertRows(unsigned char * aInitialBuffer, uint32_t aSizeOfBuffer, uint32_t aNumBytesPerRow); - nsresult ConvertColorBitMap(unsigned char * aInputBuffer, PBITMAPINFO pBitMapInfo, unsigned char * aOutBuffer); - void CalcBitmask(uint32_t aMask, uint8_t& aBegin, uint8_t& aLength); - void CalcBitShift(bitFields * aColorMask); - -}; // nsImageFromClipboard - -#endif diff --git a/widget/windows/nsNativeThemeWin.cpp b/widget/windows/nsNativeThemeWin.cpp index 475ebce94..e84a2b80c 100644 --- a/widget/windows/nsNativeThemeWin.cpp +++ b/widget/windows/nsNativeThemeWin.cpp @@ -8,6 +8,7 @@ #include "mozilla/EventStates.h" #include "mozilla/Logging.h" #include "mozilla/WindowsVersion.h" +#include "mozilla/gfx/Types.h" // for Color::FromABGR #include "nsDeviceContext.h" #include "nsRenderingContext.h" #include "nsRect.h" @@ -40,6 +41,7 @@ #include using namespace mozilla; +using namespace mozilla::gfx; using namespace mozilla::widget; extern mozilla::LazyLogModule gWindowsLog; -- cgit v1.2.3 From 77e1b07f3015ca5d5b3de99e9474efa4fb711b0c Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Thu, 14 Feb 2019 22:42:55 +0100 Subject: Preserve transparency when copying a DIB to/from the clipboard. In order to get the alpha channel when encoding BMP images from a surface, we need to supply bmp=32 in the encoder options. --- widget/windows/nsDataObj.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'widget') diff --git a/widget/windows/nsDataObj.cpp b/widget/windows/nsDataObj.cpp index ee2db7b65..a19dcb182 100644 --- a/widget/windows/nsDataObj.cpp +++ b/widget/windows/nsDataObj.cpp @@ -921,7 +921,7 @@ nsDataObj::GetDib(const nsACString& inFlavor, if ( image ) { nsCOMPtr imgTools = do_CreateInstance("@mozilla.org/image/tools;1"); - nsAutoString options; + nsAutoString options(NS_LITERAL_STRING("bpp=32;")); if (aFormat.cfFormat == CF_DIBV5) { options.AppendLiteral("version=5"); } else { @@ -1580,7 +1580,7 @@ HRESULT nsDataObj::DropImage(FORMATETC& aFE, STGMEDIUM& aSTG) nsCOMPtr imgTools = do_CreateInstance("@mozilla.org/image/tools;1"); nsCOMPtr inputStream; rv = imgTools->EncodeImage(image, NS_LITERAL_CSTRING(IMAGE_BMP), - NS_LITERAL_STRING("version=3"), + NS_LITERAL_STRING("bpp=32;version=3"), getter_AddRefs(inputStream)); if (NS_FAILED(rv) || !inputStream) { return E_FAIL; -- cgit v1.2.3