gecko-dev/cmd/macfe/central/CMochaHacks.cp
1998-03-28 02:44:41 +00:00

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;
}