00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 @import <Foundation/CPObject.j>
00024 @import <Foundation/CPRunLoop.j>
00025
00026 @import "CPEvent.j"
00027 @import "CPCompatibility.j"
00028
00029 @import "CPDOMWindowLayer.j"
00030
00031 #import "../../CoreGraphics/CGGeometry.h"
00032
00033
00034 CPSharedDOMWindowBridge = nil;
00035
00036 var ExcludedDOMElements = [];
00037
00038
00039 var CPDOMWindowGetFrame,
00040 CPDOMEventGetClickCount,
00041 CPDOMEventStop;
00042
00043 @implementation CPDOMWindowBridge : CPObject
00044 {
00045 CPArray _orderedWindows;
00046 CPWindow _mouseDownWindow;
00047
00048 DOMWindow _DOMWindow;
00049 DOMElement _DOMBodyElement;
00050 DOMElement _DOMFocusElement;
00051
00052 CPArray _windowLevels;
00053 CPDictionary _windowLayers;
00054
00055 CPRect _frame;
00056 CPRect _contentBounds;
00057
00058 BOOL _mouseIsDown;
00059 CPTimeInterval _lastMouseUp;
00060 CPTimeInterval _lastMouseDown;
00061
00062 JSObject _charCodes;
00063 unsigned _keyCode;
00064
00065 BOOL _DOMEventMode;
00066
00067
00068 DOMElement _DOMPasteboardElement;
00069 CPEvent _pasteboardKeyDownEvent;
00070
00071 CPString _overriddenEventType;
00072 }
00073
00077 + (id)sharedDOMWindowBridge
00078 {
00079 if (!CPSharedDOMWindowBridge)
00080 CPSharedDOMWindowBridge = [[CPDOMWindowBridge alloc] _initWithDOMWindow:window];
00081
00082 return CPSharedDOMWindowBridge;
00083 }
00084
00085 - (id)initWithFrame:(CPRect)aFrame
00086 {
00087 alert("unimplemented");
00088 }
00089
00090
00091 - (id)_initWithDOMWindow:(DOMWindow)aDOMWindow
00092 {
00093 self = [super init];
00094
00095 if (self)
00096 {
00097 _DOMWindow = aDOMWindow;
00098
00099 _windowLevels = [];
00100 _windowLayers = [CPDictionary dictionary];
00101
00102
00103 _DOMBodyElement = document.getElementsByTagName("body")[0];
00104 _DOMBodyElement.innerHTML = "";
00105 _DOMBodyElement.style.overflow = "hidden";
00106 _DOMBodyElement.style.webkitTouchCallout = "none";
00107
00108 [CPString _resetSize];
00109
00110 if (document.documentElement)
00111 document.documentElement.style.overflow = "hidden";
00112
00113 _frame = CPDOMWindowGetFrame(_DOMWindow);
00114 _contentBounds = CGRectMake(0.0, 0.0, CPRectGetWidth(_frame), CPRectGetHeight(_frame));
00115
00116 _DOMFocusElement = document.createElement("input");
00117 _DOMFocusElement.style.position = "absolute";
00118 _DOMFocusElement.style.zIndex = "-1000";
00119 _DOMFocusElement.style.opacity = "0";
00120 _DOMFocusElement.style.filter = "alpha(opacity=0)";
00121 _DOMBodyElement.appendChild(_DOMFocusElement);
00122
00123
00124 _DOMPasteboardElement = document.createElement("input");
00125 _DOMPasteboardElement.style.position = "absolute";
00126 _DOMPasteboardElement.style.top = "-10000px";
00127 _DOMPasteboardElement.style.zIndex = "99";
00128
00129 _DOMBodyElement.appendChild(_DOMPasteboardElement);
00130
00131
00132 _DOMPasteboardElement.blur();
00133
00134 _charCodes = {};
00135
00136
00137 var theClass = [self class],
00138
00139 keyEventSelector = @selector(_bridgeKeyEvent:),
00140 keyEventImplementation = class_getMethodImplementation(theClass, keyEventSelector),
00141 keyEventCallback = function (anEvent) { keyEventImplementation(self, nil, anEvent); },
00142
00143 mouseEventSelector = @selector(_bridgeMouseEvent:),
00144 mouseEventImplementation = class_getMethodImplementation(theClass, mouseEventSelector),
00145 mouseEventCallback = function (anEvent) { mouseEventImplementation(self, nil, anEvent); },
00146
00147 scrollEventSelector = @selector(_bridgeScrollEvent:),
00148 scrollEventImplementation = class_getMethodImplementation(theClass, scrollEventSelector),
00149 scrollEventCallback = function (anEvent) { scrollEventImplementation(self, nil, anEvent); },
00150
00151 resizeEventSelector = @selector(_bridgeResizeEvent:),
00152 resizeEventImplementation = class_getMethodImplementation(theClass, resizeEventSelector),
00153 resizeEventCallback = function (anEvent) { resizeEventImplementation(self, nil, anEvent); },
00154
00155 touchEventSelector = @selector(_bridgeTouchEvent:),
00156 touchEventImplementation = class_getMethodImplementation(theClass, touchEventSelector),
00157 touchEventCallback = function (anEvent) { touchEventImplementation(self, nil, anEvent); },
00158
00159 theDocument = _DOMWindow.document;
00160
00161 if (document.addEventListener)
00162 {
00163 _DOMWindow.addEventListener("resize", resizeEventCallback, NO);
00164
00165 theDocument.addEventListener(CPDOMEventMouseUp, mouseEventCallback, NO);
00166 theDocument.addEventListener(CPDOMEventMouseDown, mouseEventCallback, NO);
00167 theDocument.addEventListener(CPDOMEventMouseMoved, mouseEventCallback, NO);
00168
00169 theDocument.addEventListener(CPDOMEventKeyUp, keyEventCallback, NO);
00170 theDocument.addEventListener(CPDOMEventKeyDown, keyEventCallback, NO);
00171 theDocument.addEventListener(CPDOMEventKeyPress, keyEventCallback, NO);
00172
00173
00174 theDocument.addEventListener(CPDOMEventTouchStart, touchEventCallback, NO);
00175 theDocument.addEventListener(CPDOMEventTouchEnd, touchEventCallback, NO);
00176 theDocument.addEventListener(CPDOMEventTouchMove, touchEventCallback, NO);
00177 theDocument.addEventListener(CPDOMEventTouchCancel, touchEventCallback, NO);
00178
00179
00180 _DOMWindow.addEventListener("DOMMouseScroll", scrollEventCallback, NO);
00181 _DOMWindow.addEventListener(CPDOMEventScrollWheel, scrollEventCallback, NO);
00182 }
00183 else if(document.attachEvent)
00184 {
00185 _DOMWindow.attachEvent("onresize", resizeEventCallback);
00186
00187 theDocument.attachEvent("on" + CPDOMEventMouseUp, mouseEventCallback);
00188 theDocument.attachEvent("on" + CPDOMEventMouseDown, mouseEventCallback);
00189 theDocument.attachEvent("on" + CPDOMEventMouseMoved, mouseEventCallback);
00190 theDocument.attachEvent("on" + CPDOMEventDoubleClick, mouseEventCallback);
00191
00192 theDocument.attachEvent("on" + CPDOMEventKeyUp, keyEventCallback);
00193 theDocument.attachEvent("on" + CPDOMEventKeyDown, keyEventCallback);
00194 theDocument.attachEvent("on" + CPDOMEventKeyPress, keyEventCallback);
00195
00196 _DOMWindow.onmousewheel = scrollEventCallback;
00197 theDocument.onmousewheel = scrollEventCallback;
00198
00199 theDocument.body.ondrag = function () { return NO; };
00200 theDocument.body.onselectstart = function () { return window.event.srcElement == _DOMPasteboardElement; };
00201 }
00202
00203 ExcludedDOMElements["INPUT"] = YES;
00204 ExcludedDOMElements["SELECT"] = YES;
00205 ExcludedDOMElements["TEXTAREA"] = YES;
00206 ExcludedDOMElements["OPTION"] = YES;
00207 }
00208
00209 return self;
00210 }
00211
00212 - (CPRect)frame
00213 {
00214 return CGRectMakeCopy(_frame);
00215 }
00216
00217 - (CGRect)visibleFrame
00218 {
00219 var frame = [self frame];
00220
00221 frame.origin = CGPointMakeZero();
00222
00223 if ([CPMenu menuBarVisible])
00224 {
00225 var menuBarHeight = [[CPApp mainMenu] menuBarHeight];
00226
00227 frame.origin.y += menuBarHeight;
00228 frame.size.height -= menuBarHeight;
00229 }
00230
00231 return frame;
00232 }
00233
00234 - (CPRect)contentBounds
00235 {
00236 return CPRectCreateCopy(_contentBounds);
00237 }
00238
00239 - (CPArray)orderedWindowsAtLevel:(int)aLevel
00240 {
00241 var layer = [self layerAtLevel:aLevel create:NO];
00242
00243 if (!layer)
00244 return [];
00245
00246 return [layer orderedWindows];
00247 }
00248
00249 - (CPDOMWindowLayer)layerAtLevel:(int)aLevel create:(BOOL)aFlag
00250 {
00251 var layer = [_windowLayers objectForKey:aLevel];
00252
00253
00254
00255 if (!layer && aFlag)
00256 {
00257 layer = [[CPDOMWindowLayer alloc] initWithLevel:aLevel];
00258
00259 [_windowLayers setObject:layer forKey:aLevel];
00260
00261
00262
00263 var low = 0,
00264 high = _windowLevels.length - 1,
00265 middle;
00266
00267 while (low <= high)
00268 {
00269 middle = FLOOR((low + high) / 2);
00270
00271 if (_windowLevels[middle] > aLevel)
00272 high = middle - 1;
00273 else
00274 low = middle + 1;
00275 }
00276
00277 [_windowLevels insertObject:aLevel atIndex:_windowLevels[middle] > aLevel ? middle : middle + 1];
00278 layer._DOMElement.style.zIndex = aLevel;
00279 _DOMBodyElement.appendChild(layer._DOMElement);
00280 }
00281
00282 return layer;
00283 }
00284
00285 - (void)order:(CPWindowOrderingMode)aPlace window:(CPWindow)aWindow relativeTo:(CPWindow)otherWindow
00286 {
00287
00288
00289 var layer = [self layerAtLevel:[aWindow level] create:aPlace != CPWindowOut];
00290
00291
00292
00293 if (aPlace == CPWindowOut)
00294 return [layer removeWindow:aWindow];
00295
00296
00297 [layer insertWindow:aWindow atIndex:(otherWindow ? (aPlace == CPWindowAbove ? otherWindow._index + 1 : otherWindow._index) : CPNotFound)];
00298 }
00299
00300
00301 - (id)_dragHitTest:(CPPoint)aPoint pasteboard:(CPPasteboard)aPasteboard
00302 {
00303 var levels = _windowLevels,
00304 layers = _windowLayers,
00305 levelCount = levels.length;
00306
00307 while (levelCount--)
00308 {
00309
00310 if (levels[levelCount] >= CPDraggingWindowLevel)
00311 continue;
00312
00313 var windows = [layers objectForKey:levels[levelCount]]._windows,
00314 windowCount = windows.length;
00315
00316 while (windowCount--)
00317 {
00318 var theWindow = windows[windowCount];
00319
00320 if ([theWindow containsPoint:aPoint])
00321 return [theWindow _dragHitTest:aPoint pasteboard:aPasteboard];
00322 }
00323 }
00324
00325 return nil;
00326 }
00327
00328
00329 - (void)_propagateCurrentDOMEvent:(BOOL)aFlag
00330 {
00331 StopDOMEventPropagation = !aFlag;
00332 }
00333
00334 - (CPWindow)hitTest:(CPPoint)location
00335 {
00336 var levels = _windowLevels,
00337 layers = _windowLayers,
00338 levelCount = levels.length,
00339 theWindow = nil;
00340
00341 while (levelCount-- && !theWindow)
00342 {
00343 var windows = [layers objectForKey:levels[levelCount]]._windows,
00344 windowCount = windows.length;
00345
00346 while (windowCount-- && !theWindow)
00347 {
00348 var candidateWindow = windows[windowCount];
00349
00350 if (!candidateWindow._ignoresMouseEvents && [candidateWindow containsPoint:location])
00351 theWindow = candidateWindow;
00352 }
00353 }
00354
00355 return theWindow;
00356 }
00357
00358 @end
00359
00360 var CPDOMWindowGetFrame = function(_DOMWindow)
00361 {
00362 var frame = nil;
00363
00364
00365 if (_DOMWindow.outerWidth)
00366 frame = CGRectMake(0, 0, _DOMWindow.outerWidth, _DOMWindow.outerHeight);
00367
00368 else
00369 frame = CGRectMake(0, 0, -1, -1);
00370
00371 if (window.screenTop)
00372 frame.origin = CGPointMake(_DOMWindow.screenLeft, _DOMWindow.screenTop, 0);
00373
00374 else if (window.screenX)
00375 frame.origin = CGPointMake(_DOMWindow.screenX, _DOMWindow.screenY, 0);
00376
00377
00378 if (_DOMWindow.innerWidth)
00379 frame.size = CGSizeMake(_DOMWindow.innerWidth, _DOMWindow.innerHeight);
00380
00381
00382 else if (document.documentElement && document.documentElement.clientWidth)
00383 frame.size = CGSizeMake(_DOMWindow.document.documentElement.clientWidth, _DOMWindow.document.documentElement.clientHeight);
00384
00385
00386 else
00387 frame.size = CGSizeMake(_DOMWindow.document.body.clientWidth, _DOMWindow.document.body.clientHeight);
00388
00389 return frame;
00390 }
00391
00392
00393
00394
00395 var KeyCodesToPrevent = {},
00396 CharacterKeysToPrevent = {},
00397 KeyCodesWithoutKeyPressEvents = { '8':1, '9':1, '37':1, '38':1, '39':1, '40':1, '46':1, '33':1, '34':1 };
00398
00399 var CTRL_KEY_CODE = 17;
00400
00401 @implementation CPDOMWindowBridge (Events)
00402
00410 - (void)preventCharacterKeysFromPropagating:(CPArray)characters
00411 {
00412 for(var i=characters.length; i>0; i--)
00413 CharacterKeysToPrevent[""+characters[i-1].toLowerCase()] = YES;
00414 }
00415
00419 - (void)preventCharacterKeyFromPropagating:(CPString)character
00420 {
00421 CharacterKeysToPrevent[character.toLowerCase()] = YES;
00422 }
00423
00427 - (void)clearCharacterKeysToPreventFromPropagating
00428 {
00429 CharacterKeysToPrevent = {};
00430 }
00431
00436 - (void)preventKeyCodesFromPropagating:(CPArray)keyCodes
00437 {
00438 for(var i=keyCodes.length; i>0; i--)
00439 KeyCodesToPrevent[keyCodes[i-1]] = YES;
00440 }
00441
00446 - (void)preventKeyCodeFromPropagating:(CPString)keyCode
00447 {
00448 KeyCodesToPrevent[keyCode] = YES;
00449 }
00450
00454 - (void)clearKeyCodesToPreventFromPropagating
00455 {
00456 KeyCodesToPrevent = {};
00457 }
00458
00459
00460 - (void)_bridgeMouseEvent:(DOMEvent)aDOMEvent
00461 {
00462 var theType = _overriddenEventType || aDOMEvent.type;
00463
00464
00465 if (theType == CPDOMEventDoubleClick)
00466 {
00467 _overriddenEventType = CPDOMEventMouseDown;
00468 [self _bridgeMouseEvent:aDOMEvent];
00469
00470 _overriddenEventType = CPDOMEventMouseUp;
00471 [self _bridgeMouseEvent:aDOMEvent];
00472
00473 _overriddenEventType = nil;
00474
00475 return;
00476 }
00477
00478 try
00479 {
00480 var event,
00481 location = _CGPointMake(aDOMEvent.clientX, aDOMEvent.clientY),
00482 timestamp = aDOMEvent.timeStamp ? aDOMEvent.timeStamp : new Date(),
00483 sourceElement = (aDOMEvent.target || aDOMEvent.srcElement),
00484 windowNumber = 0,
00485 modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) |
00486 (aDOMEvent.ctrlKey ? CPControlKeyMask : 0) |
00487 (aDOMEvent.altKey ? CPAlternateKeyMask : 0) |
00488 (aDOMEvent.metaKey ? CPCommandKeyMask : 0);
00489
00490 StopDOMEventPropagation = YES;
00491
00492 if (_mouseDownWindow)
00493 windowNumber = [_mouseDownWindow windowNumber];
00494 else
00495 {
00496 var theWindow = [self hitTest:location];
00497
00498 if (aDOMEvent.type == CPDOMEventMouseDown && theWindow)
00499 _mouseDownWindow = theWindow;
00500
00501 windowNumber = [theWindow windowNumber];
00502 }
00503
00504 if (windowNumber)
00505 {
00506 var windowFrame = CPApp._windows[windowNumber]._frame;
00507
00508 location.x -= _CGRectGetMinX(windowFrame);
00509 location.y -= _CGRectGetMinY(windowFrame);
00510 }
00511
00512 switch (theType)
00513 {
00514 case CPDOMEventMouseUp: if(_mouseIsDown)
00515 {
00516 event = [CPEvent mouseEventWithType:CPLeftMouseUp location:location modifierFlags:modifierFlags
00517 timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1
00518 clickCount:CPDOMEventGetClickCount(_lastMouseUp, timestamp, location) pressure:0];
00519
00520 _mouseIsDown = NO;
00521 _lastMouseUp = event;
00522 _mouseDownWindow = nil;
00523 }
00524
00525 if(_DOMEventMode)
00526 {
00527 _DOMEventMode = NO;
00528 return;
00529 }
00530
00531 break;
00532
00533 case CPDOMEventMouseDown: if (ExcludedDOMElements[sourceElement.tagName] && sourceElement != _DOMFocusElement)
00534 {
00535 _DOMEventMode = YES;
00536 _mouseIsDown = YES;
00537
00538
00539 [CPApp sendEvent:[CPEvent mouseEventWithType:CPLeftMouseDown location:location modifierFlags:modifierFlags
00540 timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1
00541 clickCount:CPDOMEventGetClickCount(_lastMouseDown, timestamp, location) pressure:0]];
00542
00543 [CPApp sendEvent:[CPEvent mouseEventWithType:CPLeftMouseUp location:location modifierFlags:modifierFlags
00544 timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1
00545 clickCount:CPDOMEventGetClickCount(_lastMouseDown, timestamp, location) pressure:0]];
00546
00547 return;
00548 }
00549
00550 event = [CPEvent mouseEventWithType:CPLeftMouseDown location:location modifierFlags:modifierFlags
00551 timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1
00552 clickCount:CPDOMEventGetClickCount(_lastMouseDown, timestamp, location) pressure:0];
00553
00554 _mouseIsDown = YES;
00555 _lastMouseDown = event;
00556
00557 break;
00558
00559 case CPDOMEventMouseMoved: if (_DOMEventMode)
00560 return;
00561
00562 event = [CPEvent mouseEventWithType:_mouseIsDown ? CPLeftMouseDragged : CPMouseMoved
00563 location:location modifierFlags:modifierFlags timestamp:timestamp
00564 windowNumber:windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0];
00565
00566 break;
00567 }
00568
00569 if (event)
00570 {
00571 event._DOMEvent = aDOMEvent;
00572
00573 [CPApp sendEvent:event];
00574 }
00575
00576 if (StopDOMEventPropagation)
00577 CPDOMEventStop(aDOMEvent);
00578
00579 [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
00580 }
00581 catch (anException)
00582 {
00583 objj_exception_report(anException, {path:@"CPDOMWindowBridge.j"});
00584 }
00585 }
00586
00587
00588 - (void)_bridgeKeyEvent:(DOMEvent)aDOMEvent
00589 {
00590 try
00591 {
00592 var event,
00593 timestamp = aDOMEvent.timeStamp ? aDOMEvent.timeStamp : new Date(),
00594 sourceElement = (aDOMEvent.target || aDOMEvent.srcElement),
00595 windowNumber = [[CPApp keyWindow] windowNumber],
00596 modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) |
00597 (aDOMEvent.ctrlKey ? CPControlKeyMask : 0) |
00598 (aDOMEvent.altKey ? CPAlternateKeyMask : 0) |
00599 (aDOMEvent.metaKey ? CPCommandKeyMask : 0);
00600
00601 if (ExcludedDOMElements[sourceElement.tagName] && sourceElement != _DOMFocusElement && sourceElement != _DOMPasteboardElement)
00602 return;
00603
00604
00605 StopDOMEventPropagation = !(modifierFlags & (CPControlKeyMask | CPCommandKeyMask)) ||
00606 CharacterKeysToPrevent[String.fromCharCode(aDOMEvent.keyCode || aDOMEvent.charCode).toLowerCase()] ||
00607 KeyCodesToPrevent[aDOMEvent.keyCode];
00608
00609 var isNativePasteEvent = NO,
00610 isNativeCopyOrCutEvent = NO;
00611
00612 switch (aDOMEvent.type)
00613 {
00614 case CPDOMEventKeyDown:
00615 _keyCode = aDOMEvent.keyCode;
00616
00617 var characters = String.fromCharCode(_keyCode).toLowerCase();
00618
00619
00620
00621 if (characters == "v" && (modifierFlags & CPPlatformActionKeyMask))
00622 {
00623 _DOMPasteboardElement.select();
00624 _DOMPasteboardElement.value = "";
00625
00626 isNativePasteEvent = YES;
00627 }
00628
00629
00630
00631
00632
00633
00634 else if ((characters == "c" || characters == "x") && (modifierFlags & CPPlatformActionKeyMask))
00635 isNativeCopyOrCutEvent = YES;
00636
00637
00638
00639 else if (!CPFeatureIsCompatible(CPJavascriptRemedialKeySupport))
00640 return;
00641
00642
00643 else if (!KeyCodesWithoutKeyPressEvents[_keyCode] && (_keyCode == CTRL_KEY_CODE || !(modifierFlags & CPControlKeyMask)))
00644 return;
00645
00646
00647 case CPDOMEventKeyPress:
00648
00649
00650 if ((aDOMEvent.target || aDOMEvent.srcElement) == _DOMPasteboardElement)
00651 return;
00652
00653 var keyCode = _keyCode,
00654 charCode = aDOMEvent.keyCode || aDOMEvent.charCode,
00655 isARepeat = (_charCodes[keyCode] != nil);
00656
00657 _charCodes[keyCode] = charCode;
00658
00659 var characters = String.fromCharCode(charCode),
00660 charactersIgnoringModifiers = characters.toLowerCase();
00661
00662 event = [CPEvent keyEventWithType:CPKeyDown location:location modifierFlags:modifierFlags
00663 timestamp:timestamp windowNumber:windowNumber context:nil
00664 characters:characters charactersIgnoringModifiers:charactersIgnoringModifiers isARepeat:isARepeat keyCode:keyCode];
00665
00666 if (isNativePasteEvent)
00667 {
00668 _pasteboardKeyDownEvent = event;
00669
00670 window.setNativeTimeout(function () { [self _checkPasteboardElement] }, 0);
00671
00672 return;
00673 }
00674
00675 break;
00676
00677 case CPDOMEventKeyUp: var keyCode = aDOMEvent.keyCode,
00678 charCode = _charCodes[keyCode];
00679
00680 _charCodes[keyCode] = nil;
00681
00682 var characters = String.fromCharCode(charCode),
00683 charactersIgnoringModifiers = characters.toLowerCase();
00684
00685 if (!(modifierFlags & CPShiftKeyMask))
00686 characters = charactersIgnoringModifiers;
00687
00688 event = [CPEvent keyEventWithType:CPKeyUp location:location modifierFlags:modifierFlags
00689 timestamp: timestamp windowNumber:windowNumber context:nil
00690 characters:characters charactersIgnoringModifiers:charactersIgnoringModifiers isARepeat:NO keyCode:keyCode];
00691 break;
00692 }
00693
00694 if (event)
00695 {
00696 event._DOMEvent = aDOMEvent;
00697
00698 [CPApp sendEvent:event];
00699
00700 if (isNativeCopyOrCutEvent)
00701 {
00702 var pasteboard = [CPPasteboard generalPasteboard],
00703 types = [pasteboard types];
00704
00705
00706 if (types.length)
00707 {
00708 if ([types indexOfObjectIdenticalTo:CPStringPboardType] != CPNotFound)
00709 _DOMPasteboardElement.value = [pasteboard stringForType:CPStringPboardType];
00710 else
00711 _DOMPasteboardElement.value = [pasteboard _generateStateUID];
00712
00713 _DOMPasteboardElement.select();
00714
00715 window.setNativeTimeout(function() { [self _clearPasteboardElement]; }, 0);
00716 }
00717
00718 return;
00719 }
00720 }
00721
00722 if (StopDOMEventPropagation)
00723 CPDOMEventStop(aDOMEvent);
00724
00725 [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
00726 }
00727 catch (anException)
00728 {
00729 objj_exception_report(anException, {path:@"CPDOMWindowBridge.j"});
00730 }
00731 }
00732
00733
00734 - (void)_bridgeScrollEvent:(DOMEvent)aDOMEvent
00735 {
00736 if(!aDOMEvent)
00737 aDOMEvent = window.event;
00738
00739 try
00740 {
00741 if (CPFeatureIsCompatible(CPJavaScriptMouseWheelValues_8_15))
00742 {
00743 var x = 0.0,
00744 y = 0.0,
00745 element = aDOMEvent.target;
00746
00747 while (element.nodeType !== 1)
00748 element = element.parentNode;
00749
00750 if (element.offsetParent)
00751 {
00752 do
00753 {
00754 x += element.offsetLeft;
00755 y += element.offsetTop;
00756
00757 } while (element = element.offsetParent);
00758 }
00759
00760 var location = _CGPointMake((x + ((aDOMEvent.clientX - 8) / 15)), (y + ((aDOMEvent.clientY - 8) / 15)));}
00761 else
00762 var location = _CGPointMake(aDOMEvent.clientX, aDOMEvent.clientY);
00763
00764 var deltaX = 0.0,
00765 deltaY = 0.0,
00766 windowNumber = 0,
00767 timestamp = aDOMEvent.timeStamp ? aDOMEvent.timeStamp : new Date(),
00768 modifierFlags = (aDOMEvent.shiftKey ? CPShiftKeyMask : 0) |
00769 (aDOMEvent.ctrlKey ? CPControlKeyMask : 0) |
00770 (aDOMEvent.altKey ? CPAlternateKeyMask : 0) |
00771 (aDOMEvent.metaKey ? CPCommandKeyMask : 0);
00772
00773 StopDOMEventPropagation = YES;
00774
00775 windowNumber = [[self hitTest:location] windowNumber];
00776
00777 if (!windowNumber)
00778 return;
00779
00780 var windowFrame = CPApp._windows[windowNumber]._frame;
00781
00782 location.x -= CGRectGetMinX(windowFrame);
00783 location.y -= CGRectGetMinY(windowFrame);
00784
00785 if(typeof aDOMEvent.wheelDeltaX != "undefined")
00786 {
00787 deltaX = aDOMEvent.wheelDeltaX / 120.0;
00788 deltaY = aDOMEvent.wheelDeltaY / 120.0;
00789 }
00790
00791 else if (aDOMEvent.wheelDelta)
00792 deltaY = aDOMEvent.wheelDelta / 120.0;
00793
00794 else if (aDOMEvent.detail)
00795 deltaY = -aDOMEvent.detail / 3.0;
00796
00797 else
00798 return;
00799
00800 if(!CPFeatureIsCompatible(CPJavaScriptNegativeMouseWheelValues))
00801 {
00802 deltaX = -deltaX;
00803 deltaY = -deltaY;
00804 }
00805
00806 var event = [CPEvent mouseEventWithType:CPScrollWheel location:location modifierFlags:modifierFlags
00807 timestamp:timestamp windowNumber:windowNumber context:nil eventNumber:-1 clickCount:1 pressure:0 ];
00808
00809 event._DOMEvent = aDOMEvent;
00810 event._deltaX = ROUND(deltaX * 1.5);
00811 event._deltaY = ROUND(deltaY * 1.5);
00812
00813 [CPApp sendEvent:event];
00814
00815 if (StopDOMEventPropagation)
00816 CPDOMEventStop(aDOMEvent);
00817
00818 [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
00819 }
00820 catch (anException)
00821 {
00822 objj_exception_report(anException, {path:@"CPDOMWindowBridge.j"});
00823 }
00824
00825 }
00826
00827
00828 - (void)_bridgeResizeEvent:(DOMEvent)aDOMEvent
00829 {
00830 try
00831 {
00832
00833
00834
00835
00836 var oldSize = _frame.size;
00837
00838
00839 _frame = CPDOMWindowGetFrame(_DOMWindow);
00840 _contentBounds.size = CGSizeCreateCopy(_frame.size);
00841
00842 var levels = _windowLevels,
00843 layers = _windowLayers,
00844 levelCount = levels.length;
00845
00846 while (levelCount--)
00847 {
00848 var windows = [layers objectForKey:levels[levelCount]]._windows,
00849 windowCount = windows.length;
00850
00851 while (windowCount--)
00852 [windows[windowCount] resizeWithOldBridgeSize:oldSize];
00853 }
00854
00855
00856
00857 [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
00858 }
00859 catch (anException)
00860 {
00861 objj_exception_report(anException, {path:@"CPDOMWindowBridge.j"});
00862 }
00863 }
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875 - (void)_bridgeTouchEvent:(DOMEvent)aDOMEvent
00876 {
00877 try
00878 {
00879 if (aDOMEvent.touches && (aDOMEvent.touches.length == 1 || (aDOMEvent.touches.length == 0 && aDOMEvent.changedTouches.length == 1)))
00880 {
00881 var newEvent = {};
00882
00883 switch(aDOMEvent.type)
00884 {
00885 case CPDOMEventTouchStart: newEvent.type = CPDOMEventMouseDown;
00886 break;
00887 case CPDOMEventTouchEnd: newEvent.type = CPDOMEventMouseUp;
00888 break;
00889 case CPDOMEventTouchMove: newEvent.type = CPDOMEventMouseMoved;
00890 break;
00891 case CPDOMEventTouchCancel: newEvent.type = CPDOMEventMouseUp;
00892 break;
00893 }
00894
00895 var touch = aDOMEvent.touches.length ? aDOMEvent.touches[0] : aDOMEvent.changedTouches[0];
00896
00897 newEvent.clientX = touch.clientX;
00898 newEvent.clientY = touch.clientY;
00899
00900 newEvent.timestamp = aDOMEvent.timestamp;
00901 newEvent.target = aDOMEvent.target;
00902
00903 newEvent.shiftKey = newEvent.ctrlKey = newEvent.altKey = newEvent.metaKey = false;
00904
00905 newEvent.preventDefault = function(){if(aDOMEvent.preventDefault) aDOMEvent.preventDefault()};
00906 newEvent.stopPropagation = function(){if(aDOMEvent.stopPropagation) aDOMEvent.stopPropagation()};
00907
00908 [self _bridgeMouseEvent:newEvent];
00909
00910 return;
00911 }
00912 else
00913 {
00914 if (aDOMEvent.preventDefault)
00915 aDOMEvent.preventDefault();
00916
00917 if (aDOMEvent.stopPropagation)
00918 aDOMEvent.stopPropagation();
00919 }
00920 }
00921 catch(e)
00922 {
00923 objj_exception_report(e, {path:@"CPDOMWindowBridge.j"});
00924 }
00925
00926
00927 }
00928
00929
00930 - (void)_checkPasteboardElement
00931 {
00932 try
00933 {
00934 var value = _DOMPasteboardElement.value;
00935
00936 if ([value length])
00937 {
00938 var pasteboard = [CPPasteboard generalPasteboard];
00939
00940 if ([pasteboard _stateUID] != value)
00941 {
00942 [pasteboard declareTypes:[CPStringPboardType] owner:self];
00943
00944 [pasteboard setString:value forType:CPStringPboardType];
00945 }
00946 }
00947
00948 [self _clearPasteboardElement];
00949
00950 [CPApp sendEvent:_pasteboardKeyDownEvent];
00951
00952 _pasteboardKeyDownEvent = nil;
00953
00954 [[CPRunLoop currentRunLoop] limitDateForMode:CPDefaultRunLoopMode];
00955 }
00956 catch (anException)
00957 {
00958 objj_exception_report(anException, {path:@"CPDOMWindowBridge.j"});
00959 }
00960 }
00961
00962
00963 - (void)_clearPasteboardElement
00964 {
00965 _DOMPasteboardElement.value = "";
00966 _DOMPasteboardElement.blur();
00967 }
00968
00969 @end
00970
00971 var CLICK_SPACE_DELTA = 5.0,
00972 CLICK_TIME_DELTA = (typeof document != "undefined" && document.addEventListener) ? 350.0 : 1000.0;
00973
00974 var CPDOMEventGetClickCount = function(aComparisonEvent, aTimestamp, aLocation)
00975 {
00976 if (!aComparisonEvent)
00977 return 1;
00978
00979 var comparisonLocation = [aComparisonEvent locationInWindow];
00980
00981 return (aTimestamp - [aComparisonEvent timestamp] < CLICK_TIME_DELTA &&
00982 ABS(comparisonLocation.x - aLocation.x) < CLICK_SPACE_DELTA &&
00983 ABS(comparisonLocation.y - aLocation.y) < CLICK_SPACE_DELTA) ? [aComparisonEvent clickCount] + 1 : 1;
00984 }
00985
00986 var CPDOMEventStop = function(aDOMEvent)
00987 {
00988
00989 aDOMEvent.cancelBubble = true;
00990 aDOMEvent.returnValue = false;
00991
00992
00993 if (aDOMEvent.preventDefault)
00994 aDOMEvent.preventDefault();
00995
00996 if (aDOMEvent.stopPropagation)
00997 aDOMEvent.stopPropagation();
00998
00999 if (aDOMEvent.type == CPDOMEventMouseDown)
01000 {
01001 CPSharedDOMWindowBridge._DOMFocusElement.focus();
01002 CPSharedDOMWindowBridge._DOMFocusElement.blur();
01003 }
01004 }