Skip to content

Commit

Permalink
Add content shell notes and files.
Browse files Browse the repository at this point in the history
  • Loading branch information
gruehle committed May 25, 2012
1 parent f995f39 commit 59f7ba4
Show file tree
Hide file tree
Showing 6 changed files with 1,107 additions and 0 deletions.
97 changes: 97 additions & 0 deletions src/mac/content_shell/ShellProtoNotes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
Setup
-----
Get/Build Chromium (Content project is all you need)
Set target SDK to 10.6


Changes to build brackets shell
-------------------------------
- copy brackets_shell_mac.mm from node-shell/content_shell to chromium/src/content/shell
- copy node directory from node-shell into chromium/src/content/shell
- copy NodeWrapper.m/.h from node-shell into chromium/src/content/shell
- make sure the correct line is un-commented in NodeWrapper.m processCommand
- copy server directory from node-shell into chromium/src/content/shell

- Update content_shell.gypi with the following changes: (or use content_shell.gypi from node-shell)
- Replace "shell_mac.mm" with "brackets_shell_mac.mm"
- Add the following to 'mac_bundle_resources', after 'shell/mac/ap-Info.plist':
'shell/server/appProxy.js', # Brackets
'shell/server/clientProxy.js', # Brackets
'shell/server/config.js', # Brackets
'shell/server/server.js', # Brackets

- Add the following after the "Make sure there isn't any Objective-C in the shell" build step:
{ # Brackets begin
# Copy node
'postbuild_name': 'Copy node',
'action': [
'cp',
'shell/node/node',
'$BUILT_PRODUCTS_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/node-executable',
],
},
{
# Copy node modules
'postbuild_name': 'Copy node modules',
'action': [
'cp',
'-r',
'shell/node/node_modules',
'$BUILT_PRODUCTS_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/',
],
} # Brackets end

- Add 'shell/NodeWrapper.m' to content_shell.gypi (under brackets_shell_mac.mm)

- Add to shell_browser_main_parts_mac.mm (or use from node-shell)
#include "content/shell/NodeWrapper.h

in PreMainMessageLoopStart:
NodeWrapper *node = [[NodeWrapper alloc] init];
[node start];

- Add to shell_application_mac.h (before @end) (or use from node-shell)
- (void)goToURL:(NSString*)url;

- Add to shell_application_mac.mm (before @end) (or use from node-shell)

- (void)goToURL:(NSString *)url {
NSWindow* aWindow = [self mainWindow];

// Early in startup, mainWindow is nil. In that case, grab the first
// window from the 'windows' array
NSArray* someWindows = [self windows];

if (!aWindow && someWindows) {
aWindow = [someWindows objectAtIndex:0];
}

if (aWindow) {
[[aWindow delegate] performSelector: @selector(goToURL:) withObject:url];
}
}




Building
--------

All commands to be run from ~/chromium/src

From XCode
----------
# update projects
gclient runhooks

# open project in xcode and build

From Command Line
-----------------

# update projects
GYP_GENERATORS=ninja GYP_DEFINES=mac_sdk=10.6 ./build/gyp_chromium

# build
ninja -C out/Debug content_shell
(use out/Release for release build)
279 changes: 279 additions & 0 deletions src/mac/content_shell/brackets_shell_mac.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,279 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/shell/shell.h"

#include <algorithm>

#include "base/logging.h"
#import "base/mac/cocoa_protocols.h"
#import "base/memory/scoped_nsobject.h"
#include "base/string_piece.h"
#include "base/sys_string_conversions.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "content/shell/resource.h"
#include "googleurl/src/gurl.h"
#import "ui/base/cocoa/underlay_opengl_hosting_window.h"
#include "NodeWrapper.h"

#define SHOW_BROWSER_UI

// Receives notification that the window is closing so that it can start the
// tear-down process. Is responsible for deleting itself when done.
@interface ContentShellWindowDelegate : NSObject<NSWindowDelegate> {
@private
content::Shell* shell_;
}
- (id)initWithShell:(content::Shell*)shell;
- (void)goToURL:(NSString*)url;
@end

