diff --git a/AppKit/CPImage.j b/AppKit/CPImage.j index 2c2c72869..786cd05d5 100644 --- a/AppKit/CPImage.j +++ b/AppKit/CPImage.j @@ -245,8 +245,10 @@ function CPImageInBundle(aFilename, aSize, aBundle) } _image.src = _filename; - - isSynchronous = NO; + + // onload and friends may fire after this point but BEFORE the end of the run loop, + // crazy, I know. So don't set isSynchronous here, rather wait a bit longer. + window.setTimeout(function() { isSynchronous = NO; }, 0); } - (BOOL)isThreePartImage diff --git a/AppKit/Jakefile b/AppKit/Jakefile index 899a0fe9f..bed91b589 100644 --- a/AppKit/Jakefile +++ b/AppKit/Jakefile @@ -4,7 +4,7 @@ require("../common.jake"); $BUILD_PATH = FILE.join($BUILD_DIR, $CONFIGURATION, 'AppKit'); -AppKitFiles = new FileList("**/*.j").exclude('CoreGraphics/CGContextCanvas.j', 'CoreGraphics/CGContextVML.j', 'Themes/**/*', 'Tools/**/*'); +AppKitFiles = new FileList("**/*.j").exclude('CoreGraphics/CGContextCanvas.j', 'CoreGraphics/CGContextVML.j', 'Themes/**/*', 'Tools/**/*', "Platform/DOM/CPPlatform.j", "Platform/DOM/CPPlatformString.j"); appKitTask = framework ("AppKit", function(appKitTask) { diff --git a/AppKit/Platform/CPPlatform+DOM.j b/AppKit/Platform/CPPlatform+DOM.j deleted file mode 100644 index 55c51bfbd..000000000 --- a/AppKit/Platform/CPPlatform+DOM.j +++ /dev/null @@ -1,65 +0,0 @@ -/* - * CPPlatform+DOM.j - * AppKit - * - * Created by Francisco Tolmasky. - * Copyright 2010, 280 North, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -var DOMSafeElement = NULL, - screenNeedsInitialization = [CPPlatform isBrowser]; - -@implementation CPPlatform (DOM) - -+ (DOMElement)DOMSafeElement -{ - if (!DOMSafeElement) - { - DOMSafeElement = document.createElement("div"); - - DOMSafeElement.style.position = "absolute"; - DOMSafeElement.style.left = "-100000px"; - DOMSafeElement.style.top = "-100000px"; - DOMSafeElement.style.overflow = "visible"; - - document.body.appendChild(DOMSafeElement); - } - - return DOMSafeElement; -} - -+ (void)initializeScreenIfNecessary -{ - if (!screenNeedsInitialization) - return; - - screenNeedsInitialization = NO; - - var body = document.body; - - body.removeChild(DOMSafeElement); - - body.innerHTML = ""; // Get rid of anything that might be lingering in the body element. - body.style.overflow = "hidden"; - - body.appendChild(DOMSafeElement); - - if (document.documentElement) - document.documentElement.style.overflow = "hidden"; -} - -@end diff --git a/AppKit/Platform/CPPlatform.j b/AppKit/Platform/CPPlatform.j index 1a0dd3b1c..8bf37856e 100644 --- a/AppKit/Platform/CPPlatform.j +++ b/AppKit/Platform/CPPlatform.j @@ -25,7 +25,7 @@ #include "Platform.h" -@implementation CPPlatform : CPObject +@implementation CPBasePlatform : CPObject { } @@ -37,51 +37,42 @@ + (BOOL)isBrowser { - return typeof window.cpIsDesktop === "undefined"; + return NO; } + (BOOL)supportsDragAndDrop { - return CPFeatureIsCompatible(CPHTMLDragAndDropFeature); + return NO; } + (BOOL)supportsNativeMainMenu { - return (typeof window["cpSetMainMenu"] === "function"); + return NO; } + (void)terminateApplication { - if (typeof window["cpTerminate"] === "function") - window.cpTerminate(); } + (void)activateIgnoringOtherApps:(BOOL)shouldIgnoreOtherApps { -#if PLATFORM(DOM) - if (typeof window["cpActivateIgnoringOtherApps"] === "function") - window.cpActivateIgnoringOtherApps(!!shouldIgnoreOtherApps); -#endif } + (void)hideOtherApplications:(id)aSender { -#if PLATFORM(DOM) - if (typeof window["cpHideOtherApplications"] === "function") - window.cpHideOtherApplications(); -#endif } + (void)hide:(id)aSender { -#if PLATFORM(DOM) - if (typeof window["cpHide"] === "function") - window.cpHide(); -#endif } @end #if PLATFORM(DOM) -@import "CPPlatform+DOM.j" +#include "DOM/CPPlatform.j" +#else +@implementation CPPlatform : CPBasePlatform +{ +} +@end #endif diff --git a/AppKit/Platform/CPPlatformString.j b/AppKit/Platform/CPPlatformString.j index 850fdd4c9..26f85d738 100644 --- a/AppKit/Platform/CPPlatformString.j +++ b/AppKit/Platform/CPPlatformString.j @@ -26,101 +26,26 @@ #include "Platform.h" -#if PLATFORM(DOM) -var DOMIFrameElement = nil, - DOMSpanElement = nil, - DefaultFont = nil; -#endif - -@implementation CPPlatformString : CPObject +@implementation CPBasePlatformString : CPObject { } + (void)bootstrap { -#if PLATFORM(DOM) - var DOMSafeElement = [CPPlatform DOMSafeElement]; - - DOMIFrameElement = document.createElement("iframe"); - - DOMIFrameElement.name = name = "iframe_" + FLOOR(RAND() * 10000); - DOMIFrameElement.style.position = "absolute"; - DOMIFrameElement.style.left = "-100px"; - DOMIFrameElement.style.top = "-100px"; - DOMIFrameElement.style.width = "1px"; - DOMIFrameElement.style.height = "1px"; - DOMIFrameElement.style.borderWidth = "0px"; - DOMIFrameElement.style.background = "blue"; - DOMIFrameElement.style.overflow = "hidden"; - DOMIFrameElement.style.zIndex = 100000000000; - - DOMSafeElement.appendChild(DOMIFrameElement); - - var DOMIFrameDocument = (DOMIFrameElement.contentDocument || DOMIFrameElement.contentWindow.document); - - DOMIFrameDocument.write(""); - DOMIFrameDocument.close(); - - DOMSpanElement = DOMIFrameDocument.createElement("span"); - - DOMSpanElement.style.position = "absolute"; - DOMSpanElement.style.whiteSpace = "pre"; - DOMSpanElement.style.visibility = "visible"; - DOMSpanElement.style.padding = "0px"; - DOMSpanElement.style.margin = "0px"; - DOMSpanElement.style.background = "red"; - - DOMIFrameDocument.body.appendChild(DOMSpanElement); -#endif } + (CGSize)sizeOfString:(CPString)aString withFont:(CPFont)aFont forWidth:(float)aWidth { -#if PLATFORM(DOM) - if (!aFont) - { - if (!DefaultFont) - DefaultFont = [CPFont systemFontOfSize:12.0]; - - aFont = DefaultFont; - } - - var style = DOMSpanElement.style; - - if (aWidth === NULL) - { - style.width = ""; - style.whiteSpace = "pre"; - } - - else - { - style.width = ROUND(aWidth) + "px"; - - if (document.attachEvent) - style.wordWrap = "break-word"; - - else - { - style.whiteSpace = "-o-pre-wrap"; - style.whiteSpace = "-pre-wrap"; - style.whiteSpace = "-moz-pre-wrap"; - style.whiteSpace = "pre-wrap"; - } - } - - style.font = [aFont cssString]; - - if (CPFeatureIsCompatible(CPJavascriptInnerTextFeature)) - DOMSpanElement.innerText = aString; - - else if (CPFeatureIsCompatible(CPJavascriptTextContentFeature)) - DOMSpanElement.textContent = aString; - - return _CGSizeMake(DOMSpanElement.clientWidth, DOMSpanElement.clientHeight); -#else return _CGSizeMakeZero(); -#endif } @end + +#if PLATFORM(DOM) +#include "DOM/CPPlatformString.j" +#else +@implementation CPPlatformString : CPBasePlatformString +{ +} +@end +#endif diff --git a/AppKit/Platform/DOM/CPPlatform.j b/AppKit/Platform/DOM/CPPlatform.j new file mode 100644 index 000000000..e22819943 --- /dev/null +++ b/AppKit/Platform/DOM/CPPlatform.j @@ -0,0 +1,99 @@ +/* + * CPPlatform+DOM.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2010, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +CPPlatformDidClearBodyElementNotification = @"CPPlatformDidClearBodyElementNotification"; + +var screenNeedsInitialization = NO; + +@implementation CPPlatform : CPBasePlatform +{ +} + ++ (void)initialize +{ + if (self !== [CPPlatform class]) + return; + + screenNeedsInitialization = [CPPlatform isBrowser]; +} + ++ (BOOL)isBrowser +{ + return typeof window.cpIsDesktop === "undefined"; +} + ++ (BOOL)supportsDragAndDrop +{ + return CPFeatureIsCompatible(CPHTMLDragAndDropFeature); +} + ++ (BOOL)supportsNativeMainMenu +{ + return (typeof window["cpSetMainMenu"] === "function"); +} + ++ (void)terminateApplication +{ + if (typeof window["cpTerminate"] === "function") + window.cpTerminate(); +} + ++ (void)activateIgnoringOtherApps:(BOOL)shouldIgnoreOtherApps +{ + if (typeof window["cpActivateIgnoringOtherApps"] === "function") + window.cpActivateIgnoringOtherApps(!!shouldIgnoreOtherApps); +} + ++ (void)hideOtherApplications:(id)aSender +{ + if (typeof window["cpHideOtherApplications"] === "function") + window.cpHideOtherApplications(); +} + ++ (void)hide:(id)aSender +{ + if (typeof window["cpHide"] === "function") + window.cpHide(); +} + ++ (void)initializeScreenIfNecessary +{ + if (!screenNeedsInitialization) + return; + + screenNeedsInitialization = NO; + + var DOMBodyElement = document.body; + + // Get rid of any of the original contents of the page. + DOMBodyElement.innerHTML = ""; + DOMBodyElement.style.overflow = "hidden"; + + if (document.documentElement) + document.documentElement.style.overflow = "hidden"; + + [[CPNotificationCenter defaultCenter] + postNotificationName:CPPlatformDidClearBodyElementNotification + object:self]; +} + +@end diff --git a/AppKit/Platform/DOM/CPPlatformString.j b/AppKit/Platform/DOM/CPPlatformString.j new file mode 100644 index 000000000..4e3920aa3 --- /dev/null +++ b/AppKit/Platform/DOM/CPPlatformString.j @@ -0,0 +1,128 @@ +/* + * CPPlatformString.j + * AppKit + * + * Created by Francisco Tolmasky. + * Copyright 2010, 280 North, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "../CoreGraphics/CGGeometry.h" + + +var DOMIFrameElement = nil, + DOMSpanElement = nil, + DefaultFont = nil; + +@implementation CPPlatformString : CPBasePlatformString +{ +} + ++ (void)bootstrap +{ + [self createDOMElements]; + + [[CPNotificationCenter defaultCenter] + addObserver:self + selector:@selector(platformDidClearBodyElement:) + name:CPPlatformDidClearBodyElementNotification + object:CPPlatform]; +} + ++ (void)createDOMElements +{ + var DOMIFrameElement = document.createElement("iframe"); + + DOMIFrameElement.name = name = "iframe_" + FLOOR(RAND() * 10000); + DOMIFrameElement.style.position = "absolute"; + DOMIFrameElement.style.left = "-100px"; + DOMIFrameElement.style.top = "-100px"; + DOMIFrameElement.style.width = "1px"; + DOMIFrameElement.style.height = "1px"; + DOMIFrameElement.style.borderWidth = "0px"; + DOMIFrameElement.style.background = "blue"; + DOMIFrameElement.style.overflow = "hidden"; + DOMIFrameElement.style.zIndex = 100000000000; + + document.body.appendChild(DOMIFrameElement); + + var DOMIFrameDocument = (DOMIFrameElement.contentDocument || DOMIFrameElement.contentWindow.document); + + DOMIFrameDocument.write(""); + DOMIFrameDocument.close(); + + DOMSpanElement = DOMIFrameDocument.createElement("span"); + + DOMSpanElement.style.position = "absolute"; + DOMSpanElement.style.whiteSpace = "pre"; + DOMSpanElement.style.visibility = "visible"; + DOMSpanElement.style.padding = "0px"; + DOMSpanElement.style.margin = "0px"; + + DOMIFrameDocument.body.appendChild(DOMSpanElement); +} + ++ (void)platformDidClearBodyElement:(CPNotification)aNotification +{ + [self createDOMElements]; +} + ++ (CGSize)sizeOfString:(CPString)aString withFont:(CPFont)aFont forWidth:(float)aWidth +{ + if (!aFont) + { + if (!DefaultFont) + DefaultFont = [CPFont systemFontOfSize:12.0]; + + aFont = DefaultFont; + } + + var style = DOMSpanElement.style; + + if (aWidth === NULL) + { + style.width = ""; + style.whiteSpace = "pre"; + } + + else + { + style.width = ROUND(aWidth) + "px"; + + if (document.attachEvent) + style.wordWrap = "break-word"; + + else + { + style.whiteSpace = "-o-pre-wrap"; + style.whiteSpace = "-pre-wrap"; + style.whiteSpace = "-moz-pre-wrap"; + style.whiteSpace = "pre-wrap"; + } + } + + style.font = [aFont cssString]; + + if (CPFeatureIsCompatible(CPJavascriptInnerTextFeature)) + DOMSpanElement.innerText = aString; + + else if (CPFeatureIsCompatible(CPJavascriptTextContentFeature)) + DOMSpanElement.textContent = aString; + + return _CGSizeMake(DOMSpanElement.clientWidth, DOMSpanElement.clientHeight); +} + +@end diff --git a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j index 3e38df165..a56853597 100644 --- a/AppKit/Platform/DOM/CPPlatformWindow+DOM.j +++ b/AppKit/Platform/DOM/CPPlatformWindow+DOM.j @@ -228,28 +228,10 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; _DOMWindow.blur(); } -- (void)DOMSafeElement -{ - if (_DOMWindow === window) - return [CPPlatform DOMSafeElement]; - - return _DOMBodyElement; -} - -- (void)registerDOMWindow +- (void)createDOMElements { var theDocument = _DOMWindow.document; - _DOMBodyElement = theDocument.getElementsByTagName("body")[0]; - - var DOMSafeElement = [self DOMSafeElement]; - - // FIXME: Always do this? - if ([CPPlatform supportsDragAndDrop]) - _DOMBodyElement.style["-khtml-user-select"] = "none"; - - _DOMBodyElement.webkitTouchCallout = "none"; - // This guy fixes an issue in Firefox where if you focus the URL field, we stop getting key events _DOMFocusElement = theDocument.createElement("input"); @@ -257,8 +239,8 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; _DOMFocusElement.style.zIndex = "-1000"; _DOMFocusElement.style.opacity = "0"; _DOMFocusElement.style.filter = "alpha(opacity=0)"; - - DOMSafeElement.appendChild(_DOMFocusElement); + + _DOMBodyElement.appendChild(_DOMFocusElement); // Create Native Pasteboard handler. _DOMPasteboardElement = theDocument.createElement("textarea"); @@ -267,10 +249,37 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; _DOMPasteboardElement.style.top = "-10000px"; _DOMPasteboardElement.style.zIndex = "999"; - DOMSafeElement.appendChild(_DOMPasteboardElement); + _DOMBodyElement.appendChild(_DOMPasteboardElement); // Make sure the pastboard element is blurred. _DOMPasteboardElement.blur(); +} + +- (void)platformDidClearBodyElement:(CPNotification)aNotification +{ + [self createDOMElements]; +} + +- (void)registerDOMWindow +{ + var theDocument = _DOMWindow.document; + + _DOMBodyElement = theDocument.body; + + // FIXME: Always do this? + if ([CPPlatform supportsDragAndDrop]) + _DOMBodyElement.style["-khtml-user-select"] = "none"; + + _DOMBodyElement.webkitTouchCallout = "none"; + + [self createDOMElements]; + + if (window === _DOMWindow) + [[CPNotificationCenter defaultCenter] + addObserver:self + selector:@selector(platformDidClearBodyElement:) + name:CPPlatformDidClearBodyElementNotification + object:CPPlatform]; [self _addLayers]; @@ -488,7 +497,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; DOMDragElement.style.left = -_CGRectGetWidth(draggedWindowFrame) + "px"; DOMDragElement.style.top = -_CGRectGetHeight(draggedWindowFrame) + "px"; - document.getElementsByTagName("body")[0].appendChild(DOMDragElement); + document.body.appendChild(DOMDragElement); var draggingOffset = [dragServer draggingOffset]; @@ -709,7 +718,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; if (StopDOMEventPropagation) CPDOMEventStop(aDOMEvent, self); - + [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode]; } @@ -896,7 +905,7 @@ var supportsNativeDragAndDrop = [CPPlatform supportsDragAndDrop]; if (StopDOMEventPropagation) CPDOMEventStop(aDOMEvent, self); - + [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode]; }