gecko-dev/widget/windows/nsWindowBase.cpp
Mantaroh Yoshinaga bcd8f8c970 Bug 1405210 - Part 1: Add PrintDialogService to windows widget. r=jimm,mshal
In order to move print native dialog code to windows widget, this patch will
create skeleton of PrintDialogService to windows widget.
Toolkit code(i.e. nsIPrintingPrompotService) will call this PrintDialogService.

Note that this PrintingDialogService suppose running on main process, so we
should call this interface from main process(i.e. nsPrintingPromptService, not
nsPrintingProxy).

MozReview-Commit-ID: 3P6kac9I9W4

--HG--
extra : rebase_source : 5b5ecd104cf4cecd1b68a3d6d4b33aca9fea9548
2017-10-19 11:04:13 +09:00

246 lines
7.5 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsWindowBase.h"
#include "gfxPrefs.h"
#include "mozilla/MiscEvents.h"
#include "KeyboardLayout.h"
#include "WinUtils.h"
#include "npapi.h"
#include "nsAutoPtr.h"
#include "nsIPresShell.h"
using namespace mozilla;
using namespace mozilla::widget;
static const wchar_t kUser32LibName[] = L"user32.dll";
bool nsWindowBase::sTouchInjectInitialized = false;
InjectTouchInputPtr nsWindowBase::sInjectTouchFuncPtr;
bool
nsWindowBase::DispatchPluginEvent(const MSG& aMsg)
{
if (!ShouldDispatchPluginEvent()) {
return false;
}
WidgetPluginEvent pluginEvent(true, ePluginInputEvent, this);
LayoutDeviceIntPoint point(0, 0);
InitEvent(pluginEvent, &point);
NPEvent npEvent;
npEvent.event = aMsg.message;
npEvent.wParam = aMsg.wParam;
npEvent.lParam = aMsg.lParam;
pluginEvent.mPluginEvent.Copy(npEvent);
pluginEvent.mRetargetToFocusedDocument = true;
return DispatchWindowEvent(&pluginEvent);
}
bool
nsWindowBase::ShouldDispatchPluginEvent()
{
return PluginHasFocus();
}
// static
bool
nsWindowBase::InitTouchInjection()
{
if (!sTouchInjectInitialized) {
// Initialize touch injection on the first call
HMODULE hMod = LoadLibraryW(kUser32LibName);
if (!hMod) {
return false;
}
InitializeTouchInjectionPtr func =
(InitializeTouchInjectionPtr)GetProcAddress(hMod, "InitializeTouchInjection");
if (!func) {
WinUtils::Log("InitializeTouchInjection not available.");
return false;
}
if (!func(TOUCH_INJECT_MAX_POINTS, TOUCH_FEEDBACK_DEFAULT)) {
WinUtils::Log("InitializeTouchInjection failure. GetLastError=%d", GetLastError());
return false;
}
sInjectTouchFuncPtr =
(InjectTouchInputPtr)GetProcAddress(hMod, "InjectTouchInput");
if (!sInjectTouchFuncPtr) {
WinUtils::Log("InjectTouchInput not available.");
return false;
}
sTouchInjectInitialized = true;
}
return true;
}
bool
nsWindowBase::InjectTouchPoint(uint32_t aId, LayoutDeviceIntPoint& aPoint,
POINTER_FLAGS aFlags, uint32_t aPressure,
uint32_t aOrientation)
{
if (aId > TOUCH_INJECT_MAX_POINTS) {
WinUtils::Log("Pointer ID exceeds maximum. See TOUCH_INJECT_MAX_POINTS.");
return false;
}
POINTER_TOUCH_INFO info;
memset(&info, 0, sizeof(POINTER_TOUCH_INFO));
info.touchFlags = TOUCH_FLAG_NONE;
info.touchMask = TOUCH_MASK_CONTACTAREA|TOUCH_MASK_ORIENTATION|TOUCH_MASK_PRESSURE;
info.pressure = aPressure;
info.orientation = aOrientation;
info.pointerInfo.pointerFlags = aFlags;
info.pointerInfo.pointerType = PT_TOUCH;
info.pointerInfo.pointerId = aId;
info.pointerInfo.ptPixelLocation.x = aPoint.x;
info.pointerInfo.ptPixelLocation.y = aPoint.y;
info.rcContact.top = info.pointerInfo.ptPixelLocation.y - 2;
info.rcContact.bottom = info.pointerInfo.ptPixelLocation.y + 2;
info.rcContact.left = info.pointerInfo.ptPixelLocation.x - 2;
info.rcContact.right = info.pointerInfo.ptPixelLocation.x + 2;
if (!sInjectTouchFuncPtr(1, &info)) {
WinUtils::Log("InjectTouchInput failure. GetLastError=%d", GetLastError());
return false;
}
return true;
}
void nsWindowBase::ChangedDPI()
{
if (mWidgetListener) {
nsIPresShell* presShell = mWidgetListener->GetPresShell();
if (presShell) {
presShell->BackingScaleFactorChanged();
}
mWidgetListener->UIResolutionChanged();
}
}
nsresult
nsWindowBase::SynthesizeNativeTouchPoint(uint32_t aPointerId,
nsIWidget::TouchPointerState aPointerState,
LayoutDeviceIntPoint aPoint,
double aPointerPressure,
uint32_t aPointerOrientation,
nsIObserver* aObserver)
{
AutoObserverNotifier notifier(aObserver, "touchpoint");
if (gfxPrefs::APZTestFailsWithNativeInjection() || !InitTouchInjection()) {
// If we don't have touch injection from the OS, or if we are running a test
// that cannot properly inject events to satisfy the OS requirements (see bug
// 1313170) we can just fake it and synthesize the events from here.
MOZ_ASSERT(NS_IsMainThread());
if (aPointerState == TOUCH_HOVER) {
return NS_ERROR_UNEXPECTED;
}
if (!mSynthesizedTouchInput) {
mSynthesizedTouchInput = MakeUnique<MultiTouchInput>();
}
WidgetEventTime time = CurrentMessageWidgetEventTime();
LayoutDeviceIntPoint pointInWindow = aPoint - WidgetToScreenOffset();
MultiTouchInput inputToDispatch = UpdateSynthesizedTouchState(
mSynthesizedTouchInput.get(), time.mTime, time.mTimeStamp,
aPointerId, aPointerState, pointInWindow, aPointerPressure,
aPointerOrientation);
DispatchTouchInput(inputToDispatch);
return NS_OK;
}
bool hover = aPointerState & TOUCH_HOVER;
bool contact = aPointerState & TOUCH_CONTACT;
bool remove = aPointerState & TOUCH_REMOVE;
bool cancel = aPointerState & TOUCH_CANCEL;
// win api expects a value from 0 to 1024. aPointerPressure is a value
// from 0.0 to 1.0.
uint32_t pressure = (uint32_t)ceil(aPointerPressure * 1024);
// If we already know about this pointer id get it's record
PointerInfo* info = mActivePointers.Get(aPointerId);
// We know about this pointer, send an update
if (info) {
POINTER_FLAGS flags = POINTER_FLAG_UPDATE;
if (hover) {
flags |= POINTER_FLAG_INRANGE;
} else if (contact) {
flags |= POINTER_FLAG_INCONTACT|POINTER_FLAG_INRANGE;
} else if (remove) {
flags = POINTER_FLAG_UP;
// Remove the pointer from our tracking list. This is nsAutPtr wrapped,
// so shouldn't leak.
mActivePointers.Remove(aPointerId);
}
if (cancel) {
flags |= POINTER_FLAG_CANCELED;
}
return !InjectTouchPoint(aPointerId, aPoint, flags,
pressure, aPointerOrientation) ?
NS_ERROR_UNEXPECTED : NS_OK;
}
// Missing init state, error out
if (remove || cancel) {
return NS_ERROR_INVALID_ARG;
}
// Create a new pointer
info = new PointerInfo(aPointerId, aPoint);
POINTER_FLAGS flags = POINTER_FLAG_INRANGE;
if (contact) {
flags |= POINTER_FLAG_INCONTACT|POINTER_FLAG_DOWN;
}
mActivePointers.Put(aPointerId, info);
return !InjectTouchPoint(aPointerId, aPoint, flags,
pressure, aPointerOrientation) ?
NS_ERROR_UNEXPECTED : NS_OK;
}
nsresult
nsWindowBase::ClearNativeTouchSequence(nsIObserver* aObserver)
{
AutoObserverNotifier notifier(aObserver, "cleartouch");
if (!sTouchInjectInitialized) {
return NS_OK;
}
// cancel all input points
for (auto iter = mActivePointers.Iter(); !iter.Done(); iter.Next()) {
nsAutoPtr<PointerInfo>& info = iter.Data();
InjectTouchPoint(info.get()->mPointerId, info.get()->mPosition,
POINTER_FLAG_CANCELED);
iter.Remove();
}
nsBaseWidget::ClearNativeTouchSequence(nullptr);
return NS_OK;
}
bool
nsWindowBase::HandleAppCommandMsg(const MSG& aAppCommandMsg,
LRESULT *aRetValue)
{
ModifierKeyState modKeyState;
NativeKey nativeKey(this, aAppCommandMsg, modKeyState);
bool consumed = nativeKey.HandleAppCommandMessage();
*aRetValue = consumed ? 1 : 0;
return consumed;
}