/* vim: se cin sw=2 ts=2 et : */ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Our subclass should have invoked DetachFromNSWindow already.
NS_ASSERTION(
!mWnd, "TaskbarPreview::DetachFromNSWindow was not called before destruction");
// Make sure to release before potentially uninitializing COM
mTaskbar = nullptr;
::CoUninitialize();
}
nsresult TaskbarPreview::Init() { // TaskbarPreview may outlive the WinTaskbar that created it if (FAILED(::CoInitialize(nullptr))) { return NS_ERROR_NOT_INITIALIZED;
}
// If the nsWindow has already been destroyed but the caller is still trying // to use it then just pretend that everything succeeded. The caller doesn't // actually have a way to detect this since it's the same case as when we // CanMakeTaskbarCalls returns false. if (!IsWindowAvailable()) return NS_OK;
// If we are the active preview and our window is the active window, restore // our active state - otherwise some other non-preview window is now active // and should be displayed as so. if (sActivePreview == this) { if (mWnd == ::GetActiveWindow()) {
nsresult rvActive = ShowActive(true); if (NS_FAILED(rvActive)) rv = rvActive;
} else {
sActivePreview = nullptr;
}
} return rv;
}
nsresult TaskbarPreview::Enable() {
nsresult rv = NS_OK; if (CanMakeTaskbarCalls()) {
rv = UpdateTaskbarProperties();
} elseif (IsWindowAvailable()) {
WindowHook* hook = GetWindowHook();
MOZ_ASSERT(hook, "IsWindowAvailable() should have eliminated the null case.");
hook->AddMonitor(nsAppShell::GetTaskbarButtonCreatedMessage(),
MainWindowHook, this);
} return rv;
}
nsresult TaskbarPreview::Disable() { if (!IsWindowAvailable()) { // Window is already destroyed return NS_OK;
}
WindowHook* hook = GetWindowHook();
MOZ_ASSERT(hook, "IsWindowAvailable() should have eliminated the null case.");
(void)hook->RemoveMonitor(nsAppShell::GetTaskbarButtonCreatedMessage(),
MainWindowHook, this);
bool TaskbarPreview::CanMakeTaskbarCalls() { // If the nsWindow has already been destroyed and we know it but our caller // clearly doesn't so we can't make any calls. if (!mWnd) returnfalse; // Certain functions like SetTabOrder seem to require a visible window. During // window close, the window seems to be hidden before being destroyed. if (!::IsWindowVisible(mWnd)) returnfalse; if (mVisible) {
nsWindow* window = WinUtils::GetNSWindowPtr(mWnd);
NS_ASSERTION(window, "Could not get nsWindow from HWND"); return window ? window->HasTaskbarIconBeenCreated() : false;
} returnfalse;
}
WindowHook* TaskbarPreview::GetWindowHook() {
nsWindow* window = WinUtils::GetNSWindowPtr(mWnd);
NS_ASSERTION(window, "Cannot use taskbar previews in an embedded context!");
/* void done (in nsISupports aCanvas, in boolean aDrawBorder); */
NS_IMETHODIMP
TaskbarPreviewCallback::Done(nsISupports* aCanvas, bool aDrawBorder) { // We create and destroy TaskbarTabPreviews from front end code in response // to TabOpen and TabClose events. Each TaskbarTabPreview creates and owns a // proxy HWND which it hands to Windows as a tab identifier. When a tab // closes, TaskbarTabPreview Disable() method is called by front end, which // destroys the proxy window and clears mProxyWindow which is the HWND // returned from PreviewWindow(). So, since this is async, we should check to // be sure the tab is still alive before doing all this gfx work and making // dwm calls. To accomplish this we check the result of PreviewWindow(). if (!aCanvas || !mPreview || !mPreview->PreviewWindow() ||
!mPreview->IsWindowAvailable()) { return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIContent> content(do_QueryInterface(aCanvas)); auto canvas = dom::HTMLCanvasElement::FromNodeOrNull(content); if (!canvas) { return NS_ERROR_FAILURE;
}
RefPtr<gfx::SourceSurface> source = canvas->GetSurfaceSnapshot(); if (!source) { return NS_ERROR_FAILURE;
}
RefPtr<gfxWindowsSurface> target = new gfxWindowsSurface(
source->GetSize(), gfx::SurfaceFormat::A8R8G8B8_UINT32); if (target->CairoStatus() != CAIRO_STATUS_SUCCESS) { return NS_ERROR_FAILURE;
}
using DataSrcSurf = gfx::DataSourceSurface;
RefPtr<DataSrcSurf> srcSurface = source->GetDataSurface();
RefPtr<gfxImageSurface> imageSurface = target->GetAsImageSurface(); if (!srcSurface || !imageSurface) { return NS_ERROR_FAILURE;
}
if (DataSrcSurf::ScopedMap const sourceMap(srcSurface, DataSrcSurf::READ);
sourceMap.IsMapped()) {
mozilla::gfx::CopySurfaceDataToPackedArray(
sourceMap.GetData(), imageSurface->Data(), srcSurface->GetSize(),
sourceMap.GetStride(), BytesPerPixel(srcSurface->GetFormat()));
} elseif (source->GetSize().IsEmpty()) { // A zero-size source-surface probably shouldn't happen, but is harmless // here. Fall through.
} else { return NS_ERROR_FAILURE;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.