2007-12-19 22:40:18 +03:00
|
|
|
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2015-07-24 02:45:00 +03:00
|
|
|
/* vim: set ts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* 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/. */
|
2001-11-06 18:35:24 +03:00
|
|
|
|
|
|
|
#include "nsCocoaWindow.h"
|
|
|
|
|
2014-03-14 17:13:31 +04:00
|
|
|
#include "NativeKeyBindings.h"
|
|
|
|
#include "TextInputHandler.h"
|
2008-02-21 02:47:05 +03:00
|
|
|
#include "nsObjCExceptions.h"
|
2006-04-06 11:41:34 +04:00
|
|
|
#include "nsCOMPtr.h"
|
2001-11-06 18:35:24 +03:00
|
|
|
#include "nsWidgetsCID.h"
|
|
|
|
#include "nsIRollupListener.h"
|
2006-04-07 08:51:16 +04:00
|
|
|
#include "nsChildView.h"
|
2008-05-02 14:40:49 +04:00
|
|
|
#include "nsWindowMap.h"
|
2009-03-19 01:51:40 +03:00
|
|
|
#include "nsAppShell.h"
|
2006-04-06 11:41:34 +04:00
|
|
|
#include "nsIAppShellService.h"
|
|
|
|
#include "nsIBaseWindow.h"
|
|
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
|
|
#include "nsIXULWindow.h"
|
2007-11-07 10:30:21 +03:00
|
|
|
#include "nsToolkit.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#include "nsIDOMWindow.h"
|
|
|
|
#include "nsPIDOMWindow.h"
|
|
|
|
#include "nsIDOMElement.h"
|
2008-02-13 18:57:12 +03:00
|
|
|
#include "nsThreadUtils.h"
|
2008-03-27 06:42:57 +03:00
|
|
|
#include "nsMenuBarX.h"
|
2008-06-28 11:55:30 +04:00
|
|
|
#include "nsMenuUtilsX.h"
|
2008-10-14 19:33:40 +04:00
|
|
|
#include "nsStyleConsts.h"
|
2008-10-15 17:01:10 +04:00
|
|
|
#include "nsNativeThemeColors.h"
|
2014-08-28 04:15:27 +04:00
|
|
|
#include "nsNativeThemeCocoa.h"
|
2009-04-22 03:53:52 +04:00
|
|
|
#include "nsChildView.h"
|
2012-05-17 11:53:20 +04:00
|
|
|
#include "nsCocoaFeatures.h"
|
2012-05-19 02:16:50 +04:00
|
|
|
#include "nsIScreenManager.h"
|
2012-08-15 22:52:42 +04:00
|
|
|
#include "nsIWidgetListener.h"
|
2012-10-16 23:41:20 +04:00
|
|
|
#include "nsIPresShell.h"
|
2015-07-24 02:45:00 +03:00
|
|
|
#include "nsScreenCocoa.h"
|
2001-11-06 18:35:24 +03:00
|
|
|
|
2013-09-07 07:08:36 +04:00
|
|
|
#include "gfxPlatform.h"
|
2009-04-07 20:02:11 +04:00
|
|
|
#include "qcms.h"
|
2008-04-08 00:55:14 +04:00
|
|
|
|
2014-03-13 16:21:56 +04:00
|
|
|
#include "mozilla/AutoRestore.h"
|
2013-09-25 15:21:22 +04:00
|
|
|
#include "mozilla/BasicEvents.h"
|
2011-05-27 12:15:20 +04:00
|
|
|
#include "mozilla/Preferences.h"
|
2013-01-15 16:22:03 +04:00
|
|
|
#include <algorithm>
|
2011-05-27 12:15:20 +04:00
|
|
|
|
2010-03-01 11:03:49 +03:00
|
|
|
namespace mozilla {
|
|
|
|
namespace layers {
|
|
|
|
class LayerManager;
|
2015-07-13 18:25:42 +03:00
|
|
|
} // namespace layers
|
|
|
|
} // namespace mozilla
|
2010-03-01 11:03:49 +03:00
|
|
|
using namespace mozilla::layers;
|
2013-05-24 20:27:52 +04:00
|
|
|
using namespace mozilla::widget;
|
2011-05-27 12:15:20 +04:00
|
|
|
using namespace mozilla;
|
2010-03-01 11:03:49 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t gXULModalLevel = 0;
|
2009-03-19 01:51:40 +03:00
|
|
|
|
2008-03-24 01:30:56 +03:00
|
|
|
// In principle there should be only one app-modal window at any given time.
|
|
|
|
// But sometimes, despite our best efforts, another window appears above the
|
|
|
|
// current app-modal window. So we need to keep a linked list of app-modal
|
|
|
|
// windows. (A non-sheet window that appears above an app-modal window is
|
|
|
|
// also made app-modal.) See nsCocoaWindow::SetModal().
|
2009-03-19 01:51:40 +03:00
|
|
|
nsCocoaWindowList *gGeckoAppModalWindowList = NULL;
|
2007-09-19 23:17:06 +04:00
|
|
|
|
2006-12-19 22:26:41 +03:00
|
|
|
// defined in nsMenuBarX.mm
|
|
|
|
extern NSMenu* sApplicationMenu; // Application menu shared by all menubars
|
|
|
|
|
|
|
|
// defined in nsChildView.mm
|
2006-04-07 08:51:16 +04:00
|
|
|
extern BOOL gSomeMenuBarPainted;
|
2001-11-06 18:35:24 +03:00
|
|
|
|
2009-12-30 18:24:08 +03:00
|
|
|
extern "C" {
|
|
|
|
// CGSPrivate.h
|
|
|
|
typedef NSInteger CGSConnection;
|
|
|
|
typedef NSInteger CGSWindow;
|
2010-01-13 19:10:25 +03:00
|
|
|
typedef NSUInteger CGSWindowFilterRef;
|
2009-12-30 18:24:08 +03:00
|
|
|
extern CGSConnection _CGSDefaultConnection(void);
|
|
|
|
extern CGError CGSSetWindowShadowAndRimParameters(const CGSConnection cid, CGSWindow wid, float standardDeviation, float density, int offsetX, int offsetY, unsigned int flags);
|
2014-01-03 19:53:41 +04:00
|
|
|
extern CGError CGSSetWindowBackgroundBlurRadius(CGSConnection cid, CGSWindow wid, NSUInteger blur);
|
2009-12-30 18:24:08 +03:00
|
|
|
}
|
|
|
|
|
2006-04-06 11:41:34 +04:00
|
|
|
#define NS_APPSHELLSERVICE_CONTRACTID "@mozilla.org/appshell/appShellService;1"
|
|
|
|
|
2014-04-27 11:06:00 +04:00
|
|
|
NS_IMPL_ISUPPORTS_INHERITED(nsCocoaWindow, Inherited, nsPIWidgetCocoa)
|
2001-11-06 18:35:24 +03:00
|
|
|
|
2007-09-15 21:01:35 +04:00
|
|
|
// A note on testing to see if your object is a sheet...
|
|
|
|
// |mWindowType == eWindowType_sheet| is true if your gecko nsIWidget is a sheet
|
|
|
|
// widget - whether or not the sheet is showing. |[mWindow isSheet]| will return
|
|
|
|
// true *only when the sheet is actually showing*. Choose your test wisely.
|
|
|
|
|
2007-06-13 00:26:24 +04:00
|
|
|
static void RollUpPopups()
|
|
|
|
{
|
2012-10-26 17:15:22 +04:00
|
|
|
nsIRollupListener* rollupListener = nsBaseWidget::GetActiveRollupListener();
|
2012-12-31 21:27:04 +04:00
|
|
|
NS_ENSURE_TRUE_VOID(rollupListener);
|
2012-10-26 17:15:22 +04:00
|
|
|
nsCOMPtr<nsIWidget> rollupWidget = rollupListener->GetRollupWidget();
|
2013-01-29 01:34:00 +04:00
|
|
|
if (!rollupWidget)
|
|
|
|
return;
|
2015-01-08 04:52:20 +03:00
|
|
|
rollupListener->Rollup(0, true, nullptr, nullptr);
|
2007-06-13 00:26:24 +04:00
|
|
|
}
|
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
nsCocoaWindow::nsCocoaWindow()
|
2012-07-30 18:20:58 +04:00
|
|
|
: mParent(nullptr)
|
2006-02-08 00:00:46 +03:00
|
|
|
, mWindow(nil)
|
2006-06-08 21:29:18 +04:00
|
|
|
, mDelegate(nil)
|
|
|
|
, mSheetWindowParent(nil)
|
2006-07-25 22:51:41 +04:00
|
|
|
, mPopupContentView(nil)
|
2015-08-06 08:37:48 +03:00
|
|
|
, mFullscreenTransitionAnimation(nil)
|
2009-12-30 18:24:08 +03:00
|
|
|
, mShadowStyle(NS_STYLE_WINDOW_SHADOW_DEFAULT)
|
2012-09-29 15:36:09 +04:00
|
|
|
, mBackingScaleFactor(0.0)
|
2012-02-17 07:47:39 +04:00
|
|
|
, mAnimationType(nsIWidget::eGenericWindowAnimation)
|
2011-10-01 04:20:33 +04:00
|
|
|
, mWindowMadeHere(false)
|
|
|
|
, mSheetNeedsShow(false)
|
2015-06-04 04:49:34 +03:00
|
|
|
, mInFullScreenMode(false)
|
2012-03-29 23:18:50 +04:00
|
|
|
, mInFullScreenTransition(false)
|
2011-10-01 04:20:33 +04:00
|
|
|
, mModal(false)
|
2015-06-04 04:49:34 +03:00
|
|
|
, mSupportsNativeFullScreen(false)
|
|
|
|
, mInNativeFullScreenMode(false)
|
2012-02-17 07:47:39 +04:00
|
|
|
, mIsAnimationSuppressed(false)
|
2011-12-13 20:55:16 +04:00
|
|
|
, mInReportMoveEvent(false)
|
2014-03-13 16:21:56 +04:00
|
|
|
, mInResize(false)
|
2008-03-24 01:30:56 +03:00
|
|
|
, mNumModalDescendents(0)
|
2001-11-06 18:35:24 +03:00
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2009-06-24 19:15:32 +04:00
|
|
|
void nsCocoaWindow::DestroyNativeWindow()
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow)
|
|
|
|
return;
|
|
|
|
|
2009-06-24 19:15:32 +04:00
|
|
|
// We want to unhook the delegate here because we don't want events
|
|
|
|
// sent to it after this object has been destroyed.
|
|
|
|
[mWindow setDelegate:nil];
|
|
|
|
[mWindow close];
|
2012-06-18 19:20:02 +04:00
|
|
|
mWindow = nil;
|
2009-06-24 19:15:32 +04:00
|
|
|
[mDelegate autorelease];
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
nsCocoaWindow::~nsCocoaWindow()
|
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2009-04-23 19:54:50 +04:00
|
|
|
// Notify the children that we're gone. Popup windows (e.g. tooltips) can
|
|
|
|
// have nsChildView children. 'kid' is an nsChildView object if and only if
|
2014-12-11 17:44:07 +03:00
|
|
|
// its 'type' is 'eWindowType_child'.
|
2009-09-24 13:32:20 +04:00
|
|
|
// childView->ResetParent() can change our list of children while it's
|
|
|
|
// being iterated, so the way we iterate the list must allow for this.
|
2009-07-20 19:02:31 +04:00
|
|
|
for (nsIWidget* kid = mLastChild; kid;) {
|
2014-03-19 20:48:08 +04:00
|
|
|
nsWindowType kidType = kid->WindowType();
|
2014-12-11 17:44:07 +03:00
|
|
|
if (kidType == eWindowType_child) {
|
2009-04-23 19:54:50 +04:00
|
|
|
nsChildView* childView = static_cast<nsChildView*>(kid);
|
2009-07-20 19:02:31 +04:00
|
|
|
kid = kid->GetPrevSibling();
|
2009-04-23 19:54:50 +04:00
|
|
|
childView->ResetParent();
|
|
|
|
} else {
|
|
|
|
nsCocoaWindow* childWindow = static_cast<nsCocoaWindow*>(kid);
|
2012-07-30 18:20:58 +04:00
|
|
|
childWindow->mParent = nullptr;
|
2009-07-20 19:02:31 +04:00
|
|
|
kid = kid->GetPrevSibling();
|
2009-04-23 19:54:50 +04:00
|
|
|
}
|
2006-12-12 21:55:24 +03:00
|
|
|
}
|
|
|
|
|
2009-09-16 01:56:44 +04:00
|
|
|
if (mWindow && mWindowMadeHere) {
|
|
|
|
DestroyNativeWindow();
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
2006-07-25 22:51:41 +04:00
|
|
|
|
|
|
|
NS_IF_RELEASE(mPopupContentView);
|
2007-09-19 23:17:06 +04:00
|
|
|
|
|
|
|
// Deal with the possiblity that we're being destroyed while running modal.
|
|
|
|
if (mModal) {
|
2013-05-10 03:57:19 +04:00
|
|
|
NS_WARNING("Widget destroyed while running modal!");
|
2007-09-19 23:17:06 +04:00
|
|
|
--gXULModalLevel;
|
|
|
|
NS_ASSERTION(gXULModalLevel >= 0, "Wierdness setting modality!");
|
|
|
|
}
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2012-10-16 23:41:20 +04:00
|
|
|
// Find the screen that overlaps aRect the most,
|
|
|
|
// if none are found default to the mainScreen.
|
|
|
|
static NSScreen *FindTargetScreenForRect(const nsIntRect& aRect)
|
|
|
|
{
|
|
|
|
NSScreen *targetScreen = [NSScreen mainScreen];
|
|
|
|
NSEnumerator *screenEnum = [[NSScreen screens] objectEnumerator];
|
|
|
|
int largestIntersectArea = 0;
|
|
|
|
while (NSScreen *screen = [screenEnum nextObject]) {
|
|
|
|
nsIntRect screenRect(nsCocoaUtils::CocoaRectToGeckoRect([screen visibleFrame]));
|
|
|
|
screenRect = screenRect.Intersect(aRect);
|
|
|
|
int area = screenRect.width * screenRect.height;
|
|
|
|
if (area > largestIntersectArea) {
|
|
|
|
largestIntersectArea = area;
|
|
|
|
targetScreen = screen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return targetScreen;
|
|
|
|
}
|
|
|
|
|
|
|
|
// fits the rect to the screen that contains the largest area of it,
|
|
|
|
// or to aScreen if a screen is passed in
|
2012-10-18 14:38:26 +04:00
|
|
|
// NB: this operates with aRect in global display pixels
|
2015-06-04 04:49:34 +03:00
|
|
|
static void FitRectToVisibleAreaForScreen(nsIntRect &aRect, NSScreen *aScreen)
|
2007-12-03 19:25:36 +03:00
|
|
|
{
|
2012-09-29 15:36:09 +04:00
|
|
|
if (!aScreen) {
|
2012-10-16 23:41:20 +04:00
|
|
|
aScreen = FindTargetScreenForRect(aRect);
|
2012-09-29 15:36:09 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsIntRect screenBounds(nsCocoaUtils::CocoaRectToGeckoRect([aScreen visibleFrame]));
|
|
|
|
|
2010-10-25 05:32:12 +04:00
|
|
|
if (aRect.width > screenBounds.width) {
|
|
|
|
aRect.width = screenBounds.width;
|
2007-12-03 19:25:36 +03:00
|
|
|
}
|
2010-10-25 05:32:12 +04:00
|
|
|
if (aRect.height > screenBounds.height) {
|
|
|
|
aRect.height = screenBounds.height;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aRect.x - screenBounds.x + aRect.width > screenBounds.width) {
|
|
|
|
aRect.x += screenBounds.width - (aRect.x - screenBounds.x + aRect.width);
|
|
|
|
}
|
|
|
|
if (aRect.y - screenBounds.y + aRect.height > screenBounds.height) {
|
|
|
|
aRect.y += screenBounds.height - (aRect.y - screenBounds.y + aRect.height);
|
2007-12-03 19:25:36 +03:00
|
|
|
}
|
2011-08-19 23:52:26 +04:00
|
|
|
|
|
|
|
// If the left/top edge of the window is off the screen in either direction,
|
|
|
|
// then set the window to start at the left/top edge of the screen.
|
|
|
|
if (aRect.x < screenBounds.x || aRect.x > (screenBounds.x + screenBounds.width)) {
|
|
|
|
aRect.x = screenBounds.x;
|
|
|
|
}
|
|
|
|
if (aRect.y < screenBounds.y || aRect.y > (screenBounds.y + screenBounds.height)) {
|
|
|
|
aRect.y = screenBounds.y;
|
|
|
|
}
|
2007-12-03 19:25:36 +03:00
|
|
|
}
|
|
|
|
|
2014-10-10 19:00:29 +04:00
|
|
|
// Some applications use native popup windows
|
2009-06-24 19:15:32 +04:00
|
|
|
// (native context menus, native tooltips)
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool UseNativePopupWindows()
|
2009-06-24 19:15:32 +04:00
|
|
|
{
|
2011-06-22 01:00:47 +04:00
|
|
|
#ifdef MOZ_USE_NATIVE_POPUP_WINDOWS
|
2011-10-01 04:20:33 +04:00
|
|
|
return true;
|
2011-06-22 01:00:47 +04:00
|
|
|
#else
|
2011-10-01 04:20:33 +04:00
|
|
|
return false;
|
2011-06-22 01:00:47 +04:00
|
|
|
#endif /* MOZ_USE_NATIVE_POPUP_WINDOWS */
|
2009-06-24 19:15:32 +04:00
|
|
|
}
|
|
|
|
|
2012-10-18 14:38:26 +04:00
|
|
|
// aRect here is specified in global display pixels
|
2009-09-24 10:18:10 +04:00
|
|
|
nsresult nsCocoaWindow::Create(nsIWidget *aParent,
|
|
|
|
nsNativeWidget aNativeParent,
|
|
|
|
const nsIntRect &aRect,
|
|
|
|
nsWidgetInitData *aInitData)
|
2001-11-06 18:35:24 +03:00
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2010-04-14 00:36:03 +04:00
|
|
|
// Because the hidden window is created outside of an event loop,
|
|
|
|
// we have to provide an autorelease pool (see bug 559075).
|
|
|
|
nsAutoreleasePool localPool;
|
|
|
|
|
2010-10-25 05:32:12 +04:00
|
|
|
nsIntRect newBounds = aRect;
|
2015-06-04 04:49:34 +03:00
|
|
|
FitRectToVisibleAreaForScreen(newBounds, nullptr);
|
2007-12-03 19:25:36 +03:00
|
|
|
|
2009-09-24 13:32:20 +04:00
|
|
|
// Set defaults which can be overriden from aInitData in BaseCreate
|
|
|
|
mWindowType = eWindowType_toplevel;
|
|
|
|
mBorderStyle = eBorderStyle_default;
|
|
|
|
|
2011-10-25 19:05:32 +04:00
|
|
|
// Ensure that the toolkit is created.
|
|
|
|
nsToolkit::GetToolkit();
|
|
|
|
|
2012-10-18 14:38:26 +04:00
|
|
|
// newBounds is still display (global screen) pixels at this point;
|
|
|
|
// fortunately, BaseCreate doesn't actually use it so we don't
|
|
|
|
// need to worry about trying to convert it to device pixels
|
|
|
|
// when we don't have a window (or dev context, perhaps) yet
|
2015-02-05 08:18:30 +03:00
|
|
|
Inherited::BaseCreate(aParent, newBounds, aInitData);
|
2009-06-24 19:15:32 +04:00
|
|
|
|
2006-02-07 22:15:42 +03:00
|
|
|
mParent = aParent;
|
2007-03-30 23:51:51 +04:00
|
|
|
|
2009-09-24 10:18:10 +04:00
|
|
|
// Applications that use native popups don't want us to create popup windows.
|
|
|
|
if ((mWindowType == eWindowType_popup) && UseNativePopupWindows())
|
|
|
|
return NS_OK;
|
2009-06-24 19:15:32 +04:00
|
|
|
|
2012-10-18 14:38:26 +04:00
|
|
|
nsresult rv =
|
|
|
|
CreateNativeWindow(nsCocoaUtils::GeckoRectToCocoaRect(newBounds),
|
|
|
|
mBorderStyle, false);
|
2009-09-24 10:18:10 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2011-04-26 05:37:20 +04:00
|
|
|
if (mWindowType == eWindowType_popup) {
|
2014-01-31 17:27:43 +04:00
|
|
|
if (aInitData->mMouseTransparent) {
|
2011-04-26 05:37:20 +04:00
|
|
|
[mWindow setIgnoresMouseEvents:YES];
|
|
|
|
}
|
2012-10-18 14:38:26 +04:00
|
|
|
// now we can convert newBounds to device pixels for the window we created,
|
|
|
|
// as the child view expects a rect expressed in the dev pix of its parent
|
|
|
|
double scale = BackingScaleFactor();
|
|
|
|
newBounds.x *= scale;
|
|
|
|
newBounds.y *= scale;
|
|
|
|
newBounds.width *= scale;
|
|
|
|
newBounds.height *= scale;
|
2015-02-05 10:35:25 +03:00
|
|
|
return CreatePopupContentView(newBounds);
|
2011-04-26 05:37:20 +04:00
|
|
|
}
|
2007-03-30 23:51:51 +04:00
|
|
|
|
2012-02-17 07:47:39 +04:00
|
|
|
mIsAnimationSuppressed = aInitData->mIsAnimationSuppressed;
|
|
|
|
|
2009-06-24 19:15:32 +04:00
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
}
|
|
|
|
|
2009-06-27 17:58:03 +04:00
|
|
|
static unsigned int WindowMaskForBorderStyle(nsBorderStyle aBorderStyle)
|
2009-06-24 19:15:32 +04:00
|
|
|
{
|
2011-09-29 10:19:26 +04:00
|
|
|
bool allOrDefault = (aBorderStyle == eBorderStyle_all ||
|
2009-06-27 17:58:03 +04:00
|
|
|
aBorderStyle == eBorderStyle_default);
|
2009-06-24 19:15:32 +04:00
|
|
|
|
2009-06-27 17:58:03 +04:00
|
|
|
/* Apple's docs on NSWindow styles say that "a window's style mask should
|
|
|
|
* include NSTitledWindowMask if it includes any of the others [besides
|
|
|
|
* NSBorderlessWindowMask]". This implies that a borderless window
|
|
|
|
* shouldn't have any other styles than NSBorderlessWindowMask.
|
|
|
|
*/
|
|
|
|
if (!allOrDefault && !(aBorderStyle & eBorderStyle_title))
|
|
|
|
return NSBorderlessWindowMask;
|
2009-06-24 19:15:32 +04:00
|
|
|
|
2009-10-18 08:05:42 +04:00
|
|
|
unsigned int mask = NSTitledWindowMask;
|
2009-06-27 17:58:03 +04:00
|
|
|
if (allOrDefault || aBorderStyle & eBorderStyle_close)
|
|
|
|
mask |= NSClosableWindowMask;
|
2009-10-18 08:05:42 +04:00
|
|
|
if (allOrDefault || aBorderStyle & eBorderStyle_minimize)
|
|
|
|
mask |= NSMiniaturizableWindowMask;
|
2009-06-27 17:58:03 +04:00
|
|
|
if (allOrDefault || aBorderStyle & eBorderStyle_resizeh)
|
|
|
|
mask |= NSResizableWindowMask;
|
2009-06-24 19:15:32 +04:00
|
|
|
|
2009-06-27 17:58:03 +04:00
|
|
|
return mask;
|
|
|
|
}
|
|
|
|
|
2010-09-18 15:28:50 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::ReparentNativeWidget(nsIWidget* aNewParent)
|
|
|
|
{
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2009-07-22 12:57:39 +04:00
|
|
|
// If aRectIsFrameRect, aRect specifies the frame rect of the new window.
|
|
|
|
// Otherwise, aRect.x/y specify the position of the window's frame relative to
|
|
|
|
// the bottom of the menubar and aRect.width/height specify the size of the
|
|
|
|
// content rect.
|
|
|
|
nsresult nsCocoaWindow::CreateNativeWindow(const NSRect &aRect,
|
|
|
|
nsBorderStyle aBorderStyle,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aRectIsFrameRect)
|
2009-06-27 17:58:03 +04:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
2009-06-24 19:15:32 +04:00
|
|
|
|
2009-06-27 17:58:03 +04:00
|
|
|
// We default to NSBorderlessWindowMask, add features if needed.
|
2009-06-24 19:15:32 +04:00
|
|
|
unsigned int features = NSBorderlessWindowMask;
|
|
|
|
|
2009-06-27 17:58:03 +04:00
|
|
|
// Configure the window we will create based on the window type.
|
2009-06-24 19:15:32 +04:00
|
|
|
switch (mWindowType)
|
|
|
|
{
|
|
|
|
case eWindowType_invisible:
|
|
|
|
case eWindowType_child:
|
2009-09-24 13:32:20 +04:00
|
|
|
case eWindowType_plugin:
|
2010-07-27 17:38:03 +04:00
|
|
|
break;
|
2009-06-27 17:58:03 +04:00
|
|
|
case eWindowType_popup:
|
2010-07-27 17:38:03 +04:00
|
|
|
if (aBorderStyle != eBorderStyle_default && mBorderStyle & eBorderStyle_title) {
|
|
|
|
features |= NSTitledWindowMask;
|
2010-07-27 17:38:04 +04:00
|
|
|
if (aBorderStyle & eBorderStyle_close) {
|
|
|
|
features |= NSClosableWindowMask;
|
|
|
|
}
|
2010-07-27 17:38:03 +04:00
|
|
|
}
|
2009-06-24 19:15:32 +04:00
|
|
|
break;
|
2009-06-27 17:58:03 +04:00
|
|
|
case eWindowType_toplevel:
|
2009-06-24 19:15:32 +04:00
|
|
|
case eWindowType_dialog:
|
2009-06-27 17:58:03 +04:00
|
|
|
features = WindowMaskForBorderStyle(aBorderStyle);
|
2009-06-24 19:15:32 +04:00
|
|
|
break;
|
|
|
|
case eWindowType_sheet:
|
2014-03-19 20:48:08 +04:00
|
|
|
if (mParent->WindowType() != eWindowType_invisible &&
|
2009-06-24 19:15:32 +04:00
|
|
|
aBorderStyle & eBorderStyle_resizeh) {
|
|
|
|
features = NSResizableWindowMask;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
features = NSMiniaturizableWindowMask;
|
|
|
|
}
|
|
|
|
features |= NSTitledWindowMask;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
NS_ERROR("Unhandled window type!");
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
2007-10-19 19:47:58 +04:00
|
|
|
|
2009-07-22 12:57:39 +04:00
|
|
|
NSRect contentRect;
|
2009-06-24 19:15:32 +04:00
|
|
|
|
2009-07-22 12:57:39 +04:00
|
|
|
if (aRectIsFrameRect) {
|
|
|
|
contentRect = [NSWindow contentRectForFrameRect:aRect styleMask:features];
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* We pass a content area rect to initialize the native Cocoa window. The
|
|
|
|
* content rect we give is the same size as the size we're given by gecko.
|
|
|
|
* The origin we're given for non-popup windows is moved down by the height
|
|
|
|
* of the menu bar so that an origin of (0,100) from gecko puts the window
|
|
|
|
* 100 pixels below the top of the available desktop area. We also move the
|
|
|
|
* origin down by the height of a title bar if it exists. This is so the
|
|
|
|
* origin that gecko gives us for the top-left of the window turns out to
|
|
|
|
* be the top-left of the window we create. This is how it was done in
|
|
|
|
* Carbon. If it ought to be different we'll probably need to look at all
|
|
|
|
* the callers.
|
|
|
|
*
|
|
|
|
* Note: This means that if you put a secondary screen on top of your main
|
|
|
|
* screen and open a window in the top screen, it'll be incorrectly shifted
|
|
|
|
* down by the height of the menu bar. Same thing would happen in Carbon.
|
|
|
|
*
|
|
|
|
* Note: If you pass a rect with 0,0 for an origin, the window ends up in a
|
|
|
|
* weird place for some reason. This stops that without breaking popups.
|
|
|
|
*/
|
|
|
|
// Compensate for difference between frame and content area height (e.g. title bar).
|
|
|
|
NSRect newWindowFrame = [NSWindow frameRectForContentRect:aRect styleMask:features];
|
|
|
|
|
|
|
|
contentRect = aRect;
|
|
|
|
contentRect.origin.y -= (newWindowFrame.size.height - aRect.size.height);
|
|
|
|
|
|
|
|
if (mWindowType != eWindowType_popup)
|
2009-08-13 02:32:41 +04:00
|
|
|
contentRect.origin.y -= [[NSApp mainMenu] menuBarHeight];
|
2009-07-22 12:57:39 +04:00
|
|
|
}
|
2009-06-24 19:15:32 +04:00
|
|
|
|
|
|
|
// NSLog(@"Top-level window being created at Cocoa rect: %f, %f, %f, %f\n",
|
|
|
|
// rect.origin.x, rect.origin.y, rect.size.width, rect.size.height);
|
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
Class windowClass = [BaseWindow class];
|
2009-06-24 19:15:32 +04:00
|
|
|
// If we have a titlebar on a top-level window, we want to be able to control the
|
|
|
|
// titlebar color (for unified windows), so use the special ToolbarWindow class.
|
|
|
|
// Note that we need to check the window type because we mark sheets as
|
|
|
|
// having titlebars.
|
2009-08-04 02:39:45 +04:00
|
|
|
if ((mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog) &&
|
2009-06-24 19:15:32 +04:00
|
|
|
(features & NSTitledWindowMask))
|
|
|
|
windowClass = [ToolbarWindow class];
|
|
|
|
// If we're a popup window we need to use the PopupWindow class.
|
|
|
|
else if (mWindowType == eWindowType_popup)
|
|
|
|
windowClass = [PopupWindow class];
|
|
|
|
// If we're a non-popup borderless window we need to use the
|
|
|
|
// BorderlessWindow class.
|
|
|
|
else if (features == NSBorderlessWindowMask)
|
|
|
|
windowClass = [BorderlessWindow class];
|
|
|
|
|
|
|
|
// Create the window
|
2009-07-22 12:57:39 +04:00
|
|
|
mWindow = [[windowClass alloc] initWithContentRect:contentRect styleMask:features
|
2009-06-24 19:15:32 +04:00
|
|
|
backing:NSBackingStoreBuffered defer:YES];
|
|
|
|
|
2012-10-16 23:41:20 +04:00
|
|
|
// setup our notification delegate. Note that setDelegate: does NOT retain.
|
|
|
|
mDelegate = [[WindowDelegate alloc] initWithGeckoWindow:this];
|
|
|
|
[mWindow setDelegate:mDelegate];
|
|
|
|
|
2009-07-22 12:57:39 +04:00
|
|
|
// Make sure that the content rect we gave has been honored.
|
|
|
|
NSRect wantedFrame = [mWindow frameRectForContentRect:contentRect];
|
|
|
|
if (!NSEqualRects([mWindow frame], wantedFrame)) {
|
|
|
|
// This can happen when the window is not on the primary screen.
|
|
|
|
[mWindow setFrame:wantedFrame display:NO];
|
|
|
|
}
|
2010-12-21 14:42:47 +03:00
|
|
|
UpdateBounds();
|
2009-07-22 12:57:39 +04:00
|
|
|
|
2009-06-24 19:15:32 +04:00
|
|
|
if (mWindowType == eWindowType_invisible) {
|
|
|
|
[mWindow setLevel:kCGDesktopWindowLevelKey];
|
2015-04-23 00:13:45 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mWindowType == eWindowType_popup) {
|
2010-07-27 17:38:03 +04:00
|
|
|
SetPopupWindowLevel();
|
2009-06-30 22:41:56 +04:00
|
|
|
[mWindow setHasShadow:YES];
|
2015-04-23 00:13:45 +03:00
|
|
|
[mWindow setBackgroundColor:[NSColor clearColor]];
|
|
|
|
[mWindow setOpaque:NO];
|
|
|
|
} else {
|
|
|
|
// Make sure that regular windows are opaque from the start, so that
|
|
|
|
// nsChildView::ComputeShouldAccelerate returns true for them.
|
|
|
|
[mWindow setOpaque:YES];
|
2009-06-24 19:15:32 +04:00
|
|
|
}
|
2006-07-25 22:51:41 +04:00
|
|
|
|
2009-06-24 19:15:32 +04:00
|
|
|
[mWindow setContentMinSize:NSMakeSize(60, 60)];
|
2009-07-21 16:36:56 +04:00
|
|
|
[mWindow disableCursorRects];
|
2006-07-25 22:51:41 +04:00
|
|
|
|
2013-02-06 01:40:34 +04:00
|
|
|
// Make sure the window starts out not draggable by the background.
|
|
|
|
// We will turn it on as necessary.
|
|
|
|
[mWindow setMovableByWindowBackground:NO];
|
|
|
|
|
2009-07-22 12:57:39 +04:00
|
|
|
[[WindowDataMap sharedWindowDataMap] ensureDataForWindow:mWindow];
|
2011-10-01 04:20:33 +04:00
|
|
|
mWindowMadeHere = true;
|
2006-05-23 23:47:43 +04:00
|
|
|
|
2009-06-24 19:15:32 +04:00
|
|
|
return NS_OK;
|
2007-10-30 07:03:42 +03:00
|
|
|
|
2009-06-24 19:15:32 +04:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
}
|
2009-06-17 22:13:12 +04:00
|
|
|
|
2015-02-05 10:35:25 +03:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::CreatePopupContentView(const nsIntRect &aRect)
|
2009-06-24 19:15:32 +04:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
|
|
|
// We need to make our content view a ChildView.
|
|
|
|
mPopupContentView = new nsChildView();
|
|
|
|
if (!mPopupContentView)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
NS_ADDREF(mPopupContentView);
|
|
|
|
|
|
|
|
nsIWidget* thisAsWidget = static_cast<nsIWidget*>(this);
|
2015-02-05 10:35:25 +03:00
|
|
|
mPopupContentView->Create(thisAsWidget, nullptr, aRect, nullptr);
|
2009-06-24 19:15:32 +04:00
|
|
|
|
|
|
|
ChildView* newContentView = (ChildView*)mPopupContentView->GetNativeData(NS_NATIVE_WIDGET);
|
|
|
|
[mWindow setContentView:newContentView];
|
2009-06-17 22:13:12 +04:00
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
return NS_OK;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2006-07-25 22:51:41 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::Destroy()
|
|
|
|
{
|
2015-08-06 08:37:48 +03:00
|
|
|
if (mOnDestroyCalled)
|
|
|
|
return NS_OK;
|
|
|
|
mOnDestroyCalled = true;
|
|
|
|
|
2013-08-06 08:32:23 +04:00
|
|
|
// If we don't hide here we run into problems with panels, this is not ideal.
|
|
|
|
// (Bug 891424)
|
2013-07-20 00:57:59 +04:00
|
|
|
Show(false);
|
|
|
|
|
2006-07-25 22:51:41 +04:00
|
|
|
if (mPopupContentView)
|
|
|
|
mPopupContentView->Destroy();
|
|
|
|
|
2015-08-06 08:37:48 +03:00
|
|
|
if (mFullscreenTransitionAnimation) {
|
|
|
|
[mFullscreenTransitionAnimation stopAnimation];
|
|
|
|
ReleaseFullscreenTransitionAnimation();
|
|
|
|
}
|
|
|
|
|
2006-07-25 22:51:41 +04:00
|
|
|
nsBaseWidget::Destroy();
|
2013-08-06 08:32:23 +04:00
|
|
|
// nsBaseWidget::Destroy() calls GetParent()->RemoveChild(this). But we
|
|
|
|
// don't implement GetParent(), so we need to do the equivalent here.
|
|
|
|
if (mParent) {
|
|
|
|
mParent->RemoveChild(this);
|
|
|
|
}
|
2009-03-09 19:59:29 +03:00
|
|
|
nsBaseWidget::OnDestroy();
|
2006-07-25 22:51:41 +04:00
|
|
|
|
2015-06-04 04:49:34 +03:00
|
|
|
if (mInFullScreenMode) {
|
2012-06-18 19:20:02 +04:00
|
|
|
// On Lion we don't have to mess with the OS chrome when in Full Screen
|
|
|
|
// mode. But we do have to destroy the native window here (and not wait
|
|
|
|
// for that to happen in our destructor). We don't switch away from the
|
|
|
|
// native window's space until the window is destroyed, and otherwise this
|
|
|
|
// might not happen for several seconds (because at least one object
|
|
|
|
// holding a reference to ourselves is usually waiting to be garbage-
|
|
|
|
// collected). See bug 757618.
|
2015-06-04 04:49:34 +03:00
|
|
|
if (mInNativeFullScreenMode) {
|
2012-06-18 19:20:02 +04:00
|
|
|
DestroyNativeWindow();
|
|
|
|
} else if (mWindow) {
|
2015-08-07 06:49:12 +03:00
|
|
|
nsCocoaUtils::HideOSChromeOnScreen(false);
|
2012-06-18 19:20:02 +04:00
|
|
|
}
|
2011-02-10 00:27:24 +03:00
|
|
|
}
|
|
|
|
|
2006-07-27 18:42:28 +04:00
|
|
|
return NS_OK;
|
2006-07-25 22:51:41 +04:00
|
|
|
}
|
2001-11-06 18:35:24 +03:00
|
|
|
|
2008-05-02 15:32:50 +04:00
|
|
|
nsIWidget* nsCocoaWindow::GetSheetWindowParent(void)
|
|
|
|
{
|
|
|
|
if (mWindowType != eWindowType_sheet)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2008-05-02 15:32:50 +04:00
|
|
|
nsCocoaWindow *parent = static_cast<nsCocoaWindow*>(mParent);
|
|
|
|
while (parent && (parent->mWindowType == eWindowType_sheet))
|
|
|
|
parent = static_cast<nsCocoaWindow*>(parent->mParent);
|
|
|
|
return parent;
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
void* nsCocoaWindow::GetNativeData(uint32_t aDataType)
|
2001-11-06 18:35:24 +03:00
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSNULL;
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
void* retVal = nullptr;
|
2001-11-06 18:35:24 +03:00
|
|
|
|
2005-10-08 03:31:45 +04:00
|
|
|
switch (aDataType) {
|
2001-11-09 00:47:44 +03:00
|
|
|
// to emulate how windows works, we always have to return a NSView
|
|
|
|
// for NS_NATIVE_WIDGET
|
|
|
|
case NS_NATIVE_WIDGET:
|
|
|
|
case NS_NATIVE_DISPLAY:
|
2001-11-06 18:35:24 +03:00
|
|
|
retVal = [mWindow contentView];
|
|
|
|
break;
|
|
|
|
|
2006-07-25 22:51:41 +04:00
|
|
|
case NS_NATIVE_WINDOW:
|
2001-11-09 00:47:44 +03:00
|
|
|
retVal = mWindow;
|
2001-11-06 18:35:24 +03:00
|
|
|
break;
|
2001-11-09 00:47:44 +03:00
|
|
|
|
2006-11-27 21:08:30 +03:00
|
|
|
case NS_NATIVE_GRAPHIC:
|
|
|
|
// There isn't anything that makes sense to return here,
|
2012-07-30 18:20:58 +04:00
|
|
|
// and it doesn't matter so just return nullptr.
|
2009-08-14 18:09:00 +04:00
|
|
|
NS_ERROR("Requesting NS_NATIVE_GRAPHIC on a top-level window!");
|
2001-11-06 18:35:24 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return retVal;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSNULL;
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2012-07-19 12:57:50 +04:00
|
|
|
bool nsCocoaWindow::IsVisible() const
|
2011-01-18 10:24:19 +03:00
|
|
|
{
|
2012-07-19 12:57:50 +04:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
2011-01-27 09:54:58 +03:00
|
|
|
|
2014-02-03 20:55:26 +04:00
|
|
|
return (mWindow && ([mWindow isVisibleOrBeingShown] || mSheetNeedsShow));
|
2011-01-27 09:54:58 +03:00
|
|
|
|
2012-07-19 12:57:50 +04:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
|
2002-02-12 11:30:01 +03:00
|
|
|
}
|
2006-05-26 23:57:41 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::SetModal(bool aState)
|
2007-09-19 23:17:06 +04:00
|
|
|
{
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow)
|
|
|
|
return NS_OK;
|
|
|
|
|
2010-04-15 00:13:56 +04:00
|
|
|
// This is used during startup (outside the event loop) when creating
|
|
|
|
// the add-ons compatibility checking dialog and the profile manager UI;
|
|
|
|
// therefore, it needs to provide an autorelease pool to avoid cocoa
|
|
|
|
// objects leaking.
|
|
|
|
nsAutoreleasePool localPool;
|
|
|
|
|
2007-09-19 23:17:06 +04:00
|
|
|
mModal = aState;
|
2008-03-24 01:30:56 +03:00
|
|
|
nsCocoaWindow *aParent = static_cast<nsCocoaWindow*>(mParent);
|
2007-09-19 23:17:06 +04:00
|
|
|
if (aState) {
|
|
|
|
++gXULModalLevel;
|
2008-05-01 19:50:23 +04:00
|
|
|
// When a non-sheet window gets "set modal", make the window(s) that it
|
|
|
|
// appears over behave as they should. We can't rely on native methods to
|
|
|
|
// do this, for the following reason: The OS runs modal non-sheet windows
|
|
|
|
// in an event loop (using [NSApplication runModalForWindow:] or similar
|
|
|
|
// methods) that's incompatible with the modal event loop in nsXULWindow::
|
|
|
|
// ShowModal() (each of these event loops is "exclusive", and can't run at
|
|
|
|
// the same time as other (similar) event loops).
|
|
|
|
if (mWindowType != eWindowType_sheet) {
|
|
|
|
while (aParent) {
|
|
|
|
if (aParent->mNumModalDescendents++ == 0) {
|
|
|
|
NSWindow *aWindow = aParent->GetCocoaWindow();
|
|
|
|
if (aParent->mWindowType != eWindowType_invisible) {
|
|
|
|
[[aWindow standardWindowButton:NSWindowCloseButton] setEnabled:NO];
|
|
|
|
[[aWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled:NO];
|
|
|
|
[[aWindow standardWindowButton:NSWindowZoomButton] setEnabled:NO];
|
|
|
|
}
|
2008-03-24 01:30:56 +03:00
|
|
|
}
|
2008-05-01 19:50:23 +04:00
|
|
|
aParent = static_cast<nsCocoaWindow*>(aParent->mParent);
|
2008-03-24 01:30:56 +03:00
|
|
|
}
|
|
|
|
[mWindow setLevel:NSModalPanelWindowLevel];
|
|
|
|
nsCocoaWindowList *windowList = new nsCocoaWindowList;
|
|
|
|
if (windowList) {
|
|
|
|
windowList->window = this; // Don't ADDREF
|
2009-03-19 01:51:40 +03:00
|
|
|
windowList->prev = gGeckoAppModalWindowList;
|
|
|
|
gGeckoAppModalWindowList = windowList;
|
2008-03-24 01:30:56 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2007-09-19 23:17:06 +04:00
|
|
|
--gXULModalLevel;
|
2011-10-01 04:20:33 +04:00
|
|
|
NS_ASSERTION(gXULModalLevel >= 0, "Mismatched call to nsCocoaWindow::SetModal(false)!");
|
2008-05-01 19:50:23 +04:00
|
|
|
if (mWindowType != eWindowType_sheet) {
|
|
|
|
while (aParent) {
|
|
|
|
if (--aParent->mNumModalDescendents == 0) {
|
|
|
|
NSWindow *aWindow = aParent->GetCocoaWindow();
|
|
|
|
if (aParent->mWindowType != eWindowType_invisible) {
|
|
|
|
[[aWindow standardWindowButton:NSWindowCloseButton] setEnabled:YES];
|
|
|
|
[[aWindow standardWindowButton:NSWindowMiniaturizeButton] setEnabled:YES];
|
|
|
|
[[aWindow standardWindowButton:NSWindowZoomButton] setEnabled:YES];
|
|
|
|
}
|
2008-03-24 01:30:56 +03:00
|
|
|
}
|
2008-05-01 19:50:23 +04:00
|
|
|
NS_ASSERTION(aParent->mNumModalDescendents >= 0, "Widget hierarchy changed while modal!");
|
|
|
|
aParent = static_cast<nsCocoaWindow*>(aParent->mParent);
|
2008-03-24 01:30:56 +03:00
|
|
|
}
|
2009-03-19 01:51:40 +03:00
|
|
|
if (gGeckoAppModalWindowList) {
|
|
|
|
NS_ASSERTION(gGeckoAppModalWindowList->window == this, "Widget hierarchy changed while modal!");
|
|
|
|
nsCocoaWindowList *saved = gGeckoAppModalWindowList;
|
|
|
|
gGeckoAppModalWindowList = gGeckoAppModalWindowList->prev;
|
2008-03-24 01:30:56 +03:00
|
|
|
delete saved; // "window" not ADDREFed
|
|
|
|
}
|
|
|
|
if (mWindowType == eWindowType_popup)
|
2010-07-27 17:38:03 +04:00
|
|
|
SetPopupWindowLevel();
|
2008-03-24 01:30:56 +03:00
|
|
|
else
|
|
|
|
[mWindow setLevel:NSNormalWindowLevel];
|
|
|
|
}
|
2007-09-19 23:17:06 +04:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
// Hide or show this window
|
2011-09-29 10:19:26 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::Show(bool bState)
|
2001-11-06 18:35:24 +03:00
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow)
|
|
|
|
return NS_OK;
|
|
|
|
|
2008-02-26 22:32:19 +03:00
|
|
|
// We need to re-execute sometimes in order to bring already-visible
|
|
|
|
// windows forward.
|
2011-01-27 09:54:58 +03:00
|
|
|
if (!mSheetNeedsShow && !bState && ![mWindow isVisible])
|
2008-02-20 05:30:24 +03:00
|
|
|
return NS_OK;
|
|
|
|
|
2014-02-03 20:54:55 +04:00
|
|
|
// Protect against re-entering.
|
|
|
|
if (bState && [mWindow isBeingShown])
|
|
|
|
return NS_OK;
|
|
|
|
|
2013-11-25 22:00:55 +04:00
|
|
|
[mWindow setBeingShown:bState];
|
|
|
|
|
2006-06-08 21:29:18 +04:00
|
|
|
nsIWidget* parentWidget = mParent;
|
|
|
|
nsCOMPtr<nsPIWidgetCocoa> piParentWidget(do_QueryInterface(parentWidget));
|
|
|
|
NSWindow* nativeParentWindow = (parentWidget) ?
|
|
|
|
(NSWindow*)parentWidget->GetNativeData(NS_NATIVE_WINDOW) : nil;
|
2008-02-20 05:30:24 +03:00
|
|
|
|
2006-06-08 21:29:18 +04:00
|
|
|
if (bState && !mBounds.IsEmpty()) {
|
2014-02-03 20:54:55 +04:00
|
|
|
if (mPopupContentView) {
|
|
|
|
// Ensure our content view is visible. We never need to hide it.
|
|
|
|
mPopupContentView->Show(true);
|
|
|
|
}
|
|
|
|
|
2006-06-08 21:29:18 +04:00
|
|
|
if (mWindowType == eWindowType_sheet) {
|
|
|
|
// bail if no parent window (its basically what we do in Carbon)
|
2011-01-27 09:54:58 +03:00
|
|
|
if (!nativeParentWindow || !piParentWidget)
|
2006-06-08 21:29:18 +04:00
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
NSWindow* topNonSheetWindow = nativeParentWindow;
|
|
|
|
|
|
|
|
// If this sheet is the child of another sheet, hide the parent so that
|
|
|
|
// this sheet can be displayed. Leave the parent mSheetNeedsShow alone,
|
|
|
|
// that is only used to handle sibling sheet contention. The parent will
|
|
|
|
// return once there are no more child sheets.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool parentIsSheet = false;
|
2006-06-08 21:29:18 +04:00
|
|
|
if (NS_SUCCEEDED(piParentWidget->GetIsSheet(&parentIsSheet)) &&
|
|
|
|
parentIsSheet) {
|
|
|
|
piParentWidget->GetSheetWindowParent(&topNonSheetWindow);
|
|
|
|
[NSApp endSheet:nativeParentWindow];
|
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
nsCocoaWindow* sheetShown = nullptr;
|
2011-10-01 04:20:33 +04:00
|
|
|
if (NS_SUCCEEDED(piParentWidget->GetChildSheet(true, &sheetShown)) &&
|
2006-06-08 21:29:18 +04:00
|
|
|
(!sheetShown || sheetShown == this)) {
|
|
|
|
// If this sheet is already the sheet actually being shown, don't
|
|
|
|
// tell it to show again. Otherwise the number of calls to
|
|
|
|
// [NSApp beginSheet...] won't match up with [NSApp endSheet...].
|
2008-02-22 04:47:14 +03:00
|
|
|
if (![mWindow isVisible]) {
|
2011-10-01 04:20:33 +04:00
|
|
|
mSheetNeedsShow = false;
|
2006-06-08 21:29:18 +04:00
|
|
|
mSheetWindowParent = topNonSheetWindow;
|
2008-05-08 01:15:57 +04:00
|
|
|
// Only set contextInfo if our parent isn't a sheet.
|
|
|
|
NSWindow* contextInfo = parentIsSheet ? nil : mSheetWindowParent;
|
2008-05-02 14:40:49 +04:00
|
|
|
[TopLevelWindowData deactivateInWindow:mSheetWindowParent];
|
2006-06-08 21:29:18 +04:00
|
|
|
[NSApp beginSheet:mWindow
|
|
|
|
modalForWindow:mSheetWindowParent
|
|
|
|
modalDelegate:mDelegate
|
|
|
|
didEndSelector:@selector(didEndSheet:returnCode:contextInfo:)
|
2008-05-08 01:15:57 +04:00
|
|
|
contextInfo:contextInfo];
|
2008-05-02 14:40:49 +04:00
|
|
|
[TopLevelWindowData activateInWindow:mWindow];
|
2006-10-04 00:38:38 +04:00
|
|
|
SendSetZLevelEvent();
|
2006-06-08 21:29:18 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// A sibling of this sheet is active, don't show this sheet yet.
|
|
|
|
// When the active sheet hides, its brothers and sisters that have
|
|
|
|
// mSheetNeedsShow set will have their opportunities to display.
|
2011-10-01 04:20:33 +04:00
|
|
|
mSheetNeedsShow = true;
|
2006-06-08 21:29:18 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (mWindowType == eWindowType_popup) {
|
2007-07-18 00:29:39 +04:00
|
|
|
// If a popup window is shown after being hidden, it needs to be "reset"
|
|
|
|
// for it to receive any mouse events aside from mouse-moved events
|
|
|
|
// (because it was removed from the "window cache" when it was hidden
|
|
|
|
// -- see below). Setting the window number to -1 and then back to its
|
|
|
|
// original value seems to accomplish this. The idea was "borrowed"
|
|
|
|
// from the Java Embedding Plugin.
|
2009-09-25 08:00:28 +04:00
|
|
|
NSInteger windowNumber = [mWindow windowNumber];
|
2007-07-18 00:29:39 +04:00
|
|
|
[mWindow _setWindowNumber:-1];
|
|
|
|
[mWindow _setWindowNumber:windowNumber];
|
2009-01-30 00:57:59 +03:00
|
|
|
// For reasons that aren't yet clear, calls to [NSWindow orderFront:] or
|
|
|
|
// [NSWindow makeKeyAndOrderFront:] can sometimes trigger "Error (1000)
|
|
|
|
// creating CGSWindow", which in turn triggers an internal inconsistency
|
|
|
|
// NSException. These errors shouldn't be fatal. So we need to wrap
|
|
|
|
// calls to ...orderFront: in LOGONLY blocks. See bmo bug 470864.
|
|
|
|
NS_OBJC_BEGIN_TRY_LOGONLY_BLOCK;
|
2014-02-03 20:54:55 +04:00
|
|
|
[[mWindow contentView] setNeedsDisplay:YES];
|
2006-04-25 23:20:31 +04:00
|
|
|
[mWindow orderFront:nil];
|
2009-01-30 00:57:59 +03:00
|
|
|
NS_OBJC_END_TRY_LOGONLY_BLOCK;
|
2006-10-04 00:38:38 +04:00
|
|
|
SendSetZLevelEvent();
|
2009-12-30 18:24:08 +03:00
|
|
|
AdjustWindowShadow();
|
2014-01-03 19:53:41 +04:00
|
|
|
SetWindowBackgroundBlur();
|
2007-07-18 00:29:39 +04:00
|
|
|
// If our popup window is a non-native context menu, tell the OS (and
|
|
|
|
// other programs) that a menu has opened. This is how the OS knows to
|
|
|
|
// close other programs' context menus when ours open.
|
|
|
|
if ([mWindow isKindOfClass:[PopupWindow class]] &&
|
|
|
|
[(PopupWindow*) mWindow isContextMenu]) {
|
|
|
|
[[NSDistributedNotificationCenter defaultCenter]
|
|
|
|
postNotificationName:@"com.apple.HIToolbox.beginMenuTrackingNotification"
|
|
|
|
object:@"org.mozilla.gecko.PopupWindow"];
|
|
|
|
}
|
2007-11-28 23:18:11 +03:00
|
|
|
|
2010-07-27 17:38:03 +04:00
|
|
|
// If a parent window was supplied and this is a popup at the parent
|
|
|
|
// level, set its child window. This will cause the child window to
|
|
|
|
// appear above the parent and move when the parent does. Setting this
|
|
|
|
// needs to happen after the _setWindowNumber calls above, otherwise the
|
|
|
|
// window doesn't focus properly.
|
|
|
|
if (nativeParentWindow && mPopupLevel == ePopupLevelParent)
|
2007-11-28 23:18:11 +03:00
|
|
|
[nativeParentWindow addChildWindow:mWindow
|
|
|
|
ordered:NSWindowAbove];
|
2006-04-25 23:20:31 +04:00
|
|
|
}
|
|
|
|
else {
|
2009-01-30 00:57:59 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_LOGONLY_BLOCK;
|
2012-02-17 07:47:39 +04:00
|
|
|
if (mWindowType == eWindowType_toplevel &&
|
|
|
|
[mWindow respondsToSelector:@selector(setAnimationBehavior:)]) {
|
|
|
|
NSWindowAnimationBehavior behavior;
|
|
|
|
if (mIsAnimationSuppressed) {
|
|
|
|
behavior = NSWindowAnimationBehaviorNone;
|
|
|
|
} else {
|
|
|
|
switch (mAnimationType) {
|
|
|
|
case nsIWidget::eDocumentWindowAnimation:
|
|
|
|
behavior = NSWindowAnimationBehaviorDocumentWindow;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
NS_NOTREACHED("unexpected mAnimationType value");
|
|
|
|
// fall through
|
|
|
|
case nsIWidget::eGenericWindowAnimation:
|
|
|
|
behavior = NSWindowAnimationBehaviorDefault;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
[mWindow setAnimationBehavior:behavior];
|
|
|
|
}
|
2006-04-25 23:20:31 +04:00
|
|
|
[mWindow makeKeyAndOrderFront:nil];
|
2009-01-30 00:57:59 +03:00
|
|
|
NS_OBJC_END_TRY_LOGONLY_BLOCK;
|
2006-10-04 00:38:38 +04:00
|
|
|
SendSetZLevelEvent();
|
2006-04-25 23:20:31 +04:00
|
|
|
}
|
2006-04-06 11:41:34 +04:00
|
|
|
}
|
|
|
|
else {
|
2006-06-08 21:29:18 +04:00
|
|
|
// roll up any popups if a top-level window is going away
|
2009-08-04 02:39:45 +04:00
|
|
|
if (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog)
|
2007-06-13 00:26:24 +04:00
|
|
|
RollUpPopups();
|
2006-06-08 21:29:18 +04:00
|
|
|
|
|
|
|
// now get rid of the window/sheet
|
|
|
|
if (mWindowType == eWindowType_sheet) {
|
2008-02-20 05:30:24 +03:00
|
|
|
if (mSheetNeedsShow) {
|
|
|
|
// This is an attempt to hide a sheet that never had a chance to
|
|
|
|
// be shown. There's nothing to do other than make sure that it
|
|
|
|
// won't show.
|
2011-10-01 04:20:33 +04:00
|
|
|
mSheetNeedsShow = false;
|
2008-02-20 05:30:24 +03:00
|
|
|
}
|
|
|
|
else {
|
2006-06-08 21:29:18 +04:00
|
|
|
// get sheet's parent *before* hiding the sheet (which breaks the linkage)
|
|
|
|
NSWindow* sheetParent = mSheetWindowParent;
|
|
|
|
|
|
|
|
// hide the sheet
|
|
|
|
[NSApp endSheet:mWindow];
|
|
|
|
|
2008-05-02 14:40:49 +04:00
|
|
|
[TopLevelWindowData deactivateInWindow:mWindow];
|
2006-06-08 21:29:18 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
nsCocoaWindow* siblingSheetToShow = nullptr;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool parentIsSheet = false;
|
2008-02-20 05:30:24 +03:00
|
|
|
|
2006-06-08 21:29:18 +04:00
|
|
|
if (nativeParentWindow && piParentWidget &&
|
2011-10-01 04:20:33 +04:00
|
|
|
NS_SUCCEEDED(piParentWidget->GetChildSheet(false, &siblingSheetToShow)) &&
|
2006-06-08 21:29:18 +04:00
|
|
|
siblingSheetToShow) {
|
|
|
|
// First, give sibling sheets an opportunity to show.
|
2011-10-01 04:20:33 +04:00
|
|
|
siblingSheetToShow->Show(true);
|
2006-06-08 21:29:18 +04:00
|
|
|
}
|
|
|
|
else if (nativeParentWindow && piParentWidget &&
|
|
|
|
NS_SUCCEEDED(piParentWidget->GetIsSheet(&parentIsSheet)) &&
|
|
|
|
parentIsSheet) {
|
2008-05-08 01:15:57 +04:00
|
|
|
// Only set contextInfo if the parent of the parent sheet we're about
|
|
|
|
// to restore isn't itself a sheet.
|
|
|
|
NSWindow* contextInfo = sheetParent;
|
|
|
|
nsIWidget* grandparentWidget = nil;
|
|
|
|
if (NS_SUCCEEDED(piParentWidget->GetRealParent(&grandparentWidget)) && grandparentWidget) {
|
|
|
|
nsCOMPtr<nsPIWidgetCocoa> piGrandparentWidget(do_QueryInterface(grandparentWidget));
|
2011-09-29 10:19:26 +04:00
|
|
|
bool grandparentIsSheet = false;
|
2008-05-08 01:15:57 +04:00
|
|
|
if (piGrandparentWidget && NS_SUCCEEDED(piGrandparentWidget->GetIsSheet(&grandparentIsSheet)) &&
|
|
|
|
grandparentIsSheet) {
|
|
|
|
contextInfo = nil;
|
|
|
|
}
|
|
|
|
}
|
2006-06-08 21:29:18 +04:00
|
|
|
// If there are no sibling sheets, but the parent is a sheet, restore
|
|
|
|
// it. It wasn't sent any deactivate events when it was hidden, so
|
|
|
|
// don't call through Show, just let the OS put it back up.
|
|
|
|
[NSApp beginSheet:nativeParentWindow
|
|
|
|
modalForWindow:sheetParent
|
|
|
|
modalDelegate:[nativeParentWindow delegate]
|
|
|
|
didEndSelector:@selector(didEndSheet:returnCode:contextInfo:)
|
2008-05-08 01:15:57 +04:00
|
|
|
contextInfo:contextInfo];
|
2006-06-08 21:29:18 +04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Sheet, that was hard. No more siblings or parents, going back
|
|
|
|
// to a real window.
|
2009-01-30 00:57:59 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_LOGONLY_BLOCK;
|
2006-06-08 21:29:18 +04:00
|
|
|
[sheetParent makeKeyAndOrderFront:nil];
|
2009-01-30 00:57:59 +03:00
|
|
|
NS_OBJC_END_TRY_LOGONLY_BLOCK;
|
2006-06-08 21:29:18 +04:00
|
|
|
}
|
2006-10-04 00:38:38 +04:00
|
|
|
SendSetZLevelEvent();
|
2006-06-08 21:29:18 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2007-12-05 22:19:08 +03:00
|
|
|
// If the window is a popup window with a parent window we need to
|
|
|
|
// unhook it here before ordering it out. When you order out the child
|
|
|
|
// of a window it hides the parent window.
|
|
|
|
if (mWindowType == eWindowType_popup && nativeParentWindow)
|
|
|
|
[nativeParentWindow removeChildWindow:mWindow];
|
|
|
|
|
2006-06-08 21:29:18 +04:00
|
|
|
[mWindow orderOut:nil];
|
2007-07-18 00:29:39 +04:00
|
|
|
// Unless it's explicitly removed from NSApp's "window cache", a popup
|
|
|
|
// window will keep receiving mouse-moved events even after it's been
|
|
|
|
// "ordered out" (instead of the browser window that was underneath it,
|
|
|
|
// until you click on that window). This is bmo bug 378645, but it's
|
|
|
|
// surely an Apple bug. The "window cache" is an undocumented subsystem,
|
|
|
|
// all of whose methods are included in the NSWindowCache category of
|
|
|
|
// the NSApplication class (in header files generated using class-dump).
|
|
|
|
// This workaround was "borrowed" from the Java Embedding Plugin (which
|
|
|
|
// uses it for a different purpose).
|
2009-07-20 23:44:25 +04:00
|
|
|
if (mWindowType == eWindowType_popup)
|
2007-07-18 00:29:39 +04:00
|
|
|
[NSApp _removeWindowFromCache:mWindow];
|
2007-11-28 23:18:11 +03:00
|
|
|
|
2007-07-18 00:29:39 +04:00
|
|
|
// If our popup window is a non-native context menu, tell the OS (and
|
|
|
|
// other programs) that a menu has closed.
|
|
|
|
if ([mWindow isKindOfClass:[PopupWindow class]] &&
|
|
|
|
[(PopupWindow*) mWindow isContextMenu]) {
|
|
|
|
[[NSDistributedNotificationCenter defaultCenter]
|
|
|
|
postNotificationName:@"com.apple.HIToolbox.endMenuTrackingNotification"
|
|
|
|
object:@"org.mozilla.gecko.PopupWindow"];
|
|
|
|
}
|
2006-06-08 21:29:18 +04:00
|
|
|
}
|
2006-04-06 11:41:34 +04:00
|
|
|
}
|
2006-07-25 22:51:41 +04:00
|
|
|
|
2013-11-25 22:00:55 +04:00
|
|
|
[mWindow setBeingShown:NO];
|
|
|
|
|
2006-07-25 22:51:41 +04:00
|
|
|
return NS_OK;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2006-07-25 22:51:41 +04:00
|
|
|
}
|
|
|
|
|
2009-12-30 18:24:08 +03:00
|
|
|
struct ShadowParams {
|
|
|
|
float standardDeviation;
|
|
|
|
float density;
|
|
|
|
int offsetX;
|
|
|
|
int offsetY;
|
|
|
|
unsigned int flags;
|
|
|
|
};
|
|
|
|
|
|
|
|
// These numbers have been determined by looking at the results of
|
|
|
|
// CGSGetWindowShadowAndRimParameters for native window types.
|
2014-10-14 13:14:05 +04:00
|
|
|
static const ShadowParams kWindowShadowParametersPreYosemite[] = {
|
2009-12-30 18:24:08 +03:00
|
|
|
{ 0.0f, 0.0f, 0, 0, 0 }, // none
|
|
|
|
{ 8.0f, 0.5f, 0, 6, 1 }, // default
|
|
|
|
{ 10.0f, 0.44f, 0, 10, 512 }, // menu
|
|
|
|
{ 8.0f, 0.5f, 0, 6, 1 }, // tooltip
|
|
|
|
{ 4.0f, 0.6f, 0, 4, 512 } // sheet
|
|
|
|
};
|
|
|
|
|
2014-10-14 13:14:05 +04:00
|
|
|
static const ShadowParams kWindowShadowParametersPostYosemite[] = {
|
|
|
|
{ 0.0f, 0.0f, 0, 0, 0 }, // none
|
|
|
|
{ 8.0f, 0.5f, 0, 6, 1 }, // default
|
|
|
|
{ 9.882353f, 0.3f, 0, 4, 0 }, // menu
|
|
|
|
{ 3.294118f, 0.2f, 0, 1, 0 }, // tooltip
|
|
|
|
{ 9.882353f, 0.3f, 0, 4, 0 } // sheet
|
|
|
|
};
|
|
|
|
|
2009-12-30 18:24:08 +03:00
|
|
|
// This method will adjust the window shadow style for popup windows after
|
|
|
|
// they have been made visible. Before they're visible, their window number
|
|
|
|
// might be -1, which is not useful.
|
|
|
|
// We won't attempt to change the shadow for windows that can acquire key state
|
|
|
|
// since OS X will reset the shadow whenever that happens.
|
|
|
|
void
|
|
|
|
nsCocoaWindow::AdjustWindowShadow()
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow || ![mWindow isVisible] || ![mWindow hasShadow] ||
|
2009-12-30 18:24:08 +03:00
|
|
|
[mWindow canBecomeKeyWindow] || [mWindow windowNumber] == -1)
|
|
|
|
return;
|
|
|
|
|
2014-10-14 13:14:05 +04:00
|
|
|
const ShadowParams& params = nsCocoaFeatures::OnYosemiteOrLater()
|
|
|
|
? kWindowShadowParametersPostYosemite[mShadowStyle]
|
|
|
|
: kWindowShadowParametersPreYosemite[mShadowStyle];
|
2009-12-30 18:24:08 +03:00
|
|
|
CGSConnection cid = _CGSDefaultConnection();
|
|
|
|
CGSSetWindowShadowAndRimParameters(cid, [mWindow windowNumber],
|
|
|
|
params.standardDeviation, params.density,
|
|
|
|
params.offsetX, params.offsetY,
|
|
|
|
params.flags);
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2014-01-03 19:53:41 +04:00
|
|
|
static const NSUInteger kWindowBackgroundBlurRadius = 4;
|
|
|
|
|
2010-01-13 19:10:25 +03:00
|
|
|
void
|
2014-01-03 19:53:41 +04:00
|
|
|
nsCocoaWindow::SetWindowBackgroundBlur()
|
2010-01-13 19:10:25 +03:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow || ![mWindow isVisible] || [mWindow windowNumber] == -1)
|
2010-01-13 19:10:25 +03:00
|
|
|
return;
|
|
|
|
|
2014-01-03 19:53:41 +04:00
|
|
|
// Only blur the background of menus and fake sheets.
|
2010-01-13 19:10:25 +03:00
|
|
|
if (mShadowStyle != NS_STYLE_WINDOW_SHADOW_MENU &&
|
|
|
|
mShadowStyle != NS_STYLE_WINDOW_SHADOW_SHEET)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CGSConnection cid = _CGSDefaultConnection();
|
2014-01-03 19:53:41 +04:00
|
|
|
CGSSetWindowBackgroundBlurRadius(cid, [mWindow windowNumber], kWindowBackgroundBlurRadius);
|
2010-01-13 19:10:25 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2009-07-22 04:44:55 +04:00
|
|
|
nsresult
|
|
|
|
nsCocoaWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
|
|
|
|
{
|
2009-07-22 04:45:13 +04:00
|
|
|
if (mPopupContentView) {
|
|
|
|
mPopupContentView->ConfigureChildren(aConfigurations);
|
2009-07-22 04:44:55 +04:00
|
|
|
}
|
|
|
|
return NS_OK;
|
2009-07-22 04:45:13 +04:00
|
|
|
}
|
|
|
|
|
2011-03-23 21:46:57 +03:00
|
|
|
LayerManager*
|
2013-04-24 22:42:40 +04:00
|
|
|
nsCocoaWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
|
2011-08-09 23:38:26 +04:00
|
|
|
LayersBackend aBackendHint,
|
|
|
|
LayerManagerPersistence aPersistence,
|
|
|
|
bool* aAllowRetaining)
|
2011-03-23 21:46:57 +03:00
|
|
|
{
|
|
|
|
if (mPopupContentView) {
|
2011-08-09 23:38:26 +04:00
|
|
|
return mPopupContentView->GetLayerManager(aShadowManager,
|
|
|
|
aBackendHint,
|
|
|
|
aPersistence,
|
|
|
|
aAllowRetaining);
|
2010-03-01 11:03:49 +03:00
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2010-03-01 11:03:49 +03:00
|
|
|
}
|
|
|
|
|
2008-08-13 04:44:14 +04:00
|
|
|
nsTransparencyMode nsCocoaWindow::GetTransparencyMode()
|
2007-12-19 22:40:18 +03:00
|
|
|
{
|
2008-08-26 04:02:26 +04:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
return (!mWindow || [mWindow isOpaque]) ? eTransparencyOpaque : eTransparencyTransparent;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
2008-08-26 04:02:26 +04:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(eTransparencyOpaque);
|
2007-12-19 22:40:18 +03:00
|
|
|
}
|
|
|
|
|
2015-05-09 00:49:29 +03:00
|
|
|
// This is called from nsMenuPopupFrame when making a popup transparent, or
|
|
|
|
// from nsChildView::SetTransparencyMode for other window types.
|
2008-08-13 04:44:14 +04:00
|
|
|
void nsCocoaWindow::SetTransparencyMode(nsTransparencyMode aMode)
|
2007-12-19 22:40:18 +03:00
|
|
|
{
|
2008-08-13 04:44:14 +04:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow)
|
|
|
|
return;
|
|
|
|
|
2015-05-09 00:49:29 +03:00
|
|
|
// Transparent windows are only supported on popups.
|
|
|
|
BOOL isTransparent = aMode == eTransparencyTransparent &&
|
|
|
|
mWindowType == eWindowType_popup;
|
2007-12-19 22:40:18 +03:00
|
|
|
BOOL currentTransparency = ![mWindow isOpaque];
|
2008-08-13 04:44:14 +04:00
|
|
|
if (isTransparent != currentTransparency) {
|
2009-11-14 01:58:15 +03:00
|
|
|
[mWindow setOpaque:!isTransparent];
|
|
|
|
[mWindow setBackgroundColor:(isTransparent ? [NSColor clearColor] : [NSColor whiteColor])];
|
2007-12-19 22:40:18 +03:00
|
|
|
}
|
2008-02-21 02:47:05 +03:00
|
|
|
|
2008-08-13 04:44:14 +04:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-12-19 22:40:18 +03:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::Enable(bool aState)
|
2002-03-01 02:10:04 +03:00
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-07-23 09:19:08 +04:00
|
|
|
bool nsCocoaWindow::IsEnabled() const
|
2002-03-01 02:10:04 +03:00
|
|
|
{
|
2012-07-23 09:19:08 +04:00
|
|
|
return true;
|
2002-03-01 02:10:04 +03:00
|
|
|
}
|
|
|
|
|
2011-12-22 02:13:21 +04:00
|
|
|
#define kWindowPositionSlop 20
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::ConstrainPosition(bool aAllowSlop,
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t *aX, int32_t *aY)
|
2001-11-06 18:35:24 +03:00
|
|
|
{
|
2011-12-22 02:13:21 +04:00
|
|
|
if (!mWindow || ![mWindow screen]) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-05-19 02:16:50 +04:00
|
|
|
nsIntRect screenBounds;
|
|
|
|
|
2012-10-16 23:41:19 +04:00
|
|
|
int32_t width, height;
|
|
|
|
|
|
|
|
NSRect frame = [mWindow frame];
|
|
|
|
|
|
|
|
// zero size rects confuse the screen manager
|
2013-01-15 16:22:03 +04:00
|
|
|
width = std::max<int32_t>(frame.size.width, 1);
|
|
|
|
height = std::max<int32_t>(frame.size.height, 1);
|
2012-10-16 23:41:19 +04:00
|
|
|
|
2012-05-19 02:16:50 +04:00
|
|
|
nsCOMPtr<nsIScreenManager> screenMgr = do_GetService("@mozilla.org/gfx/screenmanager;1");
|
|
|
|
if (screenMgr) {
|
|
|
|
nsCOMPtr<nsIScreen> screen;
|
|
|
|
screenMgr->ScreenForRect(*aX, *aY, width, height, getter_AddRefs(screen));
|
|
|
|
|
|
|
|
if (screen) {
|
2012-10-16 23:41:19 +04:00
|
|
|
screen->GetRectDisplayPix(&(screenBounds.x), &(screenBounds.y),
|
|
|
|
&(screenBounds.width), &(screenBounds.height));
|
2012-05-19 02:16:50 +04:00
|
|
|
}
|
|
|
|
}
|
2011-12-22 02:13:21 +04:00
|
|
|
|
|
|
|
if (aAllowSlop) {
|
2012-10-16 23:41:19 +04:00
|
|
|
if (*aX < screenBounds.x - width + kWindowPositionSlop) {
|
|
|
|
*aX = screenBounds.x - width + kWindowPositionSlop;
|
2011-12-22 02:13:21 +04:00
|
|
|
} else if (*aX >= screenBounds.x + screenBounds.width - kWindowPositionSlop) {
|
|
|
|
*aX = screenBounds.x + screenBounds.width - kWindowPositionSlop;
|
|
|
|
}
|
|
|
|
|
2012-10-16 23:41:19 +04:00
|
|
|
if (*aY < screenBounds.y - height + kWindowPositionSlop) {
|
|
|
|
*aY = screenBounds.y - height + kWindowPositionSlop;
|
2011-12-22 02:13:21 +04:00
|
|
|
} else if (*aY >= screenBounds.y + screenBounds.height - kWindowPositionSlop) {
|
|
|
|
*aY = screenBounds.y + screenBounds.height - kWindowPositionSlop;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (*aX < screenBounds.x) {
|
|
|
|
*aX = screenBounds.x;
|
2012-10-16 23:41:19 +04:00
|
|
|
} else if (*aX >= screenBounds.x + screenBounds.width - width) {
|
|
|
|
*aX = screenBounds.x + screenBounds.width - width;
|
2011-12-22 02:13:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (*aY < screenBounds.y) {
|
|
|
|
*aY = screenBounds.y;
|
2012-10-16 23:41:19 +04:00
|
|
|
} else if (*aY >= screenBounds.y + screenBounds.height - height) {
|
|
|
|
*aY = screenBounds.y + screenBounds.height - height;
|
2011-12-22 02:13:21 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-07-31 04:43:29 +04:00
|
|
|
void nsCocoaWindow::SetSizeConstraints(const SizeConstraints& aConstraints)
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
// Popups can be smaller than (60, 60)
|
|
|
|
NSRect rect =
|
|
|
|
(mWindowType == eWindowType_popup) ? NSZeroRect : NSMakeRect(0.0, 0.0, 60, 60);
|
|
|
|
rect = [mWindow frameRectForContentRect:rect];
|
|
|
|
|
2012-09-29 15:36:09 +04:00
|
|
|
CGFloat scaleFactor = BackingScaleFactor();
|
2012-07-31 04:43:29 +04:00
|
|
|
|
2012-09-29 15:36:09 +04:00
|
|
|
SizeConstraints c = aConstraints;
|
|
|
|
c.mMinSize.width =
|
2013-01-15 16:22:03 +04:00
|
|
|
std::max(nsCocoaUtils::CocoaPointsToDevPixels(rect.size.width, scaleFactor),
|
2012-09-29 15:36:09 +04:00
|
|
|
c.mMinSize.width);
|
|
|
|
c.mMinSize.height =
|
2013-01-15 16:22:03 +04:00
|
|
|
std::max(nsCocoaUtils::CocoaPointsToDevPixels(rect.size.height, scaleFactor),
|
2012-09-29 15:36:09 +04:00
|
|
|
c.mMinSize.height);
|
|
|
|
|
|
|
|
NSSize minSize = {
|
|
|
|
nsCocoaUtils::DevPixelsToCocoaPoints(c.mMinSize.width, scaleFactor),
|
|
|
|
nsCocoaUtils::DevPixelsToCocoaPoints(c.mMinSize.height, scaleFactor)
|
|
|
|
};
|
2012-07-31 04:43:29 +04:00
|
|
|
[mWindow setMinSize:minSize];
|
|
|
|
|
2012-09-29 15:36:09 +04:00
|
|
|
NSSize maxSize = {
|
|
|
|
c.mMaxSize.width == NS_MAXSIZE ?
|
|
|
|
FLT_MAX : nsCocoaUtils::DevPixelsToCocoaPoints(c.mMaxSize.width, scaleFactor),
|
|
|
|
c.mMaxSize.height == NS_MAXSIZE ?
|
|
|
|
FLT_MAX : nsCocoaUtils::DevPixelsToCocoaPoints(c.mMaxSize.height, scaleFactor)
|
|
|
|
};
|
2012-07-31 04:43:29 +04:00
|
|
|
[mWindow setMaxSize:maxSize];
|
|
|
|
|
|
|
|
nsBaseWidget::SetSizeConstraints(c);
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2012-12-06 21:31:34 +04:00
|
|
|
// Coordinates are global display pixels
|
2012-12-12 13:57:38 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::Move(double aX, double aY)
|
2007-11-07 10:36:10 +03:00
|
|
|
{
|
2012-12-06 21:31:34 +04:00
|
|
|
if (!mWindow) {
|
2007-11-07 10:36:10 +03:00
|
|
|
return NS_OK;
|
2012-12-06 21:31:34 +04:00
|
|
|
}
|
2007-11-07 10:36:10 +03:00
|
|
|
|
|
|
|
// The point we have is in Gecko coordinates (origin top-left). Convert
|
|
|
|
// it to Cocoa ones (origin bottom-left).
|
2012-09-29 15:36:09 +04:00
|
|
|
NSPoint coord = {
|
2012-12-06 21:31:34 +04:00
|
|
|
static_cast<float>(aX),
|
2012-12-12 13:57:38 +04:00
|
|
|
static_cast<float>(nsCocoaUtils::FlippedScreenY(NSToIntRound(aY)))
|
2012-09-29 15:36:09 +04:00
|
|
|
};
|
2012-12-06 21:31:34 +04:00
|
|
|
|
|
|
|
NSRect frame = [mWindow frame];
|
|
|
|
if (frame.origin.x != coord.x ||
|
|
|
|
frame.origin.y + frame.size.height != coord.y) {
|
|
|
|
[mWindow setFrameTopLeftPoint:coord];
|
|
|
|
}
|
2007-11-07 10:36:10 +03:00
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Position the window behind the given window
|
2003-10-07 05:19:51 +04:00
|
|
|
NS_METHOD nsCocoaWindow::PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
|
2011-09-29 10:19:26 +04:00
|
|
|
nsIWidget *aWidget, bool aActivate)
|
2001-11-06 18:35:24 +03:00
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-08-29 04:12:41 +03:00
|
|
|
NS_METHOD nsCocoaWindow::SetSizeMode(nsSizeMode aMode)
|
2001-11-06 18:35:24 +03:00
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow)
|
|
|
|
return NS_OK;
|
|
|
|
|
2012-01-31 14:40:03 +04:00
|
|
|
// mSizeMode will be updated in DispatchSizeModeEvent, which will be called
|
|
|
|
// from a delegate method that handles the state change during one of the
|
|
|
|
// calls below.
|
|
|
|
nsSizeMode previousMode = mSizeMode;
|
2006-10-14 00:27:56 +04:00
|
|
|
|
|
|
|
if (aMode == nsSizeMode_Normal) {
|
2008-09-10 20:57:57 +04:00
|
|
|
if ([mWindow isMiniaturized])
|
|
|
|
[mWindow deminiaturize:nil];
|
|
|
|
else if (previousMode == nsSizeMode_Maximized && [mWindow isZoomed])
|
2006-10-14 00:27:56 +04:00
|
|
|
[mWindow zoom:nil];
|
|
|
|
}
|
|
|
|
else if (aMode == nsSizeMode_Minimized) {
|
|
|
|
if (![mWindow isMiniaturized])
|
|
|
|
[mWindow miniaturize:nil];
|
|
|
|
}
|
|
|
|
else if (aMode == nsSizeMode_Maximized) {
|
|
|
|
if ([mWindow isMiniaturized])
|
|
|
|
[mWindow deminiaturize:nil];
|
|
|
|
if (![mWindow isZoomed])
|
|
|
|
[mWindow zoom:nil];
|
|
|
|
}
|
2012-02-08 23:59:18 +04:00
|
|
|
else if (aMode == nsSizeMode_Fullscreen) {
|
2015-06-04 04:49:34 +03:00
|
|
|
if (!mInFullScreenMode)
|
2012-02-08 23:59:18 +04:00
|
|
|
MakeFullScreen(true);
|
|
|
|
}
|
2006-10-14 00:27:56 +04:00
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
return NS_OK;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2009-07-22 12:57:39 +04:00
|
|
|
// This has to preserve the window's frame bounds.
|
|
|
|
// This method requires (as does the Windows impl.) that you call Resize shortly
|
|
|
|
// after calling HideWindowChrome. See bug 498835 for fixing this.
|
2011-09-29 10:19:26 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::HideWindowChrome(bool aShouldHide)
|
2009-07-22 12:57:39 +04:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow || !mWindowMadeHere ||
|
2009-07-22 12:57:39 +04:00
|
|
|
(mWindowType != eWindowType_toplevel && mWindowType != eWindowType_dialog))
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
BOOL isVisible = [mWindow isVisible];
|
|
|
|
|
|
|
|
// Remove child windows.
|
|
|
|
NSArray* childWindows = [mWindow childWindows];
|
|
|
|
NSEnumerator* enumerator = [childWindows objectEnumerator];
|
|
|
|
NSWindow* child = nil;
|
|
|
|
while ((child = [enumerator nextObject])) {
|
|
|
|
[mWindow removeChildWindow:child];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remove the content view.
|
|
|
|
NSView* contentView = [mWindow contentView];
|
|
|
|
[contentView retain];
|
|
|
|
[contentView removeFromSuperviewWithoutNeedingDisplay];
|
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
// Save state (like window title).
|
|
|
|
NSMutableDictionary* state = [mWindow exportState];
|
|
|
|
|
2009-07-22 12:57:39 +04:00
|
|
|
// Recreate the window with the right border style.
|
|
|
|
NSRect frameRect = [mWindow frame];
|
|
|
|
DestroyNativeWindow();
|
2011-10-01 04:20:33 +04:00
|
|
|
nsresult rv = CreateNativeWindow(frameRect, aShouldHide ? eBorderStyle_none : mBorderStyle, true);
|
2009-07-22 12:57:39 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
// Re-import state.
|
|
|
|
[mWindow importState:state];
|
|
|
|
|
2009-07-22 12:57:39 +04:00
|
|
|
// Reparent the content view.
|
|
|
|
[mWindow setContentView:contentView];
|
|
|
|
[contentView release];
|
|
|
|
|
|
|
|
// Reparent child windows.
|
|
|
|
enumerator = [childWindows objectEnumerator];
|
|
|
|
while ((child = [enumerator nextObject])) {
|
|
|
|
[mWindow addChildWindow:child ordered:NSWindowAbove];
|
|
|
|
}
|
|
|
|
|
|
|
|
// Show the new window.
|
|
|
|
if (isVisible) {
|
2015-06-04 04:49:34 +03:00
|
|
|
bool wasAnimationSuppressed = mIsAnimationSuppressed;
|
|
|
|
mIsAnimationSuppressed = true;
|
2011-10-01 04:20:33 +04:00
|
|
|
rv = Show(true);
|
2015-06-04 04:49:34 +03:00
|
|
|
mIsAnimationSuppressed = wasAnimationSuppressed;
|
2009-07-22 12:57:39 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
}
|
|
|
|
|
2015-07-24 02:45:00 +03:00
|
|
|
class FullscreenTransitionData : public nsISupports
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
NS_DECL_ISUPPORTS
|
|
|
|
|
|
|
|
explicit FullscreenTransitionData(NSWindow* aWindow)
|
|
|
|
: mTransitionWindow(aWindow) { }
|
|
|
|
|
|
|
|
NSWindow* mTransitionWindow;
|
|
|
|
|
|
|
|
private:
|
|
|
|
virtual ~FullscreenTransitionData()
|
|
|
|
{
|
|
|
|
[mTransitionWindow close];
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
NS_IMPL_ISUPPORTS0(FullscreenTransitionData)
|
|
|
|
|
|
|
|
@interface FullscreenTransitionDelegate : NSObject <NSAnimationDelegate>
|
|
|
|
{
|
|
|
|
@public
|
2015-08-06 08:37:48 +03:00
|
|
|
nsCocoaWindow* mWindow;
|
2015-07-24 02:45:00 +03:00
|
|
|
nsIRunnable* mCallback;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation FullscreenTransitionDelegate
|
2015-08-06 08:37:48 +03:00
|
|
|
- (void)cleanupAndDispatch:(NSAnimation* )animation
|
2015-07-24 02:45:00 +03:00
|
|
|
{
|
|
|
|
[animation setDelegate:nil];
|
|
|
|
[self autorelease];
|
|
|
|
// The caller should have added ref for us.
|
|
|
|
NS_DispatchToMainThread(already_AddRefed<nsIRunnable>(mCallback));
|
|
|
|
}
|
2015-08-06 08:37:48 +03:00
|
|
|
|
|
|
|
- (void)animationDidEnd:(NSAnimation *)animation
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(animation == mWindow->FullscreenTransitionAnimation(),
|
|
|
|
"Should be handling the only animation on the window");
|
|
|
|
mWindow->ReleaseFullscreenTransitionAnimation();
|
|
|
|
[self cleanupAndDispatch:animation];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)animationDidStop:(NSAnimation *)animation
|
|
|
|
{
|
|
|
|
[self cleanupAndDispatch:animation];
|
|
|
|
}
|
2015-07-24 02:45:00 +03:00
|
|
|
@end
|
|
|
|
|
|
|
|
/* virtual */ bool
|
|
|
|
nsCocoaWindow::PrepareForFullscreenTransition(nsISupports** aData)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIScreen> widgetScreen = GetWidgetScreen();
|
|
|
|
nsScreenCocoa* screen = static_cast<nsScreenCocoa*>(widgetScreen.get());
|
|
|
|
NSScreen* cocoaScreen = screen->CocoaScreen();
|
|
|
|
|
|
|
|
NSWindow* win =
|
|
|
|
[[NSWindow alloc] initWithContentRect:[cocoaScreen frame]
|
|
|
|
styleMask:NSBorderlessWindowMask
|
|
|
|
backing:NSBackingStoreBuffered
|
|
|
|
defer:YES];
|
|
|
|
[win setBackgroundColor:[NSColor blackColor]];
|
|
|
|
[win setAlphaValue:0];
|
|
|
|
[win setIgnoresMouseEvents:YES];
|
|
|
|
[win setLevel:NSScreenSaverWindowLevel];
|
|
|
|
[win makeKeyAndOrderFront:nil];
|
|
|
|
|
|
|
|
auto data = new FullscreenTransitionData(win);
|
|
|
|
*aData = data;
|
|
|
|
NS_ADDREF(data);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* virtual */ void
|
|
|
|
nsCocoaWindow::PerformFullscreenTransition(FullscreenTransitionStage aStage,
|
|
|
|
uint16_t aDuration,
|
|
|
|
nsISupports* aData,
|
|
|
|
nsIRunnable* aCallback)
|
|
|
|
{
|
|
|
|
auto data = static_cast<FullscreenTransitionData*>(aData);
|
|
|
|
FullscreenTransitionDelegate* delegate =
|
|
|
|
[[FullscreenTransitionDelegate alloc] init];
|
2015-08-06 08:37:48 +03:00
|
|
|
delegate->mWindow = this;
|
2015-07-24 02:45:00 +03:00
|
|
|
// Storing already_AddRefed directly could cause static checking fail.
|
|
|
|
delegate->mCallback = nsCOMPtr<nsIRunnable>(aCallback).forget().take();
|
|
|
|
|
2015-08-06 08:37:48 +03:00
|
|
|
if (mFullscreenTransitionAnimation) {
|
|
|
|
[mFullscreenTransitionAnimation stopAnimation];
|
|
|
|
ReleaseFullscreenTransitionAnimation();
|
|
|
|
}
|
|
|
|
|
2015-07-24 02:45:00 +03:00
|
|
|
NSDictionary* dict = @{
|
|
|
|
NSViewAnimationTargetKey: data->mTransitionWindow,
|
|
|
|
NSViewAnimationEffectKey: aStage == eBeforeFullscreenToggle ?
|
|
|
|
NSViewAnimationFadeInEffect : NSViewAnimationFadeOutEffect
|
|
|
|
};
|
2015-08-06 08:37:48 +03:00
|
|
|
mFullscreenTransitionAnimation =
|
|
|
|
[[NSViewAnimation alloc] initWithViewAnimations:@[dict]];
|
|
|
|
[mFullscreenTransitionAnimation setDelegate:delegate];
|
|
|
|
[mFullscreenTransitionAnimation setDuration:aDuration / 1000.0];
|
|
|
|
[mFullscreenTransitionAnimation startAnimation];
|
2015-07-24 02:45:00 +03:00
|
|
|
}
|
|
|
|
|
2015-06-04 04:49:34 +03:00
|
|
|
void nsCocoaWindow::EnteredFullScreen(bool aFullScreen, bool aNativeMode)
|
2012-03-21 03:21:14 +04:00
|
|
|
{
|
2012-03-29 23:18:50 +04:00
|
|
|
mInFullScreenTransition = false;
|
2015-08-01 03:49:19 +03:00
|
|
|
bool wasInFullscreen = mInFullScreenMode;
|
2015-06-04 04:49:34 +03:00
|
|
|
mInFullScreenMode = aFullScreen;
|
|
|
|
if (aNativeMode || mInNativeFullScreenMode) {
|
|
|
|
mInNativeFullScreenMode = aFullScreen;
|
|
|
|
}
|
2012-03-21 03:21:14 +04:00
|
|
|
DispatchSizeModeEvent();
|
2015-08-01 03:49:19 +03:00
|
|
|
if (mWidgetListener && wasInFullscreen != aFullScreen) {
|
2015-06-10 14:13:12 +03:00
|
|
|
mWidgetListener->FullscreenChanged(aFullScreen);
|
|
|
|
}
|
2012-03-21 03:21:14 +04:00
|
|
|
}
|
2009-07-22 12:57:39 +04:00
|
|
|
|
2015-07-13 13:44:36 +03:00
|
|
|
inline bool
|
|
|
|
nsCocoaWindow::ShouldToggleNativeFullscreen(bool aFullScreen,
|
|
|
|
bool aUseSystemTransition)
|
2015-06-04 04:49:34 +03:00
|
|
|
{
|
|
|
|
if (!mSupportsNativeFullScreen) {
|
|
|
|
// If we cannot use native fullscreen, don't touch it.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (mInNativeFullScreenMode) {
|
|
|
|
// If we are using native fullscreen, go ahead to exit it.
|
|
|
|
return true;
|
|
|
|
}
|
2015-07-13 13:44:36 +03:00
|
|
|
if (!aUseSystemTransition) {
|
|
|
|
// If we do not want the system fullscreen transition,
|
|
|
|
// don't use the native fullscreen.
|
2015-06-04 04:49:34 +03:00
|
|
|
return false;
|
|
|
|
}
|
2015-07-13 13:44:36 +03:00
|
|
|
// If we are using native fullscreen, we should have returned earlier.
|
2015-06-04 04:49:34 +03:00
|
|
|
return aFullScreen;
|
|
|
|
}
|
|
|
|
|
2015-07-13 13:44:36 +03:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsCocoaWindow::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen)
|
|
|
|
{
|
|
|
|
return DoMakeFullScreen(aFullScreen, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsCocoaWindow::MakeFullScreenWithNativeTransition(bool aFullScreen,
|
|
|
|
nsIScreen* aTargetScreen)
|
|
|
|
{
|
|
|
|
return DoMakeFullScreen(aFullScreen, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsCocoaWindow::DoMakeFullScreen(bool aFullScreen, bool aUseSystemTransition)
|
2009-07-22 13:01:37 +04:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-03-21 03:21:14 +04:00
|
|
|
// We will call into MakeFullScreen redundantly when entering/exiting
|
|
|
|
// fullscreen mode via OS X controls. When that happens we should just handle
|
|
|
|
// it gracefully - no need to ASSERT.
|
2015-06-04 04:49:34 +03:00
|
|
|
if (mInFullScreenMode == aFullScreen) {
|
2012-03-21 03:21:14 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2012-06-20 19:52:13 +04:00
|
|
|
|
|
|
|
|
2012-03-29 23:18:50 +04:00
|
|
|
mInFullScreenTransition = true;
|
2009-07-22 13:01:37 +04:00
|
|
|
|
2015-07-13 13:44:36 +03:00
|
|
|
if (ShouldToggleNativeFullscreen(aFullScreen, aUseSystemTransition)) {
|
2015-06-04 04:49:34 +03:00
|
|
|
// If we're using native fullscreen mode and our native window is invisible,
|
|
|
|
// our attempt to go into fullscreen mode will fail with an assertion in
|
|
|
|
// system code, without [WindowDelegate windowDidFailToEnterFullScreen:]
|
|
|
|
// ever getting called. To pre-empt this we bail here. See bug 752294.
|
|
|
|
if (aFullScreen && ![mWindow isVisible]) {
|
|
|
|
EnteredFullScreen(false);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(mInNativeFullScreenMode != aFullScreen,
|
|
|
|
"We shouldn't have been in native fullscreen.");
|
2012-03-29 23:18:50 +04:00
|
|
|
// Calling toggleFullScreen will result in windowDid(FailTo)?(Enter|Exit)FullScreen
|
2012-03-21 03:21:14 +04:00
|
|
|
// to be called from the OS. We will call EnteredFullScreen from those methods,
|
2015-06-04 04:49:34 +03:00
|
|
|
// where mInFullScreenMode will be set and a sizemode event will be dispatched.
|
2012-03-21 03:21:14 +04:00
|
|
|
[mWindow toggleFullScreen:nil];
|
|
|
|
} else {
|
|
|
|
NSDisableScreenUpdates();
|
|
|
|
// The order here matters. When we exit full screen mode, we need to show the
|
|
|
|
// Dock first, otherwise the newly-created window won't have its minimize
|
|
|
|
// button enabled. See bug 526282.
|
2015-08-07 06:49:12 +03:00
|
|
|
nsCocoaUtils::HideOSChromeOnScreen(aFullScreen);
|
2012-03-21 03:21:14 +04:00
|
|
|
nsresult rv = nsBaseWidget::MakeFullScreen(aFullScreen);
|
|
|
|
NSEnableScreenUpdates();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2009-07-22 13:01:37 +04:00
|
|
|
|
2015-06-04 04:49:34 +03:00
|
|
|
EnteredFullScreen(aFullScreen, /* aNativeMode */ false);
|
|
|
|
}
|
|
|
|
|
2009-07-22 13:01:37 +04:00
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
}
|
|
|
|
|
2012-12-06 21:31:34 +04:00
|
|
|
// Coordinates are global display pixels
|
2012-12-12 13:57:38 +04:00
|
|
|
nsresult nsCocoaWindow::DoResize(double aX, double aY,
|
|
|
|
double aWidth, double aHeight,
|
2012-12-06 21:31:34 +04:00
|
|
|
bool aRepaint,
|
|
|
|
bool aConstrainToCurrentScreen)
|
2001-11-06 18:35:24 +03:00
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2014-03-13 16:21:56 +04:00
|
|
|
if (!mWindow || mInResize) {
|
2012-12-06 21:31:34 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2014-03-13 16:21:56 +04:00
|
|
|
AutoRestore<bool> reentrantResizeGuard(mInResize);
|
|
|
|
mInResize = true;
|
|
|
|
|
2012-12-06 21:31:34 +04:00
|
|
|
// ConstrainSize operates in device pixels, so we need to convert using
|
|
|
|
// the backing scale factor here
|
|
|
|
CGFloat scale = BackingScaleFactor();
|
2012-12-12 13:57:38 +04:00
|
|
|
int32_t width = NSToIntRound(aWidth * scale);
|
|
|
|
int32_t height = NSToIntRound(aHeight * scale);
|
|
|
|
ConstrainSize(&width, &height);
|
2012-07-31 04:43:29 +04:00
|
|
|
|
2013-04-23 00:18:28 +04:00
|
|
|
nsIntRect newBounds(NSToIntRound(aX), NSToIntRound(aY),
|
2012-12-12 13:57:38 +04:00
|
|
|
NSToIntRound(width / scale),
|
|
|
|
NSToIntRound(height / scale));
|
2012-09-29 15:36:09 +04:00
|
|
|
|
2012-12-06 21:31:34 +04:00
|
|
|
// constrain to the screen that contains the largest area of the new rect
|
2015-06-04 04:49:34 +03:00
|
|
|
FitRectToVisibleAreaForScreen(newBounds, aConstrainToCurrentScreen ?
|
|
|
|
[mWindow screen] : nullptr);
|
2007-12-03 19:25:36 +03:00
|
|
|
|
2012-12-06 21:31:34 +04:00
|
|
|
// convert requested bounds into Cocoa coordinate system
|
|
|
|
NSRect newFrame = nsCocoaUtils::GeckoRectToCocoaRect(newBounds);
|
2012-09-29 15:36:09 +04:00
|
|
|
|
2012-12-06 21:31:34 +04:00
|
|
|
NSRect frame = [mWindow frame];
|
|
|
|
BOOL isMoving = newFrame.origin.x != frame.origin.x ||
|
|
|
|
newFrame.origin.y != frame.origin.y;
|
|
|
|
BOOL isResizing = newFrame.size.width != frame.size.width ||
|
|
|
|
newFrame.size.height != frame.size.height;
|
2007-11-07 10:36:10 +03:00
|
|
|
|
2012-12-06 21:31:34 +04:00
|
|
|
if (!isMoving && !isResizing) {
|
2007-11-07 10:36:10 +03:00
|
|
|
return NS_OK;
|
2012-12-06 21:31:34 +04:00
|
|
|
}
|
2007-11-07 10:36:10 +03:00
|
|
|
|
2007-11-27 03:24:13 +03:00
|
|
|
// We ignore aRepaint -- we have to call display:YES, otherwise the
|
|
|
|
// title bar doesn't immediately get repainted and is displayed in
|
|
|
|
// the wrong place, leading to a visual jump.
|
|
|
|
[mWindow setFrame:newFrame display:YES];
|
2007-11-07 10:36:10 +03:00
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
return NS_OK;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2012-12-06 21:31:34 +04:00
|
|
|
// Coordinates are global display pixels
|
2012-12-12 13:57:38 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::Resize(double aX, double aY,
|
|
|
|
double aWidth, double aHeight,
|
2012-10-16 23:41:20 +04:00
|
|
|
bool aRepaint)
|
2001-11-06 18:35:24 +03:00
|
|
|
{
|
2012-10-16 23:41:20 +04:00
|
|
|
return DoResize(aX, aY, aWidth, aHeight, aRepaint, false);
|
|
|
|
}
|
2010-12-21 14:42:47 +03:00
|
|
|
|
2012-12-06 21:31:34 +04:00
|
|
|
// Coordinates are global display pixels
|
2012-12-12 13:57:38 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::Resize(double aWidth, double aHeight, bool aRepaint)
|
2012-10-16 23:41:20 +04:00
|
|
|
{
|
2013-09-18 04:45:19 +04:00
|
|
|
double invScale = 1.0 / GetDefaultScale().scale;
|
2012-12-12 13:57:38 +04:00
|
|
|
return DoResize(mBounds.x * invScale, mBounds.y * invScale,
|
2012-12-06 21:31:34 +04:00
|
|
|
aWidth, aHeight, aRepaint, true);
|
2010-12-21 14:42:47 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsCocoaWindow::GetClientBounds(nsIntRect &aRect)
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2012-09-29 15:36:09 +04:00
|
|
|
CGFloat scaleFactor = BackingScaleFactor();
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow) {
|
2012-09-29 15:36:09 +04:00
|
|
|
aRect = nsCocoaUtils::CocoaRectToGeckoRectDevPix(NSZeroRect, scaleFactor);
|
2012-06-18 19:20:02 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-09-29 15:36:09 +04:00
|
|
|
NSRect r;
|
2010-12-21 14:42:47 +03:00
|
|
|
if ([mWindow isKindOfClass:[ToolbarWindow class]] &&
|
|
|
|
[(ToolbarWindow*)mWindow drawsContentsIntoWindowFrame]) {
|
2012-09-29 15:36:09 +04:00
|
|
|
r = [mWindow frame];
|
2010-12-21 14:42:47 +03:00
|
|
|
} else {
|
2012-09-29 15:36:09 +04:00
|
|
|
r = [mWindow contentRectForFrameRect:[mWindow frame]];
|
2010-12-21 14:42:47 +03:00
|
|
|
}
|
|
|
|
|
2012-09-29 15:36:09 +04:00
|
|
|
aRect = nsCocoaUtils::CocoaRectToGeckoRectDevPix(r, scaleFactor);
|
|
|
|
|
2010-12-21 14:42:47 +03:00
|
|
|
return NS_OK;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2010-12-21 14:42:47 +03:00
|
|
|
void
|
|
|
|
nsCocoaWindow::UpdateBounds()
|
|
|
|
{
|
2012-06-18 19:20:02 +04:00
|
|
|
NSRect frame = NSZeroRect;
|
2012-09-29 15:36:09 +04:00
|
|
|
if (mWindow) {
|
2012-06-18 19:20:02 +04:00
|
|
|
frame = [mWindow frame];
|
2012-09-29 15:36:09 +04:00
|
|
|
}
|
|
|
|
mBounds = nsCocoaUtils::CocoaRectToGeckoRectDevPix(frame, BackingScaleFactor());
|
2010-12-21 14:42:47 +03:00
|
|
|
}
|
|
|
|
|
2010-03-25 12:25:00 +03:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::GetScreenBounds(nsIntRect &aRect)
|
|
|
|
{
|
2010-03-25 13:30:40 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2012-09-29 15:36:09 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
nsIntRect r = nsCocoaUtils::CocoaRectToGeckoRectDevPix([mWindow frame], BackingScaleFactor());
|
|
|
|
NS_ASSERTION(mWindow && mBounds == r, "mBounds out of sync!");
|
|
|
|
#endif
|
2010-12-21 14:42:47 +03:00
|
|
|
|
|
|
|
aRect = mBounds;
|
2010-03-25 12:25:00 +03:00
|
|
|
return NS_OK;
|
2010-03-25 13:30:40 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2012-09-29 15:36:09 +04:00
|
|
|
double
|
2012-10-31 04:31:35 +04:00
|
|
|
nsCocoaWindow::GetDefaultScaleInternal()
|
2012-09-29 15:36:09 +04:00
|
|
|
{
|
|
|
|
return BackingScaleFactor();
|
|
|
|
}
|
|
|
|
|
2012-12-14 13:46:16 +04:00
|
|
|
static CGFloat
|
|
|
|
GetBackingScaleFactor(NSWindow* aWindow)
|
|
|
|
{
|
|
|
|
NSRect frame = [aWindow frame];
|
|
|
|
if (frame.size.width > 0 && frame.size.height > 0) {
|
|
|
|
return nsCocoaUtils::GetBackingScaleFactor(aWindow);
|
|
|
|
}
|
|
|
|
|
|
|
|
// For windows with zero width or height, the backingScaleFactor method
|
|
|
|
// is broken - it will always return 2 on a retina macbook, even when
|
|
|
|
// the window position implies it's on a non-hidpi external display
|
|
|
|
// (to the extent that a zero-area window can be said to be "on" a
|
|
|
|
// display at all!)
|
|
|
|
// And to make matters worse, Cocoa even fires a
|
|
|
|
// windowDidChangeBackingProperties notification with the
|
|
|
|
// NSBackingPropertyOldScaleFactorKey key when a window on an
|
|
|
|
// external display is resized to/from zero height, even though it hasn't
|
|
|
|
// really changed screens.
|
|
|
|
|
|
|
|
// This causes us to handle popup window sizing incorrectly when the
|
|
|
|
// popup is resized to zero height (bug 820327) - nsXULPopupManager
|
|
|
|
// becomes (incorrectly) convinced the popup has been explicitly forced
|
|
|
|
// to a non-default size and needs to have size attributes attached.
|
|
|
|
|
|
|
|
// Workaround: instead of asking the window, we'll find the screen it is on
|
|
|
|
// and ask that for *its* backing scale factor.
|
|
|
|
|
2013-04-12 11:45:50 +04:00
|
|
|
// (See bug 853252 and additional comments in windowDidChangeScreen: below
|
|
|
|
// for further complications this causes.)
|
|
|
|
|
2012-12-14 13:46:16 +04:00
|
|
|
// First, expand the rect so that it actually has a measurable area,
|
|
|
|
// for FindTargetScreenForRect to use.
|
|
|
|
if (frame.size.width == 0) {
|
|
|
|
frame.size.width = 1;
|
|
|
|
}
|
|
|
|
if (frame.size.height == 0) {
|
|
|
|
frame.size.height = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Then identify the screen it belongs to, and return its scale factor.
|
|
|
|
NSScreen *screen =
|
|
|
|
FindTargetScreenForRect(nsCocoaUtils::CocoaRectToGeckoRect(frame));
|
|
|
|
return nsCocoaUtils::GetBackingScaleFactor(screen);
|
|
|
|
}
|
|
|
|
|
2012-09-29 15:36:09 +04:00
|
|
|
CGFloat
|
|
|
|
nsCocoaWindow::BackingScaleFactor()
|
|
|
|
{
|
|
|
|
if (mBackingScaleFactor > 0.0) {
|
|
|
|
return mBackingScaleFactor;
|
|
|
|
}
|
|
|
|
if (!mWindow) {
|
|
|
|
return 1.0;
|
|
|
|
}
|
2012-12-14 13:46:16 +04:00
|
|
|
mBackingScaleFactor = GetBackingScaleFactor(mWindow);
|
2012-09-29 15:36:09 +04:00
|
|
|
return mBackingScaleFactor;
|
|
|
|
}
|
|
|
|
|
2012-10-16 23:41:20 +04:00
|
|
|
void
|
|
|
|
nsCocoaWindow::BackingScaleFactorChanged()
|
|
|
|
{
|
2012-12-14 13:46:16 +04:00
|
|
|
CGFloat newScale = GetBackingScaleFactor(mWindow);
|
2012-10-16 23:41:20 +04:00
|
|
|
|
|
|
|
// ignore notification if it hasn't really changed (or maybe we have
|
|
|
|
// disabled HiDPI mode via prefs)
|
|
|
|
if (mBackingScaleFactor == newScale) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-10-16 23:41:20 +04:00
|
|
|
if (mBackingScaleFactor > 0.0) {
|
|
|
|
// convert size constraints to the new device pixel coordinate space
|
|
|
|
double scaleFactor = newScale / mBackingScaleFactor;
|
|
|
|
mSizeConstraints.mMinSize.width =
|
|
|
|
NSToIntRound(mSizeConstraints.mMinSize.width * scaleFactor);
|
|
|
|
mSizeConstraints.mMinSize.height =
|
|
|
|
NSToIntRound(mSizeConstraints.mMinSize.height * scaleFactor);
|
|
|
|
if (mSizeConstraints.mMaxSize.width < NS_MAXSIZE) {
|
|
|
|
mSizeConstraints.mMaxSize.width =
|
2013-01-15 16:22:03 +04:00
|
|
|
std::min(NS_MAXSIZE,
|
2012-10-16 23:41:20 +04:00
|
|
|
NSToIntRound(mSizeConstraints.mMaxSize.width * scaleFactor));
|
|
|
|
}
|
|
|
|
if (mSizeConstraints.mMaxSize.height < NS_MAXSIZE) {
|
|
|
|
mSizeConstraints.mMaxSize.height =
|
2013-01-15 16:22:03 +04:00
|
|
|
std::min(NS_MAXSIZE,
|
2012-10-16 23:41:20 +04:00
|
|
|
NSToIntRound(mSizeConstraints.mMaxSize.height * scaleFactor));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-16 23:41:20 +04:00
|
|
|
mBackingScaleFactor = newScale;
|
|
|
|
|
|
|
|
if (!mWidgetListener || mWidgetListener->GetXULWindow()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIPresShell* presShell = mWidgetListener->GetPresShell();
|
|
|
|
if (presShell) {
|
|
|
|
presShell->BackingScaleFactorChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-30 20:22:41 +04:00
|
|
|
int32_t
|
|
|
|
nsCocoaWindow::RoundsWidgetCoordinatesTo()
|
|
|
|
{
|
|
|
|
if (BackingScaleFactor() == 2.0) {
|
|
|
|
return 2;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2009-09-28 01:04:16 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::SetCursor(nsCursor aCursor)
|
|
|
|
{
|
|
|
|
if (mPopupContentView)
|
|
|
|
return mPopupContentView->SetCursor(aCursor);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsCocoaWindow::SetCursor(imgIContainer* aCursor,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aHotspotX, uint32_t aHotspotY)
|
2009-09-28 01:04:16 +04:00
|
|
|
{
|
|
|
|
if (mPopupContentView)
|
|
|
|
return mPopupContentView->SetCursor(aCursor, aHotspotX, aHotspotY);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2004-04-19 03:18:23 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::SetTitle(const nsAString& aTitle)
|
2001-11-06 18:35:24 +03:00
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow)
|
|
|
|
return NS_OK;
|
|
|
|
|
2004-04-19 03:18:23 +04:00
|
|
|
const nsString& strTitle = PromiseFlatString(aTitle);
|
2013-10-10 20:59:40 +04:00
|
|
|
NSString* title = [NSString stringWithCharacters:reinterpret_cast<const unichar*>(strTitle.get())
|
|
|
|
length:strTitle.Length()];
|
2014-01-08 13:37:59 +04:00
|
|
|
|
|
|
|
if ([mWindow drawsContentsIntoWindowFrame] && ![mWindow wantsTitleDrawn]) {
|
|
|
|
// Don't cause invalidations.
|
|
|
|
[mWindow disableSetNeedsDisplay];
|
|
|
|
[mWindow setTitle:title];
|
|
|
|
[mWindow enableSetNeedsDisplay];
|
|
|
|
} else {
|
|
|
|
[mWindow setTitle:title];
|
|
|
|
}
|
2001-11-06 18:35:24 +03:00
|
|
|
|
|
|
|
return NS_OK;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2011-12-24 07:52:21 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::Invalidate(const nsIntRect & aRect)
|
2006-07-25 22:51:41 +04:00
|
|
|
{
|
2012-09-29 15:36:09 +04:00
|
|
|
if (mPopupContentView) {
|
2011-12-24 07:52:21 +04:00
|
|
|
return mPopupContentView->Invalidate(aRect);
|
2012-09-29 15:36:09 +04:00
|
|
|
}
|
2006-07-25 22:51:41 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
// Pass notification of some drag event to Gecko
|
|
|
|
//
|
|
|
|
// The drag manager has let us know that something related to a drag has
|
|
|
|
// occurred in this window. It could be any number of things, ranging from
|
|
|
|
// a drop, to a drag enter/leave, or a drag over event. The actual event
|
|
|
|
// is passed in |aMessage| and is passed along to our event hanlder so Gecko
|
|
|
|
// knows about it.
|
2011-09-29 10:19:26 +04:00
|
|
|
bool nsCocoaWindow::DragEvent(unsigned int aMessage, Point aMouseGlobal, UInt16 aKeyModifiers)
|
2001-11-06 18:35:24 +03:00
|
|
|
{
|
2011-10-01 04:20:33 +04:00
|
|
|
return false;
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2006-10-04 00:38:38 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::SendSetZLevelEvent()
|
2005-10-08 03:31:45 +04:00
|
|
|
{
|
2012-08-15 22:52:42 +04:00
|
|
|
nsWindowZ placement = nsWindowZTop;
|
|
|
|
nsIWidget* actualBelow;
|
|
|
|
if (mWidgetListener)
|
|
|
|
mWidgetListener->ZLevelChanged(true, &placement, nullptr, &actualBelow);
|
2006-05-17 22:53:58 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::GetChildSheet(bool aShown, nsCocoaWindow** _retval)
|
2006-05-17 22:53:58 +04:00
|
|
|
{
|
2006-06-08 21:29:18 +04:00
|
|
|
nsIWidget* child = GetFirstChild();
|
|
|
|
|
|
|
|
while (child) {
|
2014-03-19 20:48:08 +04:00
|
|
|
if (child->WindowType() == eWindowType_sheet) {
|
2008-02-20 05:30:24 +03:00
|
|
|
// if it's a sheet, it must be an nsCocoaWindow
|
|
|
|
nsCocoaWindow* cocoaWindow = static_cast<nsCocoaWindow*>(child);
|
2012-06-18 19:20:02 +04:00
|
|
|
if (cocoaWindow->mWindow &&
|
|
|
|
((aShown && [cocoaWindow->mWindow isVisible]) ||
|
|
|
|
(!aShown && cocoaWindow->mSheetNeedsShow))) {
|
2008-02-20 05:30:24 +03:00
|
|
|
*_retval = cocoaWindow;
|
|
|
|
return NS_OK;
|
2006-06-08 21:29:18 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
child = child->GetNextSibling();
|
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
*_retval = nullptr;
|
2006-06-08 21:29:18 +04:00
|
|
|
|
2006-05-17 22:53:58 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-05-08 01:15:57 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::GetRealParent(nsIWidget** parent)
|
|
|
|
{
|
|
|
|
*parent = mParent;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::GetIsSheet(bool* isSheet)
|
2006-05-17 22:53:58 +04:00
|
|
|
{
|
2011-10-01 04:20:33 +04:00
|
|
|
mWindowType == eWindowType_sheet ? *isSheet = true : *isSheet = false;
|
2006-06-08 21:29:18 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsCocoaWindow::GetSheetWindowParent(NSWindow** sheetWindowParent)
|
|
|
|
{
|
|
|
|
*sheetWindowParent = mSheetWindowParent;
|
2006-05-17 22:53:58 +04:00
|
|
|
return NS_OK;
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2007-09-20 02:15:48 +04:00
|
|
|
// Invokes callback and ProcessEvent methods on Event Listener object
|
2001-11-06 18:35:24 +03:00
|
|
|
NS_IMETHODIMP
|
2013-10-02 07:46:03 +04:00
|
|
|
nsCocoaWindow::DispatchEvent(WidgetGUIEvent* event, nsEventStatus& aStatus)
|
2001-11-06 18:35:24 +03:00
|
|
|
{
|
|
|
|
aStatus = nsEventStatus_eIgnore;
|
|
|
|
|
|
|
|
nsIWidget* aWidget = event->widget;
|
|
|
|
NS_IF_ADDREF(aWidget);
|
2007-09-20 02:15:48 +04:00
|
|
|
|
2012-08-15 22:53:09 +04:00
|
|
|
if (mWidgetListener)
|
|
|
|
aStatus = mWidgetListener->HandleEvent(event, mUseAttachedEvents);
|
2001-11-06 18:35:24 +03:00
|
|
|
|
|
|
|
NS_IF_RELEASE(aWidget);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-06-04 04:49:34 +03:00
|
|
|
// aFullScreen should be the window's mInFullScreenMode. We don't have access to that
|
|
|
|
// from here, so we need to pass it in. mInFullScreenMode should be the canonical
|
2012-02-08 23:59:18 +04:00
|
|
|
// indicator that a window is currently full screen and it makes sense to keep
|
|
|
|
// all sizemode logic here.
|
2009-08-14 02:02:54 +04:00
|
|
|
static nsSizeMode
|
2012-02-08 23:59:18 +04:00
|
|
|
GetWindowSizeMode(NSWindow* aWindow, bool aFullScreen) {
|
|
|
|
if (aFullScreen)
|
|
|
|
return nsSizeMode_Fullscreen;
|
2009-08-14 02:02:54 +04:00
|
|
|
if ([aWindow isMiniaturized])
|
|
|
|
return nsSizeMode_Minimized;
|
|
|
|
if (([aWindow styleMask] & NSResizableWindowMask) && [aWindow isZoomed])
|
|
|
|
return nsSizeMode_Maximized;
|
|
|
|
return nsSizeMode_Normal;
|
|
|
|
}
|
|
|
|
|
2010-07-27 17:38:04 +04:00
|
|
|
void
|
|
|
|
nsCocoaWindow::ReportMoveEvent()
|
|
|
|
{
|
2010-12-21 14:42:47 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2011-12-13 20:55:16 +04:00
|
|
|
// Prevent recursion, which can become infinite (see bug 708278). This
|
|
|
|
// can happen when the call to [NSWindow setFrameTopLeftPoint:] in
|
|
|
|
// nsCocoaWindow::Move() triggers an immediate NSWindowDidMove notification
|
|
|
|
// (and a call to [WindowDelegate windowDidMove:]).
|
|
|
|
if (mInReportMoveEvent) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mInReportMoveEvent = true;
|
|
|
|
|
2010-12-21 14:42:47 +03:00
|
|
|
UpdateBounds();
|
|
|
|
|
2010-07-27 17:38:04 +04:00
|
|
|
// Dispatch the move event to Gecko
|
2014-02-28 11:45:08 +04:00
|
|
|
NotifyWindowMoved(mBounds.x, mBounds.y);
|
2010-12-21 14:42:47 +03:00
|
|
|
|
2011-12-13 20:55:16 +04:00
|
|
|
mInReportMoveEvent = false;
|
|
|
|
|
2010-12-21 14:42:47 +03:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2010-07-27 17:38:04 +04:00
|
|
|
}
|
|
|
|
|
2008-09-10 20:57:57 +04:00
|
|
|
void
|
2009-08-14 02:02:54 +04:00
|
|
|
nsCocoaWindow::DispatchSizeModeEvent()
|
2008-09-10 20:57:57 +04:00
|
|
|
{
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-06-04 04:49:34 +03:00
|
|
|
nsSizeMode newMode = GetWindowSizeMode(mWindow, mInFullScreenMode);
|
2012-03-29 23:18:50 +04:00
|
|
|
|
|
|
|
// Don't dispatch a sizemode event if:
|
|
|
|
// 1. the window is transitioning to fullscreen
|
|
|
|
// 2. the new sizemode is the same as the current sizemode
|
|
|
|
if (mInFullScreenTransition || mSizeMode == newMode) {
|
2012-01-31 14:40:03 +04:00
|
|
|
return;
|
2012-03-29 23:18:50 +04:00
|
|
|
}
|
2012-01-31 14:40:03 +04:00
|
|
|
|
|
|
|
mSizeMode = newMode;
|
2012-08-15 22:52:42 +04:00
|
|
|
if (mWidgetListener) {
|
|
|
|
mWidgetListener->SizeModeChanged(newMode);
|
|
|
|
}
|
2008-09-10 20:57:57 +04:00
|
|
|
}
|
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
void
|
2010-12-21 14:42:47 +03:00
|
|
|
nsCocoaWindow::ReportSizeEvent()
|
2001-11-06 18:35:24 +03:00
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2010-12-21 14:42:47 +03:00
|
|
|
UpdateBounds();
|
2009-10-21 11:05:39 +04:00
|
|
|
|
2012-08-15 22:52:42 +04:00
|
|
|
if (mWidgetListener) {
|
|
|
|
nsIntRect innerBounds;
|
|
|
|
GetClientBounds(innerBounds);
|
|
|
|
mWidgetListener->WindowResized(this, innerBounds.width, innerBounds.height);
|
|
|
|
}
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2009-04-08 22:39:58 +04:00
|
|
|
void nsCocoaWindow::SetMenuBar(nsMenuBarX *aMenuBar)
|
2005-10-08 03:31:45 +04:00
|
|
|
{
|
|
|
|
if (mMenuBar)
|
2012-07-30 18:20:58 +04:00
|
|
|
mMenuBar->SetParent(nullptr);
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow) {
|
2012-07-30 18:20:58 +04:00
|
|
|
mMenuBar = nullptr;
|
2012-06-18 19:20:02 +04:00
|
|
|
return;
|
|
|
|
}
|
2009-04-08 22:39:58 +04:00
|
|
|
mMenuBar = aMenuBar;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
|
|
|
// Only paint for active windows, or paint the hidden window menu bar if no
|
|
|
|
// other menu bar has been painted yet so that some reasonable menu bar is
|
|
|
|
// displayed when the app starts up.
|
|
|
|
id windowDelegate = [mWindow delegate];
|
|
|
|
if (mMenuBar &&
|
|
|
|
((!gSomeMenuBarPainted && nsMenuUtilsX::GetHiddenWindowMenuBar() == mMenuBar) ||
|
|
|
|
(windowDelegate && [windowDelegate toplevelActiveState])))
|
2006-04-07 08:51:16 +04:00
|
|
|
mMenuBar->Paint();
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::SetFocus(bool aState)
|
2006-07-25 22:51:41 +04:00
|
|
|
{
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow)
|
|
|
|
return NS_OK;
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (mPopupContentView) {
|
2006-07-25 22:51:41 +04:00
|
|
|
mPopupContentView->SetFocus(aState);
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
}
|
2010-02-03 15:42:12 +03:00
|
|
|
else if (aState && ([mWindow isVisible] || [mWindow isMiniaturized])) {
|
2014-08-20 04:01:32 +04:00
|
|
|
if ([mWindow isMiniaturized]) {
|
|
|
|
[mWindow deminiaturize:nil];
|
|
|
|
}
|
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
[mWindow makeKeyAndOrderFront:nil];
|
|
|
|
SendSetZLevelEvent();
|
|
|
|
}
|
2006-07-25 22:51:41 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-02-04 23:21:03 +03:00
|
|
|
LayoutDeviceIntPoint nsCocoaWindow::WidgetToScreenOffset()
|
2007-01-25 22:19:48 +03:00
|
|
|
{
|
2009-02-19 03:11:49 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
2009-02-15 20:41:16 +03:00
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
NSRect rect = NSZeroRect;
|
2012-09-29 15:36:09 +04:00
|
|
|
nsIntRect r;
|
|
|
|
if (mWindow) {
|
2012-06-18 19:20:02 +04:00
|
|
|
rect = [mWindow contentRectForFrameRect:[mWindow frame]];
|
2012-09-29 15:36:09 +04:00
|
|
|
}
|
|
|
|
r = nsCocoaUtils::CocoaRectToGeckoRectDevPix(rect, BackingScaleFactor());
|
2009-02-15 20:41:16 +03:00
|
|
|
|
2015-02-04 23:21:03 +03:00
|
|
|
return LayoutDeviceIntPoint::FromUntyped(r.TopLeft());
|
2009-02-15 20:41:16 +03:00
|
|
|
|
2015-02-04 23:21:03 +03:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntPoint(0,0));
|
2007-01-25 22:19:48 +03:00
|
|
|
}
|
|
|
|
|
2010-07-27 17:38:03 +04:00
|
|
|
nsIntPoint nsCocoaWindow::GetClientOffset()
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2010-12-21 14:42:47 +03:00
|
|
|
nsIntRect clientRect;
|
|
|
|
GetClientBounds(clientRect);
|
2010-07-27 17:38:03 +04:00
|
|
|
|
2010-12-21 14:42:47 +03:00
|
|
|
return clientRect.TopLeft() - mBounds.TopLeft();
|
2010-07-27 17:38:03 +04:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(nsIntPoint(0, 0));
|
|
|
|
}
|
|
|
|
|
2015-04-01 01:09:03 +03:00
|
|
|
LayoutDeviceIntSize
|
|
|
|
nsCocoaWindow::ClientToWindowSize(const LayoutDeviceIntSize& aClientSize)
|
2010-07-27 17:38:03 +04:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow)
|
2015-04-01 01:09:03 +03:00
|
|
|
return LayoutDeviceIntSize(0, 0);
|
2012-06-18 19:20:02 +04:00
|
|
|
|
2012-09-29 15:36:09 +04:00
|
|
|
CGFloat backingScale = BackingScaleFactor();
|
|
|
|
nsIntRect r(0, 0, aClientSize.width, aClientSize.height);
|
|
|
|
NSRect rect = nsCocoaUtils::DevPixelsToCocoaPoints(r, backingScale);
|
2010-07-27 17:38:03 +04:00
|
|
|
|
|
|
|
NSRect inflatedRect = [mWindow frameRectForContentRect:rect];
|
2015-04-01 01:09:03 +03:00
|
|
|
r = nsCocoaUtils::CocoaRectToGeckoRectDevPix(inflatedRect, backingScale);
|
|
|
|
return LayoutDeviceIntSize(r.width, r.height);
|
2010-07-27 17:38:03 +04:00
|
|
|
|
2015-04-01 01:09:03 +03:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(LayoutDeviceIntSize(0,0));
|
2010-07-27 17:38:03 +04:00
|
|
|
}
|
|
|
|
|
2008-06-28 11:55:30 +04:00
|
|
|
nsMenuBarX* nsCocoaWindow::GetMenuBar()
|
2005-10-08 03:31:45 +04:00
|
|
|
{
|
|
|
|
return mMenuBar;
|
|
|
|
}
|
2001-11-06 18:35:24 +03:00
|
|
|
|
2012-10-26 17:15:22 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::CaptureRollupEvents(nsIRollupListener* aListener, bool aDoCapture)
|
2006-03-07 23:02:09 +03:00
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
gRollupListener = nullptr;
|
2006-07-31 23:19:39 +04:00
|
|
|
|
2006-03-07 23:02:09 +03:00
|
|
|
if (aDoCapture) {
|
2011-11-07 20:43:10 +04:00
|
|
|
if (![NSApp isActive]) {
|
|
|
|
// We need to capture mouse event if we aren't
|
|
|
|
// the active application. We only set this up when needed
|
|
|
|
// because they cause spurious mouse event after crash
|
|
|
|
// and gdb sessions. See bug 699538.
|
|
|
|
nsToolkit::GetToolkit()->RegisterForAllProcessMouseEvents();
|
|
|
|
}
|
2006-03-07 23:02:09 +03:00
|
|
|
gRollupListener = aListener;
|
2009-05-15 00:13:22 +04:00
|
|
|
|
2007-10-02 01:39:52 +04:00
|
|
|
// Sometimes more than one popup window can be visible at the same time
|
|
|
|
// (e.g. nested non-native context menus, or the test case (attachment
|
2012-10-26 17:15:22 +04:00
|
|
|
// 276885) for bmo bug 392389, which displays a non-native combo-box in a
|
|
|
|
// non-native popup window). In these cases the "active" popup window should
|
|
|
|
// be the topmost -- the (nested) context menu the mouse is currently over,
|
|
|
|
// or the combo-box's drop-down list (when it's displayed). But (among
|
2007-10-02 01:39:52 +04:00
|
|
|
// windows that have the same "level") OS X makes topmost the window that
|
|
|
|
// last received a mouse-down event, which may be incorrect (in the combo-
|
|
|
|
// box case, it makes topmost the window containing the combo-box). So
|
|
|
|
// here we fiddle with a non-native popup window's level to make sure the
|
|
|
|
// "active" one is always above any other non-native popup windows that
|
|
|
|
// may be visible.
|
|
|
|
if (mWindow && (mWindowType == eWindowType_popup))
|
2010-07-27 17:38:03 +04:00
|
|
|
SetPopupWindowLevel();
|
2007-10-02 01:39:52 +04:00
|
|
|
} else {
|
2011-11-07 20:43:10 +04:00
|
|
|
nsToolkit::GetToolkit()->UnregisterAllProcessMouseEventHandlers();
|
|
|
|
|
2010-07-27 17:38:03 +04:00
|
|
|
// XXXndeakin this doesn't make sense.
|
|
|
|
// Why is the new window assumed to be a modal panel?
|
2007-10-02 01:39:52 +04:00
|
|
|
if (mWindow && (mWindowType == eWindowType_popup))
|
|
|
|
[mWindow setLevel:NSModalPanelWindowLevel];
|
2006-03-07 23:02:09 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2006-03-07 23:02:09 +03:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::GetAttention(int32_t aCycleCount)
|
2006-07-11 23:51:56 +04:00
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2006-07-11 23:51:56 +04:00
|
|
|
[NSApp requestUserAttention:NSInformationalRequest];
|
|
|
|
return NS_OK;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2006-07-11 23:51:56 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2009-04-22 03:53:52 +04:00
|
|
|
nsCocoaWindow::HasPendingInputEvent()
|
|
|
|
{
|
|
|
|
return nsChildView::DoHasPendingInputEvent();
|
|
|
|
}
|
2006-07-11 23:51:56 +04:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::SetWindowShadowStyle(int32_t aStyle)
|
2008-10-14 19:33:40 +04:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow)
|
|
|
|
return NS_OK;
|
|
|
|
|
2009-12-30 18:24:08 +03:00
|
|
|
mShadowStyle = aStyle;
|
2015-05-09 00:49:29 +03:00
|
|
|
|
|
|
|
// Shadowless windows are only supported on popups.
|
|
|
|
if (mWindowType == eWindowType_popup)
|
|
|
|
[mWindow setHasShadow:(aStyle != NS_STYLE_WINDOW_SHADOW_NONE)];
|
|
|
|
|
2015-02-05 01:25:19 +03:00
|
|
|
[mWindow setUseMenuStyle:(aStyle == NS_STYLE_WINDOW_SHADOW_MENU)];
|
2009-12-30 18:24:08 +03:00
|
|
|
AdjustWindowShadow();
|
2014-01-03 19:53:41 +04:00
|
|
|
SetWindowBackgroundBlur();
|
2009-12-30 18:24:08 +03:00
|
|
|
|
2008-10-14 19:33:40 +04:00
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
void nsCocoaWindow::SetShowsToolbarButton(bool aShow)
|
2009-08-06 00:49:59 +04:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (mWindow)
|
|
|
|
[mWindow setShowsToolbarButton:aShow];
|
2009-08-06 00:49:59 +04:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2012-03-21 03:21:14 +04:00
|
|
|
void nsCocoaWindow::SetShowsFullScreenButton(bool aShow)
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow || ![mWindow respondsToSelector:@selector(toggleFullScreen:)] ||
|
2015-06-04 04:49:34 +03:00
|
|
|
mSupportsNativeFullScreen == aShow) {
|
2012-03-21 03:21:14 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the window is currently in fullscreen mode, then we're going to
|
|
|
|
// transition out first, then set the collection behavior & toggle
|
2015-06-04 04:49:34 +03:00
|
|
|
// mSupportsNativeFullScreen, then transtion back into fullscreen mode. This
|
2012-03-21 03:21:14 +04:00
|
|
|
// prevents us from getting into a conflicting state with MakeFullScreen
|
2015-06-04 04:49:34 +03:00
|
|
|
// where mSupportsNativeFullScreen would lead us down the wrong path.
|
|
|
|
bool wasFullScreen = mInFullScreenMode;
|
2012-03-21 03:21:14 +04:00
|
|
|
|
|
|
|
if (wasFullScreen) {
|
|
|
|
MakeFullScreen(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
NSWindowCollectionBehavior newBehavior = [mWindow collectionBehavior];
|
|
|
|
if (aShow) {
|
|
|
|
newBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
|
|
|
|
} else {
|
|
|
|
newBehavior &= ~NSWindowCollectionBehaviorFullScreenPrimary;
|
|
|
|
}
|
|
|
|
[mWindow setCollectionBehavior:newBehavior];
|
2015-06-04 04:49:34 +03:00
|
|
|
mSupportsNativeFullScreen = aShow;
|
2012-03-21 03:21:14 +04:00
|
|
|
|
|
|
|
if (wasFullScreen) {
|
|
|
|
MakeFullScreen(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2012-02-17 07:47:39 +04:00
|
|
|
void nsCocoaWindow::SetWindowAnimationType(nsIWidget::WindowAnimationType aType)
|
|
|
|
{
|
|
|
|
mAnimationType = aType;
|
|
|
|
}
|
|
|
|
|
2013-12-17 20:11:13 +04:00
|
|
|
void
|
|
|
|
nsCocoaWindow::SetDrawsTitle(bool aDrawTitle)
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
[mWindow setWantsTitleDrawn:aDrawTitle];
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2014-11-04 06:14:10 +03:00
|
|
|
void
|
|
|
|
nsCocoaWindow::SetUseBrightTitlebarForeground(bool aBrightForeground)
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
[mWindow setUseBrightTitlebarForeground:aBrightForeground];
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2013-03-01 22:48:18 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::SetNonClientMargins(nsIntMargin &margins)
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
|
|
|
SetDrawsInTitlebar(margins.top == 0);
|
|
|
|
|
2015-02-02 15:14:00 +03:00
|
|
|
return NS_OK;
|
|
|
|
|
2013-03-01 22:48:18 +04:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::SetWindowTitlebarColor(nscolor aColor, bool aActive)
|
2007-10-30 07:03:42 +03:00
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow)
|
|
|
|
return NS_OK;
|
|
|
|
|
2007-10-30 07:03:42 +03:00
|
|
|
// If they pass a color with a complete transparent alpha component, use the
|
|
|
|
// native titlebar appearance.
|
|
|
|
if (NS_GET_A(aColor) == 0) {
|
2009-11-02 22:07:57 +03:00
|
|
|
[mWindow setTitlebarColor:nil forActiveWindow:(BOOL)aActive];
|
2007-10-30 07:03:42 +03:00
|
|
|
} else {
|
2008-04-08 00:55:14 +04:00
|
|
|
// Transform from sRGBA to monitor RGBA. This seems like it would make trying
|
|
|
|
// to match the system appearance lame, so probably we just shouldn't color
|
|
|
|
// correct chrome.
|
2013-09-07 07:08:36 +04:00
|
|
|
if (gfxPlatform::GetCMSMode() == eCMSMode_All) {
|
|
|
|
qcms_transform *transform = gfxPlatform::GetCMSRGBATransform();
|
2008-09-11 06:21:03 +04:00
|
|
|
if (transform) {
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t color[3];
|
2008-09-11 06:21:03 +04:00
|
|
|
color[0] = NS_GET_R(aColor);
|
|
|
|
color[1] = NS_GET_G(aColor);
|
|
|
|
color[2] = NS_GET_B(aColor);
|
2009-04-07 20:02:11 +04:00
|
|
|
qcms_transform_data(transform, color, color, 1);
|
2008-09-11 06:21:03 +04:00
|
|
|
aColor = NS_RGB(color[0], color[1], color[2]);
|
|
|
|
}
|
|
|
|
}
|
2008-04-08 00:55:14 +04:00
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
[mWindow setTitlebarColor:[NSColor colorWithDeviceRed:NS_GET_R(aColor)/255.0
|
|
|
|
green:NS_GET_G(aColor)/255.0
|
|
|
|
blue:NS_GET_B(aColor)/255.0
|
|
|
|
alpha:NS_GET_A(aColor)/255.0]
|
|
|
|
forActiveWindow:(BOOL)aActive];
|
2007-10-30 07:03:42 +03:00
|
|
|
}
|
|
|
|
return NS_OK;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
2009-09-23 06:31:37 +04:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
void nsCocoaWindow::SetDrawsInTitlebar(bool aState)
|
2009-10-21 11:05:39 +04:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2012-06-18 19:20:02 +04:00
|
|
|
if (mWindow)
|
|
|
|
[mWindow setDrawsContentsIntoWindowFrame:aState];
|
2009-10-21 11:05:39 +04:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2015-02-15 21:52:28 +03:00
|
|
|
NS_IMETHODIMP nsCocoaWindow::SynthesizeNativeMouseEvent(LayoutDeviceIntPoint aPoint,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aNativeMessage,
|
2015-04-14 18:36:36 +03:00
|
|
|
uint32_t aModifierFlags,
|
|
|
|
nsIObserver* aObserver)
|
2009-09-23 06:31:37 +04:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
|
|
|
|
2015-04-14 18:36:36 +03:00
|
|
|
AutoObserverNotifier notifier(aObserver, "mouseevent");
|
2009-09-23 06:31:37 +04:00
|
|
|
if (mPopupContentView)
|
|
|
|
return mPopupContentView->SynthesizeNativeMouseEvent(aPoint, aNativeMessage,
|
2015-04-14 18:36:36 +03:00
|
|
|
aModifierFlags, nullptr);
|
2009-09-23 06:31:37 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
2007-10-30 07:03:42 +03:00
|
|
|
}
|
|
|
|
|
2014-09-12 17:10:09 +04:00
|
|
|
void nsCocoaWindow::UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
if (mPopupContentView) {
|
|
|
|
return mPopupContentView->UpdateThemeGeometries(aThemeGeometries);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2010-07-27 17:38:03 +04:00
|
|
|
void nsCocoaWindow::SetPopupWindowLevel()
|
|
|
|
{
|
2012-06-18 19:20:02 +04:00
|
|
|
if (!mWindow)
|
|
|
|
return;
|
|
|
|
|
2010-07-27 17:38:03 +04:00
|
|
|
// Floating popups are at the floating level and hide when the window is
|
|
|
|
// deactivated.
|
|
|
|
if (mPopupLevel == ePopupLevelFloating) {
|
|
|
|
[mWindow setLevel:NSFloatingWindowLevel];
|
|
|
|
[mWindow setHidesOnDeactivate:YES];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// Otherwise, this is a top-level or parent popup. Parent popups always
|
|
|
|
// appear just above their parent and essentially ignore the level.
|
|
|
|
[mWindow setLevel:NSPopUpMenuWindowLevel];
|
|
|
|
[mWindow setHidesOnDeactivate:NO];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-28 09:27:31 +03:00
|
|
|
nsresult
|
|
|
|
nsCocoaWindow::NotifyIMEInternal(const IMENotification& aIMENotification)
|
2013-05-24 20:27:52 +04:00
|
|
|
{
|
2014-02-18 04:00:15 +04:00
|
|
|
switch (aIMENotification.mMessage) {
|
2013-05-24 20:27:52 +04:00
|
|
|
case NOTIFY_IME_OF_FOCUS:
|
|
|
|
return NS_OK;
|
|
|
|
case NOTIFY_IME_OF_BLUR:
|
|
|
|
return NS_OK;
|
|
|
|
default:
|
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP_(void)
|
|
|
|
nsCocoaWindow::SetInputContext(const InputContext& aContext,
|
|
|
|
const InputContextAction& aAction)
|
|
|
|
{
|
2013-08-07 06:49:21 +04:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2013-05-24 20:27:52 +04:00
|
|
|
mInputContext = aContext;
|
2013-08-07 06:49:21 +04:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2013-05-24 20:27:52 +04:00
|
|
|
}
|
|
|
|
|
2014-03-14 17:13:31 +04:00
|
|
|
NS_IMETHODIMP_(bool)
|
|
|
|
nsCocoaWindow::ExecuteNativeKeyBinding(NativeKeyBindingsType aType,
|
|
|
|
const WidgetKeyboardEvent& aEvent,
|
|
|
|
DoCommandCallback aCallback,
|
|
|
|
void* aCallbackData)
|
|
|
|
{
|
2014-03-14 17:13:32 +04:00
|
|
|
NativeKeyBindings* keyBindings = NativeKeyBindings::GetInstance(aType);
|
2014-03-14 17:13:32 +04:00
|
|
|
return keyBindings->Execute(aEvent, aCallback, aCallbackData);
|
2014-03-14 17:13:31 +04:00
|
|
|
}
|
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
@implementation WindowDelegate
|
|
|
|
|
2006-12-19 22:26:41 +03:00
|
|
|
// We try to find a gecko menu bar to paint. If one does not exist, just paint
|
|
|
|
// the application menu by itself so that a window doesn't have some other
|
|
|
|
// window's menu bar.
|
|
|
|
+ (void)paintMenubarForWindow:(NSWindow*)aWindow
|
2008-02-21 02:47:05 +03:00
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2006-12-19 22:26:41 +03:00
|
|
|
// make sure we only act on windows that have this kind of
|
|
|
|
// object as a delegate
|
|
|
|
id windowDelegate = [aWindow delegate];
|
|
|
|
if ([windowDelegate class] != [self class])
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsCocoaWindow* geckoWidget = [windowDelegate geckoWidget];
|
|
|
|
NS_ASSERTION(geckoWidget, "Window delegate not returning a gecko widget!");
|
|
|
|
|
2008-06-28 11:55:30 +04:00
|
|
|
nsMenuBarX* geckoMenuBar = geckoWidget->GetMenuBar();
|
2006-12-19 22:26:41 +03:00
|
|
|
if (geckoMenuBar) {
|
|
|
|
geckoMenuBar->Paint();
|
|
|
|
}
|
|
|
|
else {
|
2006-12-20 01:54:14 +03:00
|
|
|
// sometimes we don't have a native application menu early in launching
|
|
|
|
if (!sApplicationMenu)
|
|
|
|
return;
|
2006-12-19 22:26:41 +03:00
|
|
|
|
2007-11-16 05:54:00 +03:00
|
|
|
NSMenu* mainMenu = [NSApp mainMenu];
|
|
|
|
NS_ASSERTION([mainMenu numberOfItems] > 0, "Main menu does not have any items, something is terribly wrong!");
|
|
|
|
|
2008-04-08 08:38:52 +04:00
|
|
|
// Create a new menu bar.
|
|
|
|
// We create a GeckoNSMenu because all menu bar NSMenu objects should use that subclass for
|
|
|
|
// key handling reasons.
|
|
|
|
GeckoNSMenu* newMenuBar = [[GeckoNSMenu alloc] initWithTitle:@"MainMenuBar"];
|
2007-11-16 05:54:00 +03:00
|
|
|
|
|
|
|
// move the application menu from the existing menu bar to the new one
|
|
|
|
NSMenuItem* firstMenuItem = [[mainMenu itemAtIndex:0] retain];
|
|
|
|
[mainMenu removeItemAtIndex:0];
|
|
|
|
[newMenuBar insertItem:firstMenuItem atIndex:0];
|
|
|
|
[firstMenuItem release];
|
2006-12-19 22:26:41 +03:00
|
|
|
|
|
|
|
// set our new menu bar as the main menu
|
|
|
|
[NSApp setMainMenu:newMenuBar];
|
|
|
|
[newMenuBar release];
|
|
|
|
}
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2006-12-19 22:26:41 +03:00
|
|
|
}
|
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
- (id)initWithGeckoWindow:(nsCocoaWindow*)geckoWind
|
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
[super init];
|
|
|
|
mGeckoWindow = geckoWind;
|
2011-10-01 04:20:33 +04:00
|
|
|
mToplevelActiveState = false;
|
|
|
|
mHasEverBeenZoomed = false;
|
2001-11-06 18:35:24 +03:00
|
|
|
return self;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2006-04-06 23:14:02 +04:00
|
|
|
- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)proposedFrameSize
|
|
|
|
{
|
2007-06-13 00:26:24 +04:00
|
|
|
RollUpPopups();
|
2006-04-06 23:14:02 +04:00
|
|
|
|
|
|
|
return proposedFrameSize;
|
|
|
|
}
|
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
- (void)windowDidResize:(NSNotification *)aNotification
|
|
|
|
{
|
2011-08-08 18:43:13 +04:00
|
|
|
BaseWindow* window = [aNotification object];
|
|
|
|
[window updateTrackingArea];
|
|
|
|
|
2010-11-27 16:52:33 +03:00
|
|
|
if (!mGeckoWindow)
|
2006-03-07 23:02:09 +03:00
|
|
|
return;
|
2007-09-17 18:41:59 +04:00
|
|
|
|
2009-08-14 02:02:54 +04:00
|
|
|
// Resizing might have changed our zoom state.
|
|
|
|
mGeckoWindow->DispatchSizeModeEvent();
|
2007-09-17 18:41:59 +04:00
|
|
|
mGeckoWindow->ReportSizeEvent();
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2011-12-24 04:36:20 +04:00
|
|
|
- (void)windowDidChangeScreen:(NSNotification *)aNotification
|
|
|
|
{
|
|
|
|
if (!mGeckoWindow)
|
|
|
|
return;
|
|
|
|
|
2013-04-12 11:45:50 +04:00
|
|
|
// Because of Cocoa's peculiar treatment of zero-size windows (see comments
|
|
|
|
// at GetBackingScaleFactor() above), we sometimes have a situation where
|
|
|
|
// our concept of backing scale (based on the screen where the zero-sized
|
|
|
|
// window is positioned) differs from Cocoa's idea (always based on the
|
|
|
|
// Retina screen, AFAICT, even when an external non-Retina screen is the
|
|
|
|
// primary display).
|
|
|
|
//
|
|
|
|
// As a result, if the window was created with zero size on an external
|
|
|
|
// display, but then made visible on the (secondary) Retina screen, we
|
|
|
|
// will *not* get a windowDidChangeBackingProperties notification for it.
|
|
|
|
// This leads to an incorrect GetDefaultScale(), and widget coordinate
|
|
|
|
// confusion, as per bug 853252.
|
|
|
|
//
|
|
|
|
// To work around this, we check for a backing scale mismatch when we
|
|
|
|
// receive a windowDidChangeScreen notification, as we will receive this
|
|
|
|
// even if Cocoa was already treating the zero-size window as having
|
|
|
|
// Retina backing scale.
|
|
|
|
NSWindow *window = (NSWindow *)[aNotification object];
|
|
|
|
if ([window respondsToSelector:@selector(backingScaleFactor)]) {
|
|
|
|
if (GetBackingScaleFactor(window) != mGeckoWindow->BackingScaleFactor()) {
|
|
|
|
mGeckoWindow->BackingScaleFactorChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-24 04:36:20 +04:00
|
|
|
mGeckoWindow->ReportMoveEvent();
|
|
|
|
}
|
|
|
|
|
2012-03-21 03:21:14 +04:00
|
|
|
// Lion's full screen mode will bypass our internal fullscreen tracking, so
|
|
|
|
// we need to catch it when we transition and call our own methods, which in
|
|
|
|
// turn will fire "fullscreen" events.
|
|
|
|
- (void)windowDidEnterFullScreen:(NSNotification *)notification
|
|
|
|
{
|
|
|
|
if (!mGeckoWindow) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mGeckoWindow->EnteredFullScreen(true);
|
2014-10-14 02:05:59 +04:00
|
|
|
|
|
|
|
// On Yosemite, the NSThemeFrame class has two new properties --
|
|
|
|
// titlebarView (an NSTitlebarView object) and titlebarContainerView (an
|
|
|
|
// NSTitlebarContainerView object). These are used to display the titlebar
|
|
|
|
// in fullscreen mode. In Safari they're not transparent. But in Firefox
|
|
|
|
// for some reason they are, which causes bug 1069658. The following code
|
|
|
|
// works around this Apple bug or design flaw.
|
|
|
|
NSWindow *window = (NSWindow *) [notification object];
|
|
|
|
NSView *frameView = [[window contentView] superview];
|
|
|
|
NSView *titlebarView = nil;
|
|
|
|
NSView *titlebarContainerView = nil;
|
|
|
|
if ([frameView respondsToSelector:@selector(titlebarView)]) {
|
|
|
|
titlebarView = [frameView titlebarView];
|
|
|
|
}
|
|
|
|
if ([frameView respondsToSelector:@selector(titlebarContainerView)]) {
|
|
|
|
titlebarContainerView = [frameView titlebarContainerView];
|
|
|
|
}
|
|
|
|
if ([titlebarView respondsToSelector:@selector(setTransparent:)]) {
|
|
|
|
[titlebarView setTransparent:NO];
|
|
|
|
}
|
|
|
|
if ([titlebarContainerView respondsToSelector:@selector(setTransparent:)]) {
|
|
|
|
[titlebarContainerView setTransparent:NO];
|
|
|
|
}
|
2012-03-21 03:21:14 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)windowDidExitFullScreen:(NSNotification *)notification
|
|
|
|
{
|
|
|
|
if (!mGeckoWindow) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mGeckoWindow->EnteredFullScreen(false);
|
|
|
|
}
|
|
|
|
|
2012-03-29 23:18:50 +04:00
|
|
|
- (void)windowDidFailToEnterFullScreen:(NSWindow *)window
|
|
|
|
{
|
|
|
|
if (!mGeckoWindow) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mGeckoWindow->EnteredFullScreen(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)windowDidFailToExitFullScreen:(NSWindow *)window
|
|
|
|
{
|
|
|
|
if (!mGeckoWindow) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
mGeckoWindow->EnteredFullScreen(true);
|
|
|
|
}
|
|
|
|
|
2001-11-06 18:35:24 +03:00
|
|
|
- (void)windowDidBecomeMain:(NSNotification *)aNotification
|
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-06-13 00:26:24 +04:00
|
|
|
RollUpPopups();
|
2009-12-12 00:56:59 +03:00
|
|
|
ChildViewMouseTracker::ReEvaluateMouseEnterState();
|
2007-05-18 06:06:59 +04:00
|
|
|
|
2008-03-27 06:42:57 +03:00
|
|
|
// [NSApp _isRunningAppModal] will return true if we're running an OS dialog
|
|
|
|
// app modally. If one of those is up then we want it to retain its menu bar.
|
|
|
|
if ([NSApp _isRunningAppModal])
|
|
|
|
return;
|
2006-12-19 22:26:41 +03:00
|
|
|
NSWindow* window = [aNotification object];
|
|
|
|
if (window)
|
|
|
|
[WindowDelegate paintMenubarForWindow:window];
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)windowDidResignMain:(NSNotification *)aNotification
|
|
|
|
{
|
2007-06-13 00:26:24 +04:00
|
|
|
RollUpPopups();
|
2009-12-12 00:56:59 +03:00
|
|
|
ChildViewMouseTracker::ReEvaluateMouseEnterState();
|
2008-03-27 06:42:57 +03:00
|
|
|
|
|
|
|
// [NSApp _isRunningAppModal] will return true if we're running an OS dialog
|
|
|
|
// app modally. If one of those is up then we want it to retain its menu bar.
|
|
|
|
if ([NSApp _isRunningAppModal])
|
|
|
|
return;
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsMenuBarX> hiddenWindowMenuBar = nsMenuUtilsX::GetHiddenWindowMenuBar();
|
2006-04-06 11:41:34 +04:00
|
|
|
if (hiddenWindowMenuBar) {
|
2006-04-22 00:35:00 +04:00
|
|
|
// printf("painting hidden window menu bar due to window losing main status\n");
|
2006-04-06 11:41:34 +04:00
|
|
|
hiddenWindowMenuBar->Paint();
|
|
|
|
}
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2006-12-19 22:26:41 +03:00
|
|
|
- (void)windowDidBecomeKey:(NSNotification *)aNotification
|
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2009-10-06 06:59:23 +04:00
|
|
|
RollUpPopups();
|
2009-12-12 00:56:59 +03:00
|
|
|
ChildViewMouseTracker::ReEvaluateMouseEnterState();
|
2009-10-06 06:59:23 +04:00
|
|
|
|
2006-12-19 22:26:41 +03:00
|
|
|
NSWindow* window = [aNotification object];
|
|
|
|
if ([window isSheet])
|
|
|
|
[WindowDelegate paintMenubarForWindow:window];
|
2008-02-21 02:47:05 +03:00
|
|
|
|
2015-09-01 21:56:23 +03:00
|
|
|
nsChildView* mainChildView =
|
|
|
|
static_cast<nsChildView*>([[(BaseWindow*)window mainChildView] widget]);
|
|
|
|
if (mainChildView) {
|
|
|
|
if (mainChildView->GetInputContext().IsPasswordEditor()) {
|
|
|
|
TextInputHandler::EnableSecureEventInput();
|
|
|
|
} else {
|
|
|
|
TextInputHandler::EnsureSecureEventInputDisabled();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2006-12-19 22:26:41 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)windowDidResignKey:(NSNotification *)aNotification
|
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2009-10-06 06:59:23 +04:00
|
|
|
RollUpPopups();
|
2009-12-12 00:56:59 +03:00
|
|
|
ChildViewMouseTracker::ReEvaluateMouseEnterState();
|
2009-10-06 06:59:23 +04:00
|
|
|
|
2006-12-19 22:26:41 +03:00
|
|
|
// If a sheet just resigned key then we should paint the menu bar
|
|
|
|
// for whatever window is now main.
|
|
|
|
NSWindow* window = [aNotification object];
|
|
|
|
if ([window isSheet])
|
|
|
|
[WindowDelegate paintMenubarForWindow:[NSApp mainWindow]];
|
2008-02-21 02:47:05 +03:00
|
|
|
|
2015-03-19 05:08:22 +03:00
|
|
|
TextInputHandler::EnsureSecureEventInputDisabled();
|
|
|
|
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2006-12-19 22:26:41 +03:00
|
|
|
}
|
|
|
|
|
2006-03-07 23:02:09 +03:00
|
|
|
- (void)windowWillMove:(NSNotification *)aNotification
|
2001-11-06 18:35:24 +03:00
|
|
|
{
|
2007-06-13 00:26:24 +04:00
|
|
|
RollUpPopups();
|
2001-11-06 18:35:24 +03:00
|
|
|
}
|
|
|
|
|
2007-05-11 03:54:05 +04:00
|
|
|
- (void)windowDidMove:(NSNotification *)aNotification
|
|
|
|
{
|
2010-07-27 17:38:04 +04:00
|
|
|
if (mGeckoWindow)
|
|
|
|
mGeckoWindow->ReportMoveEvent();
|
2007-05-11 03:54:05 +04:00
|
|
|
}
|
2001-11-06 18:35:24 +03:00
|
|
|
|
2006-03-17 08:16:59 +03:00
|
|
|
- (BOOL)windowShouldClose:(id)sender
|
2006-02-23 02:15:25 +03:00
|
|
|
{
|
2012-08-15 22:52:42 +04:00
|
|
|
nsIWidgetListener* listener = mGeckoWindow ? mGeckoWindow->GetWidgetListener() : nullptr;
|
|
|
|
if (listener)
|
|
|
|
listener->RequestWindowClose(mGeckoWindow);
|
2006-03-17 08:16:59 +03:00
|
|
|
return NO; // gecko will do it
|
|
|
|
}
|
|
|
|
|
2006-04-25 23:20:31 +04:00
|
|
|
- (void)windowWillClose:(NSNotification *)aNotification
|
2006-03-17 08:16:59 +03:00
|
|
|
{
|
2007-06-13 00:26:24 +04:00
|
|
|
RollUpPopups();
|
2006-02-23 02:15:25 +03:00
|
|
|
}
|
|
|
|
|
2006-03-07 23:02:09 +03:00
|
|
|
- (void)windowWillMiniaturize:(NSNotification *)aNotification
|
|
|
|
{
|
2007-06-13 00:26:24 +04:00
|
|
|
RollUpPopups();
|
2006-03-07 23:02:09 +03:00
|
|
|
}
|
|
|
|
|
2008-09-10 20:57:57 +04:00
|
|
|
- (void)windowDidMiniaturize:(NSNotification *)aNotification
|
|
|
|
{
|
|
|
|
if (mGeckoWindow)
|
2009-08-14 02:02:54 +04:00
|
|
|
mGeckoWindow->DispatchSizeModeEvent();
|
2008-09-10 20:57:57 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)windowDidDeminiaturize:(NSNotification *)aNotification
|
|
|
|
{
|
|
|
|
if (mGeckoWindow)
|
2009-08-14 02:02:54 +04:00
|
|
|
mGeckoWindow->DispatchSizeModeEvent();
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)proposedFrame
|
|
|
|
{
|
|
|
|
if (!mHasEverBeenZoomed && [window isZoomed])
|
|
|
|
return NO; // See bug 429954.
|
|
|
|
|
|
|
|
mHasEverBeenZoomed = YES;
|
|
|
|
return YES;
|
2008-09-10 20:57:57 +04:00
|
|
|
}
|
|
|
|
|
2006-06-08 21:29:18 +04:00
|
|
|
- (void)didEndSheet:(NSWindow*)sheet returnCode:(int)returnCode contextInfo:(void*)contextInfo
|
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2008-05-08 01:15:57 +04:00
|
|
|
// Note: 'contextInfo' (if it is set) is the window that is the parent of
|
|
|
|
// the sheet. The value of contextInfo is determined in
|
|
|
|
// nsCocoaWindow::Show(). If it's set, 'contextInfo' is always the top-
|
|
|
|
// level window, not another sheet itself. But 'contextInfo' is nil if
|
|
|
|
// our parent window is also a sheet -- in that case we shouldn't send
|
|
|
|
// the top-level window any activate events (because it's our parent
|
|
|
|
// window that needs to get these events, not the top-level window).
|
2008-05-02 14:40:49 +04:00
|
|
|
[TopLevelWindowData deactivateInWindow:sheet];
|
2006-06-08 21:29:18 +04:00
|
|
|
[sheet orderOut:self];
|
2008-05-08 01:15:57 +04:00
|
|
|
if (contextInfo)
|
|
|
|
[TopLevelWindowData activateInWindow:(NSWindow*)contextInfo];
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2006-06-08 21:29:18 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 23:41:20 +04:00
|
|
|
- (void)windowDidChangeBackingProperties:(NSNotification *)aNotification
|
|
|
|
{
|
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
|
|
|
NSWindow *window = (NSWindow *)[aNotification object];
|
|
|
|
|
|
|
|
if ([window respondsToSelector:@selector(backingScaleFactor)]) {
|
|
|
|
CGFloat oldFactor =
|
|
|
|
[[[aNotification userInfo]
|
|
|
|
objectForKey:@"NSBackingPropertyOldScaleFactorKey"] doubleValue];
|
|
|
|
if ([window backingScaleFactor] != oldFactor) {
|
|
|
|
mGeckoWindow->BackingScaleFactorChanged();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
|
|
|
}
|
|
|
|
|
2007-04-18 02:32:40 +04:00
|
|
|
- (nsCocoaWindow*)geckoWidget
|
2006-12-19 22:26:41 +03:00
|
|
|
{
|
|
|
|
return mGeckoWindow;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
- (bool)toplevelActiveState
|
2008-05-02 14:40:49 +04:00
|
|
|
{
|
|
|
|
return mToplevelActiveState;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)sendToplevelActivateEvents
|
|
|
|
{
|
2012-08-15 22:52:42 +04:00
|
|
|
if (!mToplevelActiveState && mGeckoWindow) {
|
|
|
|
nsIWidgetListener* listener = mGeckoWindow->GetWidgetListener();
|
2014-12-11 17:44:07 +03:00
|
|
|
if (listener) {
|
2012-08-15 22:52:42 +04:00
|
|
|
listener->WindowActivated();
|
2014-12-11 17:44:07 +03:00
|
|
|
}
|
2011-10-01 04:20:33 +04:00
|
|
|
mToplevelActiveState = true;
|
2008-05-02 14:40:49 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)sendToplevelDeactivateEvents
|
|
|
|
{
|
2012-08-15 22:52:42 +04:00
|
|
|
if (mToplevelActiveState && mGeckoWindow) {
|
|
|
|
nsIWidgetListener* listener = mGeckoWindow->GetWidgetListener();
|
2014-12-11 17:44:07 +03:00
|
|
|
if (listener) {
|
2012-08-15 22:52:42 +04:00
|
|
|
listener->WindowDeactivated();
|
2014-12-11 17:44:07 +03:00
|
|
|
}
|
2011-10-01 04:20:33 +04:00
|
|
|
mToplevelActiveState = false;
|
2008-05-02 14:40:49 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-05-31 09:07:18 +04:00
|
|
|
@end
|
|
|
|
|
2010-08-19 13:35:08 +04:00
|
|
|
static float
|
|
|
|
GetDPI(NSWindow* aWindow)
|
|
|
|
{
|
|
|
|
NSScreen* screen = [aWindow screen];
|
|
|
|
if (!screen)
|
|
|
|
return 96.0f;
|
|
|
|
|
|
|
|
CGDirectDisplayID displayID =
|
|
|
|
[[[screen deviceDescription] objectForKey:@"NSScreenNumber"] intValue];
|
|
|
|
CGFloat heightMM = ::CGDisplayScreenSize(displayID).height;
|
|
|
|
size_t heightPx = ::CGDisplayPixelsHigh(displayID);
|
2014-05-28 17:22:16 +04:00
|
|
|
if (heightMM < 1 || heightPx < 1) {
|
2010-08-19 13:35:08 +04:00
|
|
|
// Something extremely bogus is going on
|
|
|
|
return 96.0f;
|
|
|
|
}
|
|
|
|
|
2014-05-28 17:22:16 +04:00
|
|
|
float dpi = heightPx / (heightMM / MM_PER_INCH_FLOAT);
|
2012-09-29 15:36:09 +04:00
|
|
|
|
|
|
|
// Account for HiDPI mode where Cocoa's "points" do not correspond to real
|
|
|
|
// device pixels
|
2012-12-14 13:46:16 +04:00
|
|
|
CGFloat backingScale = GetBackingScaleFactor(aWindow);
|
2012-09-29 15:36:09 +04:00
|
|
|
|
|
|
|
return dpi * backingScale;
|
2010-08-19 13:35:08 +04:00
|
|
|
}
|
|
|
|
|
2013-06-13 01:42:00 +04:00
|
|
|
@interface NSView(FrameViewMethodSwizzling)
|
|
|
|
- (NSPoint)FrameView__closeButtonOrigin;
|
|
|
|
- (NSPoint)FrameView__fullScreenButtonOrigin;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation NSView(FrameViewMethodSwizzling)
|
|
|
|
|
|
|
|
- (NSPoint)FrameView__closeButtonOrigin
|
|
|
|
{
|
|
|
|
NSPoint defaultPosition = [self FrameView__closeButtonOrigin];
|
|
|
|
if ([[self window] isKindOfClass:[ToolbarWindow class]]) {
|
|
|
|
return [(ToolbarWindow*)[self window] windowButtonsPositionWithDefaultPosition:defaultPosition];
|
|
|
|
}
|
|
|
|
return defaultPosition;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSPoint)FrameView__fullScreenButtonOrigin
|
|
|
|
{
|
|
|
|
NSPoint defaultPosition = [self FrameView__fullScreenButtonOrigin];
|
|
|
|
if ([[self window] isKindOfClass:[ToolbarWindow class]]) {
|
|
|
|
return [(ToolbarWindow*)[self window] fullScreenButtonPositionWithDefaultPosition:defaultPosition];
|
|
|
|
}
|
|
|
|
return defaultPosition;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
|
|
|
static NSMutableSet *gSwizzledFrameViewClasses = nil;
|
|
|
|
|
2014-01-08 13:37:59 +04:00
|
|
|
@interface NSWindow(PrivateSetNeedsDisplayInRectMethod)
|
|
|
|
- (void)_setNeedsDisplayInRect:(NSRect)aRect;
|
|
|
|
@end
|
|
|
|
|
2014-11-18 19:36:07 +03:00
|
|
|
// This method is on NSThemeFrame starting with 10.10, but since NSThemeFrame
|
|
|
|
// is not a public class, we declare the method on NSView instead. We only have
|
|
|
|
// this declaration in order to avoid compiler warnings.
|
|
|
|
@interface NSView(PrivateAddKnownSubviewMethod)
|
2014-11-20 21:23:41 +03:00
|
|
|
- (void)_addKnownSubview:(NSView*)aView positioned:(NSWindowOrderingMode)place relativeTo:(NSView*)otherView;
|
2014-11-18 19:36:07 +03:00
|
|
|
@end
|
|
|
|
|
2015-02-05 01:25:19 +03:00
|
|
|
// Available on 10.10
|
|
|
|
@interface NSWindow(PrivateCornerMaskMethod)
|
|
|
|
- (id)_cornerMask;
|
|
|
|
- (void)_cornerMaskChanged;
|
|
|
|
@end
|
|
|
|
|
|
|
|
#if !defined(MAC_OS_X_VERSION_10_10) || \
|
|
|
|
MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_10
|
|
|
|
|
|
|
|
@interface NSImage(CapInsets)
|
|
|
|
- (void)setCapInsets:(NSEdgeInsets)capInsets;
|
|
|
|
@end
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !defined(MAC_OS_X_VERSION_10_8) || \
|
|
|
|
MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_8
|
|
|
|
|
|
|
|
@interface NSImage(ImageCreationWithDrawingHandler)
|
|
|
|
+ (NSImage *)imageWithSize:(NSSize)size
|
|
|
|
flipped:(BOOL)drawingHandlerShouldBeCalledWithFlippedContext
|
|
|
|
drawingHandler:(BOOL (^)(NSRect dstRect))drawingHandler;
|
|
|
|
@end
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2011-08-08 18:43:13 +04:00
|
|
|
@interface BaseWindow(Private)
|
|
|
|
- (void)removeTrackingArea;
|
|
|
|
- (void)cursorUpdated:(NSEvent*)aEvent;
|
2013-05-23 18:49:17 +04:00
|
|
|
- (void)updateContentViewSize;
|
2013-06-13 01:42:00 +04:00
|
|
|
- (void)reflowTitlebarElements;
|
2011-08-08 18:43:13 +04:00
|
|
|
@end
|
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
@implementation BaseWindow
|
2007-10-30 07:03:42 +03:00
|
|
|
|
2015-02-05 01:25:19 +03:00
|
|
|
- (id)_cornerMask
|
|
|
|
{
|
|
|
|
if (!mUseMenuStyle) {
|
|
|
|
return [super _cornerMask];
|
|
|
|
}
|
|
|
|
|
|
|
|
CGFloat radius = 4.0f;
|
|
|
|
NSEdgeInsets insets = { 5, 5, 5, 5 };
|
|
|
|
NSSize maskSize = { 12, 12 };
|
|
|
|
NSImage* maskImage = [NSImage imageWithSize:maskSize flipped:YES drawingHandler:^BOOL(NSRect dstRect) {
|
|
|
|
NSBezierPath *path = [NSBezierPath bezierPathWithRoundedRect:dstRect xRadius:radius yRadius:radius];
|
|
|
|
[[NSColor colorWithDeviceWhite:1.0 alpha:1.0] set];
|
|
|
|
[path fill];
|
|
|
|
return YES;
|
|
|
|
}];
|
|
|
|
[maskImage setCapInsets:insets];
|
|
|
|
return maskImage;
|
|
|
|
}
|
|
|
|
|
2013-06-13 01:42:00 +04:00
|
|
|
// The frame of a window is implemented using undocumented NSView subclasses.
|
|
|
|
// We offset the window buttons by overriding the methods _closeButtonOrigin
|
|
|
|
// and _fullScreenButtonOrigin on these frame view classes. The class which is
|
|
|
|
// used for a window is determined in the window's frameViewClassForStyleMask:
|
|
|
|
// method, so this is where we make sure that we have swizzled the method on
|
|
|
|
// all encountered classes.
|
|
|
|
+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask
|
|
|
|
{
|
|
|
|
Class frameViewClass = [super frameViewClassForStyleMask:styleMask];
|
|
|
|
|
|
|
|
if (!gSwizzledFrameViewClasses) {
|
|
|
|
gSwizzledFrameViewClasses = [[NSMutableSet setWithCapacity:3] retain];
|
|
|
|
if (!gSwizzledFrameViewClasses) {
|
|
|
|
return frameViewClass;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static IMP our_closeButtonOrigin =
|
|
|
|
class_getMethodImplementation([NSView class],
|
|
|
|
@selector(FrameView__closeButtonOrigin));
|
|
|
|
static IMP our_fullScreenButtonOrigin =
|
|
|
|
class_getMethodImplementation([NSView class],
|
|
|
|
@selector(FrameView__fullScreenButtonOrigin));
|
|
|
|
|
|
|
|
if (![gSwizzledFrameViewClasses containsObject:frameViewClass]) {
|
|
|
|
// Either of these methods might be implemented in both a subclass of
|
|
|
|
// NSFrameView and one of its own subclasses. Which means that if we
|
|
|
|
// aren't careful we might end up swizzling the same method twice.
|
|
|
|
// Since method swizzling involves swapping pointers, this would break
|
|
|
|
// things.
|
|
|
|
IMP _closeButtonOrigin =
|
|
|
|
class_getMethodImplementation(frameViewClass,
|
|
|
|
@selector(_closeButtonOrigin));
|
|
|
|
if (_closeButtonOrigin && _closeButtonOrigin != our_closeButtonOrigin) {
|
|
|
|
nsToolkit::SwizzleMethods(frameViewClass, @selector(_closeButtonOrigin),
|
|
|
|
@selector(FrameView__closeButtonOrigin));
|
|
|
|
}
|
|
|
|
IMP _fullScreenButtonOrigin =
|
|
|
|
class_getMethodImplementation(frameViewClass,
|
|
|
|
@selector(_fullScreenButtonOrigin));
|
|
|
|
if (_fullScreenButtonOrigin &&
|
|
|
|
_fullScreenButtonOrigin != our_fullScreenButtonOrigin) {
|
|
|
|
nsToolkit::SwizzleMethods(frameViewClass, @selector(_fullScreenButtonOrigin),
|
|
|
|
@selector(FrameView__fullScreenButtonOrigin));
|
|
|
|
}
|
|
|
|
[gSwizzledFrameViewClasses addObject:frameViewClass];
|
|
|
|
}
|
|
|
|
|
|
|
|
return frameViewClass;
|
|
|
|
}
|
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
- (id)initWithContentRect:(NSRect)aContentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)aBufferingType defer:(BOOL)aFlag
|
2007-10-30 07:03:42 +03:00
|
|
|
{
|
2013-05-23 18:49:17 +04:00
|
|
|
mDrawsIntoWindowFrame = NO;
|
2009-11-02 22:07:57 +03:00
|
|
|
[super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag];
|
|
|
|
mState = nil;
|
|
|
|
mActiveTitlebarColor = nil;
|
|
|
|
mInactiveTitlebarColor = nil;
|
2009-12-12 00:53:22 +03:00
|
|
|
mScheduledShadowInvalidation = NO;
|
2014-01-08 13:37:59 +04:00
|
|
|
mDisabledNeedsDisplay = NO;
|
2010-08-19 13:35:08 +04:00
|
|
|
mDPI = GetDPI(self);
|
2011-08-08 18:43:13 +04:00
|
|
|
mTrackingArea = nil;
|
2014-11-07 21:11:48 +03:00
|
|
|
mDirtyRect = NSZeroRect;
|
2013-10-09 18:39:22 +04:00
|
|
|
mBeingShown = NO;
|
2013-12-17 20:11:13 +04:00
|
|
|
mDrawTitle = NO;
|
2014-11-04 06:14:10 +03:00
|
|
|
mBrightTitlebarForeground = NO;
|
2015-02-05 01:25:19 +03:00
|
|
|
mUseMenuStyle = NO;
|
2011-08-08 18:43:13 +04:00
|
|
|
[self updateTrackingArea];
|
2010-08-19 13:35:08 +04:00
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
return self;
|
|
|
|
}
|
2008-02-21 02:47:05 +03:00
|
|
|
|
2015-02-05 01:25:19 +03:00
|
|
|
- (void)setUseMenuStyle:(BOOL)aValue
|
|
|
|
{
|
|
|
|
if (aValue != mUseMenuStyle) {
|
|
|
|
mUseMenuStyle = aValue;
|
|
|
|
if ([self respondsToSelector:@selector(_cornerMaskChanged)]) {
|
|
|
|
[self _cornerMaskChanged];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-25 22:00:55 +04:00
|
|
|
- (void)setBeingShown:(BOOL)aValue
|
2013-10-09 18:39:22 +04:00
|
|
|
{
|
2013-11-25 22:00:55 +04:00
|
|
|
mBeingShown = aValue;
|
2013-10-09 18:39:22 +04:00
|
|
|
}
|
|
|
|
|
2014-02-03 20:54:55 +04:00
|
|
|
- (BOOL)isBeingShown
|
|
|
|
{
|
|
|
|
return mBeingShown;
|
|
|
|
}
|
|
|
|
|
2013-11-25 22:00:55 +04:00
|
|
|
- (BOOL)isVisibleOrBeingShown
|
2013-10-09 18:39:22 +04:00
|
|
|
{
|
2013-11-25 22:00:55 +04:00
|
|
|
return [super isVisible] || mBeingShown;
|
2013-10-09 18:39:22 +04:00
|
|
|
}
|
|
|
|
|
2014-01-08 13:37:59 +04:00
|
|
|
- (void)disableSetNeedsDisplay
|
|
|
|
{
|
|
|
|
mDisabledNeedsDisplay = YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)enableSetNeedsDisplay
|
|
|
|
{
|
|
|
|
mDisabledNeedsDisplay = NO;
|
|
|
|
}
|
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
- (void)dealloc
|
|
|
|
{
|
|
|
|
[mActiveTitlebarColor release];
|
|
|
|
[mInactiveTitlebarColor release];
|
2011-08-08 18:43:13 +04:00
|
|
|
[self removeTrackingArea];
|
|
|
|
ChildViewMouseTracker::OnDestroyWindow(self);
|
2009-11-02 22:07:57 +03:00
|
|
|
[super dealloc];
|
|
|
|
}
|
2008-02-21 02:47:05 +03:00
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
static const NSString* kStateTitleKey = @"title";
|
|
|
|
static const NSString* kStateDrawsContentsIntoWindowFrameKey = @"drawsContentsIntoWindowFrame";
|
|
|
|
static const NSString* kStateActiveTitlebarColorKey = @"activeTitlebarColor";
|
|
|
|
static const NSString* kStateInactiveTitlebarColorKey = @"inactiveTitlebarColor";
|
2009-12-30 18:24:03 +03:00
|
|
|
static const NSString* kStateShowsToolbarButton = @"showsToolbarButton";
|
2015-06-04 04:49:34 +03:00
|
|
|
static const NSString* kStateCollectionBehavior = @"collectionBehavior";
|
2009-11-02 22:07:57 +03:00
|
|
|
|
|
|
|
- (void)importState:(NSDictionary*)aState
|
|
|
|
{
|
|
|
|
[self setTitle:[aState objectForKey:kStateTitleKey]];
|
|
|
|
[self setDrawsContentsIntoWindowFrame:[[aState objectForKey:kStateDrawsContentsIntoWindowFrameKey] boolValue]];
|
|
|
|
[self setTitlebarColor:[aState objectForKey:kStateActiveTitlebarColorKey] forActiveWindow:YES];
|
|
|
|
[self setTitlebarColor:[aState objectForKey:kStateInactiveTitlebarColorKey] forActiveWindow:NO];
|
2009-12-30 18:24:03 +03:00
|
|
|
[self setShowsToolbarButton:[[aState objectForKey:kStateShowsToolbarButton] boolValue]];
|
2015-06-04 04:49:34 +03:00
|
|
|
[self setCollectionBehavior:[[aState objectForKey:kStateCollectionBehavior] unsignedIntValue]];
|
2009-11-02 22:07:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSMutableDictionary*)exportState
|
|
|
|
{
|
|
|
|
NSMutableDictionary* state = [NSMutableDictionary dictionaryWithCapacity:10];
|
|
|
|
[state setObject:[self title] forKey:kStateTitleKey];
|
|
|
|
[state setObject:[NSNumber numberWithBool:[self drawsContentsIntoWindowFrame]]
|
|
|
|
forKey:kStateDrawsContentsIntoWindowFrameKey];
|
|
|
|
NSColor* activeTitlebarColor = [self titlebarColorForActiveWindow:YES];
|
|
|
|
if (activeTitlebarColor) {
|
|
|
|
[state setObject:activeTitlebarColor forKey:kStateActiveTitlebarColorKey];
|
|
|
|
}
|
|
|
|
NSColor* inactiveTitlebarColor = [self titlebarColorForActiveWindow:NO];
|
|
|
|
if (inactiveTitlebarColor) {
|
|
|
|
[state setObject:inactiveTitlebarColor forKey:kStateInactiveTitlebarColorKey];
|
|
|
|
}
|
2009-12-30 18:24:03 +03:00
|
|
|
[state setObject:[NSNumber numberWithBool:[self showsToolbarButton]]
|
|
|
|
forKey:kStateShowsToolbarButton];
|
2015-06-04 04:49:34 +03:00
|
|
|
[state setObject:[NSNumber numberWithUnsignedInt: [self collectionBehavior]]
|
|
|
|
forKey:kStateCollectionBehavior];
|
2009-11-02 22:07:57 +03:00
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState
|
|
|
|
{
|
2013-06-13 01:42:00 +04:00
|
|
|
bool changed = (aState != mDrawsIntoWindowFrame);
|
2009-11-02 22:07:57 +03:00
|
|
|
mDrawsIntoWindowFrame = aState;
|
2013-06-13 01:42:00 +04:00
|
|
|
if (changed) {
|
|
|
|
[self updateContentViewSize];
|
|
|
|
[self reflowTitlebarElements];
|
|
|
|
}
|
2009-11-02 22:07:57 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)drawsContentsIntoWindowFrame
|
|
|
|
{
|
|
|
|
return mDrawsIntoWindowFrame;
|
|
|
|
}
|
|
|
|
|
2013-12-17 20:11:13 +04:00
|
|
|
- (void)setWantsTitleDrawn:(BOOL)aDrawTitle
|
|
|
|
{
|
|
|
|
mDrawTitle = aDrawTitle;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)wantsTitleDrawn
|
|
|
|
{
|
|
|
|
return mDrawTitle;
|
|
|
|
}
|
|
|
|
|
2014-11-04 06:14:10 +03:00
|
|
|
- (void)setUseBrightTitlebarForeground:(BOOL)aBrightForeground
|
|
|
|
{
|
|
|
|
mBrightTitlebarForeground = aBrightForeground;
|
|
|
|
[[self standardWindowButton:NSWindowFullScreenButton] setNeedsDisplay:YES];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)useBrightTitlebarForeground
|
|
|
|
{
|
|
|
|
return mBrightTitlebarForeground;
|
|
|
|
}
|
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
// Pass nil here to get the default appearance.
|
|
|
|
- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive
|
|
|
|
{
|
|
|
|
[aColor retain];
|
|
|
|
if (aActive) {
|
|
|
|
[mActiveTitlebarColor release];
|
|
|
|
mActiveTitlebarColor = aColor;
|
|
|
|
} else {
|
|
|
|
[mInactiveTitlebarColor release];
|
|
|
|
mInactiveTitlebarColor = aColor;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSColor*)titlebarColorForActiveWindow:(BOOL)aActive
|
|
|
|
{
|
|
|
|
return aActive ? mActiveTitlebarColor : mInactiveTitlebarColor;
|
2007-10-30 07:03:42 +03:00
|
|
|
}
|
|
|
|
|
2009-12-12 00:53:22 +03:00
|
|
|
- (void)deferredInvalidateShadow
|
|
|
|
{
|
|
|
|
if (mScheduledShadowInvalidation || [self isOpaque] || ![self hasShadow])
|
|
|
|
return;
|
|
|
|
|
|
|
|
[self performSelector:@selector(invalidateShadow) withObject:nil afterDelay:0];
|
|
|
|
mScheduledShadowInvalidation = YES;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)invalidateShadow
|
|
|
|
{
|
|
|
|
[super invalidateShadow];
|
|
|
|
mScheduledShadowInvalidation = NO;
|
|
|
|
}
|
|
|
|
|
2010-08-19 13:35:08 +04:00
|
|
|
- (float)getDPI
|
|
|
|
{
|
|
|
|
return mDPI;
|
|
|
|
}
|
|
|
|
|
2011-08-08 18:43:13 +04:00
|
|
|
- (NSView*)trackingAreaView
|
|
|
|
{
|
|
|
|
NSView* contentView = [self contentView];
|
|
|
|
return [contentView superview] ? [contentView superview] : contentView;
|
|
|
|
}
|
|
|
|
|
2013-04-29 19:24:26 +04:00
|
|
|
- (ChildView*)mainChildView
|
|
|
|
{
|
|
|
|
NSView *contentView = [self contentView];
|
|
|
|
// A PopupWindow's contentView is a ChildView object.
|
|
|
|
if ([contentView isKindOfClass:[ChildView class]]) {
|
|
|
|
return (ChildView*)contentView;
|
|
|
|
}
|
|
|
|
NSView* lastView = [[contentView subviews] lastObject];
|
|
|
|
if ([lastView isKindOfClass:[ChildView class]]) {
|
|
|
|
return (ChildView*)lastView;
|
|
|
|
}
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
2011-08-08 18:43:13 +04:00
|
|
|
- (void)removeTrackingArea
|
|
|
|
{
|
|
|
|
if (mTrackingArea) {
|
|
|
|
[[self trackingAreaView] removeTrackingArea:mTrackingArea];
|
|
|
|
[mTrackingArea release];
|
|
|
|
mTrackingArea = nil;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)updateTrackingArea
|
|
|
|
{
|
|
|
|
[self removeTrackingArea];
|
|
|
|
|
|
|
|
NSView* view = [self trackingAreaView];
|
|
|
|
const NSTrackingAreaOptions options =
|
|
|
|
NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways;
|
|
|
|
mTrackingArea = [[NSTrackingArea alloc] initWithRect:[view bounds]
|
|
|
|
options:options
|
|
|
|
owner:self
|
|
|
|
userInfo:nil];
|
|
|
|
[view addTrackingArea:mTrackingArea];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)mouseEntered:(NSEvent*)aEvent
|
|
|
|
{
|
|
|
|
ChildViewMouseTracker::MouseEnteredWindow(aEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)mouseExited:(NSEvent*)aEvent
|
|
|
|
{
|
|
|
|
ChildViewMouseTracker::MouseExitedWindow(aEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)mouseMoved:(NSEvent*)aEvent
|
|
|
|
{
|
|
|
|
ChildViewMouseTracker::MouseMoved(aEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)cursorUpdated:(NSEvent*)aEvent
|
|
|
|
{
|
|
|
|
// Nothing to do here, but NSTrackingArea wants us to implement this method.
|
|
|
|
}
|
|
|
|
|
2014-01-08 13:37:59 +04:00
|
|
|
- (void)_setNeedsDisplayInRect:(NSRect)aRect
|
|
|
|
{
|
|
|
|
// Prevent unnecessary invalidations due to moving NSViews (e.g. for plugins)
|
|
|
|
if (!mDisabledNeedsDisplay) {
|
|
|
|
// This method is only called by Cocoa, so when we're here, we know that
|
|
|
|
// it's available and don't need to check whether our superclass responds
|
|
|
|
// to the selector.
|
|
|
|
[super _setNeedsDisplayInRect:aRect];
|
2014-11-07 21:11:48 +03:00
|
|
|
mDirtyRect = NSUnionRect(mDirtyRect, aRect);
|
2014-01-08 13:37:59 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-07 21:11:48 +03:00
|
|
|
- (NSRect)getAndResetNativeDirtyRect
|
|
|
|
{
|
|
|
|
NSRect dirtyRect = mDirtyRect;
|
|
|
|
mDirtyRect = NSZeroRect;
|
|
|
|
return dirtyRect;
|
|
|
|
}
|
|
|
|
|
2013-05-23 18:49:17 +04:00
|
|
|
- (void)updateContentViewSize
|
|
|
|
{
|
|
|
|
NSRect rect = [self contentRectForFrameRect:[self frame]];
|
|
|
|
[[self contentView] setFrameSize:rect.size];
|
|
|
|
}
|
|
|
|
|
2013-06-13 01:42:00 +04:00
|
|
|
// Possibly move the titlebar buttons.
|
|
|
|
- (void)reflowTitlebarElements
|
|
|
|
{
|
|
|
|
NSView *frameView = [[self contentView] superview];
|
|
|
|
if ([frameView respondsToSelector:@selector(_tileTitlebarAndRedisplay:)]) {
|
|
|
|
[frameView _tileTitlebarAndRedisplay:NO];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-23 18:49:17 +04:00
|
|
|
// Override methods that translate between content rect and frame rect.
|
|
|
|
- (NSRect)contentRectForFrameRect:(NSRect)aRect
|
|
|
|
{
|
|
|
|
if ([self drawsContentsIntoWindowFrame]) {
|
|
|
|
return aRect;
|
|
|
|
}
|
|
|
|
return [super contentRectForFrameRect:aRect];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRect)contentRectForFrameRect:(NSRect)aRect styleMask:(NSUInteger)aMask
|
|
|
|
{
|
|
|
|
if ([self drawsContentsIntoWindowFrame]) {
|
|
|
|
return aRect;
|
|
|
|
}
|
|
|
|
if ([super respondsToSelector:@selector(contentRectForFrameRect:styleMask:)]) {
|
|
|
|
return [super contentRectForFrameRect:aRect styleMask:aMask];
|
|
|
|
} else {
|
|
|
|
return [NSWindow contentRectForFrameRect:aRect styleMask:aMask];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRect)frameRectForContentRect:(NSRect)aRect
|
|
|
|
{
|
|
|
|
if ([self drawsContentsIntoWindowFrame]) {
|
|
|
|
return aRect;
|
|
|
|
}
|
|
|
|
return [super frameRectForContentRect:aRect];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRect)frameRectForContentRect:(NSRect)aRect styleMask:(NSUInteger)aMask
|
|
|
|
{
|
|
|
|
if ([self drawsContentsIntoWindowFrame]) {
|
|
|
|
return aRect;
|
|
|
|
}
|
|
|
|
if ([super respondsToSelector:@selector(frameRectForContentRect:styleMask:)]) {
|
|
|
|
return [super frameRectForContentRect:aRect styleMask:aMask];
|
|
|
|
} else {
|
|
|
|
return [NSWindow frameRectForContentRect:aRect styleMask:aMask];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setContentView:(NSView*)aView
|
|
|
|
{
|
|
|
|
[super setContentView:aView];
|
|
|
|
|
|
|
|
// Now move the contentView to the bottommost layer so that it's guaranteed
|
|
|
|
// to be under the window buttons.
|
|
|
|
NSView* frameView = [aView superview];
|
|
|
|
[aView removeFromSuperview];
|
2014-11-18 19:36:07 +03:00
|
|
|
if ([frameView respondsToSelector:@selector(_addKnownSubview:positioned:relativeTo:)]) {
|
|
|
|
// 10.10 prints a warning when we call addSubview on the frame view, so we
|
|
|
|
// silence the warning by calling a private method instead.
|
|
|
|
[frameView _addKnownSubview:aView positioned:NSWindowBelow relativeTo:nil];
|
|
|
|
} else {
|
|
|
|
[frameView addSubview:aView positioned:NSWindowBelow relativeTo:nil];
|
|
|
|
}
|
2013-05-23 18:49:17 +04:00
|
|
|
}
|
|
|
|
|
2013-05-23 18:49:17 +04:00
|
|
|
- (NSArray*)titlebarControls
|
|
|
|
{
|
|
|
|
// Return all subviews of the frameView which are not the content view.
|
|
|
|
NSView* frameView = [[self contentView] superview];
|
|
|
|
NSMutableArray* array = [[[frameView subviews] mutableCopy] autorelease];
|
|
|
|
[array removeObject:[self contentView]];
|
|
|
|
return array;
|
|
|
|
}
|
|
|
|
|
2011-01-28 17:11:29 +03:00
|
|
|
- (BOOL)respondsToSelector:(SEL)aSelector
|
|
|
|
{
|
|
|
|
// Claim the window doesn't respond to this so that the system
|
|
|
|
// doesn't steal keyboard equivalents for it. Bug 613710.
|
|
|
|
if (aSelector == @selector(cancelOperation:)) {
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
|
|
|
return [super respondsToSelector:aSelector];
|
|
|
|
}
|
|
|
|
|
2010-08-17 07:26:17 +04:00
|
|
|
- (void) doCommandBySelector:(SEL)aSelector
|
|
|
|
{
|
|
|
|
// We override this so that it won't beep if it can't act.
|
|
|
|
// We want to control the beeping for missing or disabled
|
|
|
|
// commands ourselves.
|
|
|
|
[self tryToPerform:aSelector with:nil];
|
|
|
|
}
|
|
|
|
|
2011-09-27 19:38:44 +04:00
|
|
|
- (id)accessibilityAttributeValue:(NSString *)attribute
|
|
|
|
{
|
|
|
|
id retval = [super accessibilityAttributeValue:attribute];
|
|
|
|
|
|
|
|
// The following works around a problem with Text-to-Speech on OS X 10.7.
|
|
|
|
// See bug 674612 for more info.
|
|
|
|
//
|
|
|
|
// When accessibility is off, AXUIElementCopyAttributeValue(), when called
|
|
|
|
// on an AXApplication object to get its AXFocusedUIElement attribute,
|
|
|
|
// always returns an AXWindow object (the actual browser window -- never a
|
|
|
|
// mozAccessible object). This also happens with accessibility turned on,
|
|
|
|
// if no other object in the browser window has yet been focused. But if
|
|
|
|
// the browser window has a title bar (as it currently always does), the
|
|
|
|
// AXWindow object will always have four "accessible" children, one of which
|
|
|
|
// is an AXStaticText object (the title bar's "title"; the other three are
|
|
|
|
// the close, minimize and zoom buttons). This means that (for complicated
|
|
|
|
// reasons, for which see bug 674612) Text-to-Speech on OS X 10.7 will often
|
|
|
|
// "speak" the window title, no matter what text is selected, or even if no
|
|
|
|
// text at all is selected. (This always happens when accessibility is off.
|
|
|
|
// It doesn't happen in Firefox releases because Apple has (on OS X 10.7)
|
|
|
|
// special-cased the handling of apps whose CFBundleIdentifier is
|
|
|
|
// org.mozilla.firefox.)
|
|
|
|
//
|
|
|
|
// We work around this problem by only returning AXChildren that are
|
|
|
|
// mozAccessible object or are one of the titlebar's buttons (which
|
|
|
|
// instantiate subclasses of NSButtonCell).
|
2012-05-17 11:53:20 +04:00
|
|
|
if (nsCocoaFeatures::OnLionOrLater() && [retval isKindOfClass:[NSArray class]] &&
|
2011-09-27 19:38:44 +04:00
|
|
|
[attribute isEqualToString:@"AXChildren"]) {
|
|
|
|
NSMutableArray *holder = [NSMutableArray arrayWithCapacity:10];
|
|
|
|
[holder addObjectsFromArray:(NSArray *)retval];
|
|
|
|
NSUInteger count = [holder count];
|
|
|
|
for (NSInteger i = count - 1; i >= 0; --i) {
|
|
|
|
id item = [holder objectAtIndex:i];
|
|
|
|
// Remove anything from holder that isn't one of the titlebar's buttons
|
|
|
|
// (which instantiate subclasses of NSButtonCell) or a mozAccessible
|
|
|
|
// object (or one of its subclasses).
|
|
|
|
if (![item isKindOfClass:[NSButtonCell class]] &&
|
|
|
|
![item respondsToSelector:@selector(hasRepresentedView)]) {
|
|
|
|
[holder removeObjectAtIndex:i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
retval = [NSArray arrayWithArray:holder];
|
|
|
|
}
|
|
|
|
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
2013-04-29 19:24:26 +04:00
|
|
|
// If we were built on OS X 10.6 or with the 10.6 SDK and are running on Lion,
|
|
|
|
// the OS (specifically -[NSWindow sendEvent:]) won't send NSEventTypeGesture
|
|
|
|
// events to -[ChildView magnifyWithEvent:] as it should. The following code
|
|
|
|
// gets around this. See bug 863841.
|
|
|
|
#if !defined( MAC_OS_X_VERSION_10_7 ) || \
|
|
|
|
( MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 )
|
|
|
|
- (void)sendEvent:(NSEvent *)anEvent
|
|
|
|
{
|
|
|
|
if ([ChildView isLionSmartMagnifyEvent: anEvent]) {
|
|
|
|
[[self mainChildView] magnifyWithEvent:anEvent];
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
[super sendEvent:anEvent];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-10-30 07:03:42 +03:00
|
|
|
@end
|
|
|
|
|
2013-02-06 01:40:34 +04:00
|
|
|
// This class allows us to exercise control over the window's title bar. This
|
2013-05-23 18:49:17 +04:00
|
|
|
// allows for a "unified toolbar" look without having to extend the content
|
|
|
|
// area into the title bar. It works like this:
|
2007-10-30 07:03:42 +03:00
|
|
|
// 1) We set the window's style to textured.
|
|
|
|
// 2) Because of this, the background color applies to the entire window, including
|
|
|
|
// the titlebar area. For normal textured windows, the default pattern is a
|
2008-09-16 12:21:06 +04:00
|
|
|
// "brushed metal" image on Tiger and a unified gradient on Leopard.
|
2007-10-30 07:03:42 +03:00
|
|
|
// 3) We set the background color to a custom NSColor subclass that knows how tall the window is.
|
|
|
|
// When -set is called on it, it sets a pattern (with a draw callback) as the fill. In that callback,
|
2008-09-16 12:21:06 +04:00
|
|
|
// it paints the the titlebar and background colors in the correct areas of the context it's given,
|
2007-10-30 07:03:42 +03:00
|
|
|
// which will fill the entire window (CG will tile it horizontally for us).
|
2008-09-16 12:21:06 +04:00
|
|
|
// 4) Whenever the window's main state changes and when [window display] is called,
|
|
|
|
// Cocoa redraws the titlebar using the patternDraw callback function.
|
2007-10-30 07:03:42 +03:00
|
|
|
//
|
2013-05-23 18:49:17 +04:00
|
|
|
// This class also provides us with a pill button to show/hide the toolbar up to 10.6.
|
2008-09-16 12:21:06 +04:00
|
|
|
//
|
|
|
|
// Drawing the unified gradient in the titlebar and the toolbar works like this:
|
2015-10-23 11:51:34 +03:00
|
|
|
// 1) In the style sheet we set the toolbar's -moz-appearance to toolbar.
|
2010-07-24 13:35:29 +04:00
|
|
|
// 2) When the toolbar is visible and we paint the application chrome
|
2011-01-11 16:03:16 +03:00
|
|
|
// window, the array that Gecko passes nsChildView::UpdateThemeGeometries
|
2015-10-23 11:51:34 +03:00
|
|
|
// will contain an entry for the widget type NS_THEME_TOOLBAR.
|
2011-01-11 16:03:16 +03:00
|
|
|
// 3) nsChildView::UpdateThemeGeometries finds the toolbar frame's ToolbarWindow
|
|
|
|
// and passes the toolbar frame's height to setUnifiedToolbarHeight.
|
|
|
|
// 4) If the toolbar height has changed, a titlebar redraw is triggered and the
|
|
|
|
// upper part of the unified gradient is drawn in the titlebar.
|
|
|
|
// 5) The lower part of the unified gradient in the toolbar is drawn during
|
|
|
|
// normal window content painting in nsNativeThemeCocoa::DrawUnifiedToolbar.
|
2008-09-16 12:21:06 +04:00
|
|
|
//
|
|
|
|
// Whenever the unified gradient is drawn in the titlebar or the toolbar, both
|
|
|
|
// titlebar height and toolbar height must be known in order to construct the
|
2013-05-23 18:49:17 +04:00
|
|
|
// correct gradient. But you can only get from the toolbar frame
|
2008-09-16 12:21:06 +04:00
|
|
|
// to the containing window - the other direction doesn't work. That's why the
|
|
|
|
// toolbar height is cached in the ToolbarWindow but nsNativeThemeCocoa can simply
|
|
|
|
// query the window for its titlebar height when drawing the toolbar.
|
2013-05-23 18:49:17 +04:00
|
|
|
//
|
|
|
|
// Note that in drawsContentsIntoWindowFrame mode, titlebar drawing works in a
|
|
|
|
// completely different way: In that mode, the window's mainChildView will
|
|
|
|
// cover the titlebar completely and nothing that happens in the window
|
|
|
|
// background will reach the screen.
|
2007-05-31 09:07:18 +04:00
|
|
|
@implementation ToolbarWindow
|
|
|
|
|
2009-08-14 10:35:32 +04:00
|
|
|
- (id)initWithContentRect:(NSRect)aContentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)aBufferingType defer:(BOOL)aFlag
|
2007-10-30 07:03:42 +03:00
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
2007-10-30 07:03:42 +03:00
|
|
|
aStyle = aStyle | NSTexturedBackgroundWindowMask;
|
|
|
|
if ((self = [super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag])) {
|
2009-11-02 22:07:57 +03:00
|
|
|
mColor = [[TitlebarAndBackgroundColor alloc] initWithWindow:self];
|
|
|
|
// Bypass our guard method below.
|
2007-10-30 07:03:42 +03:00
|
|
|
[super setBackgroundColor:mColor];
|
2012-01-04 23:53:52 +04:00
|
|
|
mBackgroundColor = [[NSColor whiteColor] retain];
|
2007-10-30 07:03:42 +03:00
|
|
|
|
2013-05-22 13:48:47 +04:00
|
|
|
mUnifiedToolbarHeight = 22.0f;
|
2013-06-13 01:42:00 +04:00
|
|
|
mWindowButtonsRect = NSZeroRect;
|
|
|
|
mFullScreenButtonRect = NSZeroRect;
|
2008-09-16 12:21:06 +04:00
|
|
|
|
2007-10-30 07:03:42 +03:00
|
|
|
// setBottomCornerRounded: is a private API call, so we check to make sure
|
|
|
|
// we respond to it just in case.
|
|
|
|
if ([self respondsToSelector:@selector(setBottomCornerRounded:)])
|
2013-03-27 19:49:02 +04:00
|
|
|
[self setBottomCornerRounded:nsCocoaFeatures::OnLionOrLater()];
|
2009-11-14 01:59:38 +03:00
|
|
|
|
|
|
|
[self setAutorecalculatesContentBorderThickness:NO forEdge:NSMaxYEdge];
|
|
|
|
[self setContentBorderThickness:0.0f forEdge:NSMaxYEdge];
|
2007-10-30 07:03:42 +03:00
|
|
|
}
|
|
|
|
return self;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2007-10-30 07:03:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
- (void)dealloc
|
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2007-10-30 07:03:42 +03:00
|
|
|
[mColor release];
|
2009-11-02 22:07:57 +03:00
|
|
|
[mBackgroundColor release];
|
2013-02-06 01:40:34 +04:00
|
|
|
[mTitlebarView release];
|
2007-10-30 07:03:42 +03:00
|
|
|
[super dealloc];
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-10-30 07:03:42 +03:00
|
|
|
}
|
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
- (void)setTitlebarColor:(NSColor*)aColor forActiveWindow:(BOOL)aActive
|
2007-10-30 07:03:42 +03:00
|
|
|
{
|
2009-11-02 22:07:57 +03:00
|
|
|
[super setTitlebarColor:aColor forActiveWindow:aActive];
|
|
|
|
[self setTitlebarNeedsDisplayInRect:[self titlebarRect]];
|
2007-10-30 07:03:42 +03:00
|
|
|
}
|
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
- (void)setBackgroundColor:(NSColor*)aColor
|
2007-10-30 07:03:42 +03:00
|
|
|
{
|
2009-11-02 22:07:57 +03:00
|
|
|
[aColor retain];
|
|
|
|
[mBackgroundColor release];
|
|
|
|
mBackgroundColor = aColor;
|
2007-10-30 07:03:42 +03:00
|
|
|
}
|
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
- (NSColor*)windowBackgroundColor
|
2007-10-30 07:03:42 +03:00
|
|
|
{
|
2009-11-02 22:07:57 +03:00
|
|
|
return mBackgroundColor;
|
2007-10-30 07:03:42 +03:00
|
|
|
}
|
|
|
|
|
2009-10-21 11:05:39 +04:00
|
|
|
- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect
|
|
|
|
{
|
|
|
|
[self setTitlebarNeedsDisplayInRect:aRect sync:NO];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setTitlebarNeedsDisplayInRect:(NSRect)aRect sync:(BOOL)aSync
|
|
|
|
{
|
|
|
|
NSRect titlebarRect = [self titlebarRect];
|
|
|
|
NSRect rect = NSIntersectionRect(titlebarRect, aRect);
|
|
|
|
if (NSIsEmptyRect(rect))
|
|
|
|
return;
|
|
|
|
|
|
|
|
NSView* borderView = [[self contentView] superview];
|
|
|
|
if (!borderView)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (aSync) {
|
|
|
|
[borderView displayRect:rect];
|
|
|
|
} else {
|
|
|
|
[borderView setNeedsDisplayInRect:rect];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSRect)titlebarRect
|
|
|
|
{
|
2013-12-17 20:11:13 +04:00
|
|
|
CGFloat titlebarHeight = [self titlebarHeight];
|
|
|
|
return NSMakeRect(0, [self frame].size.height - titlebarHeight,
|
|
|
|
[self frame].size.width, titlebarHeight);
|
2008-08-27 19:45:24 +04:00
|
|
|
}
|
2008-02-21 02:47:05 +03:00
|
|
|
|
2013-05-22 13:48:47 +04:00
|
|
|
// Returns the unified height of titlebar + toolbar.
|
2013-05-22 13:50:57 +04:00
|
|
|
- (CGFloat)unifiedToolbarHeight
|
2008-08-27 19:45:24 +04:00
|
|
|
{
|
2008-09-16 12:21:06 +04:00
|
|
|
return mUnifiedToolbarHeight;
|
|
|
|
}
|
2008-08-27 23:40:25 +04:00
|
|
|
|
2013-05-22 13:50:57 +04:00
|
|
|
- (CGFloat)titlebarHeight
|
2008-09-16 12:21:06 +04:00
|
|
|
{
|
2013-05-21 01:38:54 +04:00
|
|
|
// We use the original content rect here, not what we return from
|
|
|
|
// [self contentRectForFrameRect:], because that would give us a
|
|
|
|
// titlebarHeight of zero in drawsContentsIntoWindowFrame mode.
|
2008-09-16 12:21:06 +04:00
|
|
|
NSRect frameRect = [self frame];
|
2013-05-21 01:38:54 +04:00
|
|
|
NSRect originalContentRect = [NSWindow contentRectForFrameRect:frameRect styleMask:[self styleMask]];
|
|
|
|
return NSMaxY(frameRect) - NSMaxY(originalContentRect);
|
2008-08-27 19:45:24 +04:00
|
|
|
}
|
2007-10-30 07:03:42 +03:00
|
|
|
|
2013-05-22 13:48:47 +04:00
|
|
|
// Stores the complete height of titlebar + toolbar.
|
2013-05-22 13:50:57 +04:00
|
|
|
- (void)setUnifiedToolbarHeight:(CGFloat)aHeight
|
2010-01-13 19:08:06 +03:00
|
|
|
{
|
2013-05-22 13:48:47 +04:00
|
|
|
if (aHeight == mUnifiedToolbarHeight)
|
2011-01-11 16:03:16 +03:00
|
|
|
return;
|
2010-01-13 19:08:06 +03:00
|
|
|
|
2011-01-11 16:03:16 +03:00
|
|
|
mUnifiedToolbarHeight = aHeight;
|
2010-07-24 13:35:29 +04:00
|
|
|
|
2015-05-22 00:49:56 +03:00
|
|
|
if (![self drawsContentsIntoWindowFrame]) {
|
|
|
|
// Redraw the title bar. If we're inside painting, we'll do it right now,
|
|
|
|
// otherwise we'll just invalidate it.
|
|
|
|
BOOL needSyncRedraw = ([NSView focusView] != nil);
|
|
|
|
[self setTitlebarNeedsDisplayInRect:[self titlebarRect] sync:needSyncRedraw];
|
|
|
|
}
|
2010-01-13 19:08:06 +03:00
|
|
|
}
|
|
|
|
|
2013-05-23 18:49:17 +04:00
|
|
|
// Extending the content area into the title bar works by resizing the
|
|
|
|
// mainChildView so that it covers the titlebar.
|
2009-10-21 11:05:39 +04:00
|
|
|
- (void)setDrawsContentsIntoWindowFrame:(BOOL)aState
|
|
|
|
{
|
2009-11-02 22:07:57 +03:00
|
|
|
BOOL stateChanged = ([self drawsContentsIntoWindowFrame] != aState);
|
|
|
|
[super setDrawsContentsIntoWindowFrame:aState];
|
2010-11-18 00:48:11 +03:00
|
|
|
if (stateChanged && [[self delegate] isKindOfClass:[WindowDelegate class]]) {
|
2013-02-06 01:40:34 +04:00
|
|
|
// Here we extend / shrink our mainChildView. We do that by firing a resize
|
|
|
|
// event which will cause the ChildView to be resized to the rect returned
|
|
|
|
// by nsCocoaWindow::GetClientBounds. GetClientBounds bases its return
|
|
|
|
// value on what we return from drawsContentsIntoWindowFrame.
|
2010-11-18 00:48:11 +03:00
|
|
|
WindowDelegate *windowDelegate = (WindowDelegate *)[self delegate];
|
|
|
|
nsCocoaWindow *geckoWindow = [windowDelegate geckoWidget];
|
2009-10-21 11:05:39 +04:00
|
|
|
if (geckoWindow) {
|
|
|
|
// Re-layout our contents.
|
|
|
|
geckoWindow->ReportSizeEvent();
|
|
|
|
}
|
2011-08-13 18:25:39 +04:00
|
|
|
|
|
|
|
// Resizing the content area causes a reflow which would send a synthesized
|
|
|
|
// mousemove event to the old mouse position relative to the top left
|
|
|
|
// corner of the content area. But the mouse has shifted relative to the
|
|
|
|
// content area, so that event would have wrong position information. So
|
|
|
|
// we'll send a mouse move event with the correct new position.
|
|
|
|
ChildViewMouseTracker::ResendLastMouseMoveEvent();
|
2009-10-21 11:05:39 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-17 20:11:13 +04:00
|
|
|
- (void)setWantsTitleDrawn:(BOOL)aDrawTitle
|
|
|
|
{
|
|
|
|
[super setWantsTitleDrawn:aDrawTitle];
|
|
|
|
[self setTitlebarNeedsDisplayInRect:[self titlebarRect]];
|
|
|
|
}
|
|
|
|
|
2015-03-06 22:43:46 +03:00
|
|
|
- (void)setSheetAttachmentPosition:(CGFloat)aY
|
|
|
|
{
|
|
|
|
CGFloat topMargin = aY - [self titlebarHeight];
|
|
|
|
[self setContentBorderThickness:topMargin forEdge:NSMaxYEdge];
|
|
|
|
}
|
|
|
|
|
2013-06-13 01:42:00 +04:00
|
|
|
- (void)placeWindowButtons:(NSRect)aRect
|
|
|
|
{
|
|
|
|
if (!NSEqualRects(mWindowButtonsRect, aRect)) {
|
|
|
|
mWindowButtonsRect = aRect;
|
|
|
|
[self reflowTitlebarElements];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSPoint)windowButtonsPositionWithDefaultPosition:(NSPoint)aDefaultPosition
|
|
|
|
{
|
2015-06-04 04:49:34 +03:00
|
|
|
NSInteger styleMask = [self styleMask];
|
|
|
|
if ([self drawsContentsIntoWindowFrame] &&
|
|
|
|
!(styleMask & NSFullScreenWindowMask) && (styleMask & NSTitledWindowMask)) {
|
2015-01-29 00:44:00 +03:00
|
|
|
if (NSIsEmptyRect(mWindowButtonsRect)) {
|
|
|
|
// Empty rect. Let's hide the buttons.
|
|
|
|
// Position is in non-flipped window coordinates. Using frame's height
|
|
|
|
// for the vertical coordinate will move the buttons above the window,
|
|
|
|
// making them invisible.
|
|
|
|
return NSMakePoint(0, [self frame].size.height);
|
|
|
|
}
|
|
|
|
return NSMakePoint(mWindowButtonsRect.origin.x, mWindowButtonsRect.origin.y);
|
2013-06-13 01:42:00 +04:00
|
|
|
}
|
|
|
|
return aDefaultPosition;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)placeFullScreenButton:(NSRect)aRect
|
|
|
|
{
|
|
|
|
if (!NSEqualRects(mFullScreenButtonRect, aRect)) {
|
|
|
|
mFullScreenButtonRect = aRect;
|
|
|
|
[self reflowTitlebarElements];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-06 11:09:39 +03:00
|
|
|
- (NSPoint)fullScreenButtonPositionWithDefaultPosition:(NSPoint)aDefaultPosition
|
2013-06-13 01:42:00 +04:00
|
|
|
{
|
|
|
|
if ([self drawsContentsIntoWindowFrame] && !NSIsEmptyRect(mFullScreenButtonRect)) {
|
|
|
|
return NSMakePoint(std::min(mFullScreenButtonRect.origin.x, aDefaultPosition.x),
|
|
|
|
std::min(mFullScreenButtonRect.origin.y, aDefaultPosition.y));
|
|
|
|
}
|
|
|
|
return aDefaultPosition;
|
|
|
|
}
|
|
|
|
|
2009-08-06 00:49:59 +04:00
|
|
|
// Returning YES here makes the setShowsToolbarButton method work even though
|
|
|
|
// the window doesn't contain an NSToolbar.
|
2007-05-31 09:07:18 +04:00
|
|
|
- (BOOL)_hasToolbar
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2007-10-30 07:03:42 +03:00
|
|
|
// Dispatch a toolbar pill button clicked message to Gecko.
|
2007-05-31 09:07:18 +04:00
|
|
|
- (void)_toolbarPillButtonClicked:(id)sender
|
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
|
|
|
|
2010-03-18 22:58:07 +03:00
|
|
|
RollUpPopups();
|
|
|
|
|
2010-11-18 00:48:11 +03:00
|
|
|
if ([[self delegate] isKindOfClass:[WindowDelegate class]]) {
|
|
|
|
WindowDelegate *windowDelegate = (WindowDelegate *)[self delegate];
|
|
|
|
nsCocoaWindow *geckoWindow = [windowDelegate geckoWidget];
|
|
|
|
if (!geckoWindow)
|
|
|
|
return;
|
2012-08-15 22:52:42 +04:00
|
|
|
|
|
|
|
nsIWidgetListener* listener = geckoWindow->GetWidgetListener();
|
|
|
|
if (listener)
|
|
|
|
listener->OSToolbarButtonPressed();
|
2010-11-18 00:48:11 +03:00
|
|
|
}
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK;
|
2007-05-31 09:07:18 +04:00
|
|
|
}
|
|
|
|
|
2007-10-23 22:34:29 +04:00
|
|
|
// Retain and release "self" to avoid crashes when our widget (and its native
|
|
|
|
// window) is closed as a result of processing a key equivalent (e.g.
|
|
|
|
// Command+w or Command+q). This workaround is only needed for a window
|
|
|
|
// that can become key.
|
|
|
|
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent
|
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2007-10-23 22:34:29 +04:00
|
|
|
NSWindow *nativeWindow = [self retain];
|
|
|
|
BOOL retval = [super performKeyEquivalent:theEvent];
|
|
|
|
[nativeWindow release];
|
|
|
|
return retval;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
|
2007-10-23 22:34:29 +04:00
|
|
|
}
|
|
|
|
|
2008-03-24 01:30:56 +03:00
|
|
|
- (void)sendEvent:(NSEvent *)anEvent
|
|
|
|
{
|
|
|
|
NSEventType type = [anEvent type];
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case NSScrollWheel:
|
|
|
|
case NSLeftMouseDown:
|
|
|
|
case NSLeftMouseUp:
|
|
|
|
case NSRightMouseDown:
|
|
|
|
case NSRightMouseUp:
|
|
|
|
case NSOtherMouseDown:
|
|
|
|
case NSOtherMouseUp:
|
|
|
|
case NSMouseMoved:
|
|
|
|
case NSLeftMouseDragged:
|
|
|
|
case NSRightMouseDragged:
|
|
|
|
case NSOtherMouseDragged:
|
2008-03-25 08:00:36 +03:00
|
|
|
{
|
2008-03-24 01:30:56 +03:00
|
|
|
// Drop all mouse events if a modal window has appeared above us.
|
|
|
|
// This helps make us behave as if the OS were running a "real" modal
|
|
|
|
// event loop.
|
|
|
|
id delegate = [self delegate];
|
|
|
|
if (delegate && [delegate isKindOfClass:[WindowDelegate class]]) {
|
|
|
|
nsCocoaWindow *widget = [(WindowDelegate *)delegate geckoWidget];
|
|
|
|
if (widget) {
|
2009-03-19 01:51:40 +03:00
|
|
|
if (gGeckoAppModalWindowList && (widget != gGeckoAppModalWindowList->window))
|
2008-03-24 01:30:56 +03:00
|
|
|
return;
|
|
|
|
if (widget->HasModalDescendents())
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2008-03-25 08:00:36 +03:00
|
|
|
}
|
|
|
|
default:
|
2008-03-24 01:30:56 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
[super sendEvent:anEvent];
|
|
|
|
}
|
|
|
|
|
2002-01-09 04:29:18 +03:00
|
|
|
@end
|
2007-07-18 00:29:39 +04:00
|
|
|
|
2007-10-30 07:03:42 +03:00
|
|
|
// Custom NSColor subclass where most of the work takes place for drawing in
|
2013-05-23 18:49:17 +04:00
|
|
|
// the titlebar area. Not used in drawsContentsIntoWindowFrame mode.
|
2007-10-30 07:03:42 +03:00
|
|
|
@implementation TitlebarAndBackgroundColor
|
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
- (id)initWithWindow:(ToolbarWindow*)aWindow
|
2007-10-30 07:03:42 +03:00
|
|
|
{
|
|
|
|
if ((self = [super init])) {
|
2007-12-11 22:52:26 +03:00
|
|
|
mWindow = aWindow; // weak ref to avoid a cycle
|
2007-10-30 07:03:42 +03:00
|
|
|
}
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2009-10-21 11:05:39 +04:00
|
|
|
static void
|
2011-08-08 18:42:20 +04:00
|
|
|
DrawNativeTitlebar(CGContextRef aContext, CGRect aTitlebarRect,
|
2013-05-22 13:50:57 +04:00
|
|
|
CGFloat aUnifiedToolbarHeight, BOOL aIsMain)
|
2011-08-08 18:42:20 +04:00
|
|
|
{
|
2014-08-28 04:15:27 +04:00
|
|
|
nsNativeThemeCocoa::DrawNativeTitlebar(aContext, aTitlebarRect, aUnifiedToolbarHeight, aIsMain, NO);
|
2011-08-08 18:42:20 +04:00
|
|
|
|
2012-05-17 11:53:20 +04:00
|
|
|
if (nsCocoaFeatures::OnLionOrLater()) {
|
2011-08-12 18:25:24 +04:00
|
|
|
// On Lion the call to CUIDraw doesn't draw the top pixel strip at some
|
|
|
|
// window widths. We don't want to have a flickering transparent line, so
|
|
|
|
// we overdraw it.
|
|
|
|
CGContextSetRGBFillColor(aContext, 0.95, 0.95, 0.95, 1);
|
|
|
|
CGContextFillRect(aContext, CGRectMake(0, CGRectGetMaxY(aTitlebarRect) - 1,
|
|
|
|
aTitlebarRect.size.width, 1));
|
|
|
|
}
|
2009-10-21 11:05:39 +04:00
|
|
|
}
|
2008-02-21 02:47:05 +03:00
|
|
|
|
2009-10-21 11:05:39 +04:00
|
|
|
// Pattern draw callback for standard titlebar gradients and solid titlebar colors
|
|
|
|
static void
|
2011-08-08 18:42:20 +04:00
|
|
|
TitlebarDrawCallback(void* aInfo, CGContextRef aContext)
|
2009-10-21 11:05:39 +04:00
|
|
|
{
|
2009-11-02 22:07:57 +03:00
|
|
|
ToolbarWindow *window = (ToolbarWindow*)aInfo;
|
2013-05-23 18:49:16 +04:00
|
|
|
if (![window drawsContentsIntoWindowFrame]) {
|
|
|
|
NSRect titlebarRect = [window titlebarRect];
|
2011-08-08 18:42:20 +04:00
|
|
|
BOOL isMain = [window isMainWindow];
|
|
|
|
NSColor *titlebarColor = [window titlebarColorForActiveWindow:isMain];
|
|
|
|
if (!titlebarColor) {
|
|
|
|
// If the titlebar color is nil, draw the default titlebar shading.
|
|
|
|
DrawNativeTitlebar(aContext, NSRectToCGRect(titlebarRect),
|
|
|
|
[window unifiedToolbarHeight], isMain);
|
|
|
|
} else {
|
|
|
|
// If the titlebar color is not nil, just set and draw it normally.
|
2011-08-13 18:15:46 +04:00
|
|
|
[NSGraphicsContext saveGraphicsState];
|
|
|
|
[NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithGraphicsPort:aContext flipped:NO]];
|
2011-08-08 18:42:20 +04:00
|
|
|
[titlebarColor set];
|
|
|
|
NSRectFill(titlebarRect);
|
2011-08-13 18:15:46 +04:00
|
|
|
[NSGraphicsContext restoreGraphicsState];
|
2011-08-08 18:42:20 +04:00
|
|
|
}
|
2007-10-30 07:03:42 +03:00
|
|
|
}
|
2009-10-21 11:05:39 +04:00
|
|
|
}
|
2008-02-21 02:47:05 +03:00
|
|
|
|
2007-10-30 07:03:42 +03:00
|
|
|
- (void)setFill
|
|
|
|
{
|
2011-08-08 18:42:20 +04:00
|
|
|
float patternWidth = [mWindow frame].size.width;
|
2010-10-15 14:34:29 +04:00
|
|
|
|
2011-08-08 18:42:20 +04:00
|
|
|
CGPatternCallbacks callbacks = {0, &TitlebarDrawCallback, NULL};
|
2009-11-02 22:07:57 +03:00
|
|
|
CGPatternRef pattern = CGPatternCreate(mWindow, CGRectMake(0.0f, 0.0f, patternWidth, [mWindow frame].size.height),
|
2009-10-21 11:05:39 +04:00
|
|
|
CGAffineTransformIdentity, patternWidth, [mWindow frame].size.height,
|
2007-10-30 07:03:42 +03:00
|
|
|
kCGPatternTilingConstantSpacing, true, &callbacks);
|
|
|
|
|
|
|
|
// Set the pattern as the fill, which is what we were asked to do. All our
|
|
|
|
// drawing will take place in the patternDraw callback.
|
|
|
|
CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL);
|
2010-10-15 14:34:29 +04:00
|
|
|
CGContextRef context = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
|
2007-10-30 07:03:42 +03:00
|
|
|
CGContextSetFillColorSpace(context, patternSpace);
|
|
|
|
CGColorSpaceRelease(patternSpace);
|
2009-08-14 10:35:32 +04:00
|
|
|
CGFloat component = 1.0f;
|
2007-10-30 07:03:42 +03:00
|
|
|
CGContextSetFillPattern(context, pattern, &component);
|
|
|
|
CGPatternRelease(pattern);
|
|
|
|
}
|
|
|
|
|
2009-11-02 22:07:57 +03:00
|
|
|
- (void)set
|
2007-10-30 07:03:42 +03:00
|
|
|
{
|
2009-11-02 22:07:57 +03:00
|
|
|
[self setFill];
|
2007-10-30 07:03:42 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString*)colorSpaceName
|
|
|
|
{
|
|
|
|
return NSDeviceRGBColorSpace;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
2007-07-18 00:29:39 +04:00
|
|
|
@implementation PopupWindow
|
|
|
|
|
2009-08-14 10:35:32 +04:00
|
|
|
- (id)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)styleMask
|
2007-07-18 00:29:39 +04:00
|
|
|
backing:(NSBackingStoreType)bufferingType defer:(BOOL)deferCreation
|
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
|
|
|
|
2007-07-18 00:29:39 +04:00
|
|
|
mIsContextMenu = false;
|
|
|
|
return [super initWithContentRect:contentRect styleMask:styleMask
|
|
|
|
backing:bufferingType defer:deferCreation];
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
|
2007-07-18 00:29:39 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)isContextMenu
|
|
|
|
{
|
|
|
|
return mIsContextMenu;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)setIsContextMenu:(BOOL)flag
|
|
|
|
{
|
|
|
|
mIsContextMenu = flag;
|
|
|
|
}
|
|
|
|
|
2010-07-27 17:38:03 +04:00
|
|
|
- (BOOL)canBecomeMainWindow
|
|
|
|
{
|
|
|
|
// This is overriden because the default is 'yes' when a titlebar is present.
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
2007-07-18 00:29:39 +04:00
|
|
|
@end
|
2007-10-19 19:47:58 +04:00
|
|
|
|
|
|
|
// According to Apple's docs on [NSWindow canBecomeKeyWindow] and [NSWindow
|
|
|
|
// canBecomeMainWindow], windows without a title bar or resize bar can't (by
|
|
|
|
// default) become key or main. But if a window can't become key, it can't
|
|
|
|
// accept keyboard input (bmo bug 393250). And it should also be possible for
|
|
|
|
// an otherwise "ordinary" window to become main. We need to override these
|
|
|
|
// two methods to make this happen.
|
|
|
|
@implementation BorderlessWindow
|
|
|
|
|
|
|
|
- (BOOL)canBecomeKeyWindow
|
|
|
|
{
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
|
2008-03-24 01:30:56 +03:00
|
|
|
- (void)sendEvent:(NSEvent *)anEvent
|
|
|
|
{
|
|
|
|
NSEventType type = [anEvent type];
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case NSScrollWheel:
|
|
|
|
case NSLeftMouseDown:
|
|
|
|
case NSLeftMouseUp:
|
|
|
|
case NSRightMouseDown:
|
|
|
|
case NSRightMouseUp:
|
|
|
|
case NSOtherMouseDown:
|
|
|
|
case NSOtherMouseUp:
|
|
|
|
case NSMouseMoved:
|
|
|
|
case NSLeftMouseDragged:
|
|
|
|
case NSRightMouseDragged:
|
|
|
|
case NSOtherMouseDragged:
|
2008-03-25 08:00:36 +03:00
|
|
|
{
|
2008-03-24 01:30:56 +03:00
|
|
|
// Drop all mouse events if a modal window has appeared above us.
|
|
|
|
// This helps make us behave as if the OS were running a "real" modal
|
|
|
|
// event loop.
|
|
|
|
id delegate = [self delegate];
|
|
|
|
if (delegate && [delegate isKindOfClass:[WindowDelegate class]]) {
|
|
|
|
nsCocoaWindow *widget = [(WindowDelegate *)delegate geckoWidget];
|
|
|
|
if (widget) {
|
2009-03-19 01:51:40 +03:00
|
|
|
if (gGeckoAppModalWindowList && (widget != gGeckoAppModalWindowList->window))
|
2008-03-24 01:30:56 +03:00
|
|
|
return;
|
|
|
|
if (widget->HasModalDescendents())
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2008-03-25 08:00:36 +03:00
|
|
|
}
|
|
|
|
default:
|
2008-03-24 01:30:56 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
[super sendEvent:anEvent];
|
|
|
|
}
|
|
|
|
|
2007-10-19 19:47:58 +04:00
|
|
|
// Apple's doc on this method says that the NSWindow class's default is not to
|
|
|
|
// become main if the window isn't "visible" -- so we should replicate that
|
|
|
|
// behavior here. As best I can tell, the [NSWindow isVisible] method is an
|
|
|
|
// accurate test of what Apple means by "visibility".
|
|
|
|
- (BOOL)canBecomeMainWindow
|
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2007-10-19 19:47:58 +04:00
|
|
|
if (![self isVisible])
|
|
|
|
return NO;
|
|
|
|
return YES;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
|
2007-10-19 19:47:58 +04:00
|
|
|
}
|
|
|
|
|
2007-10-23 22:34:29 +04:00
|
|
|
// Retain and release "self" to avoid crashes when our widget (and its native
|
|
|
|
// window) is closed as a result of processing a key equivalent (e.g.
|
|
|
|
// Command+w or Command+q). This workaround is only needed for a window
|
|
|
|
// that can become key.
|
|
|
|
- (BOOL)performKeyEquivalent:(NSEvent*)theEvent
|
|
|
|
{
|
2008-02-21 02:47:05 +03:00
|
|
|
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
|
|
|
|
|
2007-10-23 22:34:29 +04:00
|
|
|
NSWindow *nativeWindow = [self retain];
|
|
|
|
BOOL retval = [super performKeyEquivalent:theEvent];
|
|
|
|
[nativeWindow release];
|
|
|
|
return retval;
|
2008-02-21 02:47:05 +03:00
|
|
|
|
|
|
|
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(NO);
|
2007-10-23 22:34:29 +04:00
|
|
|
}
|
|
|
|
|
2007-10-19 19:47:58 +04:00
|
|
|
@end
|