mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 06:35:42 +00:00
336 lines
9.2 KiB
C++
336 lines
9.2 KiB
C++
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||
|
*
|
||
|
* The contents of this file are subject to the Netscape Public License
|
||
|
* Version 1.0 (the "NPL"); you may not use this file except in
|
||
|
* compliance with the NPL. You may obtain a copy of the NPL at
|
||
|
* http://www.mozilla.org/NPL/
|
||
|
*
|
||
|
* Software distributed under the NPL is distributed on an "AS IS" basis,
|
||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
|
||
|
* for the specific language governing rights and limitations under the
|
||
|
* NPL.
|
||
|
*
|
||
|
* The Initial Developer of this code under the NPL is Netscape
|
||
|
* Communications Corporation. Portions created by Netscape are
|
||
|
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
|
||
|
* Reserved.
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
* macmocha.cp
|
||
|
* MacFE mocha hacks
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include "CMochaHacks.h"
|
||
|
#include "lo_ele.h"
|
||
|
#include "fe_proto.h" // for FE_DestroyWindow
|
||
|
#include "proto.h" // 1997-03-02 mjc
|
||
|
#include "layers.h"
|
||
|
#include "macutil.h"
|
||
|
|
||
|
LO_Element* CMochaHacks::sMouseOverElement = NULL; // layout element the cursor is over
|
||
|
MWContext* CMochaHacks::sMouseOverElementContext = NULL; // context associated with sMouseOverElement
|
||
|
LO_AnchorData* CMochaHacks::sMouseOverMapArea = NULL; // AREA tag the cursor is over
|
||
|
|
||
|
// <where> is document-relative
|
||
|
void
|
||
|
CMochaHacks::SendOutOfElementEvent(MWContext * winContext, CL_Layer* layer, SPoint32 where) // add layer param 1997-03-02 mjc
|
||
|
{
|
||
|
Assert_(winContext);
|
||
|
|
||
|
try
|
||
|
{
|
||
|
if ( sMouseOverElement )
|
||
|
{
|
||
|
// ET_SendEvent now takes a JSEvent struct instead of an int type
|
||
|
JSEvent* event = XP_NEW_ZAP(JSEvent);
|
||
|
if (event)
|
||
|
{
|
||
|
// 97-06-21 pkc -- If we have an sMouseOverElementContext then use it
|
||
|
// instead of winContext
|
||
|
MWContext* theContext = sMouseOverElementContext ? sMouseOverElementContext : winContext;
|
||
|
event->type = EVENT_MOUSEOUT;
|
||
|
event->x = where.h;
|
||
|
event->y = where.v;
|
||
|
event->docx = event->x + CL_GetLayerXOrigin(layer);
|
||
|
event->docy = event->y + CL_GetLayerYOrigin(layer);
|
||
|
|
||
|
int32 x_offset, y_offset;
|
||
|
FE_GetWindowOffset(theContext, &x_offset, &y_offset);
|
||
|
event->screenx = event->docx + x_offset;
|
||
|
event->screeny = event->docy + y_offset;
|
||
|
event->layer_id = LO_GetIdFromLayer(theContext, layer);
|
||
|
ET_SendEvent( theContext, sMouseOverElement, event, NULL, NULL );
|
||
|
sMouseOverElement = NULL;
|
||
|
sMouseOverElementContext = NULL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
catch(...)
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void
|
||
|
CMochaHacks::SendOutOfMapAreaEvent(MWContext * winContext, CL_Layer* layer, SPoint32 where) // add layer param 1997-03-02 mjc
|
||
|
{
|
||
|
Assert_(winContext);
|
||
|
|
||
|
try
|
||
|
{
|
||
|
if ( sMouseOverMapArea )
|
||
|
{
|
||
|
CMochaEventCallback * cb = new CMochaEventCallback; // Need it because of LO_AnchorData
|
||
|
cb->SendEvent( winContext, sMouseOverMapArea, EVENT_MOUSEOUT, layer, where );
|
||
|
sMouseOverMapArea = NULL;
|
||
|
}
|
||
|
}
|
||
|
catch(...)
|
||
|
{
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// CMochaEventCallback
|
||
|
//
|
||
|
void
|
||
|
CMochaHacks::ResetMochaMouse()
|
||
|
{
|
||
|
sMouseOverElement = NULL;
|
||
|
sMouseOverMapArea = NULL;
|
||
|
}
|
||
|
|
||
|
// Returns mocha modifier bitset given mac modifiers.
|
||
|
uint32
|
||
|
CMochaHacks::MochaModifiers(const UInt16 inModifiers)
|
||
|
{
|
||
|
return ((inModifiers & shiftKey) ? EVENT_SHIFT_MASK : 0) |
|
||
|
((inModifiers & controlKey) ? EVENT_CONTROL_MASK : 0) |
|
||
|
((inModifiers & optionKey) ? EVENT_ALT_MASK : 0) |
|
||
|
((inModifiers & cmdKey) ? EVENT_META_MASK : 0);
|
||
|
}
|
||
|
|
||
|
// Returns mocha modifiers by reading the keyboard.
|
||
|
uint32
|
||
|
CMochaHacks::MochaModifiersFromKeyboard(void)
|
||
|
{
|
||
|
union
|
||
|
{
|
||
|
KeyMap asMap;
|
||
|
Byte asBytes[16];
|
||
|
};
|
||
|
|
||
|
::GetKeys(asMap);
|
||
|
return ((asBytes[kShiftKey >> 3] & (1 << (kShiftKey & 0x07))) ? EVENT_SHIFT_MASK : 0) |
|
||
|
((asBytes[kCtlKey >> 3] & (1 << (kCtlKey & 0x07))) ? EVENT_CONTROL_MASK : 0) |
|
||
|
((asBytes[kOptionKey >> 3] & (1 << (kOptionKey & 0x07))) ? EVENT_ALT_MASK : 0) |
|
||
|
((asBytes[kCommandKey >> 3] & (1 << (kCommandKey & 0x07))) ? EVENT_META_MASK : 0);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Returns true if the window is a dependent of another.
|
||
|
// Parameters:
|
||
|
// inContext: the context for this window.
|
||
|
Boolean
|
||
|
CMochaHacks::IsDependent(MWContext* inContext)
|
||
|
{
|
||
|
return (inContext->js_parent != nil);
|
||
|
}
|
||
|
|
||
|
// Add a window as a dependent of another.
|
||
|
// Called in FE_MakeNewWindow.
|
||
|
// Parameters:
|
||
|
// inParent: the parent context.
|
||
|
// inChild: the context for this window which will be made a dependent of the parent.
|
||
|
void
|
||
|
CMochaHacks::AddDependent(MWContext* inParent, MWContext* inChild)
|
||
|
{
|
||
|
// inParent could be a grid context, but dependencies are between windows so find root context.
|
||
|
MWContext* theParentRoot = XP_GetNonGridContext(inParent);
|
||
|
if (theParentRoot != nil && inChild != nil)
|
||
|
{
|
||
|
if (theParentRoot->js_dependent_list == NULL)
|
||
|
theParentRoot->js_dependent_list = XP_ListNew();
|
||
|
if (theParentRoot->js_dependent_list != NULL)
|
||
|
{
|
||
|
XP_ListAddObject(theParentRoot->js_dependent_list, inChild);
|
||
|
inChild->js_parent = theParentRoot;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// Remove dependents of the window.
|
||
|
// Called in destructor for window.
|
||
|
// Parameters:
|
||
|
// inContext: the context for this window.
|
||
|
void
|
||
|
CMochaHacks::RemoveDependents(MWContext* inContext)
|
||
|
{
|
||
|
// FE_DestroyWindow makes this recursive; keep track of how many levels deep we are.
|
||
|
static int recursionLevel = 0;
|
||
|
++recursionLevel;
|
||
|
if (inContext->js_dependent_list)
|
||
|
{
|
||
|
MWContext *depContext;
|
||
|
// destroy windows which are dependent on this window
|
||
|
for (int i = 1; i <= XP_ListCount(inContext->js_dependent_list); i++)
|
||
|
{
|
||
|
depContext = (MWContext *)XP_ListGetObjectNum(inContext->js_dependent_list, i);
|
||
|
FE_DestroyWindow(depContext);
|
||
|
}
|
||
|
XP_ListDestroy(inContext->js_dependent_list);
|
||
|
inContext->js_dependent_list = NULL;
|
||
|
}
|
||
|
--recursionLevel;
|
||
|
// remove self from parent's dependent list but only if we're the window
|
||
|
// at the top of the chain (don't alter lists we're iterating over).
|
||
|
if (recursionLevel == 0 && inContext->js_parent != nil)
|
||
|
{
|
||
|
if (XP_ListCount(inContext->js_parent->js_dependent_list) == 1)
|
||
|
{
|
||
|
// if the last element in the list, destroy the list.
|
||
|
XP_ListDestroy(inContext->js_parent->js_dependent_list);
|
||
|
inContext->js_parent->js_dependent_list = NULL;
|
||
|
}
|
||
|
else XP_ListRemoveObject(inContext->js_parent->js_dependent_list, inContext);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Send move event to mocha every time a window or pane is moved.
|
||
|
void
|
||
|
CMochaHacks::SendMoveEvent(MWContext* inContext, int32 inX, int32 inY)
|
||
|
{
|
||
|
JSEvent *event;
|
||
|
|
||
|
event = XP_NEW_ZAP(JSEvent);
|
||
|
if (event)
|
||
|
{
|
||
|
event->type = EVENT_MOVE;
|
||
|
event->x = inX;
|
||
|
event->y = inY;
|
||
|
}
|
||
|
ET_SendEvent(inContext, 0, event, 0, 0);
|
||
|
}
|
||
|
|
||
|
// Send the event specified, with no callback.
|
||
|
void
|
||
|
CMochaHacks::SendEvent(MWContext* inContext, int32 inType, LO_Element* inElement)
|
||
|
{
|
||
|
JSEvent *event;
|
||
|
event = XP_NEW_ZAP(JSEvent);
|
||
|
if (event)
|
||
|
{
|
||
|
event->type = inType;
|
||
|
ET_SendEvent(inContext, inElement, event, 0, 0);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// CMochaEventCallback
|
||
|
//
|
||
|
|
||
|
#ifdef DEBUG
|
||
|
static int sCallbackCount = 0;
|
||
|
#endif
|
||
|
|
||
|
CMochaEventCallback::CMochaEventCallback()
|
||
|
{
|
||
|
#ifdef DEBUG
|
||
|
sCallbackCount++;
|
||
|
#endif
|
||
|
fDummyElement = NULL;
|
||
|
}
|
||
|
|
||
|
CMochaEventCallback::~CMochaEventCallback()
|
||
|
{
|
||
|
#ifdef DEBUG
|
||
|
sCallbackCount--;
|
||
|
#endif
|
||
|
if (fDummyElement != NULL)
|
||
|
XP_FREE( fDummyElement );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Plain SendEvent
|
||
|
//
|
||
|
void
|
||
|
CMochaEventCallback::SendEvent(MWContext * context, LO_Element * element, int32 type, CL_Layer* layer, SPoint32 where)
|
||
|
{
|
||
|
// ET_SendEvent now takes a JSEvent struct instead of an int type
|
||
|
JSEvent* event = XP_NEW_ZAP(JSEvent);
|
||
|
if (event)
|
||
|
{
|
||
|
event->type = type;
|
||
|
event->x = where.h;
|
||
|
event->y = where.v;
|
||
|
event->docx = event->x + CL_GetLayerXOrigin(layer);
|
||
|
event->docy = event->y + CL_GetLayerYOrigin(layer);
|
||
|
|
||
|
int32 x_offset, y_offset;
|
||
|
FE_GetWindowOffset(context, &x_offset, &y_offset);
|
||
|
event->screenx = event->docx + x_offset;
|
||
|
event->screeny = event->docy + y_offset;
|
||
|
event->layer_id = LO_GetIdFromLayer(context, layer);
|
||
|
ET_SendEvent( context, element, event, MochaCallback, this);
|
||
|
// PR_Yield(); To speed up processing?
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// LO_AnchorData SendEvent
|
||
|
//
|
||
|
void
|
||
|
CMochaEventCallback::SendEvent(MWContext * context, LO_AnchorData * data, int32 type, CL_Layer* layer, SPoint32 where)
|
||
|
{
|
||
|
// Create fake layout element
|
||
|
fDummyElement = XP_NEW_ZAP(LO_Element);
|
||
|
if (fDummyElement)
|
||
|
{
|
||
|
fDummyElement->type = LO_TEXT;
|
||
|
fDummyElement->lo_text.anchor_href = data;
|
||
|
fDummyElement->lo_text.text = data->anchor;
|
||
|
|
||
|
// ET_SendEvent now takes a JSEvent struct instead of an int type
|
||
|
JSEvent* event = XP_NEW_ZAP(JSEvent);
|
||
|
if (event)
|
||
|
{
|
||
|
event->type = type;
|
||
|
event->x = where.h;
|
||
|
event->y = where.v;
|
||
|
event->docx = event->x + CL_GetLayerXOrigin(layer);
|
||
|
event->docy = event->y + CL_GetLayerYOrigin(layer);
|
||
|
|
||
|
int32 x_offset, y_offset;
|
||
|
FE_GetWindowOffset(context, &x_offset, &y_offset);
|
||
|
event->screenx = event->docx + x_offset;
|
||
|
event->screeny = event->docy + y_offset;
|
||
|
event->layer_id = LO_GetIdFromLayer(context, layer);
|
||
|
ET_SendEvent( context, fDummyElement, event, MochaCallback, this);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// EventComplete, does nothing
|
||
|
//
|
||
|
void
|
||
|
CMochaEventCallback::Complete(MWContext * /*context*/, LO_Element * /*element*/,
|
||
|
int32 /*type*/, ETEventStatus /*status*/)
|
||
|
{
|
||
|
// EVENT_OK means we should handle the event/
|
||
|
// EVENT_CANCEL, EVENT_PANIC, means mocha has cancelled the click
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// MochaCallback, called by mocha after event is processed
|
||
|
//
|
||
|
void CMochaEventCallback::MochaCallback(MWContext * context, LO_Element * element,
|
||
|
int32 type, void * inCallback, ETEventStatus status)
|
||
|
{
|
||
|
CMochaEventCallback * callback = (CMochaEventCallback *) inCallback;
|
||
|
callback->Complete( context, element, type, status );
|
||
|
delete callback;
|
||
|
}
|