2016-08-19 159 views
1

以下JNA使用JNA 4.2.2崩潰 - 如果您在最小化和最大化窗口的情況下運行JVM,請使用以下參數。發生在Ubuntu 16.04上,但更常見於Redhat 6u2上。X11 JNA Bad Window(無效窗口參數)導致JVM退出

X error of failed request: BadWindow (invalid Window parameter) 
Major opcode of failed request: 20 (X_GetProperty) 
... 

我猜窗口ID是有效的,當他們從XQueryTree返回,但調用XGetWMName之前變得無效。問題是這導致JVM退出,而不僅僅是一個我可以很好地處理的異常。我如何避免這個問題?

public class X11WindowFinder { 

    private X11 x11; 

    public X11WindowFinder() { 
     x11 = X11.INSTANCE; 
    } 

    public List<Window> find(Pattern title) { 
     Display display = x11.XOpenDisplay(null); 
     Window root = x11.XDefaultRootWindow(display); 
     List<Window> windows = recurse(x11, display, root, title); 
     x11.XCloseDisplay(display); 
     return windows; 
    } 

    private synchronized List<Window> recurse(X11 x11, Display display, Window root, Pattern pattern) { 
     List<Window> windows = new ArrayList<>(1); 
     X11.WindowByReference windowRef = new X11.WindowByReference(); 
     X11.WindowByReference parentRef = new X11.WindowByReference(); 
     PointerByReference childrenRef = new PointerByReference(); 
     IntByReference childCountRef = new IntByReference(); 

     x11.XQueryTree(display, root, windowRef, parentRef, childrenRef, childCountRef); 
     if (childrenRef.getValue() == null) { 
      return Collections.emptyList(); 
     } 


     long[] ids = {}; 

     if (Native.LONG_SIZE == Long.BYTES) { 
      ids = childrenRef.getValue().getLongArray(0, childCountRef.getValue()); 
     } else if (Native.LONG_SIZE == Integer.BYTES) { 
      int[] intIds = childrenRef.getValue().getIntArray(0, childCountRef.getValue()); 
      ids = new long[intIds.length]; 
      for (int i = 0; i < intIds.length; i++) { 
       ids[i] = intIds[i]; 
      } 
     } 

     for (long id : ids) { 
      Window child = new Window(id); 
      X11.XTextProperty name = new X11.XTextProperty(); 
      x11.XGetWMName(display, child, name); 
      String value = name.value; 
      if (value != null) { 
       System.out.println(String.format("Found window %s free %s", value, name)); 
      } 
      if (value != null && pattern.matcher(value).matches()) { 
       windows.add(child); 
      } 
      windows.addAll(recurse(x11, display, child, pattern)); 
     } 
     return windows; 
    } 

    public static void main(String[] args) { 
     X11WindowFinder finder = new X11WindowFinder(); 
     while (true) { 
      finder.find(Pattern.compile(".*Firefox.*")); 
     } 
    } 
} 

回答

1

看起來像默認錯誤處理程序導致退出,但可以覆蓋。例如

x11.XSetErrorHandler(new XErrorHandler() { 

    @Override 
    public int apply(Display display, XErrorEvent errorEvent) { 
     System.err.println("bad fish " + errorEvent); 
     return 0; 
    } 
});