<commit_before>/*
 * MouseTracker.java
 *
 * Copyright (C) 2009-16 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */
package org.rstudio.core.client;

import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Event.NativePreviewHandler;
import com.google.inject.Singleton;

@Singleton
public class MouseTracker
{
   public MouseTracker()
   {
      Event.addNativePreviewHandler(new NativePreviewHandler()
      {
         @Override
         public void onPreviewNativeEvent(NativePreviewEvent preview)
         {
            if ((preview.getTypeInt() & Event.MOUSEEVENTS) == 0)
               return;
            
            NativeEvent event = preview.getNativeEvent();
            lastMouseX_ = event.getClientX();
            lastMouseY_ = event.getClientY();
         }
      });
   }
   
   public int getLastMouseX()
   {
      return lastMouseX_;
   }
   
   public int getLastMouseY()
   {
      return lastMouseY_;
   }
   
   private int lastMouseX_;
   private int lastMouseY_;
}
<commit_msg>suppress synthesized mouse events on modifier key<commit_after>/*
 * MouseTracker.java
 *
 * Copyright (C) 2009-17 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */
package org.rstudio.core.client;

import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.Event.NativePreviewHandler;
import com.google.inject.Singleton;

@Singleton
public class MouseTracker
{
   public MouseTracker()
   {
      Event.addNativePreviewHandler(new NativePreviewHandler()
      {
         @Override
         public void onPreviewNativeEvent(NativePreviewEvent preview)
         {
            int type = preview.getTypeInt();
            if ((type & Event.MOUSEEVENTS) == 0)
            {
               lastEventType_ = type;
               return;
            }
            
            NativeEvent event = preview.getNativeEvent();
            
            // Safari triggers certain mouse events when modifier keys are
            // pressed. Suppress those as they can cause unexpected behavior
            // when e.g. typing in a textbox while the mouse happens to lie
            // over a popup panel (e.g. C++ completions, Find in Files)
            if (isSafariModifierKeyCausingMouseEvent(event, type))
            {
               event.stopPropagation();
               event.preventDefault();
            }
            
            lastEventType_ = type;
            lastMouseX_ = event.getClientX();
            lastMouseY_ = event.getClientY();
         }
      });
   }
   
   private boolean isSafariModifierKeyCausingMouseEvent(NativeEvent event,
                                                        int type)
   {
      if (!IS_SAFARI)
         return false;
      
      // If the last event was a key event, and we just got a mouse event,
      // suppress it. (The intention here is to suppress a 'mouseout' or
      // 'mouseover' event synthesized in respond to a modifier keypress.
      //
      // Note that these events can be emitted in response to a keyup as
      // well; in such a case the associated modifier key will no longer
      // be held down and so we just globally suppress 'mouseover' and
      // 'mouseout' following a keyevent.
      if ((lastEventType_ & Event.KEYEVENTS) != 0 &&
          (type == Event.ONMOUSEOVER || type == Event.ONMOUSEOUT))
      {
         suppressing_ = true;
         return true;
      }
      
      // Stop suppressing once we get a new non-mouseover/mouseout event.
      else if (type != Event.ONMOUSEOVER && type != Event.ONMOUSEOUT)
      {
         suppressing_ = false;
         return false;
      }
      
      // For other intermediate events, return status of suppressing flag.
      return suppressing_;
   }
   
   public int getLastMouseX()
   {
      return lastMouseX_;
   }
   
   public int getLastMouseY()
   {
      return lastMouseY_;
   }
   
   private int lastMouseX_;
   private int lastMouseY_;
   
   private int lastEventType_;
   private boolean suppressing_;
   
   private static final boolean IS_SAFARI =
         BrowseCap.isSafari() || BrowseCap.isMacintoshDesktop();
}

{'fraction_non_alphanumeric': 0.07897727272727273, 'fraction_numerical': 0.003977272727272727, 'mean_word_length': 2.300625, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6715760', 'n_tokens_mistral': 1467, 'n_tokens_neox': 1426, 'n_words': 460}