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