mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1130935 part.7 Set composition font when selection is changed since some IMEs need to be set candidate window position even before WM_IME_STARTCOMPOSITION r=emk (57b43c453) - Bug 1130935 part.8 nsIMM32Handler should set focused editor rect to the result of IMR_QUERYCHARPOSITION r=emk (b534d4921) - Bug 1130935 part.9 Needs some hack for Google Japanese Input in nsIMM32Handle because it doesn't support vertical writing mode r=emk (01555b5cc) - Bug 1130935 part.10 nsIMM32Handler should forcibly update composition font when active IME is changed r=emk (84748aa9c) - Bug 1130935 part.11 Disable test_backspace_delete.xul due to bug 1163311 r=smontagu (8bdbe49d3) - Bug 1130935 - mingw fixup. (55841cba1) - Bug 1168219 - Make nsIWidget::Configuration::mChild a smart pointer. r=vlad (4a8804a1e) - Add an API for snapshotting widgets as they are presented by the operating system. (bug 1167477, r=mattwoodrow, dom r=khuey) (c2592f279) - Bug 1130937 part.1 nsGtkIMModule should cache selection r=m_kato (b0d7c550d) - Bug 1174287: Use mozilla:: prefix for namespaced classes in nsGtkIMModule.h. r=Ms2ger (dcf6732db) - Bug 1130937 part.2 nsGtkIMModule should set candidiate window position to bottom left of the target clause in vertical writing mode r=m_kato (5c8d74129) - Bug 1130937 part.3 nsGtkIMModule should adjust candidate window position when layout is changed r=m_kato (88c472773) - Bug 1165903: For Windows NPAPI do window re-parenting in the chrome process to allow for sandboxing. r=jimm (27254a070)
This commit is contained in:
@@ -918,6 +918,8 @@ pref("browser.tabs.remote", false);
|
||||
// This will require a restart.
|
||||
pref("security.sandbox.windows.log", false);
|
||||
|
||||
pref("dom.ipc.plugins.sandbox-level.flash", 0);
|
||||
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
// This controls the strength of the Windows content process sandbox for testing
|
||||
// purposes. This will require a restart.
|
||||
|
||||
@@ -4807,6 +4807,7 @@ CanvasRenderingContext2D::DrawWindow(nsGlobalWindow& window, double x,
|
||||
if (!sw || !sh) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxContext> thebes;
|
||||
RefPtr<DrawTarget> drawDT;
|
||||
// Rendering directly is faster and can be done if mTarget supports Azure
|
||||
@@ -4961,6 +4962,51 @@ CanvasRenderingContext2D::AsyncDrawXULElement(nsXULElement& elem,
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
CanvasRenderingContext2D::DrawWidgetAsOnScreen(nsGlobalWindow& aWindow,
|
||||
mozilla::ErrorResult& error)
|
||||
{
|
||||
EnsureTarget();
|
||||
|
||||
// This is an internal API.
|
||||
if (!nsContentUtils::IsCallerChrome()) {
|
||||
error.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<nsPresContext> presContext;
|
||||
nsIDocShell* docshell = aWindow.GetDocShell();
|
||||
if (docshell) {
|
||||
docshell->GetPresContext(getter_AddRefs(presContext));
|
||||
}
|
||||
if (!presContext) {
|
||||
error.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
nsIWidget* widget = presContext->GetRootWidget();
|
||||
if (!widget) {
|
||||
error.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
RefPtr<SourceSurface> snapshot = widget->SnapshotWidgetOnScreen();
|
||||
if (!snapshot) {
|
||||
error.Throw(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
mgfx::Rect sourceRect(mgfx::Point(0, 0), mgfx::Size(snapshot->GetSize()));
|
||||
mTarget->DrawSurface(snapshot, sourceRect, sourceRect,
|
||||
DrawSurfaceOptions(mgfx::Filter::POINT),
|
||||
DrawOptions(GlobalAlpha(), CompositionOp::OP_OVER,
|
||||
AntialiasMode::NONE));
|
||||
mTarget->Flush();
|
||||
|
||||
RedrawUser(gfxRect(0, 0,
|
||||
std::min(mWidth, snapshot->GetSize().width),
|
||||
std::min(mHeight, snapshot->GetSize().height)));
|
||||
}
|
||||
|
||||
//
|
||||
// device pixel getting/setting
|
||||
//
|
||||
|
||||
@@ -471,6 +471,7 @@ public:
|
||||
void DrawWindow(nsGlobalWindow& window, double x, double y, double w, double h,
|
||||
const nsAString& bgColor, uint32_t flags,
|
||||
mozilla::ErrorResult& error);
|
||||
void DrawWidgetAsOnScreen(nsGlobalWindow& aWindow, mozilla::ErrorResult& error);
|
||||
void AsyncDrawXULElement(nsXULElement& elem, double x, double y, double w,
|
||||
double h, const nsAString& bgColor, uint32_t flags,
|
||||
mozilla::ErrorResult& error);
|
||||
|
||||
@@ -41,6 +41,12 @@ parent:
|
||||
* native HWND of the plugin widget.
|
||||
*/
|
||||
sync GetNativePluginPort() returns (uintptr_t value);
|
||||
|
||||
/**
|
||||
* Sends an NS_NATIVE_CHILD_WINDOW to be adopted by the widget's native window
|
||||
* on the chrome side. This is only currently used on Windows.
|
||||
*/
|
||||
sync SetNativeChildWindow(uintptr_t childWindow);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult GetPluginWidget(nsIWidget **aWidget) {
|
||||
nsresult GetPluginWidget(nsIWidget **aWidget) const {
|
||||
NS_IF_ADDREF(*aWidget = mWidget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,10 @@ intr protocol PPluginInstance
|
||||
child:
|
||||
intr __delete__();
|
||||
|
||||
intr NPP_SetWindow(NPRemoteWindow window);
|
||||
// Return value is only used on Windows and only when the window needs its
|
||||
// parent set to the chrome widget native window.
|
||||
intr NPP_SetWindow(NPRemoteWindow window)
|
||||
returns (NPRemoteWindow childWindowToBeAdopted);
|
||||
|
||||
intr NPP_GetValue_NPPVpluginWantsAllNetworkStreams()
|
||||
returns (bool value, NPError result);
|
||||
|
||||
@@ -1122,7 +1122,8 @@ void PluginInstanceChild::DeleteWindow()
|
||||
#endif
|
||||
|
||||
bool
|
||||
PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
|
||||
PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow,
|
||||
NPRemoteWindow* aChildWindowToBeAdopted)
|
||||
{
|
||||
PLUGIN_LOG_DEBUG(("%s (aWindow=<window: 0x%lx, x: %d, y: %d, width: %d, height: %d>)",
|
||||
FULLFUNCTION,
|
||||
@@ -1213,9 +1214,32 @@ PluginInstanceChild::AnswerNPP_SetWindow(const NPRemoteWindow& aWindow)
|
||||
if (!CreatePluginWindow())
|
||||
return false;
|
||||
|
||||
ReparentPluginWindow(reinterpret_cast<HWND>(aWindow.window));
|
||||
SizePluginWindow(aWindow.width, aWindow.height);
|
||||
|
||||
// If the window is not our parent set the return child window so that
|
||||
// it can be re-parented in the chrome process. Re-parenting now
|
||||
// happens there as we might not have sufficient permission.
|
||||
// Also, this needs to be after SizePluginWindow because SetWindowPos
|
||||
// relies on things that it sets.
|
||||
HWND parentWindow = reinterpret_cast<HWND>(aWindow.window);
|
||||
if (mPluginParentHWND != parentWindow && IsWindow(parentWindow)) {
|
||||
mPluginParentHWND = parentWindow;
|
||||
aChildWindowToBeAdopted->window =
|
||||
reinterpret_cast<uint64_t>(mPluginWindowHWND);
|
||||
} else {
|
||||
// Now we know that the window has the correct parent we can show
|
||||
// it. The actual visibility is controlled by its parent.
|
||||
// First time round, these calls are made by our caller after the
|
||||
// parent is set.
|
||||
ShowWindow(mPluginWindowHWND, SW_SHOWNA);
|
||||
|
||||
// This used to be called in SizePluginWindow, but we need to make
|
||||
// sure that mPluginWindowHWND has had it's parent set correctly,
|
||||
// otherwise it can cause a focus issue.
|
||||
SetWindowPos(mPluginWindowHWND, nullptr, 0, 0, aWindow.width,
|
||||
aWindow.height, SWP_NOZORDER | SWP_NOREPOSITION);
|
||||
}
|
||||
|
||||
mWindow.window = (void*)mPluginWindowHWND;
|
||||
mWindow.x = aWindow.x;
|
||||
mWindow.y = aWindow.y;
|
||||
@@ -1401,25 +1425,6 @@ PluginInstanceChild::DestroyPluginWindow()
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::ReparentPluginWindow(HWND hWndParent)
|
||||
{
|
||||
if (hWndParent != mPluginParentHWND && IsWindow(hWndParent)) {
|
||||
// Fix the child window's style to be a child window.
|
||||
LONG_PTR style = GetWindowLongPtr(mPluginWindowHWND, GWL_STYLE);
|
||||
style |= WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
|
||||
style &= ~WS_POPUP;
|
||||
SetWindowLongPtr(mPluginWindowHWND, GWL_STYLE, style);
|
||||
|
||||
// Do the reparenting.
|
||||
SetParent(mPluginWindowHWND, hWndParent);
|
||||
|
||||
// Make sure we're visible.
|
||||
ShowWindow(mPluginWindowHWND, SW_SHOWNA);
|
||||
}
|
||||
mPluginParentHWND = hWndParent;
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::SizePluginWindow(int width,
|
||||
int height)
|
||||
@@ -1427,8 +1432,6 @@ PluginInstanceChild::SizePluginWindow(int width,
|
||||
if (mPluginWindowHWND) {
|
||||
mPluginSize.x = width;
|
||||
mPluginSize.y = height;
|
||||
SetWindowPos(mPluginWindowHWND, nullptr, 0, 0, width, height,
|
||||
SWP_NOZORDER | SWP_NOREPOSITION);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,8 @@ class PluginInstanceChild : public PPluginInstanceChild
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual bool AnswerNPP_SetWindow(const NPRemoteWindow& window) override;
|
||||
bool AnswerNPP_SetWindow(const NPRemoteWindow& window,
|
||||
NPRemoteWindow* aChildWindowToBeAdopted) override;
|
||||
|
||||
virtual bool
|
||||
AnswerNPP_GetValue_NPPVpluginWantsAllNetworkStreams(bool* wantsAllStreams, NPError* rv) override;
|
||||
@@ -276,7 +277,6 @@ private:
|
||||
static bool RegisterWindowClass();
|
||||
bool CreatePluginWindow();
|
||||
void DestroyPluginWindow();
|
||||
void ReparentPluginWindow(HWND hWndParent);
|
||||
void SizePluginWindow(int width, int height);
|
||||
int16_t WinlessHandleEvent(NPEvent& event);
|
||||
void CreateWinlessPopupSurrogate();
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
#include "mozilla/plugins/PluginSurfaceParent.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsPluginNativeWindow.h"
|
||||
extern const wchar_t* kFlashFullscreenClass;
|
||||
#elif defined(MOZ_WIDGET_GTK)
|
||||
#include <gdk/gdk.h>
|
||||
@@ -1025,8 +1027,30 @@ PluginInstanceParent::NPP_SetWindow(const NPWindow* aWindow)
|
||||
window.colormap = ws_info->colormap;
|
||||
#endif
|
||||
|
||||
if (!CallNPP_SetWindow(window))
|
||||
NPRemoteWindow childWindow;
|
||||
if (!CallNPP_SetWindow(window, &childWindow)) {
|
||||
return NPERR_GENERIC_ERROR;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
// If a child window is returned it means that we need to re-parent it.
|
||||
if (childWindow.window) {
|
||||
nsCOMPtr<nsIWidget> widget;
|
||||
static_cast<const nsPluginNativeWindow*>(aWindow)->
|
||||
GetPluginWidget(getter_AddRefs(widget));
|
||||
if (widget) {
|
||||
widget->SetNativeData(NS_NATIVE_CHILD_WINDOW,
|
||||
static_cast<uintptr_t>(childWindow.window));
|
||||
}
|
||||
|
||||
// Now it has got the correct parent, make sure it is visible.
|
||||
// In subsequent calls to SetWindow these calls happen in the Child.
|
||||
HWND childHWND = reinterpret_cast<HWND>(childWindow.window);
|
||||
ShowWindow(childHWND, SW_SHOWNA);
|
||||
SetWindowPos(childHWND, nullptr, 0, 0, window.width, window.height,
|
||||
SWP_NOZORDER | SWP_NOREPOSITION);
|
||||
}
|
||||
#endif
|
||||
|
||||
return NPERR_NO_ERROR;
|
||||
}
|
||||
|
||||
@@ -210,5 +210,20 @@ PluginWidgetParent::RecvGetNativePluginPort(uintptr_t* value)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
PluginWidgetParent::RecvSetNativeChildWindow(const uintptr_t& aChildWindow)
|
||||
{
|
||||
#if defined(XP_WIN)
|
||||
ENSURE_CHANNEL;
|
||||
PWLOG("PluginWidgetParent::RecvSetNativeChildWindow(%p)\n",
|
||||
static_cast<void*>(aChildWindow));
|
||||
mWidget->SetNativeData(NS_NATIVE_CHILD_WINDOW, aChildWindow);
|
||||
return true;
|
||||
#else
|
||||
NS_NOTREACHED("PluginWidgetParent::RecvSetNativeChildWindow not implemented!");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace plugins
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -31,6 +31,7 @@ public:
|
||||
virtual bool RecvCreate(nsresult* aResult) override;
|
||||
virtual bool RecvSetFocus(const bool& aRaise) override;
|
||||
virtual bool RecvGetNativePluginPort(uintptr_t* value) override;
|
||||
bool RecvSetNativeChildWindow(const uintptr_t& aChildWindow) override;
|
||||
|
||||
// Helper for compositor checks on the channel
|
||||
bool ActorDestroyed() { return !mWidget; }
|
||||
|
||||
@@ -223,6 +223,18 @@ interface CanvasRenderingContext2D {
|
||||
void asyncDrawXULElement(XULElement elem, double x, double y, double w,
|
||||
double h, DOMString bgColor,
|
||||
optional unsigned long flags = 0);
|
||||
|
||||
/**
|
||||
* Render the root widget of a window into the canvas. Unlike drawWindow,
|
||||
* this uses the operating system to snapshot the widget on-screen, rather
|
||||
* than reading from our own compositor.
|
||||
*
|
||||
* Currently, this is only supported on Windows, and only on widgets that
|
||||
* use OMTC, and only from within the chrome process.
|
||||
*/
|
||||
[Throws, ChromeOnly]
|
||||
void drawWidgetAsOnScreen(Window window);
|
||||
|
||||
/**
|
||||
* This causes a context that is currently using a hardware-accelerated
|
||||
* backend to fallback to a software one. All state should be preserved.
|
||||
|
||||
@@ -804,6 +804,18 @@ CompositorParent::RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorParent::RecvMakeWidgetSnapshot(const SurfaceDescriptor& aInSnapshot)
|
||||
{
|
||||
if (!mCompositor || !mCompositor->GetWidget()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> target = GetDrawTargetForDescriptor(aInSnapshot, gfx::BackendType::CAIRO);
|
||||
mCompositor->GetWidget()->CaptureWidgetOnScreen(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CompositorParent::RecvFlushRendering()
|
||||
{
|
||||
@@ -1700,6 +1712,8 @@ public:
|
||||
virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
|
||||
const gfx::IntRect& aRect) override
|
||||
{ return true; }
|
||||
virtual bool RecvMakeWidgetSnapshot(const SurfaceDescriptor& aInSnapshot) override
|
||||
{ return true; }
|
||||
virtual bool RecvFlushRendering() override { return true; }
|
||||
virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) override { return true; }
|
||||
virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) override { return true; }
|
||||
|
||||
@@ -241,6 +241,7 @@ public:
|
||||
virtual bool RecvAdoptChild(const uint64_t& child) override;
|
||||
virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
|
||||
const gfx::IntRect& aRect) override;
|
||||
virtual bool RecvMakeWidgetSnapshot(const SurfaceDescriptor& aInSnapshot) override;
|
||||
virtual bool RecvFlushRendering() override;
|
||||
|
||||
virtual bool RecvGetTileSize(int32_t* aWidth, int32_t* aHeight) override;
|
||||
|
||||
@@ -115,6 +115,14 @@ parent:
|
||||
// and so forth being interpolated. That's what we want to happen.
|
||||
sync MakeSnapshot(SurfaceDescriptor inSnapshot, IntRect dirtyRect);
|
||||
|
||||
// Same as Makesnapshot(), except the snapshot is read from the underlying
|
||||
// operating system desktop rather than the compositor's backbuffer. This
|
||||
// is intended for testing whether hardware acceleration works.
|
||||
//
|
||||
// This call is part of IPDL, even though it simply wraps an nsIWidget
|
||||
// call, to make sure it does not occur in the middle of a composite.
|
||||
sync MakeWidgetSnapshot(SurfaceDescriptor inSnapshot);
|
||||
|
||||
// Make sure any pending composites are started immediately and
|
||||
// block until they are completed.
|
||||
sync FlushRendering();
|
||||
|
||||
@@ -7,6 +7,7 @@ support-files =
|
||||
frame_selection_underline.xhtml
|
||||
|
||||
[test_backspace_delete.xul]
|
||||
skip-if = true # Bug 1163311
|
||||
[test_bug348681.html]
|
||||
[test_bug469613.xul]
|
||||
[test_bug469774.xul]
|
||||
|
||||
@@ -3403,6 +3403,13 @@ pref("intl.imm.composition_font.japanist_2003", "MS PGothic");
|
||||
// FYI: Changing this pref requires to restart.
|
||||
pref("intl.imm.vertical_writing.always_assume_not_supported", false);
|
||||
|
||||
// We cannot retrieve active IME name with IMM32 API if a TIP of TSF is active.
|
||||
// This pref can specify active IME name when Japanese TIP is active.
|
||||
// For example:
|
||||
// Google Japanese Input: "Google 日本語入力 IMM32 モジュール"
|
||||
// ATOK 2011: "ATOK 2011" (similarly, e.g., ATOK 2013 is "ATOK 2013")
|
||||
pref("intl.imm.japanese.assume_active_tip_name_as", "");
|
||||
|
||||
// See bug 448927, on topmost panel, some IMEs are not usable on Windows.
|
||||
pref("ui.panel.default_level_parent", false);
|
||||
|
||||
|
||||
@@ -141,6 +141,29 @@ PluginWidgetProxy::GetNativeData(uint32_t aDataType)
|
||||
return (void*)value;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN)
|
||||
void
|
||||
PluginWidgetProxy::SetNativeData(uint32_t aDataType, uintptr_t aVal)
|
||||
{
|
||||
if (!mActor) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto tab = static_cast<mozilla::dom::TabChild*>(mActor->Manager());
|
||||
if (tab && tab->IsDestroyed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aDataType) {
|
||||
case NS_NATIVE_CHILD_WINDOW:
|
||||
mActor->SendSetNativeChildWindow(aVal);
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("SetNativeData called with unsupported data type.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
NS_IMETHODIMP
|
||||
PluginWidgetProxy::SetFocus(bool aRaise)
|
||||
{
|
||||
|
||||
@@ -43,6 +43,9 @@ public:
|
||||
|
||||
virtual nsIWidget* GetParent(void) override;
|
||||
virtual void* GetNativeData(uint32_t aDataType) override;
|
||||
#if defined(XP_WIN)
|
||||
void SetNativeData(uint32_t aDataType, uintptr_t aVal) override;
|
||||
#endif
|
||||
virtual nsTransparencyMode GetTransparencyMode() override
|
||||
{ return eTransparencyOpaque; }
|
||||
virtual void GetWindowClipRegion(nsTArray<nsIntRect>* aRects) override;
|
||||
|
||||
@@ -227,7 +227,7 @@ PuppetWidget::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
|
||||
{
|
||||
for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
|
||||
const Configuration& configuration = aConfigurations[i];
|
||||
PuppetWidget* w = static_cast<PuppetWidget*>(configuration.mChild);
|
||||
PuppetWidget* w = static_cast<PuppetWidget*>(configuration.mChild.get());
|
||||
NS_ASSERTION(w->GetParent() == this,
|
||||
"Configured widget is not a child");
|
||||
w->SetWindowClipRegion(configuration.mClipRegion, true);
|
||||
|
||||
+152
-73
@@ -56,8 +56,30 @@ GetEnabledStateName(uint32_t aState)
|
||||
}
|
||||
}
|
||||
|
||||
class GetWritingModeName : public nsAutoCString
|
||||
{
|
||||
public:
|
||||
explicit GetWritingModeName(const WritingMode& aWritingMode)
|
||||
{
|
||||
if (!aWritingMode.IsVertical()) {
|
||||
AssignLiteral("Horizontal");
|
||||
return;
|
||||
}
|
||||
if (aWritingMode.IsVerticalLR()) {
|
||||
AssignLiteral("Vertical (LTR)");
|
||||
return;
|
||||
}
|
||||
AssignLiteral("Vertical (RTL)");
|
||||
}
|
||||
virtual ~GetWritingModeName() {}
|
||||
};
|
||||
|
||||
const static bool kUseSimpleContextDefault = MOZ_WIDGET_GTK == 2;
|
||||
|
||||
/******************************************************************************
|
||||
* nsGtkIMModule
|
||||
******************************************************************************/
|
||||
|
||||
nsGtkIMModule* nsGtkIMModule::sLastFocusedModule = nullptr;
|
||||
bool nsGtkIMModule::sUseSimpleContext;
|
||||
|
||||
@@ -74,6 +96,7 @@ nsGtkIMModule::nsGtkIMModule(nsWindow* aOwnerWindow)
|
||||
, mCompositionState(eCompositionState_NotComposing)
|
||||
, mIsIMFocused(false)
|
||||
, mIsDeletingSurrounding(false)
|
||||
, mLayoutChanged(false)
|
||||
{
|
||||
if (!gGtkIMLog) {
|
||||
gGtkIMLog = PR_NewLogModule("nsGtkIMModuleWidgets");
|
||||
@@ -396,6 +419,7 @@ nsGtkIMModule::OnFocusChangeInGecko(bool aFocus)
|
||||
|
||||
// We shouldn't carry over the removed string to another editor.
|
||||
mSelectedString.Truncate();
|
||||
mSelection.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -452,13 +476,28 @@ nsGtkIMModule::EndIMEComposition(nsWindow* aCaller)
|
||||
}
|
||||
|
||||
void
|
||||
nsGtkIMModule::OnUpdateComposition()
|
||||
nsGtkIMModule::OnLayoutChange()
|
||||
{
|
||||
if (MOZ_UNLIKELY(IsDestroyed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetCursorPosition(GetActiveContext(), mCompositionTargetOffset);
|
||||
mLayoutChanged = true;
|
||||
}
|
||||
|
||||
void
|
||||
nsGtkIMModule::OnUpdateComposition()
|
||||
{
|
||||
if (MOZ_UNLIKELY(IsDestroyed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we've already set candidate window position, we don't need to update
|
||||
// the position with update composition notification.
|
||||
if (!mLayoutChanged) {
|
||||
SetCursorPosition(GetActiveContext(), mCompositionTargetOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -660,8 +699,11 @@ nsGtkIMModule::Blur()
|
||||
}
|
||||
|
||||
void
|
||||
nsGtkIMModule::OnSelectionChange(nsWindow* aCaller)
|
||||
nsGtkIMModule::OnSelectionChange(nsWindow* aCaller,
|
||||
const IMENotification& aIMENotification)
|
||||
{
|
||||
mSelection.Assign(aIMENotification);
|
||||
|
||||
if (MOZ_UNLIKELY(IsDestroyed())) {
|
||||
return;
|
||||
}
|
||||
@@ -685,42 +727,13 @@ nsGtkIMModule::OnSelectionChange(nsWindow* aCaller)
|
||||
// event handler. So, we're dispatching NS_COMPOSITION_START,
|
||||
// we should ignore selection change notification.
|
||||
if (mCompositionState == eCompositionState_CompositionStartDispatched) {
|
||||
nsCOMPtr<nsIWidget> focusedWindow(mLastFocusedWindow);
|
||||
nsEventStatus status;
|
||||
WidgetQueryContentEvent selection(true, NS_QUERY_SELECTED_TEXT,
|
||||
focusedWindow);
|
||||
InitEvent(selection);
|
||||
mLastFocusedWindow->DispatchEvent(&selection, status);
|
||||
|
||||
bool cannotContinueComposition = false;
|
||||
if (MOZ_UNLIKELY(IsDestroyed())) {
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
(" ERROR: nsGtkIMModule instance is destroyed during "
|
||||
"querying selection offset"));
|
||||
return;
|
||||
} else if (NS_WARN_IF(!selection.mSucceeded)) {
|
||||
cannotContinueComposition = true;
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
(" ERROR: failed to retrieve new caret offset"));
|
||||
} else if (selection.mReply.mOffset == UINT32_MAX) {
|
||||
cannotContinueComposition = true;
|
||||
if (NS_WARN_IF(!mSelection.IsValid())) {
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
(" ERROR: new offset is too large, cannot keep composing"));
|
||||
} else if (!mLastFocusedWindow || focusedWindow != mLastFocusedWindow) {
|
||||
cannotContinueComposition = true;
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
(" ERROR: focus is changed during querying selection "
|
||||
"offset"));
|
||||
} else if (focusedWindow->Destroyed()) {
|
||||
cannotContinueComposition = true;
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
(" ERROR: focused window started to be being destroyed "
|
||||
"during querying selection offset"));
|
||||
}
|
||||
|
||||
if (!cannotContinueComposition) {
|
||||
} else {
|
||||
// Modify the selection start offset with new offset.
|
||||
mCompositionStart = selection.mReply.mOffset;
|
||||
mCompositionStart = mSelection.mOffset;
|
||||
// XXX We should modify mSelectedString? But how?
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
(" NOTE: mCompositionStart is updated to %u, "
|
||||
"the selection change doesn't cause resetting IM context",
|
||||
@@ -1023,13 +1036,7 @@ nsGtkIMModule::DispatchCompositionStart(GtkIMContext* aContext)
|
||||
return false;
|
||||
}
|
||||
|
||||
nsEventStatus status;
|
||||
WidgetQueryContentEvent selection(true, NS_QUERY_SELECTED_TEXT,
|
||||
mLastFocusedWindow);
|
||||
InitEvent(selection);
|
||||
mLastFocusedWindow->DispatchEvent(&selection, status);
|
||||
|
||||
if (!selection.mSucceeded || selection.mReply.mOffset == UINT32_MAX) {
|
||||
if (NS_WARN_IF(!EnsureToCacheSelection())) {
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
(" FAILED, cannot query the selection offset"));
|
||||
return false;
|
||||
@@ -1039,7 +1046,7 @@ nsGtkIMModule::DispatchCompositionStart(GtkIMContext* aContext)
|
||||
// even though we strongly hope it doesn't happen.
|
||||
// Every composition event should have the start offset for the result
|
||||
// because it may high cost if we query the offset every time.
|
||||
mCompositionStart = selection.mReply.mOffset;
|
||||
mCompositionStart = mSelection.mOffset;
|
||||
mDispatchedCompositionString.Truncate();
|
||||
|
||||
if (mProcessingKeyEvent && !mKeyDownEventWasSent &&
|
||||
@@ -1067,6 +1074,7 @@ nsGtkIMModule::DispatchCompositionStart(GtkIMContext* aContext)
|
||||
mLastFocusedWindow);
|
||||
InitEvent(compEvent);
|
||||
nsCOMPtr<nsIWidget> kungFuDeathGrip = mLastFocusedWindow;
|
||||
nsEventStatus status;
|
||||
mLastFocusedWindow->DispatchEvent(&compEvent, status);
|
||||
if (static_cast<nsWindow*>(kungFuDeathGrip.get())->IsDestroyed() ||
|
||||
kungFuDeathGrip != mLastFocusedWindow) {
|
||||
@@ -1108,15 +1116,12 @@ nsGtkIMModule::DispatchCompositionChangeEvent(
|
||||
// Store the selected string which will be removed by following
|
||||
// compositionchange event.
|
||||
if (mCompositionState == eCompositionState_CompositionStartDispatched) {
|
||||
// XXX We should assume, for now, any web applications don't change
|
||||
// selection at handling this compositionchange event.
|
||||
WidgetQueryContentEvent querySelectedTextEvent(true,
|
||||
NS_QUERY_SELECTED_TEXT,
|
||||
mLastFocusedWindow);
|
||||
mLastFocusedWindow->DispatchEvent(&querySelectedTextEvent, status);
|
||||
if (querySelectedTextEvent.mSucceeded) {
|
||||
mSelectedString = querySelectedTextEvent.mReply.mString;
|
||||
mCompositionStart = querySelectedTextEvent.mReply.mOffset;
|
||||
if (NS_WARN_IF(!EnsureToCacheSelection(&mSelectedString))) {
|
||||
// XXX How should we behave in this case??
|
||||
} else {
|
||||
// XXX We should assume, for now, any web applications don't change
|
||||
// selection at handling this compositionchange event.
|
||||
mCompositionStart = mSelection.mOffset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1135,6 +1140,14 @@ nsGtkIMModule::DispatchCompositionChangeEvent(
|
||||
|
||||
mCompositionState = eCompositionState_CompositionChangeEventDispatched;
|
||||
|
||||
// We cannot call SetCursorPosition for e10s-aware.
|
||||
// DispatchEvent is async on e10s, so composition rect isn't updated now
|
||||
// on tab parent.
|
||||
mLayoutChanged = false;
|
||||
mCompositionTargetRange.mOffset = targetOffset;
|
||||
mCompositionTargetRange.mLength =
|
||||
compositionChangeEvent.mRanges->TargetClauseLength();
|
||||
|
||||
mLastFocusedWindow->DispatchEvent(&compositionChangeEvent, status);
|
||||
if (lastFocusedWindow->IsDestroyed() ||
|
||||
lastFocusedWindow != mLastFocusedWindow) {
|
||||
@@ -1143,12 +1156,6 @@ nsGtkIMModule::DispatchCompositionChangeEvent(
|
||||
"compositionchange event"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// We cannot call SetCursorPosition for e10s-aware.
|
||||
// DispatchEvent is async on e10s, so composition rect isn't updated now
|
||||
// on tab parent.
|
||||
mCompositionTargetOffset = targetOffset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1424,14 +1431,14 @@ nsGtkIMModule::GetCurrentParagraph(nsAString& aText, uint32_t& aCursorPos)
|
||||
// current selection.
|
||||
if (!EditorHasCompositionString()) {
|
||||
// Query cursor position & selection
|
||||
WidgetQueryContentEvent querySelectedTextEvent(true,
|
||||
NS_QUERY_SELECTED_TEXT,
|
||||
mLastFocusedWindow);
|
||||
mLastFocusedWindow->DispatchEvent(&querySelectedTextEvent, status);
|
||||
NS_ENSURE_TRUE(querySelectedTextEvent.mSucceeded, NS_ERROR_FAILURE);
|
||||
if (NS_WARN_IF(!EnsureToCacheSelection())) {
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
(" FAILED, due to no valid selection information"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
selOffset = querySelectedTextEvent.mReply.mOffset;
|
||||
selLength = querySelectedTextEvent.mReply.mString.Length();
|
||||
selOffset = mSelection.mOffset;
|
||||
selLength = mSelection.mLength;
|
||||
}
|
||||
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
@@ -1529,14 +1536,12 @@ nsGtkIMModule::DeleteText(GtkIMContext* aContext,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
} else {
|
||||
// Query cursor position & selection
|
||||
WidgetQueryContentEvent querySelectedTextEvent(true,
|
||||
NS_QUERY_SELECTED_TEXT,
|
||||
mLastFocusedWindow);
|
||||
lastFocusedWindow->DispatchEvent(&querySelectedTextEvent, status);
|
||||
NS_ENSURE_TRUE(querySelectedTextEvent.mSucceeded, NS_ERROR_FAILURE);
|
||||
|
||||
selOffset = querySelectedTextEvent.mReply.mOffset;
|
||||
if (NS_WARN_IF(!EnsureToCacheSelection())) {
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ALWAYS,
|
||||
(" FAILED, due to no valid selection information"));
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
selOffset = mSelection.mOffset;
|
||||
}
|
||||
|
||||
// Get all text contents of the focused editor
|
||||
@@ -1659,3 +1664,77 @@ nsGtkIMModule::InitEvent(WidgetGUIEvent& aEvent)
|
||||
{
|
||||
aEvent.time = PR_Now() / 1000;
|
||||
}
|
||||
|
||||
bool
|
||||
nsGtkIMModule::EnsureToCacheSelection(nsAString* aSelectedString)
|
||||
{
|
||||
if (aSelectedString) {
|
||||
aSelectedString->Truncate();
|
||||
}
|
||||
|
||||
if (mSelection.IsValid() &&
|
||||
(!mSelection.Collapsed() || !aSelectedString)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!mLastFocusedWindow)) {
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ERROR,
|
||||
("GtkIMModule(%p): EnsureToCacheSelection(), FAILED, due to "
|
||||
"no focused window", this));
|
||||
return false;
|
||||
}
|
||||
|
||||
nsEventStatus status;
|
||||
WidgetQueryContentEvent selection(true, NS_QUERY_SELECTED_TEXT,
|
||||
mLastFocusedWindow);
|
||||
InitEvent(selection);
|
||||
mLastFocusedWindow->DispatchEvent(&selection, status);
|
||||
if (NS_WARN_IF(!selection.mSucceeded)) {
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ERROR,
|
||||
("GtkIMModule(%p): EnsureToCacheSelection(), FAILED, due to "
|
||||
"failure of query selection event", this));
|
||||
return false;
|
||||
}
|
||||
|
||||
mSelection.Assign(selection);
|
||||
if (!mSelection.IsValid()) {
|
||||
PR_LOG(gGtkIMLog, PR_LOG_ERROR,
|
||||
("GtkIMModule(%p): EnsureToCacheSelection(), FAILED, due to "
|
||||
"failure of query selection event (invalid result)", this));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mSelection.Collapsed() && aSelectedString) {
|
||||
aSelectedString->Assign(selection.mReply.mString);
|
||||
}
|
||||
|
||||
PR_LOG(gGtkIMLog, PR_LOG_DEBUG,
|
||||
("GtkIMModule(%p): EnsureToCacheSelection(), Succeeded, mSelection="
|
||||
"{ mOffset=%u, mLength=%u, mWritingMode=%s }",
|
||||
this, mSelection.mOffset, mSelection.mLength,
|
||||
GetWritingModeName(mSelection.mWritingMode).get()));
|
||||
return true;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* nsGtkIMModule::Selection
|
||||
******************************************************************************/
|
||||
|
||||
void
|
||||
nsGtkIMModule::Selection::Assign(const IMENotification& aIMENotification)
|
||||
{
|
||||
MOZ_ASSERT(aIMENotification.mMessage == NOTIFY_IME_OF_SELECTION_CHANGE);
|
||||
mOffset = aIMENotification.mSelectionChangeData.mOffset;
|
||||
mLength = aIMENotification.mSelectionChangeData.mLength;
|
||||
mWritingMode = aIMENotification.mSelectionChangeData.GetWritingMode();
|
||||
}
|
||||
|
||||
void
|
||||
nsGtkIMModule::Selection::Assign(const WidgetQueryContentEvent& aEvent)
|
||||
{
|
||||
MOZ_ASSERT(aEvent.message == NS_QUERY_SELECTED_TEXT);
|
||||
MOZ_ASSERT(aEvent.mSucceeded);
|
||||
mOffset = aEvent.mReply.mOffset;
|
||||
mLength = aEvent.mReply.mString.Length();
|
||||
mWritingMode = aEvent.GetWritingMode();
|
||||
}
|
||||
|
||||
@@ -16,13 +16,16 @@
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "WritingModes.h"
|
||||
|
||||
class nsWindow;
|
||||
|
||||
class nsGtkIMModule
|
||||
{
|
||||
protected:
|
||||
typedef mozilla::widget::IMENotification IMENotification;
|
||||
typedef mozilla::widget::InputContext InputContext;
|
||||
typedef mozilla::widget::InputContextAction InputContextAction;
|
||||
|
||||
@@ -48,7 +51,8 @@ public:
|
||||
void OnFocusChangeInGecko(bool aFocus);
|
||||
// OnSelectionChange is a notification that selection (caret) is changed
|
||||
// in the focused editor.
|
||||
void OnSelectionChange(nsWindow* aCaller);
|
||||
void OnSelectionChange(nsWindow* aCaller,
|
||||
const IMENotification& aIMENotification);
|
||||
|
||||
// OnKeyEvent is called when aWindow gets a native key press event or a
|
||||
// native key release event. If this returns TRUE, the key event was
|
||||
@@ -65,6 +69,7 @@ public:
|
||||
const InputContextAction* aAction);
|
||||
InputContext GetInputContext();
|
||||
void OnUpdateComposition();
|
||||
void OnLayoutChange();
|
||||
|
||||
protected:
|
||||
~nsGtkIMModule();
|
||||
@@ -167,6 +172,44 @@ protected:
|
||||
}
|
||||
}
|
||||
|
||||
struct Selection final
|
||||
{
|
||||
uint32_t mOffset;
|
||||
uint32_t mLength;
|
||||
mozilla::WritingMode mWritingMode;
|
||||
|
||||
Selection()
|
||||
: mOffset(UINT32_MAX)
|
||||
, mLength(UINT32_MAX)
|
||||
{
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
mOffset = UINT32_MAX;
|
||||
mLength = UINT32_MAX;
|
||||
mWritingMode = mozilla::WritingMode();
|
||||
}
|
||||
|
||||
void Assign(const IMENotification& aIMENotification);
|
||||
void Assign(const mozilla::WidgetQueryContentEvent& aSelectedTextEvent);
|
||||
|
||||
bool IsValid() const { return mOffset != UINT32_MAX; }
|
||||
bool Collapsed() const { return !mLength; }
|
||||
uint32_t EndOffset() const
|
||||
{
|
||||
if (NS_WARN_IF(!IsValid())) {
|
||||
return UINT32_MAX;
|
||||
}
|
||||
mozilla::CheckedInt<uint32_t> endOffset =
|
||||
mozilla::CheckedInt<uint32_t>(mOffset) + mLength;
|
||||
if (NS_WARN_IF(!endOffset.isValid())) {
|
||||
return UINT32_MAX;
|
||||
}
|
||||
return endOffset.value();
|
||||
}
|
||||
} mSelection;
|
||||
bool EnsureToCacheSelection(nsAString* aSelectedString = nullptr);
|
||||
|
||||
// mIsIMFocused is set to TRUE when we call gtk_im_context_focus_in(). And
|
||||
// it's set to FALSE when we call gtk_im_context_focus_out().
|
||||
@@ -184,6 +227,9 @@ protected:
|
||||
// mIsDeletingSurrounding is true while OnDeleteSurroundingNative() is
|
||||
// trying to delete the surrounding text.
|
||||
bool mIsDeletingSurrounding;
|
||||
// mLayoutChanged is true after OnLayoutChange() is called. This is reset
|
||||
// when NS_COMPOSITION_CHANGE is being dispatched.
|
||||
bool mLayoutChanged;
|
||||
|
||||
// sLastFocusedModule is a pointer to the last focused instance of this
|
||||
// class. When a instance is destroyed and sLastFocusedModule refers it,
|
||||
|
||||
@@ -4159,7 +4159,7 @@ nsWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
|
||||
|
||||
for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
|
||||
const Configuration& configuration = aConfigurations[i];
|
||||
nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
|
||||
nsWindow* w = static_cast<nsWindow*>(configuration.mChild.get());
|
||||
NS_ASSERTION(w->GetParent() == this,
|
||||
"Configured widget is not a child");
|
||||
w->SetWindowClipRegion(configuration.mClipRegion, true);
|
||||
@@ -6027,11 +6027,14 @@ nsWindow::NotifyIMEInternal(const IMENotification& aIMENotification)
|
||||
case NOTIFY_IME_OF_BLUR:
|
||||
mIMModule->OnFocusChangeInGecko(false);
|
||||
return NS_OK;
|
||||
case NOTIFY_IME_OF_POSITION_CHANGE:
|
||||
mIMModule->OnLayoutChange();
|
||||
return NS_OK;
|
||||
case NOTIFY_IME_OF_COMPOSITION_UPDATE:
|
||||
mIMModule->OnUpdateComposition();
|
||||
return NS_OK;
|
||||
case NOTIFY_IME_OF_SELECTION_CHANGE:
|
||||
mIMModule->OnSelectionChange(this);
|
||||
mIMModule->OnSelectionChange(this, aIMENotification);
|
||||
return NS_OK;
|
||||
default:
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
@@ -6070,7 +6073,8 @@ nsIMEUpdatePreference
|
||||
nsWindow::GetIMEUpdatePreference()
|
||||
{
|
||||
nsIMEUpdatePreference updatePreference(
|
||||
nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE);
|
||||
nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE |
|
||||
nsIMEUpdatePreference::NOTIFY_POSITION_CHANGE);
|
||||
// We shouldn't notify IME of selection change caused by changes of
|
||||
// composition string. Therefore, we don't need to be notified selection
|
||||
// changes which are caused by compositionchange events handled.
|
||||
|
||||
@@ -1930,6 +1930,60 @@ nsIWidget::UpdateRegisteredPluginWindowVisibility(nsTArray<uintptr_t>& aVisibleL
|
||||
#endif
|
||||
}
|
||||
|
||||
already_AddRefed<mozilla::gfx::SourceSurface>
|
||||
nsIWidget::SnapshotWidgetOnScreen()
|
||||
{
|
||||
// This is only supported on a widget with a compositor.
|
||||
LayerManager* layerManager = GetLayerManager();
|
||||
if (!layerManager) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ClientLayerManager* lm = layerManager->AsClientLayerManager();
|
||||
if (!lm) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CompositorChild* cc = lm->GetRemoteRenderer();
|
||||
if (!cc) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIntRect bounds;
|
||||
GetBounds(bounds);
|
||||
if (bounds.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
gfx::IntSize size(bounds.width, bounds.height);
|
||||
|
||||
ShadowLayerForwarder* forwarder = lm->AsShadowForwarder();
|
||||
SurfaceDescriptor surface;
|
||||
if (!forwarder->AllocSurfaceDescriptor(size, gfxContentType::COLOR_ALPHA, &surface)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!cc->SendMakeWidgetSnapshot(surface)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<gfx::DataSourceSurface> snapshot = GetSurfaceForDescriptor(surface);
|
||||
RefPtr<gfx::DrawTarget> dt =
|
||||
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(size, gfx::SurfaceFormat::B8G8R8A8);
|
||||
if (!snapshot || !dt) {
|
||||
forwarder->DestroySharedSurface(&surface);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
dt->DrawSurface(snapshot,
|
||||
gfx::Rect(gfx::Point(), gfx::Size(size)),
|
||||
gfx::Rect(gfx::Point(), gfx::Size(size)),
|
||||
gfx::DrawSurfaceOptions(gfx::Filter::POINT));
|
||||
|
||||
forwarder->DestroySharedSurface(&surface);
|
||||
return dt->Snapshot();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
//////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
||||
@@ -294,6 +294,10 @@ public:
|
||||
virtual const SizeConstraints& GetSizeConstraints() const override;
|
||||
virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override;
|
||||
|
||||
virtual bool CaptureWidgetOnScreen(mozilla::RefPtr<mozilla::gfx::DrawTarget> aDT) override {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this when GetLayerManager() returns a BasicLayerManager
|
||||
* (nsBaseWidget::GetLayerManager() does). This sets up the widget's
|
||||
|
||||
+20
-1
@@ -58,6 +58,7 @@ struct ScrollableLayerGuid;
|
||||
}
|
||||
namespace gfx {
|
||||
class DrawTarget;
|
||||
class SourceSurface;
|
||||
}
|
||||
namespace widget {
|
||||
class TextEventDispatcher;
|
||||
@@ -109,6 +110,7 @@ typedef void* nsNativeWidget;
|
||||
#define NS_NATIVE_TSF_CATEGORY_MGR 101
|
||||
#define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
|
||||
#define NS_NATIVE_ICOREWINDOW 103 // winrt specific
|
||||
#define NS_NATIVE_CHILD_WINDOW 104
|
||||
#endif
|
||||
#if defined(MOZ_WIDGET_GTK)
|
||||
// set/get nsPluginNativeWindowGtk, e10s specific
|
||||
@@ -1464,7 +1466,7 @@ class nsIWidget : public nsISupports {
|
||||
* a child widget.
|
||||
*/
|
||||
struct Configuration {
|
||||
nsIWidget* mChild;
|
||||
nsCOMPtr<nsIWidget> mChild;
|
||||
uintptr_t mWindowID; // e10s specific, the unique plugin port id
|
||||
bool mVisible; // e10s specific, widget visibility
|
||||
nsIntRect mBounds;
|
||||
@@ -2118,6 +2120,23 @@ class nsIWidget : public nsISupports {
|
||||
*/
|
||||
virtual nsresult ClearNativeTouchSequence(nsIObserver* aObserver);
|
||||
|
||||
/*
|
||||
* Snapshot the contents of the widget by reading pixels back from the
|
||||
* Operating System. Unlike RenderDocument(), this does not read from our
|
||||
* own backbuffers, so that we can test if there is a difference in how
|
||||
* our buffers are being presented.
|
||||
*
|
||||
* This is only supported for widgets using OMTC.
|
||||
*/
|
||||
already_AddRefed<mozilla::gfx::SourceSurface> SnapshotWidgetOnScreen();
|
||||
|
||||
/*
|
||||
* Implementation of SnapshotWidgetOnScreen. This is invoked by the
|
||||
* compositor for SnapshotWidgetOnScreen(), and should not be called
|
||||
* otherwise.
|
||||
*/
|
||||
virtual bool CaptureWidgetOnScreen(mozilla::RefPtr<mozilla::gfx::DrawTarget> aDT) = 0;
|
||||
|
||||
private:
|
||||
class LongTapInfo
|
||||
{
|
||||
|
||||
@@ -180,6 +180,7 @@ IMEHandler::NotifyIME(nsWindow* aWindow,
|
||||
// composition window position.
|
||||
if (IsIMMActive()) {
|
||||
nsIMM32Handler::OnUpdateComposition(aWindow);
|
||||
nsIMM32Handler::OnSelectionChange(aWindow, aIMENotification);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
@@ -238,6 +239,9 @@ IMEHandler::NotifyIME(nsWindow* aWindow,
|
||||
case NOTIFY_IME_OF_COMPOSITION_UPDATE:
|
||||
nsIMM32Handler::OnUpdateComposition(aWindow);
|
||||
return NS_OK;
|
||||
case NOTIFY_IME_OF_SELECTION_CHANGE:
|
||||
nsIMM32Handler::OnSelectionChange(aWindow, aIMENotification);
|
||||
return NS_OK;
|
||||
case NOTIFY_IME_OF_MOUSE_BUTTON_EVENT:
|
||||
return nsIMM32Handler::OnMouseButtonEvent(aWindow, aIMENotification);
|
||||
#ifdef NS_ENABLE_TSF
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "nsWindowDefs.h"
|
||||
#include "WinUtils.h"
|
||||
#include "KeyboardLayout.h"
|
||||
#include "WritingModes.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "mozilla/MiscEvents.h"
|
||||
@@ -132,6 +131,7 @@ static UINT sWM_MSIME_MOUSE = 0; // mouse message for MSIME 98/2000
|
||||
#define IMEMOUSE_WUP 0x10 // wheel up
|
||||
#define IMEMOUSE_WDOWN 0x20 // wheel down
|
||||
|
||||
WritingMode nsIMM32Handler::sWritingModeOfCompositionFont;
|
||||
nsString nsIMM32Handler::sIMEName;
|
||||
UINT nsIMM32Handler::sCodePage = 0;
|
||||
DWORD nsIMM32Handler::sIMEProperty = 0;
|
||||
@@ -158,7 +158,7 @@ nsIMM32Handler::Initialize()
|
||||
sAssumeVerticalWritingModeNotSupported =
|
||||
Preferences::GetBool(
|
||||
"intl.imm.vertical_writing.always_assume_not_supported", false);
|
||||
InitKeyboardLayout(::GetKeyboardLayout(0));
|
||||
InitKeyboardLayout(nullptr, ::GetKeyboardLayout(0));
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
@@ -205,6 +205,15 @@ nsIMM32Handler::IsJapanist2003Active()
|
||||
return sIMEName.EqualsLiteral("Japanist 2003");
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsIMM32Handler::IsGoogleJapaneseInputActive()
|
||||
{
|
||||
// NOTE: Even on Windows for en-US, the name of Google Japanese Input is
|
||||
// written in Japanese.
|
||||
return sIMEName.Equals(L"Google \x65E5\x672C\x8A9E\x5165\x529B "
|
||||
L"IMM32 \x30E2\x30B8\x30E5\x30FC\x30EB");
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsIMM32Handler::ShouldDrawCompositionStringOurselves()
|
||||
{
|
||||
@@ -223,18 +232,24 @@ nsIMM32Handler::IsVerticalWritingSupported()
|
||||
if (sAssumeVerticalWritingModeNotSupported) {
|
||||
return false;
|
||||
}
|
||||
// Google Japanese Input doesn't support vertical writing mode. We should
|
||||
// return false if it's active IME.
|
||||
if (IsGoogleJapaneseInputActive()) {
|
||||
return false;
|
||||
}
|
||||
return !!(sIMEUIProperty & (UI_CAP_2700 | UI_CAP_ROT90 | UI_CAP_ROTANY));
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsIMM32Handler::InitKeyboardLayout(HKL aKeyboardLayout)
|
||||
nsIMM32Handler::InitKeyboardLayout(nsWindow* aWindow,
|
||||
HKL aKeyboardLayout)
|
||||
{
|
||||
UINT IMENameLength = ::ImmGetDescriptionW(aKeyboardLayout, nullptr, 0);
|
||||
if (IMENameLength) {
|
||||
// Add room for the terminating null character
|
||||
sIMEName.SetLength(++IMENameLength);
|
||||
IMENameLength =
|
||||
::ImmGetDescriptionW(aKeyboardLayout, sIMEName.BeginWriting(),
|
||||
::ImmGetDescriptionW(aKeyboardLayout, wwc(sIMEName.BeginWriting()),
|
||||
IMENameLength);
|
||||
// Adjust the length to ignore the terminating null character
|
||||
sIMEName.SetLength(IMENameLength);
|
||||
@@ -248,6 +263,22 @@ nsIMM32Handler::InitKeyboardLayout(HKL aKeyboardLayout)
|
||||
(PWSTR)&sCodePage, sizeof(sCodePage) / sizeof(WCHAR));
|
||||
sIMEProperty = ::ImmGetProperty(aKeyboardLayout, IGP_PROPERTY);
|
||||
sIMEUIProperty = ::ImmGetProperty(aKeyboardLayout, IGP_UI);
|
||||
|
||||
// If active IME is a TIP of TSF, we cannot retrieve the name with IMM32 API.
|
||||
// For hacking some bugs of some TIP, we should set an IME name from the
|
||||
// pref.
|
||||
if (sCodePage == 932 && sIMEName.IsEmpty()) {
|
||||
sIMEName =
|
||||
Preferences::GetString("intl.imm.japanese.assume_active_tip_name_as");
|
||||
}
|
||||
|
||||
// Whether the IME supports vertical writing mode might be changed or
|
||||
// some IMEs may need specific font for their UI. Therefore, we should
|
||||
// update composition font forcibly here.
|
||||
if (aWindow) {
|
||||
MaybeAdjustCompositionFont(aWindow, sWritingModeOfCompositionFont, true);
|
||||
}
|
||||
|
||||
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
|
||||
("IMM32: InitKeyboardLayout, aKeyboardLayout=%08x (\"%s\"), sCodePage=%lu, "
|
||||
"sIMEProperty=%s, sIMEUIProperty=%s",
|
||||
@@ -268,6 +299,7 @@ nsIMM32Handler::GetIMEUpdatePreference()
|
||||
{
|
||||
return nsIMEUpdatePreference(
|
||||
nsIMEUpdatePreference::NOTIFY_POSITION_CHANGE |
|
||||
nsIMEUpdatePreference::NOTIFY_SELECTION_CHANGE |
|
||||
nsIMEUpdatePreference::NOTIFY_MOUSE_BUTTON_EVENT_ON_CHAR);
|
||||
}
|
||||
|
||||
@@ -389,6 +421,43 @@ nsIMM32Handler::OnUpdateComposition(nsWindow* aWindow)
|
||||
gIMM32Handler->SetIMERelatedWindowsPos(aWindow, IMEContext);
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsIMM32Handler::OnSelectionChange(nsWindow* aWindow,
|
||||
const IMENotification& aIMENotification)
|
||||
{
|
||||
if (aIMENotification.mSelectionChangeData.mCausedByComposition) {
|
||||
return;
|
||||
}
|
||||
MaybeAdjustCompositionFont(aWindow,
|
||||
aIMENotification.mSelectionChangeData.GetWritingMode());
|
||||
}
|
||||
|
||||
// static
|
||||
void
|
||||
nsIMM32Handler::MaybeAdjustCompositionFont(nsWindow* aWindow,
|
||||
const WritingMode& aWritingMode,
|
||||
bool aForceUpdate)
|
||||
{
|
||||
switch (sCodePage) {
|
||||
case 932: // Japanese Shift-JIS
|
||||
case 936: // Simlified Chinese GBK
|
||||
case 949: // Korean
|
||||
case 950: // Traditional Chinese Big5
|
||||
EnsureHandlerInstance();
|
||||
break;
|
||||
default:
|
||||
// If there is no instance of nsIMM32Hander, we shouldn't waste footprint.
|
||||
if (!gIMM32Handler) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Like Navi-Bar of ATOK, some IMEs may require proper composition font even
|
||||
// before sending WM_IME_STARTCOMPOSITION.
|
||||
nsIMEContext IMEContext(aWindow->GetWindowHandle());
|
||||
gIMM32Handler->AdjustCompositionFont(IMEContext, aWritingMode, aForceUpdate);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsIMM32Handler::ProcessInputLangChangeMessage(nsWindow* aWindow,
|
||||
@@ -402,7 +471,7 @@ nsIMM32Handler::ProcessInputLangChangeMessage(nsWindow* aWindow,
|
||||
if (gIMM32Handler) {
|
||||
gIMM32Handler->OnInputLangChange(aWindow, wParam, lParam, aResult);
|
||||
}
|
||||
InitKeyboardLayout(reinterpret_cast<HKL>(lParam));
|
||||
InitKeyboardLayout(aWindow, reinterpret_cast<HKL>(lParam));
|
||||
// We can release the instance here, because the instance may be never
|
||||
// used. E.g., the new keyboard layout may not use IME, or it may use TSF.
|
||||
Terminate();
|
||||
@@ -1487,18 +1556,46 @@ nsIMM32Handler::HandleQueryCharPosition(nsWindow* aWindow,
|
||||
// even if the content of the popup window has focus.
|
||||
ResolveIMECaretPos(aWindow->GetTopLevelWindow(false),
|
||||
r, nullptr, screenRect);
|
||||
|
||||
// XXX This might need to check writing mode. However, MSDN doesn't explain
|
||||
// how to set the values in vertical writing mode. Additionally, IME
|
||||
// doesn't work well with top-left of the character (this is explicitly
|
||||
// documented) and its horizontal width. So, it might be better to set
|
||||
// top-right corner of the character and horizontal width, but we're not
|
||||
// sure if it doesn't cause any problems with a lot of IMEs...
|
||||
pCharPosition->pt.x = screenRect.x;
|
||||
pCharPosition->pt.y = screenRect.y;
|
||||
|
||||
pCharPosition->cLineHeight = r.height;
|
||||
|
||||
// XXX we should use NS_QUERY_EDITOR_RECT event here.
|
||||
::GetWindowRect(aWindow->GetWindowHandle(), &pCharPosition->rcDocument);
|
||||
WidgetQueryContentEvent editorRect(true, NS_QUERY_EDITOR_RECT, aWindow);
|
||||
aWindow->InitEvent(editorRect);
|
||||
aWindow->DispatchWindowEvent(&editorRect);
|
||||
if (NS_WARN_IF(!editorRect.mSucceeded)) {
|
||||
PR_LOG(gIMM32Log, PR_LOG_ERROR,
|
||||
("IMM32: HandleQueryCharPosition, NS_QUERY_EDITOR_RECT failed"));
|
||||
::GetWindowRect(aWindow->GetWindowHandle(), &pCharPosition->rcDocument);
|
||||
} else {
|
||||
nsIntRect editorRectInWindow =
|
||||
LayoutDevicePixel::ToUntyped(editorRect.mReply.mRect);
|
||||
nsWindow* window = editorRect.mReply.mFocusedWidget ?
|
||||
static_cast<nsWindow*>(editorRect.mReply.mFocusedWidget) : aWindow;
|
||||
nsIntRect editorRectInScreen;
|
||||
ResolveIMECaretPos(window, editorRectInWindow, nullptr, editorRectInScreen);
|
||||
::SetRect(&pCharPosition->rcDocument,
|
||||
editorRectInScreen.x, editorRectInScreen.y,
|
||||
editorRectInScreen.XMost(), editorRectInScreen.YMost());
|
||||
}
|
||||
|
||||
*oResult = TRUE;
|
||||
|
||||
PR_LOG(gIMM32Log, PR_LOG_ALWAYS,
|
||||
("IMM32: HandleQueryCharPosition, SUCCEEDED\n"));
|
||||
("IMM32: HandleQueryCharPosition, SUCCEEDED, pCharPosition={ pt={ x=%d, "
|
||||
"y=%d }, cLineHeight=%d, rcDocument={ left=%d, top=%d, right=%d, "
|
||||
"bottom=%d } }",
|
||||
pCharPosition->pt.x, pCharPosition->pt.y, pCharPosition->cLineHeight,
|
||||
pCharPosition->rcDocument.left, pCharPosition->rcDocument.top,
|
||||
pCharPosition->rcDocument.right, pCharPosition->rcDocument.bottom));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -2252,7 +2349,8 @@ SetVerticalFontToLogFont(const nsAString& aFontFace,
|
||||
|
||||
void
|
||||
nsIMM32Handler::AdjustCompositionFont(const nsIMEContext& aIMEContext,
|
||||
const WritingMode& aWritingMode)
|
||||
const WritingMode& aWritingMode,
|
||||
bool aForceUpdate)
|
||||
{
|
||||
// An instance of nsIMM32Handler is destroyed when active IME is changed.
|
||||
// Therefore, we need to store the information which are set to the IM
|
||||
@@ -2264,13 +2362,13 @@ nsIMM32Handler::AdjustCompositionFont(const nsIMEContext& aIMEContext,
|
||||
// If composition font is customized by pref, we need to modify the
|
||||
// composition font of the IME context at first time even if the writing mode
|
||||
// is horizontal.
|
||||
bool setCompositionFontForcibly =
|
||||
!sCompositionFontsInitialized && !sCompositionFont.IsEmpty();
|
||||
bool setCompositionFontForcibly = aForceUpdate ||
|
||||
(!sCompositionFontsInitialized && !sCompositionFont.IsEmpty());
|
||||
|
||||
static WritingMode sCurrentWritingMode;
|
||||
static nsString sCurrentIMEName;
|
||||
if (!setCompositionFontForcibly &&
|
||||
sCurrentWritingMode == aWritingMode &&
|
||||
sWritingModeOfCompositionFont == aWritingMode &&
|
||||
sCurrentIMEName == sIMEName) {
|
||||
// Nothing to do if writing mode isn't being changed.
|
||||
return;
|
||||
@@ -2319,7 +2417,7 @@ nsIMM32Handler::AdjustCompositionFont(const nsIMEContext& aIMEContext,
|
||||
}
|
||||
}
|
||||
|
||||
sCurrentWritingMode = aWritingMode;
|
||||
sWritingModeOfCompositionFont = aWritingMode;
|
||||
sCurrentIMEName = sIMEName;
|
||||
|
||||
LOGFONTW logFont;
|
||||
|
||||
@@ -14,13 +14,11 @@
|
||||
#include "nsIWidget.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "nsRect.h"
|
||||
#include "WritingModes.h"
|
||||
|
||||
class nsWindow;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class WritingMode;
|
||||
|
||||
namespace widget {
|
||||
|
||||
struct MSGResult;
|
||||
@@ -146,6 +144,8 @@ public:
|
||||
static void CommitComposition(nsWindow* aWindow, bool aForce = false);
|
||||
static void CancelComposition(nsWindow* aWindow, bool aForce = false);
|
||||
static void OnUpdateComposition(nsWindow* aWindow);
|
||||
static void OnSelectionChange(nsWindow* aWindow,
|
||||
const IMENotification& aIMENotification);
|
||||
|
||||
static nsIMEUpdatePreference GetIMEUpdatePreference();
|
||||
|
||||
@@ -162,10 +162,12 @@ protected:
|
||||
static bool IsComposingWindow(nsWindow* aWindow);
|
||||
|
||||
static bool IsJapanist2003Active();
|
||||
static bool IsGoogleJapaneseInputActive();
|
||||
|
||||
static bool ShouldDrawCompositionStringOurselves();
|
||||
static bool IsVerticalWritingSupported();
|
||||
static void InitKeyboardLayout(HKL aKeyboardLayout);
|
||||
// aWindow can be nullptr if it's called without receiving WM_INPUTLANGCHANGE.
|
||||
static void InitKeyboardLayout(nsWindow* aWindow, HKL aKeyboardLayout);
|
||||
static UINT GetKeyboardCodePage();
|
||||
|
||||
/**
|
||||
@@ -295,9 +297,23 @@ protected:
|
||||
|
||||
/**
|
||||
* AdjustCompositionFont() makes IME vertical writing mode if it's supported.
|
||||
* If aForceUpdate is true, it will update composition font even if writing
|
||||
* mode isn't being changed.
|
||||
*/
|
||||
void AdjustCompositionFont(const nsIMEContext& aIMEContext,
|
||||
const mozilla::WritingMode& aWritingMode);
|
||||
const mozilla::WritingMode& aWritingMode,
|
||||
bool aForceUpdate = false);
|
||||
|
||||
/**
|
||||
* MaybeAdjustCompositionFont() calls AdjustCompositionFont() when the
|
||||
* locale of active IME is CJK. Note that this creates an instance even
|
||||
* when there is no composition but the locale is CJK.
|
||||
*/
|
||||
static void MaybeAdjustCompositionFont(
|
||||
nsWindow* aWindow,
|
||||
const mozilla::WritingMode& aWritingMode,
|
||||
bool aForceUpdate = false);
|
||||
|
||||
/**
|
||||
* Get the current target clause of composition string.
|
||||
* If there are one or more characters whose attribute is ATTR_TARGET_*,
|
||||
@@ -375,6 +391,7 @@ protected:
|
||||
bool mIsComposingOnPlugin;
|
||||
bool mNativeCaretIsCreated;
|
||||
|
||||
static mozilla::WritingMode sWritingModeOfCompositionFont;
|
||||
static nsString sIMEName;
|
||||
static UINT sCodePage;
|
||||
static DWORD sIMEProperty;
|
||||
|
||||
@@ -2939,6 +2939,29 @@ void* nsWindow::GetNativeData(uint32_t aDataType)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsWindow::SetNativeData(uint32_t aDataType, uintptr_t aVal)
|
||||
{
|
||||
switch (aDataType) {
|
||||
case NS_NATIVE_CHILD_WINDOW:
|
||||
{
|
||||
HWND childWindow = reinterpret_cast<HWND>(aVal);
|
||||
|
||||
// Make sure the window is styled to be a child window.
|
||||
LONG_PTR style = GetWindowLongPtr(childWindow, GWL_STYLE);
|
||||
style |= WS_CHILD;
|
||||
style &= ~WS_POPUP;
|
||||
SetWindowLongPtr(childWindow, GWL_STYLE, style);
|
||||
|
||||
// Do the reparenting.
|
||||
::SetParent(childWindow, mWnd);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
NS_ERROR("SetNativeData called with unsupported data type.");
|
||||
}
|
||||
}
|
||||
|
||||
// Free some native data according to aDataType
|
||||
void nsWindow::FreeNativeData(void * data, uint32_t aDataType)
|
||||
{
|
||||
@@ -6388,7 +6411,7 @@ nsWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
|
||||
// need.
|
||||
for (uint32_t i = 0; i < aConfigurations.Length(); ++i) {
|
||||
const Configuration& configuration = aConfigurations[i];
|
||||
nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
|
||||
nsWindow* w = static_cast<nsWindow*>(configuration.mChild.get());
|
||||
NS_ASSERTION(w->GetParent() == this,
|
||||
"Configured widget is not a child");
|
||||
nsresult rv = w->SetWindowClipRegion(configuration.mClipRegion, true);
|
||||
@@ -7599,6 +7622,47 @@ void nsWindow::PickerClosed()
|
||||
}
|
||||
}
|
||||
|
||||
bool nsWindow::CaptureWidgetOnScreen(RefPtr<DrawTarget> aDT)
|
||||
{
|
||||
BOOL dwmEnabled = false;
|
||||
if (WinUtils::dwmIsCompositionEnabledPtr &&
|
||||
WinUtils::dwmFlushProcPtr &&
|
||||
WinUtils::dwmIsCompositionEnabledPtr(&dwmEnabled) &&
|
||||
dwmEnabled)
|
||||
{
|
||||
WinUtils::dwmFlushProcPtr();
|
||||
}
|
||||
|
||||
HDC dc = ::GetDC(mWnd);
|
||||
uint32_t flags = (mTransparencyMode == eTransparencyOpaque)
|
||||
? 0
|
||||
: gfxWindowsSurface::FLAG_IS_TRANSPARENT;
|
||||
|
||||
nsRefPtr<gfxASurface> surf = new gfxWindowsSurface(dc, flags);
|
||||
IntSize size(surf->GetSize().width, surf->GetSize().height);
|
||||
if (size.width < 0 || size.height < 0) {
|
||||
::ReleaseDC(mWnd, dc);
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> source = Factory::CreateDrawTargetForCairoSurface(surf->CairoSurface(), size);
|
||||
if (!source) {
|
||||
::ReleaseDC(mWnd, dc);
|
||||
return false;
|
||||
}
|
||||
RefPtr<SourceSurface> snapshot = source->Snapshot();
|
||||
if (!snapshot) {
|
||||
::ReleaseDC(mWnd, dc);
|
||||
return false;
|
||||
}
|
||||
|
||||
aDT->DrawSurface(snapshot,
|
||||
Rect(0, 0, size.width, size.height),
|
||||
Rect(0, 0, size.width, size.height));
|
||||
::ReleaseDC(mWnd, dc);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool nsWindow::PreRender(LayerManagerComposite*)
|
||||
{
|
||||
// This can block waiting for WM_SETTEXT to finish
|
||||
|
||||
@@ -133,6 +133,7 @@ public:
|
||||
bool aIncludeChildren = false);
|
||||
NS_IMETHOD Invalidate(const nsIntRect & aRect);
|
||||
virtual void* GetNativeData(uint32_t aDataType);
|
||||
void SetNativeData(uint32_t aDataType, uintptr_t aVal) override;
|
||||
virtual void FreeNativeData(void * data, uint32_t aDataType);
|
||||
NS_IMETHOD SetTitle(const nsAString& aTitle);
|
||||
NS_IMETHOD SetIcon(const nsAString& aIconSpec);
|
||||
@@ -281,6 +282,8 @@ public:
|
||||
bool IsPopup();
|
||||
virtual bool ShouldUseOffMainThreadCompositing();
|
||||
|
||||
bool CaptureWidgetOnScreen(mozilla::RefPtr<mozilla::gfx::DrawTarget> aDT);
|
||||
|
||||
protected:
|
||||
virtual ~nsWindow();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user