nsTitleBarFrame.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #include "nsCOMPtr.h"
  6. #include "nsTitleBarFrame.h"
  7. #include "nsIContent.h"
  8. #include "nsIDocument.h"
  9. #include "nsIDOMNodeList.h"
  10. #include "nsGkAtoms.h"
  11. #include "nsIWidget.h"
  12. #include "nsMenuPopupFrame.h"
  13. #include "nsPresContext.h"
  14. #include "nsIDocShell.h"
  15. #include "nsPIDOMWindow.h"
  16. #include "nsDisplayList.h"
  17. #include "nsContentUtils.h"
  18. #include "mozilla/MouseEvents.h"
  19. using namespace mozilla;
  20. //
  21. // NS_NewTitleBarFrame
  22. //
  23. // Creates a new TitleBar frame and returns it
  24. //
  25. nsIFrame*
  26. NS_NewTitleBarFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
  27. {
  28. return new (aPresShell) nsTitleBarFrame(aContext);
  29. }
  30. NS_IMPL_FRAMEARENA_HELPERS(nsTitleBarFrame)
  31. nsTitleBarFrame::nsTitleBarFrame(nsStyleContext* aContext)
  32. :nsBoxFrame(aContext, false)
  33. {
  34. mTrackingMouseMove = false;
  35. UpdateMouseThrough();
  36. }
  37. void
  38. nsTitleBarFrame::BuildDisplayListForChildren(nsDisplayListBuilder* aBuilder,
  39. const nsDisplayListSet& aLists)
  40. {
  41. // override, since we don't want children to get events
  42. if (aBuilder->IsForEventDelivery()) {
  43. if (!mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::allowevents,
  44. nsGkAtoms::_true, eCaseMatters))
  45. return;
  46. }
  47. nsBoxFrame::BuildDisplayListForChildren(aBuilder, aLists);
  48. }
  49. nsresult
  50. nsTitleBarFrame::HandleEvent(nsPresContext* aPresContext,
  51. WidgetGUIEvent* aEvent,
  52. nsEventStatus* aEventStatus)
  53. {
  54. NS_ENSURE_ARG_POINTER(aEventStatus);
  55. if (nsEventStatus_eConsumeNoDefault == *aEventStatus) {
  56. return NS_OK;
  57. }
  58. bool doDefault = true;
  59. switch (aEvent->mMessage) {
  60. case eMouseDown: {
  61. if (aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
  62. // titlebar has no effect in non-chrome shells
  63. nsCOMPtr<nsIDocShellTreeItem> dsti = aPresContext->GetDocShell();
  64. if (dsti) {
  65. if (dsti->ItemType() == nsIDocShellTreeItem::typeChrome) {
  66. // we're tracking.
  67. mTrackingMouseMove = true;
  68. // start capture.
  69. nsIPresShell::SetCapturingContent(GetContent(), CAPTURE_IGNOREALLOWED);
  70. // remember current mouse coordinates.
  71. mLastPoint = aEvent->mRefPoint;
  72. }
  73. }
  74. *aEventStatus = nsEventStatus_eConsumeNoDefault;
  75. doDefault = false;
  76. }
  77. }
  78. break;
  79. case eMouseUp: {
  80. if (mTrackingMouseMove &&
  81. aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) {
  82. // we're done tracking.
  83. mTrackingMouseMove = false;
  84. // end capture
  85. nsIPresShell::SetCapturingContent(nullptr, 0);
  86. *aEventStatus = nsEventStatus_eConsumeNoDefault;
  87. doDefault = false;
  88. }
  89. }
  90. break;
  91. case eMouseMove: {
  92. if(mTrackingMouseMove)
  93. {
  94. LayoutDeviceIntPoint nsMoveBy = aEvent->mRefPoint - mLastPoint;
  95. nsIFrame* parent = GetParent();
  96. while (parent) {
  97. nsMenuPopupFrame* popupFrame = do_QueryFrame(parent);
  98. if (popupFrame)
  99. break;
  100. parent = parent->GetParent();
  101. }
  102. // if the titlebar is in a popup, move the popup frame, otherwise
  103. // move the widget associated with the window
  104. if (parent) {
  105. nsMenuPopupFrame* menuPopupFrame = static_cast<nsMenuPopupFrame*>(parent);
  106. nsCOMPtr<nsIWidget> widget = menuPopupFrame->GetWidget();
  107. LayoutDeviceIntRect bounds = widget->GetScreenBounds();
  108. CSSPoint cssPos = (bounds.TopLeft() + nsMoveBy)
  109. / aPresContext->CSSToDevPixelScale();
  110. menuPopupFrame->MoveTo(RoundedToInt(cssPos), false);
  111. }
  112. else {
  113. nsIPresShell* presShell = aPresContext->PresShell();
  114. nsPIDOMWindowOuter *window = presShell->GetDocument()->GetWindow();
  115. if (window) {
  116. window->MoveBy(nsMoveBy.x, nsMoveBy.y);
  117. }
  118. }
  119. *aEventStatus = nsEventStatus_eConsumeNoDefault;
  120. doDefault = false;
  121. }
  122. }
  123. break;
  124. case eMouseClick: {
  125. WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
  126. if (mouseEvent->IsLeftClickEvent()) {
  127. MouseClicked(mouseEvent);
  128. }
  129. break;
  130. }
  131. default:
  132. break;
  133. }
  134. if ( doDefault )
  135. return nsBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
  136. else
  137. return NS_OK;
  138. }
  139. void
  140. nsTitleBarFrame::MouseClicked(WidgetMouseEvent* aEvent)
  141. {
  142. // Execute the oncommand event handler.
  143. nsContentUtils::DispatchXULCommand(mContent, aEvent && aEvent->IsTrusted());
  144. }