JavaFX MacOS – окно не перемещается с прозрачным заголовкомJAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 JavaFX MacOS – окно не перемещается с прозрачным заголовком

Сообщение Anonymous »

Мне удалось манипулировать окном JavaFX с помощью Java FFM и собственного объекта NSWindow для MacOS. Однако при установке для заголовкаAppearsTransparent значения true и добавлении NSWindowStyleMaskFullSizeContentView окно становится подвижным только тогда, когда вам удается перетащить его за самую верхнюю границу. Несмотря на то, что строка заголовка в этот момент не видна, я бы хотел иметь возможность перетаскивать окно с помощью «воображаемой» панели инструментов...
Итак, как мне получить окно распознать строку заголовка как подвижный прямоугольник, даже если он прозрачен?
Пока это то, что я сделал, чтобы достичь этого. Код очень избыточен, но сейчас я просто бездельничаю, пытаясь доказать концепцию...
  • Получить дескриптор NSWindow
private long getNSWindowHandle() throws Throwable {

// Get class NSApplication
try (Arena arena = Arena.ofConfined()) {

long nsApplication = (long) objc_getClass.invoke(arena.allocateFrom("NSApplication"));
System.out.println("nsApplication: " + Long.toHexString(nsApplication));

// Get selector for sharedApplication
long sharedAppSelector = (long) sel_registerName.invoke(arena.allocateFrom("sharedApplication"));
System.out.println("sharedAppSelector: " + Long.toHexString(sharedAppSelector));

// Get NSApplication shared instance
long sharedApplication = (long) LINKER.downcallHandle(
symbolLookup.find("objc_msgSend").orElseThrow(),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG))
.invoke(nsApplication, sharedAppSelector);
System.out.println("sharedApplication: " + Long.toHexString(sharedApplication));

// Get selector for windows array
long windowsSelector = (long) sel_registerName.invoke(arena.allocateFrom("windows"));
System.out.println("windowsSelector: " + Long.toHexString(windowsSelector));

// Get array of windows (NSArray of NSWindow objects)
long windowsArray = (long) LINKER.downcallHandle(
symbolLookup.find("objc_msgSend").orElseThrow(),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG))
.invoke(sharedApplication, windowsSelector);
System.out.println("windowsArray: " + Long.toHexString(windowsArray));

// Get selector for objectAtIndex:
long objectAtIndexSelector = (long) sel_registerName.invoke(arena.allocateFrom("objectAtIndex:"));
System.out.println("objectAtIndexSelector: " + Long.toHexString(objectAtIndexSelector));

// Get first window (NSWindow) in the array (index 0)
long nsWindow = (long) LINKER.downcallHandle(
symbolLookup.find("objc_msgSend").orElseThrow(),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG))
.invoke(windowsArray, objectAtIndexSelector, (long) 0);
System.out.println("nsWindow: " + Long.toHexString(nsWindow));

return nsWindow;
}
}

  • Измените NSWindow на желаемый стиль
private void setCustomWindow(long nsWindow) throws Throwable {

try (Arena arena = Arena.ofConfined()) {

// TRANSPARENT TITLE BAR
var titleBarTransparentSelector = (long) sel_registerName.invoke(arena.allocateFrom("setTitlebarAppearsTransparent:"));
LINKER.downcallHandle(
symbolLookup.find("objc_msgSend").orElseThrow(),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_BOOLEAN))
.invoke(nsWindow, titleBarTransparentSelector, true);

// UPDATE STYLE MASK
long styleMaskSelector = (long) sel_registerName.invoke(arena.allocateFrom("styleMask"));
long setStyleMaskSelector = (long) sel_registerName.invoke(arena.allocateFrom("setStyleMask:"));
long styleMask = (long) LINKER.downcallHandle(
symbolLookup.find("objc_msgSend").orElseThrow(),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG))
.invoke(nsWindow, styleMaskSelector);

styleMask &= ~NSWindowStyleMaskUnifiedTitleAndToolbar;
styleMask |= NSWindowStyleMaskFullSizeContentView;
styleMask |= NSWindowStyleMaskTitled;
LINKER.downcallHandle(symbolLookup.find("objc_msgSend")
.orElseThrow(), FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG))
.invoke(nsWindow, setStyleMaskSelector, styleMask);

// TITLE SEPARATOR
int titleSeparator = 1;
long setTitlebarSeparator = (long) sel_registerName.invoke(arena.allocateFrom("setTitlebarSeparatorStyle:"));
LINKER.downcallHandle(symbolLookup.find("objc_msgSend")
.orElseThrow(), FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_INT))
.invoke(nsWindow, setTitlebarSeparator, titleSeparator);

// TITLE VISIBILITY (0 = visible, 1 = hidden)
int titleVisible = 0;
long setTitleVisibility = (long) sel_registerName.invoke(arena.allocateFrom("setTitleVisibility:"));
LINKER.downcallHandle(symbolLookup.find("objc_msgSend")
.orElseThrow(), FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_INT))
.invoke(nsWindow, setTitleVisibility, titleVisible);

// MOVABLE
var setMovableSelector = (long) sel_registerName.invoke(arena.allocateFrom("setMovable:"));
LINKER.downcallHandle(symbolLookup.find("objc_msgSend")
.orElseThrow(), FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_BOOLEAN))
.invoke(nsWindow, setMovableSelector, true);

// MOVABLE BY BACKGROUND
var isMovableByBackgroundSelector = (long) sel_registerName.invoke(arena.allocateFrom("setMovableByWindowBackground:"));
LINKER.downcallHandle(symbolLookup.find("objc_msgSend")
.orElseThrow(), FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_LONG, ValueLayout.JAVA_BOOLEAN))
.invoke(nsWindow, isMovableByBackgroundSelector, true);

}
}


Подробнее здесь: https://stackoverflow.com/questions/790 ... t-titlebar
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»