1 /* 2 * Copyright (c) 2010, 2015, 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.X11; 26 27 import java.awt.FileDialog; 28 import java.awt.peer.FileDialogPeer; 29 import java.io.File; 30 import java.io.FilenameFilter; 31 import sun.awt.AWTAccessor; 32 33 /** 34 * FileDialogPeer for the GtkFileChooser. 35 * 36 * @author Costantino Cerbo (c.cerbo@gmail.com) 37 */ 38 final class GtkFileDialogPeer extends XDialogPeer implements FileDialogPeer { 39 40 private final FileDialog fd; 41 42 // A pointer to the native GTK FileChooser widget 43 private volatile long widget = 0L; 44 private long standaloneWindow; 45 private volatile boolean quit; 46 GtkFileDialogPeer(FileDialog fd)47 GtkFileDialogPeer(FileDialog fd) { 48 super(fd); 49 this.fd = fd; 50 } 51 initIDs()52 private static native void initIDs(); 53 static { initIDs()54 initIDs(); 55 } 56 run(String title, int mode, String dir, String file, FilenameFilter filter, boolean isMultipleMode, int x, int y)57 private native void run(String title, int mode, String dir, String file, 58 FilenameFilter filter, boolean isMultipleMode, int x, int y); quit()59 private native void quit(); 60 61 @Override toFront()62 public native void toFront(); 63 64 @Override setBounds(int x, int y, int width, int height, int op)65 public native void setBounds(int x, int y, int width, int height, int op); 66 67 /** 68 * Called exclusively by the native C code. 69 */ setFileInternal(String directory, String[] filenames)70 private void setFileInternal(String directory, String[] filenames) { 71 AWTAccessor.FileDialogAccessor accessor = AWTAccessor 72 .getFileDialogAccessor(); 73 74 if (filenames == null) { 75 accessor.setDirectory(fd, null); 76 accessor.setFile(fd, null); 77 accessor.setFiles(fd, null); 78 } else { 79 // Fix 6987233: add the trailing slash if it's absent 80 String with_separator = directory; 81 if (directory != null) { 82 with_separator = directory.endsWith(File.separator) ? 83 directory : (directory + File.separator); 84 } 85 accessor.setDirectory(fd, with_separator); 86 accessor.setFile(fd, filenames[0]); 87 88 int filesNumber = (filenames != null) ? filenames.length : 0; 89 File[] files = new File[filesNumber]; 90 for (int i = 0; i < filesNumber; i++) { 91 files[i] = new File(directory, filenames[i]); 92 } 93 accessor.setFiles(fd, files); 94 } 95 } 96 97 /** 98 * Called exclusively by the native C code. 99 */ filenameFilterCallback(String fullname)100 private boolean filenameFilterCallback(String fullname) { 101 if (fd.getFilenameFilter() == null) { 102 // no filter, accept all. 103 return true; 104 } 105 106 File filen = new File(fullname); 107 return fd.getFilenameFilter().accept(new File(filen.getParent()), 108 filen.getName()); 109 } 110 111 @Override setVisible(boolean b)112 public void setVisible(boolean b) { 113 XToolkit.awtLock(); 114 try { 115 quit = !b; 116 if (b) { 117 Runnable task = () -> { 118 showNativeDialog(); 119 standaloneWindow = 0; 120 fd.setVisible(false); 121 }; 122 new Thread(null, task, "ShowDialog", 0, false).start(); 123 } else { 124 quit(); 125 fd.setVisible(false); 126 } 127 } finally { 128 XToolkit.awtUnlock(); 129 } 130 } 131 132 @Override dispose()133 public void dispose() { 134 XToolkit.awtLock(); 135 try { 136 quit = true; 137 quit(); 138 } 139 finally { 140 XToolkit.awtUnlock(); 141 } 142 super.dispose(); 143 } 144 145 @Override setDirectory(String dir)146 public void setDirectory(String dir) { 147 // We do not implement this method because we 148 // have delegated to FileDialog#setDirectory 149 } 150 151 @Override setFile(String file)152 public void setFile(String file) { 153 // We do not implement this method because we 154 // have delegated to FileDialog#setFile 155 } 156 requestXFocus(long time, boolean timeProvided)157 protected void requestXFocus(long time, boolean timeProvided) { 158 if(standaloneWindow == 0) { 159 super.requestXFocus(time, timeProvided); 160 return; 161 } 162 XNETProtocol net_protocol = XWM.getWM().getNETProtocol(); 163 if (net_protocol != null) { 164 net_protocol.setActiveWindow(standaloneWindow); 165 } 166 } 167 168 @Override setFilenameFilter(FilenameFilter filter)169 public void setFilenameFilter(FilenameFilter filter) { 170 // We do not implement this method because we 171 // have delegated to FileDialog#setFilenameFilter 172 } 173 showNativeDialog()174 private void showNativeDialog() { 175 String dirname = fd.getDirectory(); 176 // File path has a priority against directory path. 177 String filename = fd.getFile(); 178 if (filename != null) { 179 final File file = new File(filename); 180 if (fd.getMode() == FileDialog.LOAD 181 && dirname != null 182 && file.getParent() == null) { 183 // File path for gtk_file_chooser_set_filename. 184 filename = dirname + (dirname.endsWith(File.separator) ? "" : 185 File.separator) + filename; 186 } 187 if (fd.getMode() == FileDialog.SAVE && file.getParent() != null) { 188 // Filename for gtk_file_chooser_set_current_name. 189 filename = file.getName(); 190 // Directory path for gtk_file_chooser_set_current_folder. 191 dirname = file.getParent(); 192 } 193 } 194 if (!quit) { 195 run(fd.getTitle(), fd.getMode(), dirname, filename, 196 fd.getFilenameFilter(), fd.isMultipleMode(), fd.getX(), fd.getY()); 197 } 198 } 199 200 /** 201 * Called by native code when GTK dialog is created. 202 */ setWindow(long xid)203 boolean setWindow(long xid) { 204 if (!quit && widget != 0) { 205 standaloneWindow = xid; 206 requestXFocus(); 207 return true; 208 } 209 return false; 210 } 211 } 212