1 /*
   2  * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package sun.awt.windows;
  26 
  27 import java.awt.*;
  28 import java.awt.peer.*;
  29 
  30 import sun.awt.AWTAccessor;
  31 
  32 final class WPopupMenuPeer extends WMenuPeer implements PopupMenuPeer {
  33     // We can't use target.getParent() for TrayIcon popup
  34     // because this method should return null for the TrayIcon
  35     // popup regardless of that whether it has parent or not.
  36 
  37     WPopupMenuPeer(PopupMenu target) {
  38         this.target = target;
  39         MenuContainer parent = null;
  40 
  41         // We can't use target.getParent() for TrayIcon popup
  42         // because this method should return null for the TrayIcon
  43         // popup regardless of that whether it has parent or not.
  44         boolean isTrayIconPopup = AWTAccessor.getPopupMenuAccessor().isTrayIconPopup(target);
  45         if (isTrayIconPopup) {
  46             parent = AWTAccessor.getMenuComponentAccessor().getParent(target);
  47         } else {
  48             parent = target.getParent();
  49         }
  50 
  51         if (parent instanceof Component) {
  52             WComponentPeer parentPeer = (WComponentPeer) WToolkit.targetToPeer(parent);
  53             if (parentPeer == null) {
  54                 // because the menu isn't a component (sigh) we first have to wait
  55                 // for a failure to map the peer which should only happen for a
  56                 // lightweight container, then find the actual native parent from
  57                 // that component.
  58                 parent = WToolkit.getNativeContainer((Component)parent);
  59                 parentPeer = (WComponentPeer) WToolkit.targetToPeer(parent);
  60             }
  61             parentPeer.addChildPeer(this);
  62             createMenu(parentPeer);
  63             // fix for 5088782: check if menu object is created successfully
  64             checkMenuCreation();
  65         } else {
  66             throw new IllegalArgumentException(
  67                 "illegal popup menu container class");
  68         }
  69     }
  70 
  71     private native void createMenu(WComponentPeer parent);
  72 
  73     public void show(Event e) {
  74         Component origin = (Component)e.target;
  75         WComponentPeer peer = (WComponentPeer) WToolkit.targetToPeer(origin);
  76         if (peer == null) {
  77             // A failure to map the peer should only happen for a
  78             // lightweight component, then find the actual native parent from
  79             // that component.  The event coorinates are going to have to be
  80             // remapped as well.
  81             Component nativeOrigin = WToolkit.getNativeContainer(origin);
  82             e.target = nativeOrigin;
  83 
  84             // remove the event coordinates
  85             for (Component c = origin; c != nativeOrigin; c = c.getParent()) {
  86                 Point p = c.getLocation();
  87                 e.x += p.x;
  88                 e.y += p.y;
  89             }
  90         }
  91         _show(e);
  92     }
  93 
  94     /*
  95      * This overloaded method is for TrayIcon.
  96      * Its popup has special parent.
  97      */
  98     void show(Component origin, Point p) {
  99         WComponentPeer peer = (WComponentPeer) WToolkit.targetToPeer(origin);
 100         Event e = new Event(origin, 0, Event.MOUSE_DOWN, p.x, p.y, 0, 0);
 101         if (peer == null) {
 102             Component nativeOrigin = WToolkit.getNativeContainer(origin);
 103             e.target = nativeOrigin;
 104         }
 105         e.x = p.x;
 106         e.y = p.y;
 107         _show(e);
 108     }
 109 
 110     private native void _show(Event e);
 111 }