зеркало из https://github.com/mozilla/gecko-dev.git
implement single-window mode with simple UI. (bug 274143)
This commit is contained in:
Родитель
c7a9f3ac75
Коммит
6c4c1b02c4
|
@ -18,6 +18,7 @@
|
|||
LANGUAGE = ObjC;
|
||||
OUTLETS = {
|
||||
checkboxLoadTabsInBackground = NSButton;
|
||||
mSingleWindowMode = NSButton;
|
||||
mTabBarVisiblity = NSButton;
|
||||
radioOpenForAE = NSMatrix;
|
||||
radioOpenTabsForCommand = NSMatrix;
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
<key>IBDocumentLocation</key>
|
||||
<string>22 17 522 320 0 0 1280 1002 </string>
|
||||
<key>IBFramework Version</key>
|
||||
<string>364.0</string>
|
||||
<string>443.0</string>
|
||||
<key>IBSystem Version</key>
|
||||
<string>7W98</string>
|
||||
<string>8I1119</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
Двоичный файл не отображается.
|
@ -47,6 +47,7 @@
|
|||
IBOutlet NSMatrix* radioOpenForAE;
|
||||
IBOutlet NSButton *checkboxLoadTabsInBackground;
|
||||
IBOutlet NSButton* mTabBarVisiblity;
|
||||
IBOutlet NSButton* mSingleWindowMode;
|
||||
}
|
||||
|
||||
- (IBAction)checkboxClicked:(id)sender;
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#import "Tabs.h"
|
||||
#import "nsIBrowserDOMWindow.h"
|
||||
|
||||
@implementation OrgMozillaChimeraPreferenceTabs
|
||||
|
||||
|
@ -64,6 +65,7 @@
|
|||
[radioOpenForAE selectCellWithTag:[self getIntPref:"browser.reuse_window" withSuccess:&gotPref]];
|
||||
[checkboxLoadTabsInBackground setState:[self getBooleanPref:"browser.tabs.loadInBackground" withSuccess:&gotPref]];
|
||||
[mTabBarVisiblity setState:[self getBooleanPref:"camino.tab_bar_always_visible" withSuccess:&gotPref]];
|
||||
[mSingleWindowMode setState:([self getIntPref:"browser.link.open_newwindow" withSuccess:&gotPref] == nsIBrowserDOMWindow::OPEN_NEWTAB)];
|
||||
}
|
||||
|
||||
- (IBAction)checkboxClicked:(id)sender
|
||||
|
@ -83,6 +85,10 @@
|
|||
else if (sender == mTabBarVisiblity) {
|
||||
[self setPref:"camino.tab_bar_always_visible" toBoolean:[sender state]];
|
||||
}
|
||||
else if (sender == mSingleWindowMode) {
|
||||
int newState = [sender state] ? nsIBrowserDOMWindow::OPEN_NEWTAB : nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW;
|
||||
[self setPref:"browser.link.open_newwindow" toInt:newState];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
|
@ -2982,6 +2982,19 @@ enum BWCOpenDest {
|
|||
[[newTab view] loadURI:aURLSpec referrer:aReferrer flags:NSLoadFlagsNone activate:!aLoadInBG allowPopups:inAllowPopups];
|
||||
}
|
||||
|
||||
//
|
||||
// -createNewTabBrowser:
|
||||
// BrowserUICreationDelegate
|
||||
//
|
||||
// create a new tab in the window associated with this wrapper and get its
|
||||
// browser view without loading anything into it.
|
||||
//
|
||||
- (CHBrowserView*)createNewTabBrowser:(BOOL)inLoadInBG
|
||||
{
|
||||
BrowserTabViewItem* newTab = [self openNewTab:inLoadInBG];
|
||||
return [[newTab view] getBrowserView];
|
||||
}
|
||||
|
||||
//
|
||||
// -openNewTab:
|
||||
//
|
||||
|
@ -3088,6 +3101,7 @@ enum BWCOpenDest {
|
|||
{
|
||||
BrowserTabViewItem* newTab = [BrowserTabView makeNewTabItem];
|
||||
BrowserWrapper* newView = [[BrowserWrapper alloc] initWithTab:newTab inWindow:[self window]];
|
||||
[newView setUICreationDelegate:self];
|
||||
|
||||
// register the bookmarks as a custom view
|
||||
BookmarkViewController* bmController = [[[BookmarkViewController alloc] initWithBrowserWindowController:self] autorelease];
|
||||
|
|
|
@ -74,6 +74,20 @@ class nsISupportsArray;
|
|||
|
||||
@end
|
||||
|
||||
//
|
||||
// The BrowserWrapper requests UI to be created via this delegate. Unlike the
|
||||
// |BrowserUIDelegate|, this delegate is always present even when in a
|
||||
// background tab.
|
||||
//
|
||||
@protocol BrowserUICreationDelegate
|
||||
|
||||
// create a new tab in the window associated with this wrapper and get it's
|
||||
// browser view without loading anything into it. why is the name so funny? BWC
|
||||
// already has openNewTab: and createNewTab: methods...
|
||||
- (CHBrowserView*)createNewTabBrowser:(BOOL)inLoadInBg;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
//
|
||||
// ContentViewProvider
|
||||
|
@ -137,7 +151,8 @@ class nsISupportsArray;
|
|||
|
||||
double mProgress;
|
||||
|
||||
id<BrowserUIDelegate> mDelegate; // not retained
|
||||
id<BrowserUIDelegate> mDelegate; // not retained, NULL if in bg
|
||||
id<BrowserUICreationDelegate> mCreateDelegate; // not retained, always present
|
||||
|
||||
NSMutableDictionary* mContentViewProviders; // ContentViewProviders keyed by the url that shows them
|
||||
|
||||
|
@ -154,6 +169,8 @@ class nsISupportsArray;
|
|||
// only the BrowserWrapper in the frontmost tab has a non-null delegate
|
||||
- (void)setDelegate:(id<BrowserUIDelegate>)delegate;
|
||||
- (id<BrowserUIDelegate>)delegate;
|
||||
// all BrowserWrappers have one of these, even if in the bg.
|
||||
- (void)setUICreationDelegate:(id<BrowserUICreationDelegate>)delegate;
|
||||
|
||||
- (void)windowClosed;
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@
|
|||
#include "nsPIDOMWindow.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsIBrowserDOMWindow.h"
|
||||
|
||||
|
||||
static NSString* const kOfflineNotificationName = @"offlineModeChanged";
|
||||
|
@ -206,6 +207,11 @@ static NSString* const kOfflineNotificationName = @"offlineModeChanged";
|
|||
mWindow = nil;
|
||||
}
|
||||
|
||||
- (void)setUICreationDelegate:(id<BrowserUICreationDelegate>)delegate
|
||||
{
|
||||
mCreateDelegate = delegate;
|
||||
}
|
||||
|
||||
- (void)setDelegate:(id<BrowserUIDelegate>)delegate
|
||||
{
|
||||
mDelegate = delegate;
|
||||
|
@ -898,6 +904,44 @@ static NSString* const kOfflineNotificationName = @"offlineModeChanged";
|
|||
return [[controller getBrowserWrapper] getBrowserView];
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// -reuseExistingBrowserWindow:
|
||||
//
|
||||
// Check the exact value of the "single-window mode" pref and if it's set to
|
||||
// reuse the same view, return it. If it's set to create a new tab, do that
|
||||
// and return that tab's view.
|
||||
//
|
||||
- (CHBrowserView*)reuseExistingBrowserWindow:(unsigned int)aMask
|
||||
{
|
||||
CHBrowserView* viewToUse = mBrowserView;
|
||||
int openNewWindow = [[PreferenceManager sharedInstance] getIntPref:"browser.link.open_newwindow" withSuccess:NULL];
|
||||
if (openNewWindow == nsIBrowserDOMWindow::OPEN_NEWTAB) {
|
||||
// we decide whether or not to open the new tab in the background based on
|
||||
// if we're the fg tab. If we are, we assume the user wants to see the new tab
|
||||
// because it's contextually relevat. If this tab is in the bg, the user doesn't
|
||||
// want to be bothered with a bg tab throwing things up in their face. We know
|
||||
// we're in the bg if our delegate is nil.
|
||||
viewToUse = [mCreateDelegate createNewTabBrowser:(mDelegate == nil)];
|
||||
}
|
||||
|
||||
return viewToUse;
|
||||
}
|
||||
|
||||
//
|
||||
// -shouldReuseExistingWindow
|
||||
//
|
||||
// Checks the pref to see if we want to reuse the same window (either in a new tab
|
||||
// or re-use the same browser view) when loading a URL requesting a new window
|
||||
//
|
||||
- (BOOL)shouldReuseExistingWindow
|
||||
{
|
||||
int openNewWindow = [[PreferenceManager sharedInstance] getIntPref:"browser.link.open_newwindow" withSuccess:NULL];
|
||||
BOOL shouldReuse = (openNewWindow == nsIBrowserDOMWindow::OPEN_CURRENTWINDOW ||
|
||||
openNewWindow == nsIBrowserDOMWindow::OPEN_NEWTAB);
|
||||
return shouldReuse;
|
||||
}
|
||||
|
||||
- (CHBrowserView*)getBrowserView
|
||||
{
|
||||
return mBrowserView;
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
#include "nsIWebProgressListener2.h"
|
||||
#include "nsIEmbeddingSiteWindow2.h"
|
||||
#include "nsIWindowCreator.h"
|
||||
#include "nsIWindowProvider.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
|
||||
#include "nsIContextMenuListener.h"
|
||||
|
@ -56,6 +57,7 @@ class CHBrowserListener : public nsSupportsWeakReference,
|
|||
public nsIInterfaceRequestor,
|
||||
public nsIWebBrowserChrome,
|
||||
public nsIWindowCreator,
|
||||
public nsIWindowProvider,
|
||||
public nsIEmbeddingSiteWindow2,
|
||||
public nsIWebProgressListener2,
|
||||
public nsIContextMenuListener,
|
||||
|
@ -70,6 +72,7 @@ public:
|
|||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSIWEBBROWSERCHROME
|
||||
NS_DECL_NSIWINDOWCREATOR
|
||||
NS_DECL_NSIWINDOWPROVIDER
|
||||
NS_DECL_NSIEMBEDDINGSITEWINDOW
|
||||
NS_DECL_NSIEMBEDDINGSITEWINDOW2
|
||||
NS_DECL_NSIWEBPROGRESSLISTENER
|
||||
|
|
|
@ -89,10 +89,36 @@ CHBrowserListener::~CHBrowserListener()
|
|||
[mContainer release];
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS11(CHBrowserListener,
|
||||
// Gecko's macros only go to 11, but this baby goes to 12!
|
||||
#define NS_IMPL_QUERY_INTERFACE12(_class, _i1, _i2, _i3, _i4, _i5, _i6, \
|
||||
_i7, _i8, _i9, _i10, _i11, _i12) \
|
||||
NS_INTERFACE_MAP_BEGIN(_class) \
|
||||
NS_INTERFACE_MAP_ENTRY(_i1) \
|
||||
NS_INTERFACE_MAP_ENTRY(_i2) \
|
||||
NS_INTERFACE_MAP_ENTRY(_i3) \
|
||||
NS_INTERFACE_MAP_ENTRY(_i4) \
|
||||
NS_INTERFACE_MAP_ENTRY(_i5) \
|
||||
NS_INTERFACE_MAP_ENTRY(_i6) \
|
||||
NS_INTERFACE_MAP_ENTRY(_i7) \
|
||||
NS_INTERFACE_MAP_ENTRY(_i8) \
|
||||
NS_INTERFACE_MAP_ENTRY(_i9) \
|
||||
NS_INTERFACE_MAP_ENTRY(_i10) \
|
||||
NS_INTERFACE_MAP_ENTRY(_i11) \
|
||||
NS_INTERFACE_MAP_ENTRY(_i12) \
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, _i1) \
|
||||
NS_INTERFACE_MAP_END
|
||||
#define NS_IMPL_ISUPPORTS12(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
|
||||
_i9, _i10, _i11, _i12) \
|
||||
NS_IMPL_ADDREF(_class) \
|
||||
NS_IMPL_RELEASE(_class) \
|
||||
NS_IMPL_QUERY_INTERFACE12(_class, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, \
|
||||
_i9, _i10, _i11, _i12)
|
||||
|
||||
NS_IMPL_ISUPPORTS12(CHBrowserListener,
|
||||
nsIInterfaceRequestor,
|
||||
nsIWebBrowserChrome,
|
||||
nsIWindowCreator,
|
||||
nsIWindowProvider,
|
||||
nsIEmbeddingSiteWindow,
|
||||
nsIEmbeddingSiteWindow2,
|
||||
nsIWebProgressListener,
|
||||
|
@ -168,6 +194,36 @@ CHBrowserListener::CreateChromeWindow(nsIWebBrowserChrome *parent,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//
|
||||
// ProvideWindow
|
||||
//
|
||||
// Called when Gecko wants to open a new window. We check our prefs and if they're
|
||||
// set to reuse the existing window, we ask the container for a dom window (could be an
|
||||
// existing one or from a newly created tab) and tell Gecko to use that. Setting
|
||||
// |outDOMWindow| to NULL tells Gecko to create a new window.
|
||||
//
|
||||
NS_IMETHODIMP
|
||||
CHBrowserListener::ProvideWindow(nsIDOMWindow *inParent, PRUint32 inChromeFlags, PRBool aPositionSpecified, PRBool
|
||||
aSizeSpecified, nsIURI *aURI, const nsAString & aName, const nsACString & aFeatures,
|
||||
PRBool *outWindowIsNew, nsIDOMWindow **outDOMWindow)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(outDOMWindow);
|
||||
*outDOMWindow = NULL;
|
||||
*outWindowIsNew = PR_FALSE;
|
||||
|
||||
// if the container prefers to reuse the existing window, tell it to do so and return
|
||||
// the DOMWindow it gives us. Otherwise we'll let Gecko create a new window.
|
||||
BOOL prefersTabs = [mContainer shouldReuseExistingWindow];
|
||||
if (prefersTabs) {
|
||||
CHBrowserView* newContainer = [mContainer reuseExistingBrowserWindow:inChromeFlags];
|
||||
nsCOMPtr<nsIDOMWindow> contentWindow = [newContainer getContentWindow];
|
||||
*outDOMWindow = contentWindow.get();
|
||||
NS_IF_ADDREF(*outDOMWindow);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Implementation of nsIContextMenuListener
|
||||
NS_IMETHODIMP
|
||||
CHBrowserListener::OnShowContextMenu(PRUint32 aContextFlags, nsIDOMEvent* aEvent, nsIDOMNode* aNode)
|
||||
|
|
|
@ -102,8 +102,16 @@ typedef enum {
|
|||
// Set the dimensions of our NSView. The container might need to do
|
||||
// some adjustment, so the view doesn't do it directly.
|
||||
- (void)sizeBrowserTo:(NSSize)dimensions;
|
||||
|
||||
// Create a new browser container window and return the contained view.
|
||||
- (CHBrowserView*)createBrowserWindow:(unsigned int)mask;
|
||||
// Return the view of the current window, or perhaps a new tab within that window,
|
||||
// in which to load the request.
|
||||
- (CHBrowserView*)reuseExistingBrowserWindow:(unsigned int)mask;
|
||||
|
||||
// Return whether the container prefers to create new windows or to re-use
|
||||
// the existing one (will return YES if implementing "single-window mode")
|
||||
- (BOOL)shouldReuseExistingWindow;
|
||||
|
||||
- (NSMenu*)getContextMenu;
|
||||
- (NSWindow*)getNativeWindow;
|
||||
|
|
Загрузка…
Ссылка в новой задаче