org.gnome.gio.FileMonitor Maven / Gradle / Ivy
Show all versions of gio Show documentation
// This file was automatically generated by Java-GI. Do not edit this file
// directly! Visit for more information.
//
// The API documentation in this file was derived from GObject-Introspection
// metadata and may include text or comments from the original C sources.
//
// Copyright (c), upstream authors as identified in the GObject-Introspection
// metadata.
//
// This generated file is distributed under the same license as the original
// GObject-Introspection data, unless otherwise specified. Users of this file
// are responsible for complying with any licenses or terms required by the
// original authors.
//
// THIS FILE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
//
package org.gnome.gio;
import io.github.jwharm.javagi.Constants;
import io.github.jwharm.javagi.base.FunctionPointer;
import io.github.jwharm.javagi.gobject.InstanceCache;
import io.github.jwharm.javagi.gobject.SignalConnection;
import io.github.jwharm.javagi.gobject.types.Overrides;
import io.github.jwharm.javagi.gobject.types.Signals;
import io.github.jwharm.javagi.gobject.types.Types;
import io.github.jwharm.javagi.interop.Arenas;
import io.github.jwharm.javagi.interop.Interop;
import java.lang.FunctionalInterface;
import java.lang.NullPointerException;
import java.lang.foreign.Arena;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.Linker;
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import java.lang.invoke.MethodHandle;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.annotation.processing.Generated;
import org.gnome.glib.GLib;
import org.gnome.glib.LogLevelFlags;
import org.gnome.glib.Type;
import org.gnome.gobject.GObject;
import org.gnome.gobject.Value;
import org.jetbrains.annotations.Nullable;
/**
* Monitors a file or directory for changes.
*
* To obtain a {@code GFileMonitor} for a file or directory, use
* {@link File#monitor}, {@link File#monitorFile}, or
* {@link File#monitorDirectory}.
*
* To get informed about changes to the file or directory you are
* monitoring, connect to the {@code Gio.FileMonitor::changed} signal. The
* signal will be emitted in the thread-default main context (see
* {@link org.gnome.glib.MainContext#pushThreadDefault}) of the thread that the monitor
* was created in (though if the global default main context is blocked, this
* may cause notifications to be blocked even if the thread-default
* context is still running).
*/
@Generated("io.github.jwharm.JavaGI")
public abstract class FileMonitor extends GObject {
static {
Gio.javagi$ensureInitialized();
}
/**
* Create a FileMonitor proxy instance for the provided memory address.
*
* @param address the memory address of the native object
*/
public FileMonitor(MemorySegment address) {
super(Interop.reinterpret(address, getMemoryLayout().byteSize()));
}
/**
* Get the GType of the FileMonitor class
*
* @return the GType
*/
public static Type getType() {
return Interop.getType("g_file_monitor_get_type");
}
/**
* The memory layout of the native struct.
* @return the memory layout
*/
public static MemoryLayout getMemoryLayout() {
return MemoryLayout.structLayout(
GObject.getMemoryLayout().withName("parent_instance"),
ValueLayout.ADDRESS.withName("priv")
).withName("GFileMonitor");
}
/**
* Returns this instance as if it were its parent type. This is mostly
* synonymous to the Java {@code super} keyword, but will set the native
* typeclass function pointers to the parent type. When overriding a native
* virtual method in Java, "chaining up" with {@code super.methodName()}
* doesn't work, because it invokes the overridden function pointer again.
* To chain up, call {@code asParent().methodName()}. This will call the
* native function pointer of this virtual method in the typeclass of the
* parent type.
*/
protected FileMonitor asParent() {
FileMonitor _parent = new FileMonitorImpl(handle());
_parent.callParent(true);
return _parent;
}
/**
* Cancels a file monitor.
*
* @return always {@code true}
*/
public boolean cancel() {
int _result;
try {
if (callParent()) {
FunctionDescriptor _fdesc = FunctionDescriptor.of(ValueLayout.JAVA_INT,
ValueLayout.ADDRESS);
MemorySegment _func = Overrides.lookupVirtualMethodParent(handle(),
FileMonitorClass.getMemoryLayout(), "cancel");
if (_func.equals(MemorySegment.NULL)) throw new NullPointerException();
_result = (int) Interop.downcallHandle(_func, _fdesc).invokeExact(handle());
} else {
_result = (int) MethodHandles.g_file_monitor_cancel.invokeExact(handle());
}
} catch (Throwable _err) {
throw new AssertionError(_err);
}
return _result != 0;
}
/**
* Emits the {@code GFileMonitor}::changed signal if a change
* has taken place. Should be called from file monitor
* implementations only.
*
* Implementations are responsible to call this method from the
* [thread-default main context][g-main-context-push-thread-default] of the
* thread that the monitor was created in.
*
* @param child a {@code GFile}.
* @param otherFile a {@code GFile}.
* @param eventType a set of {@code GFileMonitorEvent} flags.
*/
public void emitEvent(File child, File otherFile, FileMonitorEvent eventType) {
try {
MethodHandles.g_file_monitor_emit_event.invokeExact(handle(),
(MemorySegment) (child == null ? MemorySegment.NULL : child.handle()),
(MemorySegment) (otherFile == null ? MemorySegment.NULL : otherFile.handle()),
eventType.getValue());
} catch (Throwable _err) {
throw new AssertionError(_err);
}
}
/**
* Returns whether the monitor is canceled.
*
* @return {@code true} if monitor is canceled. {@code false} otherwise.
*/
public boolean isCancelled() {
int _result;
try {
_result = (int) MethodHandles.g_file_monitor_is_cancelled.invokeExact(handle());
} catch (Throwable _err) {
throw new AssertionError(_err);
}
return _result != 0;
}
/**
* Sets the rate limit to which the this FileMonitor will report
* consecutive change events to the same file.
*
* @param limitMsecs a non-negative integer with the limit in milliseconds
* to poll for changes
*/
public void setRateLimit(int limitMsecs) {
try {
MethodHandles.g_file_monitor_set_rate_limit.invokeExact(handle(), limitMsecs);
} catch (Throwable _err) {
throw new AssertionError(_err);
}
}
protected void changed(File file, File otherFile, FileMonitorEvent eventType) {
try {
FunctionDescriptor _fdesc = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS,
ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.JAVA_INT);
MemorySegment _func = Overrides.lookupVirtualMethodParent(handle(),
FileMonitorClass.getMemoryLayout(), "changed");
if (_func.equals(MemorySegment.NULL)) throw new NullPointerException();
Interop.downcallHandle(_func, _fdesc).invokeExact(handle(),
(MemorySegment) (file == null ? MemorySegment.NULL : file.handle()),
(MemorySegment) (otherFile == null ? MemorySegment.NULL : otherFile.handle()),
eventType.getValue());
} catch (Throwable _err) {
throw new AssertionError(_err);
}
}
/**
* Emitted when {@code file} has been changed.
*
* If using {@link org.gnome.gio.FileMonitorFlags#WATCH_MOVES} on a directory monitor, and
* the information is available (and if supported by the backend),
* {@code eventType} may be {@link org.gnome.gio.FileMonitorEvent#RENAMED},
* {@link org.gnome.gio.FileMonitorEvent#MOVED_IN} or {@link org.gnome.gio.FileMonitorEvent#MOVED_OUT}.
*
* In all cases {@code file} will be a child of the monitored directory. For
* renames, {@code file} will be the old name and {@code otherFile} is the new
* name. For "moved in" events, {@code file} is the name of the file that
* appeared and {@code otherFile} is the old name that it was moved from (in
* another directory). For "moved out" events, {@code file} is the name of
* the file that used to be in this directory and {@code otherFile} is the
* name of the file at its new location.
*
* It makes sense to treat {@link org.gnome.gio.FileMonitorEvent#MOVED_IN} as
* equivalent to {@link org.gnome.gio.FileMonitorEvent#CREATED} and
* {@link org.gnome.gio.FileMonitorEvent#MOVED_OUT} as equivalent to
* {@link org.gnome.gio.FileMonitorEvent#DELETED}, with extra information.
* {@link org.gnome.gio.FileMonitorEvent#RENAMED} is equivalent to a delete/create
* pair. This is exactly how the events will be reported in the case
* that the {@link org.gnome.gio.FileMonitorFlags#WATCH_MOVES} flag is not in use.
*
* If using the deprecated flag {@link org.gnome.gio.FileMonitorFlags#SEND_MOVED} flag and {@code eventType} is
* {@link org.gnome.gio.FileMonitorEvent#MOVED}, {@code file} will be set to a {@code GFile} containing the
* old path, and {@code otherFile} will be set to a {@code GFile} containing the new path.
*
* In all the other cases, {@code otherFile} will be set to {@code NULL}.
*
* @param handler the signal handler
* @return a signal handler ID to keep track of the signal connection
* @see ChangedCallback#run
*/
public SignalConnection onChanged(ChangedCallback handler) {
try (Arena _arena = Arena.ofConfined()) {
try {
var _name = Interop.allocateNativeString("changed", _arena);
var _callbackArena = Arena.ofShared();
var _result = (int) (long) Signals.g_signal_connect_data.invokeExact(handle(),
_name, handler.toCallback(_callbackArena),
Arenas.cacheArena(_callbackArena), Arenas.CLOSE_CB_SYM, 0);
return new SignalConnection<>(handle(), _result);
} catch (Throwable _err) {
throw new AssertionError(_err);
}
}
}
/**
* Emits the "changed" signal. See {@link #onChanged}.
*/
public void emitChanged(File file, @Nullable File otherFile, FileMonitorEvent eventType) {
try (Arena _arena = Arena.ofConfined()) {
MemorySegment _name = Interop.allocateNativeString("changed", _arena);
Object[] _args = new Object[] {
(MemorySegment) (file == null ? MemorySegment.NULL : file.handle()),
(MemorySegment) (otherFile == null ? MemorySegment.NULL : otherFile.handle()),
eventType.getValue()};
Signals.g_signal_emit_by_name.invokeExact(handle(), _name, _args);
} catch (Throwable _err) {
throw new AssertionError(_err);
}
}
/**
* A {@link Builder} object constructs a {@code FileMonitor}
* with the specified properties.
* Use the various {@code set...()} methods to set properties,
* and finish construction with {@link Builder#build()}.
*/
public static Builder extends Builder> builder() {
return new Builder<>();
}
/**
* Functional interface declaration of the {@code ChangedCallback} callback.
*
* @see ChangedCallback#run
*/
@FunctionalInterface
public interface ChangedCallback extends FunctionPointer {
/**
* Emitted when {@code file} has been changed.
*
* If using {@link org.gnome.gio.FileMonitorFlags#WATCH_MOVES} on a directory monitor, and
* the information is available (and if supported by the backend),
* {@code eventType} may be {@link org.gnome.gio.FileMonitorEvent#RENAMED},
* {@link org.gnome.gio.FileMonitorEvent#MOVED_IN} or {@link org.gnome.gio.FileMonitorEvent#MOVED_OUT}.
*
* In all cases {@code file} will be a child of the monitored directory. For
* renames, {@code file} will be the old name and {@code otherFile} is the new
* name. For "moved in" events, {@code file} is the name of the file that
* appeared and {@code otherFile} is the old name that it was moved from (in
* another directory). For "moved out" events, {@code file} is the name of
* the file that used to be in this directory and {@code otherFile} is the
* name of the file at its new location.
*
* It makes sense to treat {@link org.gnome.gio.FileMonitorEvent#MOVED_IN} as
* equivalent to {@link org.gnome.gio.FileMonitorEvent#CREATED} and
* {@link org.gnome.gio.FileMonitorEvent#MOVED_OUT} as equivalent to
* {@link org.gnome.gio.FileMonitorEvent#DELETED}, with extra information.
* {@link org.gnome.gio.FileMonitorEvent#RENAMED} is equivalent to a delete/create
* pair. This is exactly how the events will be reported in the case
* that the {@link org.gnome.gio.FileMonitorFlags#WATCH_MOVES} flag is not in use.
*
* If using the deprecated flag {@link org.gnome.gio.FileMonitorFlags#SEND_MOVED} flag and {@code eventType} is
* {@link org.gnome.gio.FileMonitorEvent#MOVED}, {@code file} will be set to a {@code GFile} containing the
* old path, and {@code otherFile} will be set to a {@code GFile} containing the new path.
*
* In all the other cases, {@code otherFile} will be set to {@code NULL}.
*/
void run(File file, @Nullable File otherFile, FileMonitorEvent eventType);
/**
* The {@code upcall} method is called from native code. The parameters
* are marshaled and {@link #run} is executed.
*/
default void upcall(MemorySegment sourceFileMonitor, MemorySegment file,
MemorySegment otherFile, int eventType) {
run((File) InstanceCache.getForType(file, File.FileImpl::new, false), (File) InstanceCache.getForType(otherFile, File.FileImpl::new, false), FileMonitorEvent.of(eventType));
}
/**
* Creates a native function pointer to the {@link #upcall} method.
*
* @return the native function pointer
*/
default MemorySegment toCallback(Arena arena) {
FunctionDescriptor _fdesc = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS,
ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.JAVA_INT);
MethodHandle _handle = Interop.upcallHandle(java.lang.invoke.MethodHandles.lookup(), ChangedCallback.class, _fdesc);
return Linker.nativeLinker().upcallStub(_handle.bindTo(this), _fdesc, arena);
}
}
public static class FileMonitorClass extends GObject.ObjectClass {
private Method _changedMethod;
private Method _cancelMethod;
/**
* Create a FileMonitorClass proxy instance for the provided memory address.
*
* @param address the memory address of the native object
*/
public FileMonitorClass(MemorySegment address) {
super(Interop.reinterpret(address, getMemoryLayout().byteSize()));
}
/**
* Allocate a new FileMonitorClass.
*
* @param arena to control the memory allocation scope
*/
public FileMonitorClass(Arena arena) {
super(arena.allocate(getMemoryLayout()));
}
/**
* Allocate a new FileMonitorClass.
* The memory is allocated with {@link Arena#ofAuto}.
*/
public FileMonitorClass() {
super(Arena.ofAuto().allocate(getMemoryLayout()));
}
/**
* The memory layout of the native struct.
* @return the memory layout
*/
public static MemoryLayout getMemoryLayout() {
return MemoryLayout.structLayout(
GObject.ObjectClass.getMemoryLayout().withName("parent_class"),
ValueLayout.ADDRESS.withName("changed"),
ValueLayout.ADDRESS.withName("cancel"),
ValueLayout.ADDRESS.withName("_g_reserved1"),
ValueLayout.ADDRESS.withName("_g_reserved2"),
ValueLayout.ADDRESS.withName("_g_reserved3"),
ValueLayout.ADDRESS.withName("_g_reserved4"),
ValueLayout.ADDRESS.withName("_g_reserved5")
).withName("GFileMonitorClass");
}
/**
* Override virtual method {@code changed}.
*
* @param method the method to invoke
*/
public void overrideChanged(Arena arena, Method method) {
this._changedMethod = method;
FunctionDescriptor _fdesc = FunctionDescriptor.ofVoid(ValueLayout.ADDRESS,
ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.JAVA_INT);
MethodHandle _handle = Interop.upcallHandle(java.lang.invoke.MethodHandles.lookup(), FileMonitorClass.class, "changedUpcall", _fdesc);
MemorySegment _address = Linker.nativeLinker().upcallStub(_handle.bindTo(this), _fdesc, arena);
getMemoryLayout().varHandle(MemoryLayout.PathElement.groupElement("changed"))
.set(handle(), 0, (method == null ? MemorySegment.NULL : _address));
}
private void changedUpcall(MemorySegment monitor, MemorySegment file,
MemorySegment otherFile, int eventType) {
try {
Arena _arena = Arena.ofAuto();
this._changedMethod.invoke((FileMonitor) InstanceCache.getForType(monitor, FileMonitorImpl::new, false), (File) InstanceCache.getForType(file, File.FileImpl::new, false), (File) InstanceCache.getForType(otherFile, File.FileImpl::new, false), FileMonitorEvent.of(eventType));
} catch (InvocationTargetException ite) {
GLib.log(Constants.LOG_DOMAIN, LogLevelFlags.LEVEL_WARNING, ite.getCause().toString() + " in " + _changedMethod);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* Override virtual method {@code cancel}.
*
* @param method the method to invoke
*/
public void overrideCancel(Arena arena, Method method) {
this._cancelMethod = method;
FunctionDescriptor _fdesc = FunctionDescriptor.of(ValueLayout.JAVA_INT,
ValueLayout.ADDRESS);
MethodHandle _handle = Interop.upcallHandle(java.lang.invoke.MethodHandles.lookup(), FileMonitorClass.class, "cancelUpcall", _fdesc);
MemorySegment _address = Linker.nativeLinker().upcallStub(_handle.bindTo(this), _fdesc, arena);
getMemoryLayout().varHandle(MemoryLayout.PathElement.groupElement("cancel"))
.set(handle(), 0, (method == null ? MemorySegment.NULL : _address));
}
private int cancelUpcall(MemorySegment monitor) {
try {
Arena _arena = Arena.ofAuto();
var _result = (boolean) this._cancelMethod.invoke((FileMonitor) InstanceCache.getForType(monitor, FileMonitorImpl::new, false));
return _result ? 1 : 0;
} catch (InvocationTargetException ite) {
GLib.log(Constants.LOG_DOMAIN, LogLevelFlags.LEVEL_WARNING, ite.getCause().toString() + " in " + _cancelMethod);
return 0;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
/**
* The FileMonitorImpl type represents a native instance of the abstract FileMonitor class.
*/
public static class FileMonitorImpl extends FileMonitor {
/**
* Creates a new instance of FileMonitor for the provided memory address.
*
* @param address the memory address of the instance
*/
public FileMonitorImpl(MemorySegment address) {
super(address);
}
}
/**
* Inner class implementing a builder pattern to construct a GObject with
* properties.
*
* @param the type of the Builder that is returned
*/
public static class Builder> extends GObject.Builder {
/**
* Default constructor for a {@code Builder} object.
*/
protected Builder() {
}
/**
* Finish building the {@code FileMonitor} object. This will call
* {@link GObject#withProperties} to create a new GObject instance,
* which is then cast to {@code FileMonitor}.
*
* @return a new instance of {@code FileMonitor} with the properties
* that were set in the Builder object.
*/
public FileMonitor build() {
try {
var _instance = (FileMonitor) GObject.withProperties(FileMonitor.getType(), getNames(), getValues());
connectSignals(_instance.handle());
return _instance;
} finally {
for (Value _value : getValues()) _value.unset();
getArena().close();
}
}
/**
* The limit of the monitor to watch for changes, in milliseconds.
*
* @param rateLimit the value for the {@code rate-limit} property
* @return the {@code Builder} instance is returned, to allow method chaining
*/
public B setRateLimit(int rateLimit) {
Arena _arena = getArena();
Value _value = new Value(_arena);
_value.init(Types.INT);
_value.setInt(rateLimit);
addBuilderProperty("rate-limit", _value);
return (B) this;
}
/**
* Emitted when {@code file} has been changed.
*
* If using {@link org.gnome.gio.FileMonitorFlags#WATCH_MOVES} on a directory monitor, and
* the information is available (and if supported by the backend),
* {@code eventType} may be {@link org.gnome.gio.FileMonitorEvent#RENAMED},
* {@link org.gnome.gio.FileMonitorEvent#MOVED_IN} or {@link org.gnome.gio.FileMonitorEvent#MOVED_OUT}.
*
* In all cases {@code file} will be a child of the monitored directory. For
* renames, {@code file} will be the old name and {@code otherFile} is the new
* name. For "moved in" events, {@code file} is the name of the file that
* appeared and {@code otherFile} is the old name that it was moved from (in
* another directory). For "moved out" events, {@code file} is the name of
* the file that used to be in this directory and {@code otherFile} is the
* name of the file at its new location.
*
* It makes sense to treat {@link org.gnome.gio.FileMonitorEvent#MOVED_IN} as
* equivalent to {@link org.gnome.gio.FileMonitorEvent#CREATED} and
* {@link org.gnome.gio.FileMonitorEvent#MOVED_OUT} as equivalent to
* {@link org.gnome.gio.FileMonitorEvent#DELETED}, with extra information.
* {@link org.gnome.gio.FileMonitorEvent#RENAMED} is equivalent to a delete/create
* pair. This is exactly how the events will be reported in the case
* that the {@link org.gnome.gio.FileMonitorFlags#WATCH_MOVES} flag is not in use.
*
* If using the deprecated flag {@link org.gnome.gio.FileMonitorFlags#SEND_MOVED} flag and {@code eventType} is
* {@link org.gnome.gio.FileMonitorEvent#MOVED}, {@code file} will be set to a {@code GFile} containing the
* old path, and {@code otherFile} will be set to a {@code GFile} containing the new path.
*
* In all the other cases, {@code otherFile} will be set to {@code NULL}.
*
* @param handler the signal handler
* @return the {@code Builder} instance is returned, to allow method chaining
* @see ChangedCallback#run
*/
public B onChanged(ChangedCallback handler) {
connect("changed", handler);
return (B) this;
}
}
private static final class MethodHandles {
static final MethodHandle g_file_monitor_cancel = Interop.downcallHandle(
"g_file_monitor_cancel", FunctionDescriptor.of(ValueLayout.JAVA_INT,
ValueLayout.ADDRESS), false);
static final MethodHandle g_file_monitor_emit_event = Interop.downcallHandle(
"g_file_monitor_emit_event", FunctionDescriptor.ofVoid(ValueLayout.ADDRESS,
ValueLayout.ADDRESS, ValueLayout.ADDRESS, ValueLayout.JAVA_INT), false);
static final MethodHandle g_file_monitor_is_cancelled = Interop.downcallHandle(
"g_file_monitor_is_cancelled", FunctionDescriptor.of(ValueLayout.JAVA_INT,
ValueLayout.ADDRESS), false);
static final MethodHandle g_file_monitor_set_rate_limit = Interop.downcallHandle(
"g_file_monitor_set_rate_limit", FunctionDescriptor.ofVoid(ValueLayout.ADDRESS,
ValueLayout.JAVA_INT), false);
}
}