gecko-dev/layout/xul/nsTitleBarFrame.cpp

174 строки
4.9 KiB
C++

/* -*- 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/. */
#include "nsCOMPtr.h"
#include "nsTitleBarFrame.h"
#include "nsIContent.h"
#include "nsIDocument.h"
#include "nsIDOMNodeList.h"
#include "nsGkAtoms.h"
#include "nsIWidget.h"
#include "nsMenuPopupFrame.h"
#include "nsPresContext.h"
#include "nsIDocShell.h"
#include "nsPIDOMWindow.h"
#include "nsDisplayList.h"
#include "nsContentUtils.h"
#include "mozilla/MouseEvents.h"
using namespace mozilla;
//
// NS_NewTitleBarFrame
//
// Creates a new TitleBar frame and returns it
//
nsIFrame*
NS_NewTitleBarFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
{
return new (aPresShell) nsTitleBarFrame(aContext);
}
NS_IMPL_FRAMEARENA_HELPERS(nsTitleBarFrame)
nsTitleBarFrame::nsTitleBarFrame(nsStyleContext* aContext)
:nsBoxFrame(aContext, false)
{
mTrackingMouseMove = false;
UpdateMouseThrough();
}
void
nsTitleBarFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
// override, since we don't want children to get events
if (aBuilder->IsForEventDelivery()) {
if (!mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::allowevents,
nsGkAtoms::_true, eCaseMatters))
return;
}
nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
}
nsresult
nsTitleBarFrame::HandleEvent(nsPresContext* aPresContext,
WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus)
{
NS_ENSURE_ARG_POINTER(aEventStatus);
if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
return NS_OK;
}
bool doDefault = true;
switch (aEvent->mMessage) {
case eMouseDown: {
if (aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
// titlebar has no effect in non-chrome shells
nsCOMPtr<nsIDocShellTreeItem> dsti = aPresContext->GetDocShell();
if (dsti) {
if (dsti->ItemType() == nsIDocShellTreeItem::typeChrome) {
// we're tracking.
mTrackingMouseMove = true;
// start capture.
nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
// remember current mouse coordinates.
mLastPoint = aEvent->mRefPoint;
}
}
*aEventStatus = nsEventStatus_eConsumeNoDefault;
doDefault = false;
}
}
break;
case eMouseUp: {
if (mTrackingMouseMove &&
aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
// we're done tracking.
mTrackingMouseMove = false;
// end capture
nsIPresShell::SetCapturingContent(nullptr, 0);
*aEventStatus = nsEventStatus_eConsumeNoDefault;
doDefault = false;
}
}
break;
case eMouseMove: {
if(mTrackingMouseMove)
{
LayoutDeviceIntPoint nsMoveBy = aEvent->mRefPoint - mLastPoint;
nsIFrame* parent = GetParent();
while (parent) {
nsMenuPopupFrame* popupFrame = do_QueryFrame(parent);
if (popupFrame)
break;
parent = parent->GetParent();
}
// if the titlebar is in a popup, move the popup frame, otherwise
// move the widget associated with the window
if (parent) {
nsMenuPopupFrame* menuPopupFrame = static_cast<nsMenuPopupFrame*>(parent);
nsCOMPtr<nsIWidget> widget = menuPopupFrame->GetWidget();
LayoutDeviceIntRect bounds;
widget->GetScreenBounds(bounds);
CSSPoint cssPos = (bounds.TopLeft() + nsMoveBy)
/ aPresContext->CSSToDevPixelScale();
menuPopupFrame->MoveTo(RoundedToInt(cssPos), false);
}
else {
nsIPresShell* presShell = aPresContext->PresShell();
nsPIDOMWindowOuter *window = presShell->GetDocument()->GetWindow();
if (window) {
window->MoveBy(nsMoveBy.x, nsMoveBy.y);
}
}
*aEventStatus = nsEventStatus_eConsumeNoDefault;
doDefault = false;
}
}
break;
case eMouseClick: {
WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
if (mouseEvent->IsLeftClickEvent()) {
MouseClicked(mouseEvent);
}
break;
}
default:
break;
}
if ( doDefault )
return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
else
return NS_OK;
}
void
nsTitleBarFrame::MouseClicked(WidgetMouseEvent* aEvent)
{
// Execute the oncommand event handler.
nsContentUtils::DispatchXULCommand(mContent, aEvent && aEvent->IsTrusted());
}