@SuppressWarnings("SameParameterValue")
    private @Nullable <T> T getWindowProperty(long window, long name, long type, long expectedFormat) throws Exception {
      long data = unsafe.allocateMemory(64);
      awtLock.invoke(null);
      try {
        unsafe.setMemory(data, 64, (byte)0);

        int result = (Integer)XGetWindowProperty.invoke(
          null, display, window, name, 0L, 65535L, (long)False, type, data, data + 8, data + 16, data + 24, data + 32);
        if (result == 0) {
          int format = unsafe.getInt(data + 8);
          long pointer = Native.LONG_SIZE == 4 ? unsafe.getInt(data + 32) : unsafe.getLong(data + 32);

          if (pointer != None && format == expectedFormat) {
            int length = Native.LONG_SIZE == 4 ? unsafe.getInt(data + 16) : (int)unsafe.getLong(data + 16);
            if (format == FORMAT_BYTE) {
              byte[] bytes = new byte[length];
              for (int i = 0; i < length; i++) bytes[i] = unsafe.getByte(pointer + i);
              return (T)bytes;
            }
            else if (format == FORMAT_LONG) {
              long[] values = new long[length];
              for (int i = 0; i < length; i++) {
                values[i] = Native.LONG_SIZE == 4 ? unsafe.getInt(pointer + 4L * i) : unsafe.getLong(pointer + 8L * i);
              }
              return (T)values;
            }
            else if (format != None) {
              LOG.info("unexpected format: " + format);
            }
          }

          if (pointer != None) XFree.invoke(null, pointer);

        }
      }
      finally {
        awtUnlock.invoke(null);
        unsafe.freeMemory(data);
      }

      return null;
    }
@SuppressWarnings("SameParameterValue")
    private @Nullable <T> T getWindowProperty(long window, long name, long type, long expectedFormat)