зеркало из https://github.com/mozilla/gecko-dev.git
Bug 865374 - Position tabs in the OSX titlebar. Cocoa Widget work by Steven Michaud. r=dao,bgirard.
This commit is contained in:
Родитель
094a6c7847
Коммит
40ddc57727
|
@ -412,10 +412,10 @@ pref("browser.tabs.loadBookmarksInBackground", false);
|
|||
pref("browser.tabs.tabClipWidth", 140);
|
||||
pref("browser.tabs.animate", true);
|
||||
pref("browser.tabs.onTop", true);
|
||||
#ifdef XP_WIN
|
||||
pref("browser.tabs.drawInTitlebar", true);
|
||||
#else
|
||||
#ifdef UNIX_BUT_NOT_MAC
|
||||
pref("browser.tabs.drawInTitlebar", false);
|
||||
#else
|
||||
pref("browser.tabs.drawInTitlebar", true);
|
||||
#endif
|
||||
|
||||
// Where to show tab close buttons:
|
||||
|
|
|
@ -125,6 +125,23 @@ toolbar[printpreview="true"] {
|
|||
#main-window[tabsintitlebar] #titlebar-buttonbox {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#titlebar-buttonbox {
|
||||
-moz-appearance: -moz-window-button-box;
|
||||
}
|
||||
|
||||
%ifdef XP_MACOSX
|
||||
#titlebar-fullscreen-button {
|
||||
-moz-appearance: -moz-mac-fullscreen-button;
|
||||
}
|
||||
%endif
|
||||
|
||||
%ifdef XP_WIN
|
||||
#main-window[sizemode="maximized"] #titlebar-buttonbox {
|
||||
-moz-appearance: -moz-window-button-box-maximized;
|
||||
}
|
||||
%endif
|
||||
|
||||
%endif
|
||||
|
||||
.bookmarks-toolbar-customize,
|
||||
|
|
|
@ -4598,7 +4598,10 @@ var TabsInTitlebar = {
|
|||
#endif
|
||||
let captionButtonsBox = $("titlebar-buttonbox");
|
||||
this._sizePlaceholder("caption-buttons", rect(captionButtonsBox).width);
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
let fullscreenButton = $("titlebar-fullscreen-button");
|
||||
this._sizePlaceholder("fullscreen-button", rect(fullscreenButton).width);
|
||||
#endif
|
||||
let titlebarContentHeight = rect(titlebarContent).height;
|
||||
let menuHeight = this._outerHeight(menubar);
|
||||
|
||||
|
|
|
@ -485,13 +485,20 @@
|
|||
</hbox>
|
||||
#endif
|
||||
<spacer id="titlebar-spacer" flex="1"/>
|
||||
<hbox id="titlebar-buttonbox-container" align="start">
|
||||
<hbox id="titlebar-buttonbox-container" align="start"
|
||||
#ifdef XP_MACOSX
|
||||
ordinal="0"
|
||||
#endif
|
||||
>
|
||||
<hbox id="titlebar-buttonbox">
|
||||
<toolbarbutton class="titlebar-button" id="titlebar-min" oncommand="window.minimize();"/>
|
||||
<toolbarbutton class="titlebar-button" id="titlebar-max" oncommand="onTitlebarMaxClick();"/>
|
||||
<toolbarbutton class="titlebar-button" id="titlebar-close" command="cmd_closeWindow"/>
|
||||
</hbox>
|
||||
</hbox>
|
||||
#ifdef XP_MACOSX
|
||||
<hbox id="titlebar-fullscreen-button" ordinal="1000"/>
|
||||
#endif
|
||||
</hbox>
|
||||
</vbox>
|
||||
#endif
|
||||
|
@ -519,8 +526,21 @@
|
|||
</toolbaritem>
|
||||
|
||||
#ifdef CAN_DRAW_IN_TITLEBAR
|
||||
#ifdef MENUBAR_CAN_AUTOHIDE
|
||||
<hbox class="titlebar-placeholder" type="appmenu-button" ordinal="0"/>
|
||||
<hbox class="titlebar-placeholder" type="caption-buttons" ordinal="1000"/>
|
||||
#endif
|
||||
|
||||
<hbox class="titlebar-placeholder" type="caption-buttons"
|
||||
#ifdef XP_MACOSX
|
||||
ordinal="0"
|
||||
#else
|
||||
ordinal="1000"
|
||||
#endif
|
||||
/>
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
<hbox class="titlebar-placeholder" type="fullscreen-button" ordinal="1000"/>
|
||||
#endif
|
||||
#endif
|
||||
</toolbar>
|
||||
|
||||
|
@ -827,8 +847,20 @@
|
|||
tooltiptext="&closeTab.label;"/>
|
||||
|
||||
#ifdef CAN_DRAW_IN_TITLEBAR
|
||||
#ifdef MENUBAR_CAN_AUTOHIDE
|
||||
<hbox class="titlebar-placeholder" type="appmenu-button" ordinal="0"/>
|
||||
<hbox class="titlebar-placeholder" type="caption-buttons" ordinal="1000"/>
|
||||
#endif
|
||||
<hbox class="titlebar-placeholder" type="caption-buttons"
|
||||
#ifdef XP_MACOSX
|
||||
ordinal="0"
|
||||
#else
|
||||
ordinal="1000"
|
||||
#endif
|
||||
/>
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
<hbox class="titlebar-placeholder" type="fullscreen-button"
|
||||
ordinal="1000"/>
|
||||
#endif
|
||||
</toolbar>
|
||||
|
||||
|
|
|
@ -40,12 +40,12 @@
|
|||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
#titlebar-buttonbox-container {
|
||||
#titlebar-buttonbox > .titlebar-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#titlebar {
|
||||
height: 22px;
|
||||
padding-top: 9px;
|
||||
}
|
||||
|
||||
#main-window:not(:-moz-lwtheme):not([privatebrowsingmode=temporary]) > #titlebar {
|
||||
|
|
|
@ -588,14 +588,9 @@
|
|||
* themes with Aero Glass.
|
||||
*/
|
||||
#titlebar-buttonbox {
|
||||
-moz-appearance: -moz-window-button-box;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
#main-window[sizemode="maximized"] #titlebar-buttonbox {
|
||||
-moz-appearance: -moz-window-button-box-maximized;
|
||||
}
|
||||
|
||||
.titlebar-placeholder[type="appmenu-button"] {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
|
|
@ -246,8 +246,9 @@
|
|||
#define NS_THEME_WIN_MEDIA_TOOLBOX 222
|
||||
#define NS_THEME_WIN_BROWSER_TAB_BAR_TOOLBOX 223
|
||||
|
||||
// Unified toolbar on the Mac
|
||||
// Unified toolbar and titlebar elements on the Mac
|
||||
#define NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR 224
|
||||
#define NS_THEME_MOZ_MAC_FULLSCREEN_BUTTON 226
|
||||
|
||||
// Vista glass
|
||||
#define NS_THEME_WIN_BORDERLESS_GLASS 229
|
||||
|
|
|
@ -107,6 +107,7 @@ CSS_KEY(-moz-mac-alternateprimaryhighlight, _moz_mac_alternateprimaryhighlight)
|
|||
CSS_KEY(-moz-mac-chrome-active, _moz_mac_chrome_active)
|
||||
CSS_KEY(-moz-mac-chrome-inactive, _moz_mac_chrome_inactive)
|
||||
CSS_KEY(-moz-mac-focusring, _moz_mac_focusring)
|
||||
CSS_KEY(-moz-mac-fullscreen-button, _moz_mac_fullscreen_button)
|
||||
CSS_KEY(-moz-mac-menuselect, _moz_mac_menuselect)
|
||||
CSS_KEY(-moz-mac-menushadow, _moz_mac_menushadow)
|
||||
CSS_KEY(-moz-mac-menutextdisable, _moz_mac_menutextdisable)
|
||||
|
|
|
@ -596,6 +596,7 @@ const int32_t nsCSSProps::kAppearanceKTable[] = {
|
|||
eCSSKeyword__moz_win_glass, NS_THEME_WIN_GLASS,
|
||||
eCSSKeyword__moz_win_borderless_glass, NS_THEME_WIN_BORDERLESS_GLASS,
|
||||
eCSSKeyword__moz_mac_unified_toolbar, NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR,
|
||||
eCSSKeyword__moz_mac_fullscreen_button, NS_THEME_MOZ_MAC_FULLSCREEN_BUTTON,
|
||||
eCSSKeyword__moz_window_titlebar, NS_THEME_WINDOW_TITLEBAR,
|
||||
eCSSKeyword__moz_window_titlebar_maximized, NS_THEME_WINDOW_TITLEBAR_MAXIMIZED,
|
||||
eCSSKeyword__moz_window_frame_left, NS_THEME_WINDOW_FRAME_LEFT,
|
||||
|
|
|
@ -115,6 +115,25 @@ typedef struct _nsCocoaWindowList {
|
|||
- (void)setBottomCornerRounded:(BOOL)rounded;
|
||||
- (BOOL)bottomCornerRounded;
|
||||
|
||||
// Present since at least OS X 10.5. The OS calls this method on NSWindow
|
||||
// (and its subclasses) to find out which NSFrameView subclass to instantiate
|
||||
// to create its "frame view".
|
||||
+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask;
|
||||
|
||||
@end
|
||||
|
||||
// Present since at least OS X 10.5 in NSFrameView or one of its subclasses.
|
||||
@interface NSObject (NSFrameViewMethods)
|
||||
- (NSButton*)closeButton;
|
||||
- (NSButton*)zoomButton;
|
||||
- (NSButton*)minimizeButton;
|
||||
- (NSButton*)fullScreenButton;
|
||||
- (void)initTitleCell:(id)cell;
|
||||
@end
|
||||
|
||||
@interface NSView (MozFrameViewMethods)
|
||||
- (int32_t)buttonBoxDisplayPixelsWidth;
|
||||
- (int32_t)fullScreenButtonDisplayPixelsWidth;
|
||||
@end
|
||||
|
||||
@interface PopupWindow : BaseWindow
|
||||
|
|
|
@ -2475,6 +2475,110 @@ GetDPI(NSWindow* aWindow)
|
|||
return dpi * backingScale;
|
||||
}
|
||||
|
||||
// Methods of our MozTitleCell and MozFrameView classes, created below as
|
||||
// subclasses of the appropriate undocumented superclasses. Since we don't
|
||||
// know beforehand exactly what the superclasses will be, each of these
|
||||
// classes is created dynamically, using low-level Objective-C runtime
|
||||
// methods. So their methods' declarations can't use Objective-C syntax.
|
||||
|
||||
static Class gMozTitleCellClass = nil;
|
||||
|
||||
typedef void (*NSCell_drawWithFrame)(struct objc_super *, SEL, NSRect, NSView *);
|
||||
|
||||
static void MozTitleCell_drawWithFrame(id self, SEL sel, NSRect cellFrame,
|
||||
NSView *controlView)
|
||||
{
|
||||
BaseWindow *window = nil;
|
||||
// The documentation for -[NSCell drawWithFrame:(NSRect)cellFrame
|
||||
// inView:(NSView*)controlView] says "this method draws the cell in the
|
||||
// currently focused view", which is what's returned by [NSView focusView].
|
||||
// So in the very unlikely event that 'controlView' is nil, we fall back
|
||||
// to using [NSView focusView].
|
||||
if (controlView) {
|
||||
window = (BaseWindow *) [controlView window];
|
||||
} else {
|
||||
window = (BaseWindow *) [[NSView focusView] window];
|
||||
}
|
||||
if ([window isKindOfClass:[BaseWindow class]]) {
|
||||
if ([window drawsContentsIntoWindowFrame]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
struct objc_super target;
|
||||
target.receiver = self;
|
||||
target.super_class = [self superclass];
|
||||
NSCell_drawWithFrame super = (NSCell_drawWithFrame) objc_msgSendSuper;
|
||||
super(&target, sel, cellFrame, controlView);
|
||||
}
|
||||
|
||||
static NSMutableDictionary *gFrameViewClassesByStyleMask = nil;
|
||||
|
||||
typedef void (*NSFrameView_initTitleCell)(struct objc_super *, SEL, id);
|
||||
|
||||
static void MozFrameView_initTitleCell(id self, SEL sel, id cell)
|
||||
{
|
||||
struct objc_super target;
|
||||
target.receiver = self;
|
||||
target.super_class = [self superclass];
|
||||
NSFrameView_initTitleCell super = (NSFrameView_initTitleCell) objc_msgSendSuper;
|
||||
super(&target, sel, cell);
|
||||
Class oldCellClass = [cell class];
|
||||
if (cell) {
|
||||
if (!gMozTitleCellClass) {
|
||||
Class superclass = [cell class];
|
||||
Class newClass = objc_allocateClassPair(superclass,
|
||||
"MozTitleCell", 0);
|
||||
if (newClass) {
|
||||
if ([superclass instancesRespondToSelector:@selector(drawWithFrame:inView:)]) {
|
||||
class_addMethod(newClass, @selector(drawWithFrame:inView:),
|
||||
(IMP)MozTitleCell_drawWithFrame,
|
||||
"v@:{_NSRect={_NSPoint=ff}{_NSSize=ff}}@");
|
||||
}
|
||||
objc_registerClassPair(newClass);
|
||||
gMozTitleCellClass = newClass;
|
||||
}
|
||||
}
|
||||
if (gMozTitleCellClass) {
|
||||
object_setClass(cell, gMozTitleCellClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t MozFrameView_buttonBoxDisplayPixelsWidth(id self, SEL sel)
|
||||
{
|
||||
NSRect buttonBox = NSZeroRect;
|
||||
NSButton *closeButton = [self closeButton];
|
||||
if (closeButton) {
|
||||
NSRect closeButtonBox = [self convertRect:[closeButton bounds]
|
||||
fromView:closeButton];
|
||||
buttonBox = NSUnionRect(buttonBox, closeButtonBox);
|
||||
}
|
||||
NSButton *minimizeButton = [self minimizeButton];
|
||||
if (minimizeButton) {
|
||||
NSRect minimizeButtonBox = [self convertRect:[minimizeButton bounds]
|
||||
fromView:minimizeButton];
|
||||
buttonBox = NSUnionRect(buttonBox, minimizeButtonBox);
|
||||
}
|
||||
NSButton *zoomButton = [self zoomButton];
|
||||
if (zoomButton) {
|
||||
NSRect zoomButtonBox = [self convertRect:[zoomButton bounds]
|
||||
fromView:zoomButton];
|
||||
buttonBox = NSUnionRect(buttonBox, zoomButtonBox);
|
||||
}
|
||||
return rint(buttonBox.size.width);
|
||||
}
|
||||
|
||||
static int32_t MozFrameView_fullScreenButtonDisplayPixelsWidth(id self, SEL sel)
|
||||
{
|
||||
CGFloat floatWidth = 0;
|
||||
NSButton *fullScreenButton = [self fullScreenButton];
|
||||
if (fullScreenButton) {
|
||||
floatWidth += [self convertSize:[fullScreenButton bounds].size
|
||||
fromView:fullScreenButton].width;
|
||||
}
|
||||
return rint(floatWidth);
|
||||
}
|
||||
|
||||
@interface BaseWindow(Private)
|
||||
- (void)removeTrackingArea;
|
||||
- (void)cursorUpdated:(NSEvent*)aEvent;
|
||||
|
@ -2482,6 +2586,50 @@ GetDPI(NSWindow* aWindow)
|
|||
|
||||
@implementation BaseWindow
|
||||
|
||||
+ (Class)frameViewClassForStyleMask:(NSUInteger)styleMask
|
||||
{
|
||||
Class retval = [super frameViewClassForStyleMask:styleMask];
|
||||
|
||||
if (!gFrameViewClassesByStyleMask) {
|
||||
gFrameViewClassesByStyleMask =
|
||||
[[NSMutableDictionary dictionaryWithCapacity:3] retain];
|
||||
}
|
||||
if (!gFrameViewClassesByStyleMask) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
NSString *styleMaskString =
|
||||
[NSString stringWithFormat:@"%p", (void *) styleMask];
|
||||
Class existingClass = (Class)
|
||||
[gFrameViewClassesByStyleMask valueForKey:styleMaskString];
|
||||
if (existingClass) {
|
||||
retval = existingClass;
|
||||
} else if (retval) {
|
||||
char newClassName[32];
|
||||
snprintf(newClassName, sizeof(newClassName) - 1, "MozFrameView%s",
|
||||
[styleMaskString UTF8String]);
|
||||
Class newClass = objc_allocateClassPair(retval, newClassName, 0);
|
||||
if (newClass) {
|
||||
if ([retval instancesRespondToSelector:@selector(initTitleCell:)]) {
|
||||
class_addMethod(newClass, @selector(initTitleCell:),
|
||||
(IMP)MozFrameView_initTitleCell,
|
||||
"v@:@");
|
||||
}
|
||||
class_addMethod(newClass, @selector(buttonBoxDisplayPixelsWidth),
|
||||
(IMP)MozFrameView_buttonBoxDisplayPixelsWidth,
|
||||
"l@:");
|
||||
class_addMethod(newClass, @selector(fullScreenButtonDisplayPixelsWidth),
|
||||
(IMP)MozFrameView_fullScreenButtonDisplayPixelsWidth,
|
||||
"l@:");
|
||||
objc_registerClassPair(newClass);
|
||||
[gFrameViewClassesByStyleMask setValue:newClass forKey:styleMaskString];
|
||||
retval = newClass;
|
||||
}
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
- (id)initWithContentRect:(NSRect)aContentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)aBufferingType defer:(BOOL)aFlag
|
||||
{
|
||||
[super initWithContentRect:aContentRect styleMask:aStyle backing:aBufferingType defer:aFlag];
|
||||
|
|
|
@ -357,6 +357,38 @@ static NSWindow* NativeWindowForFrame(nsIFrame* aFrame,
|
|||
return (NSWindow*)topLevelWidget->GetNativeData(NS_NATIVE_WINDOW);
|
||||
}
|
||||
|
||||
static NSView* FrameViewForFrame(nsIFrame* aFrame)
|
||||
{
|
||||
NSWindow* window = NativeWindowForFrame(aFrame);
|
||||
return [[window contentView] superview];
|
||||
}
|
||||
|
||||
static int32_t ButtonBoxDisplayPixelsWidth(nsIFrame* aFrame)
|
||||
{
|
||||
int32_t retval = 60; // Default value;
|
||||
NSView *frameView = FrameViewForFrame(aFrame);
|
||||
if ([frameView respondsToSelector:@selector(buttonBoxDisplayPixelsWidth)]) {
|
||||
int32_t measuredWidth = [frameView buttonBoxDisplayPixelsWidth];
|
||||
if (measuredWidth) {
|
||||
retval = measuredWidth;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int32_t FullScreenButtonDisplayPixelsWidth(nsIFrame* aFrame)
|
||||
{
|
||||
int32_t retval = 20; // Default value;
|
||||
NSView *frameView = FrameViewForFrame(aFrame);
|
||||
if ([frameView respondsToSelector:@selector(fullScreenButtonDisplayPixelsWidth)]) {
|
||||
int32_t measuredWidth = [frameView fullScreenButtonDisplayPixelsWidth];
|
||||
if (measuredWidth) {
|
||||
retval = measuredWidth;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
static BOOL FrameIsInActiveWindow(nsIFrame* aFrame)
|
||||
{
|
||||
nsIWidget* topLevelWidget = NULL;
|
||||
|
@ -2685,7 +2717,17 @@ nsNativeThemeCocoa::GetMinimumWidgetSize(nsRenderingContext* aContext,
|
|||
aResult->SizeTo(0, (2 + 2) /* top */ + 9 + (1 + 1) /* bottom */);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case NS_THEME_WINDOW_BUTTON_BOX: {
|
||||
aResult->SizeTo(ButtonBoxDisplayPixelsWidth(aFrame), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NS_THEME_MOZ_MAC_FULLSCREEN_BUTTON: {
|
||||
aResult->SizeTo(FullScreenButtonDisplayPixelsWidth(aFrame), 0);
|
||||
break;
|
||||
}
|
||||
|
||||
case NS_THEME_PROGRESSBAR:
|
||||
{
|
||||
SInt32 barHeight = 0;
|
||||
|
@ -2947,10 +2989,12 @@ nsNativeThemeCocoa::ThemeSupportsWidget(nsPresContext* aPresContext, nsIFrame* a
|
|||
|
||||
case NS_THEME_DIALOG:
|
||||
case NS_THEME_WINDOW:
|
||||
case NS_THEME_WINDOW_BUTTON_BOX:
|
||||
case NS_THEME_WINDOW_TITLEBAR:
|
||||
case NS_THEME_MENUPOPUP:
|
||||
case NS_THEME_MENUITEM:
|
||||
case NS_THEME_MENUSEPARATOR:
|
||||
case NS_THEME_MOZ_MAC_FULLSCREEN_BUTTON:
|
||||
case NS_THEME_TOOLTIP:
|
||||
|
||||
case NS_THEME_CHECKBOX:
|
||||
|
|
Загрузка…
Ссылка в новой задаче