@implementation ContentShellWindowDelegate

- (id)initWithShell:(content::Shell*)shell {
if ((self = [super init])) {
shell_ = shell;
}
return self;
}

// Called when the window is about to close. Perform the self-destruction
// sequence by getting rid of the shell and removing it and the window from
// the various global lists. Instead of doing it here, however, we fire off
// a delayed call to |-cleanup:| to allow everything to get off the stack
// before we go deleting objects. By returning YES, we allow the window to be
// removed from the screen.
- (BOOL)windowShouldClose:(id)window {
[window autorelease];

// Clean ourselves up and do the work after clearing the stack of anything
// that might have the shell on it.
[self performSelectorOnMainThread:@selector(cleanup:)
withObject:window
waitUntilDone:NO];

return YES;
}

// Does the work of removing the window from our various bookkeeping lists
// and gets rid of the shell.
- (void)cleanup:(id)window {
delete shell_;

[self release];
}

- (void)performAction:(id)sender {
shell_->ActionPerformed([sender tag]);
}

- (void)takeURLStringValueFrom:(id)sender {
shell_->URLEntered(base::SysNSStringToUTF8([sender stringValue]));
}

- (void)goToURL:(NSString*)url {
shell_->URLEntered(base::SysNSStringToUTF8(url));
}

@end

namespace {

NSString* kWindowTitle = @"Brackets";

// Layout constants (in view coordinates)
const CGFloat kButtonWidth = 72;
const CGFloat kURLBarHeight = 24;

// The minimum size of the window's content (in view coordinates)
const CGFloat kMinimumWindowWidth = 400;
const CGFloat kMinimumWindowHeight = 300;

#ifdef SHOW_BROWSER_UI
void MakeShellButton(NSRect* rect,
NSString* title,
NSView* parent,
int control,
NSView* target) {
scoped_nsobject<NSButton> button([[NSButton alloc] initWithFrame:*rect]);
[button setTitle:title];
[button setBezelStyle:NSSmallSquareBezelStyle];
[button setAutoresizingMask:(NSViewMaxXMargin | NSViewMinYMargin)];
[button setTarget:target];
[button setAction:@selector(performAction:)];
[button setTag:control];
[parent addSubview:button];
rect->origin.x += kButtonWidth;
}
#endif // SHOW_BROWSER_UI

} // namespace

