1/* 2 * Copyright (c) 2005, 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 */ 25package java.awt; 26 27import java.awt.event.*; 28 29import sun.awt.AppContext; 30 31abstract class ModalEventFilter implements EventFilter { 32 33 protected Dialog modalDialog; 34 protected boolean disabled; 35 36 protected ModalEventFilter(Dialog modalDialog) { 37 this.modalDialog = modalDialog; 38 disabled = false; 39 } 40 41 Dialog getModalDialog() { 42 return modalDialog; 43 } 44 45 public FilterAction acceptEvent(AWTEvent event) { 46 if (disabled || !modalDialog.isVisible()) { 47 return FilterAction.ACCEPT; 48 } 49 int eventID = event.getID(); 50 if ((eventID >= MouseEvent.MOUSE_FIRST && 51 eventID <= MouseEvent.MOUSE_LAST) || 52 (eventID >= ActionEvent.ACTION_FIRST && 53 eventID <= ActionEvent.ACTION_LAST) || 54 eventID == WindowEvent.WINDOW_CLOSING) 55 { 56 Object o = event.getSource(); 57 if (o instanceof sun.awt.ModalExclude) { 58 // Exclude this object from modality and 59 // continue to pump it's events. 60 } else if (o instanceof Component) { 61 Component c = (Component)o; 62 while ((c != null) && !(c instanceof Window)) { 63 c = c.getParent_NoClientCode(); 64 } 65 if (c != null) { 66 return acceptWindow((Window)c); 67 } 68 } 69 } 70 return FilterAction.ACCEPT; 71 } 72 73 protected abstract FilterAction acceptWindow(Window w); 74 75 // When a modal dialog is hidden its modal filter may not be deleted from 76 // EventDispatchThread event filters immediately, so we need to mark the filter 77 // as disabled to prevent it from working. Simple checking for visibility of 78 // the modalDialog is not enough, as it can be hidden and then shown again 79 // with a new event pump and a new filter 80 void disable() { 81 disabled = true; 82 } 83 84 int compareTo(ModalEventFilter another) { 85 Dialog anotherDialog = another.getModalDialog(); 86 // check if modalDialog is from anotherDialog's hierarchy 87 // or vice versa 88 Component c = modalDialog; 89 while (c != null) { 90 if (c == anotherDialog) { 91 return 1; 92 } 93 c = c.getParent_NoClientCode(); 94 } 95 c = anotherDialog; 96 while (c != null) { 97 if (c == modalDialog) { 98 return -1; 99 } 100 c = c.getParent_NoClientCode(); 101 } 102 // check if one dialog blocks (directly or indirectly) another 103 Dialog blocker = modalDialog.getModalBlocker(); 104 while (blocker != null) { 105 if (blocker == anotherDialog) { 106 return -1; 107 } 108 blocker = blocker.getModalBlocker(); 109 } 110 blocker = anotherDialog.getModalBlocker(); 111 while (blocker != null) { 112 if (blocker == modalDialog) { 113 return 1; 114 } 115 blocker = blocker.getModalBlocker(); 116 } 117 // compare modality types 118 return modalDialog.getModalityType().compareTo(anotherDialog.getModalityType()); 119 } 120 121 static ModalEventFilter createFilterForDialog(Dialog modalDialog) { 122 switch (modalDialog.getModalityType()) { 123 case DOCUMENT_MODAL: return new DocumentModalEventFilter(modalDialog); 124 case APPLICATION_MODAL: return new ApplicationModalEventFilter(modalDialog); 125 case TOOLKIT_MODAL: return new ToolkitModalEventFilter(modalDialog); 126 } 127 return null; 128 } 129 130 private static class ToolkitModalEventFilter extends ModalEventFilter { 131 132 private AppContext appContext; 133 134 ToolkitModalEventFilter(Dialog modalDialog) { 135 super(modalDialog); 136 appContext = modalDialog.appContext; 137 } 138 139 protected FilterAction acceptWindow(Window w) { 140 if (w.isModalExcluded(Dialog.ModalExclusionType.TOOLKIT_EXCLUDE)) { 141 return FilterAction.ACCEPT; 142 } 143 if (w.appContext != appContext) { 144 return FilterAction.REJECT; 145 } 146 while (w != null) { 147 if (w == modalDialog) { 148 return FilterAction.ACCEPT_IMMEDIATELY; 149 } 150 w = w.getOwner(); 151 } 152 return FilterAction.REJECT; 153 } 154 } 155 156 private static class ApplicationModalEventFilter extends ModalEventFilter { 157 158 private AppContext appContext; 159 160 ApplicationModalEventFilter(Dialog modalDialog) { 161 super(modalDialog); 162 appContext = modalDialog.appContext; 163 } 164 165 protected FilterAction acceptWindow(Window w) { 166 if (w.isModalExcluded(Dialog.ModalExclusionType.APPLICATION_EXCLUDE)) { 167 return FilterAction.ACCEPT; 168 } 169 if (w.appContext == appContext) { 170 while (w != null) { 171 if (w == modalDialog) { 172 return FilterAction.ACCEPT_IMMEDIATELY; 173 } 174 w = w.getOwner(); 175 } 176 return FilterAction.REJECT; 177 } 178 return FilterAction.ACCEPT; 179 } 180 } 181 182 private static class DocumentModalEventFilter extends ModalEventFilter { 183 184 private Window documentRoot; 185 186 DocumentModalEventFilter(Dialog modalDialog) { 187 super(modalDialog); 188 documentRoot = modalDialog.getDocumentRoot(); 189 } 190 191 protected FilterAction acceptWindow(Window w) { 192 // application- and toolkit-excluded windows are blocked by 193 // document-modal dialogs from their child hierarchy 194 if (w.isModalExcluded(Dialog.ModalExclusionType.APPLICATION_EXCLUDE)) { 195 Window w1 = modalDialog.getOwner(); 196 while (w1 != null) { 197 if (w1 == w) { 198 return FilterAction.REJECT; 199 } 200 w1 = w1.getOwner(); 201 } 202 return FilterAction.ACCEPT; 203 } 204 while (w != null) { 205 if (w == modalDialog) { 206 return FilterAction.ACCEPT_IMMEDIATELY; 207 } 208 if (w == documentRoot) { 209 return FilterAction.REJECT; 210 } 211 w = w.getOwner(); 212 } 213 return FilterAction.ACCEPT; 214 } 215 } 216} 217