home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / cmd / macfe / central / CMochaHacks.cp < prev    next >
Encoding:
Text File  |  1998-04-08  |  9.6 KB  |  336 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. /*
  20.  * macmocha.cp
  21.  * MacFE mocha hacks
  22.  *
  23.  */
  24.  
  25. #include "CMochaHacks.h"
  26. #include "lo_ele.h"
  27. #include "fe_proto.h" // for FE_DestroyWindow
  28. #include "proto.h" // 1997-03-02 mjc
  29. #include "layers.h"
  30. #include "macutil.h"
  31.  
  32. LO_Element* CMochaHacks::sMouseOverElement = NULL;    // layout element the cursor is over
  33. MWContext* CMochaHacks::sMouseOverElementContext = NULL;    // context associated with sMouseOverElement
  34. LO_AnchorData* CMochaHacks::sMouseOverMapArea = NULL;    // AREA tag the cursor is over
  35.  
  36. // <where> is document-relative
  37. void 
  38. CMochaHacks::SendOutOfElementEvent(MWContext * winContext, CL_Layer* layer, SPoint32 where) // add layer param 1997-03-02 mjc
  39. {
  40.     Assert_(winContext);
  41.     
  42.     try
  43.     {
  44.         if ( sMouseOverElement )
  45.         {
  46.             // ET_SendEvent now takes a JSEvent struct instead of an int type
  47.             JSEvent* event = XP_NEW_ZAP(JSEvent);
  48.             if (event)
  49.             {
  50.                 // 97-06-21 pkc -- If we have an sMouseOverElementContext then use it
  51.                 // instead of winContext
  52.                 MWContext* theContext = sMouseOverElementContext ? sMouseOverElementContext : winContext;
  53.                 event->type = EVENT_MOUSEOUT;
  54.                 event->x = where.h;
  55.                 event->y = where.v;
  56.                 event->docx = event->x + CL_GetLayerXOrigin(layer);
  57.                 event->docy = event->y + CL_GetLayerYOrigin(layer);
  58.                 
  59.                 int32 x_offset, y_offset;
  60.                 FE_GetWindowOffset(theContext, &x_offset, &y_offset);
  61.                 event->screenx = event->docx + x_offset;
  62.                 event->screeny = event->docy + y_offset;
  63.                 event->layer_id = LO_GetIdFromLayer(theContext, layer);
  64.                 ET_SendEvent( theContext, sMouseOverElement, event, NULL, NULL );
  65.                 sMouseOverElement = NULL;
  66.                 sMouseOverElementContext = NULL;
  67.             }
  68.         }
  69.             
  70.     }
  71.     catch(...)
  72.     {
  73.     }
  74. }
  75.  
  76. void 
  77. CMochaHacks::SendOutOfMapAreaEvent(MWContext * winContext, CL_Layer* layer, SPoint32 where) // add layer param 1997-03-02 mjc
  78. {
  79.     Assert_(winContext);
  80.     
  81.     try
  82.     {
  83.         if ( sMouseOverMapArea )
  84.         {
  85.             CMochaEventCallback * cb = new CMochaEventCallback;    // Need it because of LO_AnchorData
  86.             cb->SendEvent( winContext, sMouseOverMapArea, EVENT_MOUSEOUT, layer, where );
  87.             sMouseOverMapArea = NULL;
  88.         }
  89.     }
  90.     catch(...)
  91.     {
  92.     }
  93. }
  94.  
  95. //
  96. // CMochaEventCallback
  97. //
  98. void
  99. CMochaHacks::ResetMochaMouse()
  100. {
  101.     sMouseOverElement = NULL;
  102.     sMouseOverMapArea = NULL;
  103. }
  104.  
  105. // Returns mocha modifier bitset given mac modifiers.
  106. uint32 
  107. CMochaHacks::MochaModifiers(const UInt16 inModifiers)
  108. {
  109.     return ((inModifiers & shiftKey) ? EVENT_SHIFT_MASK : 0) |
  110.             ((inModifiers & controlKey) ? EVENT_CONTROL_MASK : 0) |
  111.             ((inModifiers & optionKey) ? EVENT_ALT_MASK : 0) |
  112.             ((inModifiers & cmdKey) ? EVENT_META_MASK : 0);
  113. }
  114.  
  115. // Returns mocha modifiers by reading the keyboard.
  116. uint32 
  117. CMochaHacks::MochaModifiersFromKeyboard(void)
  118. {
  119.     union
  120.     {
  121.         KeyMap asMap;
  122.         Byte asBytes[16];
  123.     };
  124.  
  125.     ::GetKeys(asMap);
  126.     return ((asBytes[kShiftKey >> 3] & (1 << (kShiftKey & 0x07))) ? EVENT_SHIFT_MASK : 0) |
  127.             ((asBytes[kCtlKey >> 3] & (1 << (kCtlKey & 0x07))) ? EVENT_CONTROL_MASK : 0) |
  128.             ((asBytes[kOptionKey >> 3] & (1 << (kOptionKey & 0x07))) ? EVENT_ALT_MASK : 0) |
  129.             ((asBytes[kCommandKey >> 3] & (1 << (kCommandKey & 0x07))) ? EVENT_META_MASK : 0);
  130. }
  131.     
  132.  
  133. // Returns true if the window is a dependent of another.
  134. // Parameters:
  135. //     inContext: the context for this window.
  136. Boolean     
  137. CMochaHacks::IsDependent(MWContext* inContext)
  138. {
  139.     return (inContext->js_parent != nil);
  140. }
  141.  
  142. // Add a window as a dependent of another.
  143. // Called in FE_MakeNewWindow.
  144. // Parameters:
  145. //        inParent: the parent context.
  146. //        inChild: the context for this window which will be made a dependent of the parent.
  147. void 
  148. CMochaHacks::AddDependent(MWContext* inParent, MWContext* inChild)
  149. {
  150.     // inParent could be a grid context, but dependencies are between windows so find root context.
  151.     MWContext* theParentRoot = XP_GetNonGridContext(inParent);
  152.     if (theParentRoot != nil && inChild != nil)
  153.     {
  154.         if (theParentRoot->js_dependent_list == NULL)
  155.             theParentRoot->js_dependent_list = XP_ListNew();
  156.         if (theParentRoot->js_dependent_list != NULL)
  157.         {
  158.             XP_ListAddObject(theParentRoot->js_dependent_list, inChild);
  159.             inChild->js_parent = theParentRoot;
  160.         }
  161.     }
  162.  
  163. }
  164.  
  165. // Remove dependents of the window.
  166. // Called in destructor for window.
  167. // Parameters:
  168. //     inContext: the context for this window.
  169. void 
  170. CMochaHacks::RemoveDependents(MWContext* inContext)
  171. {
  172.     // FE_DestroyWindow makes this recursive; keep track of how many levels deep we are.
  173.     static int recursionLevel = 0;
  174.     ++recursionLevel;
  175.     if (inContext->js_dependent_list)
  176.     {
  177.         MWContext *depContext;
  178.         // destroy windows which are dependent on this window
  179.         for (int i = 1; i <= XP_ListCount(inContext->js_dependent_list); i++)
  180.         {
  181.             depContext = (MWContext *)XP_ListGetObjectNum(inContext->js_dependent_list, i);
  182.             FE_DestroyWindow(depContext);
  183.         }
  184.         XP_ListDestroy(inContext->js_dependent_list);
  185.         inContext->js_dependent_list = NULL;
  186.     }
  187.     --recursionLevel;
  188.     // remove self from parent's dependent list but only if we're the window
  189.     // at the top of the chain (don't alter lists we're iterating over).
  190.     if (recursionLevel == 0 && inContext->js_parent != nil)
  191.     {
  192.         if (XP_ListCount(inContext->js_parent->js_dependent_list) == 1)
  193.         {
  194.             // if the last element in the list, destroy the list.
  195.             XP_ListDestroy(inContext->js_parent->js_dependent_list);
  196.             inContext->js_parent->js_dependent_list = NULL;
  197.         }
  198.         else XP_ListRemoveObject(inContext->js_parent->js_dependent_list, inContext);
  199.     }
  200. }
  201.  
  202. // Send move event to mocha every time a window or pane is moved.
  203. void 
  204. CMochaHacks::SendMoveEvent(MWContext* inContext, int32 inX, int32 inY)
  205. {
  206.     JSEvent *event;
  207.     
  208.     event = XP_NEW_ZAP(JSEvent);
  209.     if (event)
  210.     {
  211.         event->type = EVENT_MOVE;
  212.         event->x = inX;
  213.         event->y = inY;
  214.     }
  215.     ET_SendEvent(inContext, 0, event, 0, 0);
  216. }
  217.  
  218. // Send the event specified, with no callback.
  219. void
  220. CMochaHacks::SendEvent(MWContext* inContext, int32 inType, LO_Element* inElement)
  221. {
  222.     JSEvent *event;
  223.     event = XP_NEW_ZAP(JSEvent);
  224.     if (event)
  225.     {
  226.         event->type = inType;
  227.         ET_SendEvent(inContext, inElement, event, 0, 0);
  228.     }
  229. }
  230.  
  231. //
  232. // CMochaEventCallback
  233. //
  234.  
  235. #ifdef DEBUG
  236. static int sCallbackCount = 0;
  237. #endif
  238.  
  239. CMochaEventCallback::CMochaEventCallback()
  240. {
  241. #ifdef DEBUG
  242.     sCallbackCount++;
  243. #endif
  244.     fDummyElement = NULL;
  245. }
  246.  
  247. CMochaEventCallback::~CMochaEventCallback()
  248. {
  249. #ifdef DEBUG
  250.     sCallbackCount--;
  251. #endif
  252.     if (fDummyElement != NULL)
  253.         XP_FREE( fDummyElement );
  254. }
  255.  
  256. //
  257. // Plain SendEvent
  258. //
  259. void
  260. CMochaEventCallback::SendEvent(MWContext * context, LO_Element * element, int32 type, CL_Layer* layer, SPoint32 where)
  261. {
  262.     // ET_SendEvent now takes a JSEvent struct instead of an int type
  263.     JSEvent* event = XP_NEW_ZAP(JSEvent);
  264.     if (event)
  265.     {
  266.         event->type = type;
  267.         event->x = where.h;
  268.         event->y = where.v;
  269.         event->docx = event->x + CL_GetLayerXOrigin(layer);
  270.         event->docy = event->y + CL_GetLayerYOrigin(layer);
  271.         
  272.         int32 x_offset, y_offset;
  273.         FE_GetWindowOffset(context, &x_offset, &y_offset);
  274.         event->screenx = event->docx + x_offset;
  275.         event->screeny = event->docy + y_offset;
  276.         event->layer_id = LO_GetIdFromLayer(context, layer);
  277.         ET_SendEvent( context, element, event, MochaCallback, this);
  278.         // PR_Yield();    To speed up processing?
  279.     }
  280. }
  281.  
  282. // 
  283. // LO_AnchorData SendEvent
  284. //
  285. void
  286. CMochaEventCallback::SendEvent(MWContext * context, LO_AnchorData * data, int32 type, CL_Layer* layer, SPoint32 where)
  287. {
  288.     // Create fake layout element
  289.     fDummyElement = XP_NEW_ZAP(LO_Element);
  290.     if (fDummyElement)
  291.     {
  292.         fDummyElement->type = LO_TEXT;
  293.         fDummyElement->lo_text.anchor_href = data;
  294.         fDummyElement->lo_text.text = data->anchor;
  295.         
  296.         // ET_SendEvent now takes a JSEvent struct instead of an int type
  297.         JSEvent* event = XP_NEW_ZAP(JSEvent);
  298.         if (event)
  299.         {
  300.             event->type = type;
  301.             event->x = where.h;
  302.             event->y = where.v;
  303.             event->docx = event->x + CL_GetLayerXOrigin(layer);
  304.             event->docy = event->y + CL_GetLayerYOrigin(layer);
  305.             
  306.             int32 x_offset, y_offset;
  307.             FE_GetWindowOffset(context, &x_offset, &y_offset);
  308.             event->screenx = event->docx + x_offset;
  309.             event->screeny = event->docy + y_offset;
  310.             event->layer_id = LO_GetIdFromLayer(context, layer);
  311.             ET_SendEvent( context, fDummyElement, event, MochaCallback, this);
  312.         }
  313.     }
  314. }
  315.  
  316. // 
  317. // EventComplete, does nothing
  318. //
  319. void
  320. CMochaEventCallback::Complete(MWContext * /*context*/, LO_Element * /*element*/, 
  321.                                         int32 /*type*/, ETEventStatus /*status*/)
  322. {
  323. // EVENT_OK means we should handle the event/
  324. // EVENT_CANCEL, EVENT_PANIC, means mocha has cancelled the click
  325. }
  326.  
  327. //
  328. // MochaCallback, called by mocha after event is processed
  329. //
  330. void CMochaEventCallback::MochaCallback(MWContext * context, LO_Element * element, 
  331.                  int32 type, void * inCallback, ETEventStatus status)
  332. {
  333.     CMochaEventCallback * callback = (CMochaEventCallback *) inCallback;
  334.     callback->Complete( context, element, type, status );
  335.     delete callback;
  336. }