namespace content {

void Shell::PlatformInitialize() {
}

base::StringPiece Shell::PlatformResourceProvider(int key) {
return base::StringPiece();
}

void Shell::PlatformCleanUp() {
}

void Shell::PlatformEnableUIControl(UIControl control, bool is_enabled) {
#ifdef SHOW_BROWSER_UI
int id;
switch (control) {
case BACK_BUTTON:
id = IDC_NAV_BACK;
break;
case FORWARD_BUTTON:
id = IDC_NAV_FORWARD;
break;
case STOP_BUTTON:
id = IDC_NAV_STOP;
break;
default:
NOTREACHED() << "Unknown UI control";
return;
}
[[[window_ contentView] viewWithTag:id] setEnabled:is_enabled];
#endif // SHOW_BROWSER_UI
}

void Shell::PlatformSetAddressBarURL(const GURL& url) {
#ifdef SHOW_BROWSER_UI
NSString* url_string = base::SysUTF8ToNSString(url.spec());
[url_edit_view_ setStringValue:url_string];
#endif // SHOW_BROWSER_UI
}

void Shell::PlatformSetIsLoading(bool loading) {
}

void Shell::PlatformCreateWindow(int width, int height) {
NSRect initial_window_bounds = NSMakeRect(0, 0, width, height);
window_ = [[UnderlayOpenGLHostingWindow alloc]
initWithContentRect:initial_window_bounds
styleMask:(NSTitledWindowMask |
NSClosableWindowMask |
NSMiniaturizableWindowMask |
NSResizableWindowMask )
backing:NSBackingStoreBuffered
defer:NO];
[window_ setTitle:kWindowTitle];
NSView* content = [window_ contentView];

// If the window is allowed to get too small, it will wreck the view bindings.
NSSize min_size = NSMakeSize(kMinimumWindowWidth, kMinimumWindowHeight);
min_size = [content convertSize:min_size toView:nil];
// Note that this takes window coordinates.
[window_ setContentMinSize:min_size];

// Rely on the window delegate to clean us up rather than immediately
// releasing when the window gets closed. We use the delegate to do
// everything from the autorelease pool so the shell isn't on the stack
// during cleanup (ie, a window close from javascript).
[window_ setReleasedWhenClosed:NO];

// Create a window delegate to watch for when it's asked to go away. It will
// clean itself up so we don't need to hold a reference.
ContentShellWindowDelegate* delegate =
[[ContentShellWindowDelegate alloc] initWithShell:this];
[window_ setDelegate:delegate];

#ifdef SHOW_BROWSER_UI
NSRect button_frame =
NSMakeRect(0, NSMaxY(initial_window_bounds) - kURLBarHeight,
kButtonWidth, kURLBarHeight);

MakeShellButton(&button_frame, @"Back", content, IDC_NAV_BACK,
(NSView*)delegate);
MakeShellButton(&button_frame, @"Forward", content, IDC_NAV_FORWARD,
(NSView*)delegate);
MakeShellButton(&button_frame, @"Reload", content, IDC_NAV_RELOAD,
(NSView*)delegate);
MakeShellButton(&button_frame, @"Stop", content, IDC_NAV_STOP,
(NSView*)delegate);

button_frame.size.width =
NSWidth(initial_window_bounds) - NSMinX(button_frame);
scoped_nsobject<NSTextField> url_edit_view(
[[NSTextField alloc] initWithFrame:button_frame]);
[content addSubview:url_edit_view];
[url_edit_view setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)];
[url_edit_view setTarget:delegate];
[url_edit_view setAction:@selector(takeURLStringValueFrom:)];
[[url_edit_view cell] setWraps:NO];
[[url_edit_view cell] setScrollable:YES];
url_edit_view_ = url_edit_view.get();
#endif // SHOW_BROWSER_UI
// show the window
[window_ makeKeyAndOrderFront:nil];
}

void Shell::PlatformSetContents() {
NSView* web_view = web_contents_->GetView()->GetNativeView();
NSView* content = [window_ contentView];
[content addSubview:web_view];

NSRect frame = [content bounds];
#ifdef SHOW_BROWSER_UI
frame.size.height -= kURLBarHeight;
#endif // SHOW_BROWSER_UI
[web_view setFrame:frame];
[web_view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
[web_view setNeedsDisplay:YES];
}

void Shell::PlatformResizeSubViews() {
// Not needed; subviews are bound.
}

void Shell::Close() {
[window_ performClose:nil];
}

void Shell::ActionPerformed(int control) {
#ifdef SHOW_BROWSER_UI
switch (control) {
case IDC_NAV_BACK:
GoBackOrForward(-1);
break;
case IDC_NAV_FORWARD:
GoBackOrForward(1);
break;
case IDC_NAV_RELOAD:
Reload();
break;
case IDC_NAV_STOP:
Stop();
break;
}
#endif
}

void Shell::URLEntered(std::string url_string) {
if (!url_string.empty()) {
GURL url(url_string);
if (!url.has_scheme())
url = GURL("http://" + url_string);
LoadURL(url);
}
}

void Shell::HandleKeyboardEvent(const NativeWebKeyboardEvent& event) {
if (event.skip_in_browser)
return;

// The event handling to get this strictly right is a tangle; cheat here a bit
// by just letting the menus have a chance at it.
if ([event.os_event type] == NSKeyDown)
[[NSApp mainMenu] performKeyEquivalent:event.os_event];
}

} // namespace content
Loading

0 comments on commit 59f7ba4

Please sign in to comment.