View Javadoc
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   */
25  package java.awt;
26  
27  import java.awt.event.*;
28  
29  import sun.awt.AppContext;
30  
31  abstract 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 }