mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2026-01-05 16:11:39 +01:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
644fb1db0a | ||
|
|
6b2a8b03f7 | ||
|
|
0665558bcc | ||
|
|
17cefef4f9 | ||
|
|
0d95dbe3eb | ||
|
|
44fca1c619 | ||
|
|
4a50c3cc82 | ||
|
|
a139bc7866 | ||
|
|
8e05c17afb | ||
|
|
6ef6b1d328 | ||
|
|
7092fb7d71 | ||
|
|
2f8123cf84 |
@@ -38,7 +38,7 @@ else
|
||||
max_attempts=3
|
||||
attempt=1
|
||||
while [ $attempt -le $max_attempts ]; do
|
||||
if "$JETSIGN_CLIENT" -log-format text -denoted-content-type "$contentType" -extensions "$jetSignExtensions" "$pathToBeSigned"; then
|
||||
if "$JETSIGN_CLIENT" -log-format text -max-wait 1m -denoted-content-type "$contentType" -extensions "$jetSignExtensions" "$pathToBeSigned"; then
|
||||
break
|
||||
else
|
||||
if [ $attempt -eq $max_attempts ]; then
|
||||
|
||||
@@ -75,9 +75,11 @@ public abstract class VKSurfaceData extends SurfaceData
|
||||
private static final String DESC_VK_TEXTURE = "VK Texture";
|
||||
|
||||
|
||||
// We want non-premultiplied alpha to prevent precision loss, so use PixelConverter.Argb
|
||||
// See also VKUtil_DecodeJavaColor.
|
||||
static final SurfaceType VKSurface =
|
||||
SurfaceType.Any.deriveSubType(DESC_VK_SURFACE,
|
||||
PixelConverter.ArgbPre.instance);
|
||||
PixelConverter.Argb.instance);
|
||||
static final SurfaceType VKSurfaceRTT =
|
||||
VKSurface.deriveSubType(DESC_VK_SURFACE_RTT);
|
||||
static final SurfaceType VKTexture =
|
||||
|
||||
@@ -33,15 +33,15 @@
|
||||
#undef SHADER_ENTRY
|
||||
#undef BYTECODE_END
|
||||
|
||||
struct VKPipelineSet {
|
||||
typedef struct VKPipelineSet {
|
||||
VkPipeline pipelines[PIPELINE_COUNT];
|
||||
};
|
||||
} VKPipelineSet;
|
||||
|
||||
struct VKShaders {
|
||||
typedef struct VKShaders {
|
||||
# define SHADER_ENTRY(NAME, TYPE) VkPipelineShaderStageCreateInfo NAME ## _ ## TYPE;
|
||||
# include "vulkan/shader_list.h"
|
||||
# undef SHADER_ENTRY
|
||||
};
|
||||
} VKShaders;
|
||||
|
||||
static void VKPipelines_DestroyShaders(VKDevice* device, VKShaders* shaders) {
|
||||
assert(device != NULL);
|
||||
@@ -79,19 +79,19 @@ static VKShaders* VKPipelines_CreateShaders(VKDevice* device) {
|
||||
return shaders;
|
||||
}
|
||||
|
||||
#define MAKE_INPUT_STATE(TYPE, ...) \
|
||||
static const VkVertexInputAttributeDescription attributes[] = { __VA_ARGS__ }; \
|
||||
static const VkVertexInputBindingDescription binding = { \
|
||||
.binding = 0, \
|
||||
.stride = sizeof(TYPE), \
|
||||
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX \
|
||||
}; \
|
||||
static const VkPipelineVertexInputStateCreateInfo inputState = { \
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, \
|
||||
.vertexBindingDescriptionCount = 1, \
|
||||
.pVertexBindingDescriptions = &binding, \
|
||||
.vertexAttributeDescriptionCount = SARRAY_COUNT_OF(attributes), \
|
||||
.pVertexAttributeDescriptions = attributes \
|
||||
#define MAKE_INPUT_STATE(NAME, TYPE, ...) \
|
||||
static const VkVertexInputAttributeDescription INPUT_STATE_ATTRIBUTES_##NAME[] = { __VA_ARGS__ }; \
|
||||
static const VkVertexInputBindingDescription INPUT_STATE_BINDING_##NAME = { \
|
||||
.binding = 0, \
|
||||
.stride = sizeof(TYPE), \
|
||||
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX \
|
||||
}; \
|
||||
static const VkPipelineVertexInputStateCreateInfo INPUT_STATE_##NAME = { \
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, \
|
||||
.vertexBindingDescriptionCount = 1, \
|
||||
.pVertexBindingDescriptions = &INPUT_STATE_BINDING_##NAME, \
|
||||
.vertexAttributeDescriptionCount = SARRAY_COUNT_OF(INPUT_STATE_ATTRIBUTES_##NAME), \
|
||||
.pVertexAttributeDescriptions = INPUT_STATE_ATTRIBUTES_##NAME \
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
@@ -177,13 +177,62 @@ static const VkPipelineInputAssemblyStateCreateInfo INPUT_ASSEMBLY_STATE_LINE_LI
|
||||
.topology = VK_PRIMITIVE_TOPOLOGY_LINE_LIST
|
||||
};
|
||||
|
||||
const VkPipelineColorBlendAttachmentState BLEND_STATE = {
|
||||
.blendEnable = VK_FALSE,
|
||||
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT
|
||||
// Blend states are hard-coded, but can also be loaded dynamically to implement custom composites.
|
||||
#define DEF_BLEND(NAME, SRC_COLOR, DST_COLOR, SRC_ALPHA, DST_ALPHA) \
|
||||
{ .blendEnable = VK_TRUE, \
|
||||
.srcColorBlendFactor = VK_BLEND_FACTOR_ ## SRC_COLOR, \
|
||||
.dstColorBlendFactor = VK_BLEND_FACTOR_ ## DST_COLOR, \
|
||||
.colorBlendOp = VK_BLEND_OP_ADD, \
|
||||
.srcAlphaBlendFactor = VK_BLEND_FACTOR_ ## SRC_ALPHA, \
|
||||
.dstAlphaBlendFactor = VK_BLEND_FACTOR_ ## DST_ALPHA, \
|
||||
.alphaBlendOp = VK_BLEND_OP_ADD, \
|
||||
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | \
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT }
|
||||
|
||||
|
||||
const VkPipelineColorBlendAttachmentState COMPOSITE_BLEND_STATES[COMPOSITE_COUNT] = {
|
||||
{ .blendEnable = VK_FALSE, // LOGIC_XOR
|
||||
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT },
|
||||
// NAME || SRC_COLOR | DST_COLOR | SRC_ALPHA | DST_ALPHA ||
|
||||
DEF_BLEND(| CLEAR |, ZERO , ZERO , ZERO , ZERO ),
|
||||
DEF_BLEND(| SRC |, ONE , ZERO , ONE , ZERO ),
|
||||
DEF_BLEND(| SRC_OVER |, ONE , ONE_MINUS_SRC_ALPHA , ONE , ONE_MINUS_SRC_ALPHA ),
|
||||
DEF_BLEND(| DST_OVER |, ONE_MINUS_DST_ALPHA , ONE , ONE_MINUS_DST_ALPHA , ONE ),
|
||||
DEF_BLEND(| SRC_IN |, DST_ALPHA , ZERO , DST_ALPHA , ZERO ),
|
||||
DEF_BLEND(| DST_IN |, ZERO , SRC_ALPHA , ZERO , SRC_ALPHA ),
|
||||
DEF_BLEND(| SRC_OUT |, ONE_MINUS_DST_ALPHA , ZERO , ONE_MINUS_DST_ALPHA , ZERO ),
|
||||
DEF_BLEND(| DST_OUT |, ZERO , ONE_MINUS_SRC_ALPHA , ZERO , ONE_MINUS_SRC_ALPHA ),
|
||||
DEF_BLEND(| DST |, ZERO , ONE , ZERO , ONE ),
|
||||
DEF_BLEND(| SRC_ATOP |, DST_ALPHA , ONE_MINUS_SRC_ALPHA , ZERO , ONE ),
|
||||
DEF_BLEND(| DST_ATOP |, ONE_MINUS_DST_ALPHA , SRC_ALPHA , ONE , ZERO ),
|
||||
DEF_BLEND(| XOR |, ONE_MINUS_DST_ALPHA , ONE_MINUS_SRC_ALPHA , ONE_MINUS_DST_ALPHA , ONE_MINUS_SRC_ALPHA ),
|
||||
};
|
||||
|
||||
static const VkVertexInputAttributeDescription INPUT_ATTRIBUTE_POSITION = {
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT,
|
||||
.offset = 0
|
||||
};
|
||||
static const VkVertexInputAttributeDescription INPUT_ATTRIBUTE_COLOR = {
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = sizeof(float) * 2
|
||||
};
|
||||
static const VkVertexInputAttributeDescription INPUT_ATTRIBUTE_TEXCOORD = {
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT,
|
||||
.offset = sizeof(float) * 2
|
||||
};
|
||||
|
||||
MAKE_INPUT_STATE(COLOR_VERTEX, VKColorVertex, INPUT_ATTRIBUTE_POSITION, INPUT_ATTRIBUTE_COLOR);
|
||||
MAKE_INPUT_STATE(TEXCOORD_VERTEX, VKTxVertex, INPUT_ATTRIBUTE_POSITION, INPUT_ATTRIBUTE_TEXCOORD);
|
||||
|
||||
static void VKPipelines_DestroyPipelineSet(VKDevice* device, VKPipelineSet* set) {
|
||||
assert(device != NULL);
|
||||
if (set == NULL) return;
|
||||
for (uint32_t i = 0; i < PIPELINE_COUNT; i++) {
|
||||
device->vkDestroyPipeline(device->handle, set->pipelines[i], NULL);
|
||||
@@ -191,8 +240,9 @@ static void VKPipelines_DestroyPipelineSet(VKDevice* device, VKPipelineSet* set)
|
||||
free(set);
|
||||
}
|
||||
|
||||
static VKPipelineSet* VKPipelines_CreatePipelineSet(VKRenderPassContext* renderPassContext) {
|
||||
static VKPipelineSet* VKPipelines_CreatePipelineSet(VKRenderPassContext* renderPassContext, VKCompositeMode composite) {
|
||||
assert(renderPassContext != NULL && renderPassContext->pipelineContext != NULL);
|
||||
assert(composite < COMPOSITE_COUNT);
|
||||
VKPipelineContext* pipelineContext = renderPassContext->pipelineContext;
|
||||
|
||||
VKPipelineSet* set = calloc(1, sizeof(VKPipelineSet));
|
||||
@@ -205,7 +255,8 @@ static VKPipelineSet* VKPipelines_CreatePipelineSet(VKRenderPassContext* renderP
|
||||
VKPipelines_InitPipelineCreateState(&base);
|
||||
base.createInfo.layout = pipelineContext->pipelineLayout;
|
||||
base.createInfo.renderPass = renderPassContext->renderPass;
|
||||
base.colorBlendState.pAttachments = &BLEND_STATE;
|
||||
base.colorBlendState.pAttachments = &COMPOSITE_BLEND_STATES[composite];
|
||||
if (COMPOSITE_GROUP(composite) == LOGIC_COMPOSITE_GROUP) base.colorBlendState.logicOpEnable = VK_TRUE;
|
||||
assert(base.dynamicState.dynamicStateCount <= SARRAY_COUNT_OF(base.dynamicStates));
|
||||
|
||||
ShaderStages stages[PIPELINE_COUNT];
|
||||
@@ -215,36 +266,15 @@ static VKPipelineSet* VKPipelines_CreatePipelineSet(VKRenderPassContext* renderP
|
||||
createInfos[i].pStages = stages[i].createInfos;
|
||||
}
|
||||
|
||||
static const VkVertexInputAttributeDescription positionAttribute = {
|
||||
.location = 0,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT,
|
||||
.offset = 0
|
||||
};
|
||||
static const VkVertexInputAttributeDescription texcoordAttribute = {
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32_SFLOAT,
|
||||
.offset = sizeof(float) * 2
|
||||
};
|
||||
static const VkVertexInputAttributeDescription colorAttribute = {
|
||||
.location = 1,
|
||||
.binding = 0,
|
||||
.format = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.offset = sizeof(float) * 2
|
||||
};
|
||||
|
||||
{ // Setup plain color pipelines.
|
||||
MAKE_INPUT_STATE(VKColorVertex, positionAttribute, colorAttribute);
|
||||
createInfos[PIPELINE_DRAW_COLOR].pVertexInputState = createInfos[PIPELINE_FILL_COLOR].pVertexInputState = &inputState;
|
||||
createInfos[PIPELINE_DRAW_COLOR].pVertexInputState = createInfos[PIPELINE_FILL_COLOR].pVertexInputState = &INPUT_STATE_COLOR_VERTEX;
|
||||
createInfos[PIPELINE_FILL_COLOR].pInputAssemblyState = &INPUT_ASSEMBLY_STATE_TRIANGLE_LIST;
|
||||
createInfos[PIPELINE_DRAW_COLOR].pInputAssemblyState = &INPUT_ASSEMBLY_STATE_LINE_LIST;
|
||||
stages[PIPELINE_DRAW_COLOR] = stages[PIPELINE_FILL_COLOR] = (ShaderStages) {{ shaders->color_vert, shaders->color_frag }};
|
||||
}
|
||||
|
||||
{ // Setup texture pipeline.
|
||||
MAKE_INPUT_STATE(VKTxVertex, positionAttribute, texcoordAttribute);
|
||||
createInfos[PIPELINE_BLIT].pVertexInputState = &inputState;
|
||||
createInfos[PIPELINE_BLIT].pVertexInputState = &INPUT_STATE_TEXCOORD_VERTEX;
|
||||
createInfos[PIPELINE_BLIT].pInputAssemblyState = &INPUT_ASSEMBLY_STATE_TRIANGLE_STRIP;
|
||||
createInfos[PIPELINE_BLIT].layout = pipelineContext->texturePipelineLayout;
|
||||
stages[PIPELINE_BLIT] = (ShaderStages) {{ shaders->blit_vert, shaders->blit_frag }};
|
||||
@@ -254,11 +284,12 @@ static VKPipelineSet* VKPipelines_CreatePipelineSet(VKRenderPassContext* renderP
|
||||
// TODO pipeline cache
|
||||
VK_IF_ERROR(device->vkCreateGraphicsPipelines(device->handle, VK_NULL_HANDLE, PIPELINE_COUNT,
|
||||
createInfos, NULL, set->pipelines)) VK_UNHANDLED_ERROR();
|
||||
J2dRlsTraceLn(J2D_TRACE_INFO, "VKPipelines_CreatePipelineSet");
|
||||
J2dRlsTraceLn1(J2D_TRACE_INFO, "VKPipelines_CreatePipelineSet: composite=%d", composite);
|
||||
return set;
|
||||
}
|
||||
|
||||
static VkResult VKPipelines_InitRenderPass(VKDevice* device, VKRenderPassContext* renderPassContext) {
|
||||
assert(device != NULL && renderPassContext != NULL);
|
||||
VkAttachmentDescription colorAttachment = {
|
||||
.format = renderPassContext->format,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
@@ -304,8 +335,13 @@ static void VKPipelines_DestroyRenderPassContext(VKRenderPassContext* renderPass
|
||||
if (renderPassContext == NULL) return;
|
||||
VKDevice* device = renderPassContext->pipelineContext->device;
|
||||
assert(device != NULL);
|
||||
VKPipelines_DestroyPipelineSet(device, renderPassContext->pipelineSet);
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(renderPassContext->pipelineSets); i++) {
|
||||
VKPipelines_DestroyPipelineSet(device, renderPassContext->pipelineSets[i]);
|
||||
}
|
||||
ARRAY_FREE(renderPassContext->pipelineSets);
|
||||
device->vkDestroyRenderPass(device->handle, renderPassContext->renderPass, NULL);
|
||||
J2dRlsTraceLn2(J2D_TRACE_INFO, "VKPipelines_DestroyRenderPassContext(%p): format=%d",
|
||||
renderPassContext, renderPassContext->format);
|
||||
free(renderPassContext);
|
||||
}
|
||||
|
||||
@@ -321,6 +357,7 @@ static VKRenderPassContext* VKPipelines_CreateRenderPassContext(VKPipelineContex
|
||||
return NULL;
|
||||
}
|
||||
|
||||
J2dRlsTraceLn2(J2D_TRACE_INFO, "VKPipelines_CreateRenderPassContext(%p): format=%d", renderPassContext, format);
|
||||
return renderPassContext;
|
||||
}
|
||||
|
||||
@@ -397,6 +434,7 @@ VKPipelineContext* VKPipelines_CreateContext(VKDevice* device) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
J2dRlsTraceLn1(J2D_TRACE_INFO, "VKPipelines_CreateContext(%p)", pipelineContext);
|
||||
return pipelineContext;
|
||||
}
|
||||
|
||||
@@ -417,13 +455,16 @@ void VKPipelines_DestroyContext(VKPipelineContext* pipelineContext) {
|
||||
device->vkDestroyPipelineLayout(device->handle, pipelineContext->texturePipelineLayout, NULL);
|
||||
device->vkDestroyDescriptorSetLayout(device->handle, pipelineContext->textureDescriptorSetLayout, NULL);
|
||||
|
||||
J2dRlsTraceLn1(J2D_TRACE_INFO, "VKPipelines_DestroyContext(%p)", pipelineContext);
|
||||
free(pipelineContext);
|
||||
}
|
||||
|
||||
VKRenderPassContext* VKPipelines_GetRenderPassContext(VKPipelineContext* pipelineContext, VkFormat format) {
|
||||
assert(pipelineContext != NULL && pipelineContext->device != NULL);
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(pipelineContext->renderPassContexts); i++) {
|
||||
if (pipelineContext->renderPassContexts[i]->format == format) return pipelineContext->renderPassContexts[i];
|
||||
if (pipelineContext->renderPassContexts[i]->format == format) {
|
||||
return pipelineContext->renderPassContexts[i];
|
||||
}
|
||||
}
|
||||
// Not found, create.
|
||||
VKRenderPassContext* renderPassContext = VKPipelines_CreateRenderPassContext(pipelineContext, format);
|
||||
@@ -431,9 +472,16 @@ VKRenderPassContext* VKPipelines_GetRenderPassContext(VKPipelineContext* pipelin
|
||||
return renderPassContext;
|
||||
}
|
||||
|
||||
VkPipeline VKPipelines_GetPipeline(VKRenderPassContext* renderPassContext, VKPipeline pipeline) {
|
||||
if (renderPassContext->pipelineSet == NULL) {
|
||||
renderPassContext->pipelineSet = VKPipelines_CreatePipelineSet(renderPassContext);
|
||||
VkPipeline VKPipelines_GetPipeline(VKRenderPassContext* renderPassContext, VKCompositeMode composite, VKPipeline pipeline) {
|
||||
assert(renderPassContext != NULL);
|
||||
assert(composite < COMPOSITE_COUNT); // We could append custom composites after that index.
|
||||
assert(pipeline < PIPELINE_COUNT); // We could append custom pipelines after that index.
|
||||
// Currently, our pipelines map to composite modes 1-to-1, but this may change in future when we'll add more states.
|
||||
uint32_t setIndex = (uint32_t) composite;
|
||||
|
||||
while (ARRAY_SIZE(renderPassContext->pipelineSets) <= setIndex) ARRAY_PUSH_BACK(renderPassContext->pipelineSets, NULL);
|
||||
if (renderPassContext->pipelineSets[setIndex] == NULL) {
|
||||
renderPassContext->pipelineSets[setIndex] = VKPipelines_CreatePipelineSet(renderPassContext, composite);
|
||||
}
|
||||
return renderPassContext->pipelineSet->pipelines[pipeline];
|
||||
return renderPassContext->pipelineSets[setIndex]->pipelines[pipeline];
|
||||
}
|
||||
|
||||
@@ -24,22 +24,51 @@
|
||||
#ifndef VKPipelines_h_Included
|
||||
#define VKPipelines_h_Included
|
||||
|
||||
#include "java_awt_AlphaComposite.h"
|
||||
#include "VKTypes.h"
|
||||
|
||||
typedef struct VKShaders VKShaders;
|
||||
typedef struct VKPipelineSet VKPipelineSet;
|
||||
|
||||
/**
|
||||
* All pipeline types, use these to index into VKPipelineSet.pipelines.
|
||||
* All pipeline types.
|
||||
*/
|
||||
typedef enum {
|
||||
PIPELINE_FILL_COLOR = 0,
|
||||
PIPELINE_DRAW_COLOR = 1,
|
||||
PIPELINE_BLIT = 2,
|
||||
PIPELINE_COUNT = 3,
|
||||
NO_PIPELINE = PIPELINE_COUNT
|
||||
PIPELINE_BLIT = 2,
|
||||
PIPELINE_COUNT = 3,
|
||||
NO_PIPELINE = 0x7FFFFFFF
|
||||
} VKPipeline;
|
||||
|
||||
/**
|
||||
* There are two groups of composite modes:
|
||||
* - Logic composite - using logicOp.
|
||||
* - Alpha compisite - using blending.
|
||||
*/
|
||||
typedef enum {
|
||||
LOGIC_COMPOSITE_XOR = 0,
|
||||
LOGIC_COMPOSITE_GROUP = LOGIC_COMPOSITE_XOR,
|
||||
ALPHA_COMPOSITE_CLEAR = java_awt_AlphaComposite_CLEAR,
|
||||
ALPHA_COMPOSITE_SRC = java_awt_AlphaComposite_SRC,
|
||||
ALPHA_COMPOSITE_DST = java_awt_AlphaComposite_DST,
|
||||
ALPHA_COMPOSITE_SRC_OVER = java_awt_AlphaComposite_SRC_OVER,
|
||||
ALPHA_COMPOSITE_DST_OVER = java_awt_AlphaComposite_DST_OVER,
|
||||
ALPHA_COMPOSITE_SRC_IN = java_awt_AlphaComposite_SRC_IN,
|
||||
ALPHA_COMPOSITE_DST_IN = java_awt_AlphaComposite_DST_IN,
|
||||
ALPHA_COMPOSITE_SRC_OUT = java_awt_AlphaComposite_SRC_OUT,
|
||||
ALPHA_COMPOSITE_DST_OUT = java_awt_AlphaComposite_DST_OUT,
|
||||
ALPHA_COMPOSITE_SRC_ATOP = java_awt_AlphaComposite_SRC_ATOP,
|
||||
ALPHA_COMPOSITE_DST_ATOP = java_awt_AlphaComposite_DST_ATOP,
|
||||
ALPHA_COMPOSITE_XOR = java_awt_AlphaComposite_XOR,
|
||||
ALPHA_COMPOSITE_GROUP = ALPHA_COMPOSITE_XOR,
|
||||
COMPOSITE_COUNT = ALPHA_COMPOSITE_GROUP + 1,
|
||||
NO_COMPOSITE = 0x7FFFFFFF
|
||||
} VKCompositeMode;
|
||||
#define COMPOSITE_GROUP(COMPOSITE) ( \
|
||||
(COMPOSITE) <= LOGIC_COMPOSITE_GROUP ? LOGIC_COMPOSITE_GROUP : \
|
||||
(COMPOSITE) <= ALPHA_COMPOSITE_GROUP ? ALPHA_COMPOSITE_GROUP : \
|
||||
NO_COMPOSITE )
|
||||
|
||||
extern const VkPipelineColorBlendAttachmentState COMPOSITE_BLEND_STATES[COMPOSITE_COUNT];
|
||||
|
||||
/**
|
||||
* Global pipeline context.
|
||||
*/
|
||||
@@ -51,7 +80,7 @@ struct VKPipelineContext {
|
||||
|
||||
VkSampler linearRepeatSampler;
|
||||
|
||||
VKShaders* shaders;
|
||||
struct VKShaders* shaders;
|
||||
VKRenderPassContext** renderPassContexts;
|
||||
};
|
||||
|
||||
@@ -59,10 +88,10 @@ struct VKPipelineContext {
|
||||
* Per-format context.
|
||||
*/
|
||||
struct VKRenderPassContext {
|
||||
VKPipelineContext* pipelineContext;
|
||||
VkFormat format;
|
||||
VkRenderPass renderPass;
|
||||
VKPipelineSet* pipelineSet; // TODO we will need a real hash map for this in the future.
|
||||
VKPipelineContext* pipelineContext;
|
||||
VkFormat format;
|
||||
VkRenderPass renderPass;
|
||||
struct VKPipelineSet** pipelineSets; // TODO we will need a real hash map for this in the future.
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -79,6 +108,6 @@ VKPipelineContext* VKPipelines_CreateContext(VKDevice* device);
|
||||
void VKPipelines_DestroyContext(VKPipelineContext* pipelines);
|
||||
|
||||
VKRenderPassContext* VKPipelines_GetRenderPassContext(VKPipelineContext* pipelineContext, VkFormat format);
|
||||
VkPipeline VKPipelines_GetPipeline(VKRenderPassContext* renderPassContext, VKPipeline pipeline);
|
||||
VkPipeline VKPipelines_GetPipeline(VKRenderPassContext* renderPassContext, VKCompositeMode composite, VKPipeline pipeline);
|
||||
|
||||
#endif //VKPipelines_h_Included
|
||||
|
||||
@@ -94,9 +94,18 @@
|
||||
// Rendering context is only accessed from VKRenderQueue_flushBuffer,
|
||||
// which is only called from queue flusher thread, no need for synchronization.
|
||||
static VKRenderingContext context = {
|
||||
NULL, {},
|
||||
{1.0, 0.0, 0.0,0.0, 1.0, 0.0},
|
||||
{{0, 0}, {INT_MAX, INT_MAX}}};
|
||||
.surface = NULL,
|
||||
.transform = {1.0, 0.0, 0.0,0.0, 1.0, 0.0},
|
||||
.clipRect = {{0, 0},{INT_MAX, INT_MAX}},
|
||||
.color = {},
|
||||
.composite = ALPHA_COMPOSITE_SRC_OVER,
|
||||
.extraAlpha = 1.0f
|
||||
};
|
||||
// We keep this color separately from context.color,
|
||||
// because we need consistent state when switching between XOR and alpha composite modes.
|
||||
// This variable holds last value set by SET_COLOR, while context.color holds color,
|
||||
// currently used for drawing, which may have also been provided by SET_XOR_COMPOSITE.
|
||||
Color color;
|
||||
|
||||
JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
|
||||
(JNIEnv *env, jobject oglrq, jlong buf, jint limit)
|
||||
@@ -430,11 +439,14 @@ JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
|
||||
break;
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_ALPHA_COMPOSITE:
|
||||
{
|
||||
jint rule = NEXT_INT(b);
|
||||
jint rule = NEXT_INT(b);
|
||||
jfloat extraAlpha = NEXT_FLOAT(b);
|
||||
jint flags = NEXT_INT(b);
|
||||
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
|
||||
"VKRenderQueue_flushBuffer: SET_ALPHA_COMPOSITE");
|
||||
jint flags = NEXT_INT(b);
|
||||
J2dRlsTraceLn3(J2D_TRACE_VERBOSE,
|
||||
"VKRenderQueue_flushBuffer: SET_ALPHA_COMPOSITE(%d, %f, %d)", rule, extraAlpha, flags);
|
||||
context.color = color;
|
||||
context.composite = (VKCompositeMode) rule;
|
||||
context.extraAlpha = extraAlpha;
|
||||
}
|
||||
break;
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_XOR_COMPOSITE:
|
||||
@@ -442,12 +454,19 @@ JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
|
||||
jint xorPixel = NEXT_INT(b);
|
||||
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
|
||||
"VKRenderQueue_flushBuffer: SET_XOR_COMPOSITE");
|
||||
context.color = VKUtil_DecodeJavaColor(xorPixel);
|
||||
context.color.a = 0.0f; // Alpha is left unchanged in XOR mode.
|
||||
context.composite = LOGIC_COMPOSITE_XOR;
|
||||
context.extraAlpha = 1.0f;
|
||||
}
|
||||
break;
|
||||
case sun_java2d_pipe_BufferedOpCodes_RESET_COMPOSITE:
|
||||
{
|
||||
J2dRlsTraceLn(J2D_TRACE_VERBOSE,
|
||||
"VKRenderQueue_flushBuffer: RESET_COMPOSITE");
|
||||
context.color = color;
|
||||
context.composite = ALPHA_COMPOSITE_SRC;
|
||||
context.extraAlpha = 1.0f;
|
||||
}
|
||||
break;
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_TRANSFORM:
|
||||
@@ -582,10 +601,11 @@ JNIEXPORT void JNICALL Java_sun_java2d_vulkan_VKRenderQueue_flushBuffer
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_COLOR:
|
||||
{
|
||||
jint javaColor = NEXT_INT(b);
|
||||
context.color = VKUtil_DecodeJavaColor(javaColor);
|
||||
J2dRlsTraceLn5(J2D_TRACE_VERBOSE,
|
||||
"VKRenderQueue_flushBuffer: SET_COLOR 0x%08x, linear_rgba={%.3f, %.3f, %.3f, %.3f}",
|
||||
javaColor, context.color.r, context.color.g, context.color.b, context.color.a);
|
||||
color = VKUtil_DecodeJavaColor(javaColor);
|
||||
if (COMPOSITE_GROUP(context.composite) == ALPHA_COMPOSITE_GROUP) context.color = color;
|
||||
J2dRlsTraceLn1(J2D_TRACE_VERBOSE, "VKRenderQueue_flushBuffer: SET_COLOR(0x%08x)", javaColor);
|
||||
J2dTraceLn4(J2D_TRACE_VERBOSE, // Print color values with straight alpha for convenience.
|
||||
" srgb={%.3f, %.3f, %.3f, %.3f}", color.r/color.a, color.g/color.a, color.b/color.a, color.a);
|
||||
}
|
||||
break;
|
||||
case sun_java2d_pipe_BufferedOpCodes_SET_GRADIENT_PAINT:
|
||||
|
||||
@@ -142,11 +142,12 @@ struct VKRenderPass {
|
||||
uint32_t vertexCount;
|
||||
BufferWritingState vertexBufferWriting;
|
||||
|
||||
VKPipeline currentPipeline;
|
||||
VkBool32 pendingFlush;
|
||||
VkBool32 pendingCommands;
|
||||
VkBool32 pendingClear;
|
||||
uint64_t lastTimestamp; // When was this surface last used?
|
||||
VKCompositeMode currentComposite;
|
||||
VKPipeline currentPipeline;
|
||||
VkBool32 pendingFlush;
|
||||
VkBool32 pendingCommands;
|
||||
VkBool32 pendingClear;
|
||||
uint64_t lastTimestamp; // When was this surface last used?
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -464,6 +465,7 @@ inline void VKRenderer_FlushDraw(VKSDOps* surface) {
|
||||
*/
|
||||
static void VKRenderer_ResetDrawing(VKSDOps* surface) {
|
||||
assert(surface != NULL && surface->renderPass != NULL);
|
||||
surface->renderPass->currentComposite = NO_COMPOSITE;
|
||||
surface->renderPass->currentPipeline = NO_PIPELINE;
|
||||
surface->renderPass->firstVertex = 0;
|
||||
surface->renderPass->vertexCount = 0;
|
||||
@@ -502,9 +504,7 @@ void VKRenderer_DestroyRenderPass(VKSDOps* surface) {
|
||||
VKRenderer_Wait(device->renderer, surface->renderPass->lastTimestamp);
|
||||
VKRenderer_DiscardRenderPass(surface);
|
||||
// Release resources.
|
||||
if (surface->renderPass->framebuffer != VK_NULL_HANDLE) {
|
||||
device->vkDestroyFramebuffer(device->handle, surface->renderPass->framebuffer, NULL);
|
||||
}
|
||||
device->vkDestroyFramebuffer(device->handle, surface->renderPass->framebuffer, NULL);
|
||||
if (surface->renderPass->commandBuffer != VK_NULL_HANDLE) {
|
||||
POOL_RETURN(device->renderer, secondaryCommandBufferPool, surface->renderPass->commandBuffer);
|
||||
}
|
||||
@@ -535,6 +535,7 @@ static VkBool32 VKRenderer_InitRenderPass(VKSDOps* surface) {
|
||||
(*renderPass) = (VKRenderPass) {
|
||||
.pendingCommands = VK_FALSE,
|
||||
.pendingClear = VK_TRUE, // Clear the surface by default
|
||||
.currentComposite = NO_COMPOSITE,
|
||||
.currentPipeline = NO_PIPELINE,
|
||||
.lastTimestamp = 0
|
||||
};
|
||||
@@ -556,7 +557,7 @@ static VkBool32 VKRenderer_InitRenderPass(VKSDOps* surface) {
|
||||
.layers = 1
|
||||
};
|
||||
VK_IF_ERROR(device->vkCreateFramebuffer(device->handle, &framebufferCreateInfo, NULL,
|
||||
&renderPass->framebuffer)) VK_UNHANDLED_ERROR();
|
||||
&renderPass->framebuffer)) VK_UNHANDLED_ERROR();
|
||||
}
|
||||
|
||||
J2dRlsTraceLn1(J2D_TRACE_VERBOSE, "VKRenderer_InitRenderPass(%p)", surface);
|
||||
@@ -888,28 +889,39 @@ VkBool32 VKRenderer_Validate(VKRenderingContext* context, VKPipeline pipeline) {
|
||||
assert(context != NULL && context->surface != NULL);
|
||||
VKSDOps* surface = context->surface;
|
||||
|
||||
// Validate render pass state.
|
||||
// Init render pass.
|
||||
if (surface->renderPass == NULL || !surface->renderPass->pendingCommands) {
|
||||
// We must only [re]init render pass between frames.
|
||||
// Now this is correct, but in future we may have frames consisting of multiple render passes,
|
||||
// so we must be careful to NOT call VKRenderer_InitRenderPass between render passes within single frame.
|
||||
// Be careful to NOT call VKRenderer_InitRenderPass between render passes within single frame.
|
||||
if (!VKRenderer_InitRenderPass(surface)) return VK_FALSE;
|
||||
// In the future, we may need to restart the render pass within single frame,
|
||||
// for example when switching between blended and XOR drawing modes.
|
||||
// So, generally, this should depend on VKRenderingContext, but now we just start the render pass once.
|
||||
VKRenderer_BeginRenderPass(surface);
|
||||
}
|
||||
VKRenderPass* renderPass = surface->renderPass;
|
||||
|
||||
// Validate render pass state.
|
||||
if (renderPass->currentComposite != context->composite) {
|
||||
// ALPHA_COMPOSITE_DST keeps destination intact, so don't even bother to change the state.
|
||||
if (context->composite == ALPHA_COMPOSITE_DST) return VK_FALSE;
|
||||
VKCompositeMode oldComposite = renderPass->currentComposite;
|
||||
// Update state.
|
||||
VKRenderer_FlushDraw(surface);
|
||||
renderPass->currentComposite = context->composite;
|
||||
// Begin render pass.
|
||||
if (!renderPass->pendingCommands) VKRenderer_BeginRenderPass(surface);
|
||||
// Validate current composite.
|
||||
J2dTraceLn2(J2D_TRACE_VERBOSE, "VKRenderer_Validate: updating composite, old=%d, new=%d", oldComposite, context->composite);
|
||||
// Reset the pipeline.
|
||||
renderPass->currentPipeline = NO_PIPELINE;
|
||||
}
|
||||
|
||||
// Validate current pipeline.
|
||||
if (renderPass->currentPipeline != pipeline) {
|
||||
J2dTraceLn2(J2D_TRACE_VERBOSE, "VKRenderer_Validate: updating pipeline, old=%d, new=%d",
|
||||
surface->renderPass->currentPipeline, pipeline);
|
||||
renderPass->currentPipeline, pipeline);
|
||||
VKRenderer_FlushDraw(surface);
|
||||
VkCommandBuffer cb = renderPass->commandBuffer;
|
||||
renderPass->currentPipeline = pipeline;
|
||||
surface->device->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
VKPipelines_GetPipeline(renderPass->context, pipeline));
|
||||
VKPipelines_GetPipeline(renderPass->context, context->composite, pipeline));
|
||||
renderPass->vertexBufferWriting.bound = VK_FALSE;
|
||||
}
|
||||
return VK_TRUE;
|
||||
|
||||
@@ -31,10 +31,14 @@
|
||||
#include "VKPipelines.h"
|
||||
|
||||
struct VKRenderingContext {
|
||||
VKSDOps* surface;
|
||||
Color color;
|
||||
VKTransform transform;
|
||||
VkRect2D clipRect;
|
||||
VKSDOps* surface;
|
||||
VKTransform transform;
|
||||
VkRect2D clipRect;
|
||||
Color color;
|
||||
VKCompositeMode composite;
|
||||
// Extra alpha is not used when painting with plain color,
|
||||
// in this case color.a already includes it.
|
||||
float extraAlpha;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -84,7 +84,10 @@ VkBool32 VKSD_ConfigureImageSurface(VKSDOps* vksdo) {
|
||||
vksdo->requestedExtent.width != vksdo->image->extent.width ||
|
||||
vksdo->requestedExtent.height != vksdo->image->extent.height)) {
|
||||
// VK_FORMAT_B8G8R8A8_UNORM is the most widely-supported format for our use.
|
||||
// Currently, we only support *_SRGB and *_UNORM formats,
|
||||
// as other types may not be trivial to alias for logicOp rendering.
|
||||
VkFormat format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
|
||||
VKImage* image = VKImage_Create(device, vksdo->requestedExtent.width, vksdo->requestedExtent.height,
|
||||
0, format, VK_IMAGE_TILING_OPTIMAL,
|
||||
VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
|
||||
@@ -24,14 +24,13 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "VKImage.h"
|
||||
#include "VKUtil.h"
|
||||
#include "VKTexturePool.h"
|
||||
#include "AccelTexturePool.h"
|
||||
#include "jni.h"
|
||||
#include "jni_util.h"
|
||||
#include "Trace.h"
|
||||
|
||||
|
||||
@@ -103,15 +102,11 @@ static ATexturePrivPtr* VKTexturePool_createTexture(ADevicePrivPtr *device,
|
||||
}
|
||||
|
||||
static int VKTexturePool_bytesPerPixel(long format) {
|
||||
switch ((VkFormat)format) {
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
return 4;
|
||||
case VK_FORMAT_R8_UNORM:
|
||||
return 1;
|
||||
default:
|
||||
J2dRlsTraceLn1(J2D_TRACE_ERROR, "VKTexturePool_bytesPerPixel: format=%d not supported (4 bytes by default)", format);
|
||||
return 4;
|
||||
}
|
||||
FormatGroup group = VKUtil_GetFormatGroup((VkFormat)format);
|
||||
if (group.bytes == 0) {
|
||||
J2dRlsTraceLn1(J2D_TRACE_ERROR, "VKTexturePool_bytesPerPixel: format=%d not supported (4 bytes by default)", format);
|
||||
return 4;
|
||||
} else return (int) group.bytes;
|
||||
}
|
||||
|
||||
static void VKTexturePool_freeTexture(ADevicePrivPtr *device, ATexturePrivPtr *texture) {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
/**
|
||||
* Floating-point RGBA color with sRGB encoding.
|
||||
* Floating-point RGBA color with sRGB encoding and pre-multiplied alpha.
|
||||
*/
|
||||
typedef union {
|
||||
struct {
|
||||
@@ -56,7 +56,6 @@ typedef struct VKRenderPass VKRenderPass;
|
||||
typedef struct VKRenderingContext VKRenderingContext;
|
||||
typedef struct VKPipelineContext VKPipelineContext;
|
||||
typedef struct VKRenderPassContext VKRenderPassContext;
|
||||
typedef struct VKShaders VKShaders;
|
||||
typedef struct VKBuffer VKBuffer;
|
||||
typedef struct VKImage VKImage;
|
||||
typedef struct VKSDOps VKSDOps;
|
||||
|
||||
@@ -21,9 +21,11 @@
|
||||
// or visit www.oracle.com if you need additional information or have any
|
||||
// questions.
|
||||
|
||||
#include <assert.h>
|
||||
#include "VKUtil.h"
|
||||
|
||||
Color VKUtil_DecodeJavaColor(uint32_t srgb) {
|
||||
Color VKUtil_DecodeJavaColor(uint32_t color) {
|
||||
assert(sizeof(Color) == sizeof(float) * 4);
|
||||
// Just map [0, 255] integer colors onto [0, 1] floating-point range, it remains in sRGB color space.
|
||||
// sRGB gamma correction remains unsupported.
|
||||
static const float NormTable256[256] = {
|
||||
@@ -32,13 +34,17 @@ Color VKUtil_DecodeJavaColor(uint32_t srgb) {
|
||||
#define NORM64(N) NORM8(N),NORM8(N+8),NORM8(N+16),NORM8(N+24),NORM8(N+32),NORM8(N+40),NORM8(N+48),NORM8(N+56)
|
||||
NORM64(0),NORM64(64),NORM64(128),NORM64(192)
|
||||
};
|
||||
Color c = {
|
||||
.r = NormTable256[(srgb >> 16) & 0xFF],
|
||||
.g = NormTable256[(srgb >> 8) & 0xFF],
|
||||
.b = NormTable256[ srgb & 0xFF],
|
||||
.a = NormTable256[(srgb >> 24) & 0xFF]
|
||||
Color srgb = {
|
||||
.r = NormTable256[(color >> 16) & 0xFF],
|
||||
.g = NormTable256[(color >> 8) & 0xFF],
|
||||
.b = NormTable256[ color & 0xFF],
|
||||
.a = NormTable256[(color >> 24) & 0xFF]
|
||||
};
|
||||
return c;
|
||||
// Convert to pre-multiplied alpha.
|
||||
srgb.r *= srgb.a;
|
||||
srgb.g *= srgb.a;
|
||||
srgb.b *= srgb.a;
|
||||
return srgb;
|
||||
}
|
||||
|
||||
uint32_t VKUtil_Log2(uint64_t i) {
|
||||
@@ -59,6 +65,209 @@ uint32_t VKUtil_Log2(uint64_t i) {
|
||||
else return LogTable256[i & 0xFF];
|
||||
}
|
||||
|
||||
FormatGroup VKUtil_GetFormatGroup(VkFormat format) {
|
||||
#define GROUP(SIZE, ...) return ((FormatGroup) { .bytes = SIZE, .aliases[FORMAT_ALIAS_ORIGINAL] = format, __VA_ARGS__ })
|
||||
switch (format) {
|
||||
case VK_FORMAT_R4G4_UNORM_PACK8: GROUP(1, .aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R4G4_UNORM_PACK8);
|
||||
case VK_FORMAT_R4G4B4A4_UNORM_PACK16: GROUP(2, .aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R4G4B4A4_UNORM_PACK16);
|
||||
case VK_FORMAT_B4G4R4A4_UNORM_PACK16: GROUP(2, .aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_B4G4R4A4_UNORM_PACK16);
|
||||
case VK_FORMAT_R5G6B5_UNORM_PACK16: GROUP(2, .aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R5G6B5_UNORM_PACK16);
|
||||
case VK_FORMAT_B5G6R5_UNORM_PACK16: GROUP(2, .aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_B5G6R5_UNORM_PACK16);
|
||||
case VK_FORMAT_R5G5B5A1_UNORM_PACK16: GROUP(2, .aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R5G5B5A1_UNORM_PACK16);
|
||||
case VK_FORMAT_B5G5R5A1_UNORM_PACK16: GROUP(2, .aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_B5G5R5A1_UNORM_PACK16);
|
||||
case VK_FORMAT_A1R5G5B5_UNORM_PACK16: GROUP(2, .aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_A1R5G5B5_UNORM_PACK16);
|
||||
case VK_FORMAT_R8_UNORM:
|
||||
case VK_FORMAT_R8_SNORM:
|
||||
case VK_FORMAT_R8_USCALED:
|
||||
case VK_FORMAT_R8_SSCALED:
|
||||
case VK_FORMAT_R8_UINT:
|
||||
case VK_FORMAT_R8_SINT:
|
||||
case VK_FORMAT_R8_SRGB:
|
||||
GROUP(1, .aliases[FORMAT_ALIAS_SRGB] = VK_FORMAT_R8_SRGB,
|
||||
.aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R8_UNORM, .aliases[FORMAT_ALIAS_SNORM] = VK_FORMAT_R8_SNORM,
|
||||
.aliases[FORMAT_ALIAS_USCALED] = VK_FORMAT_R8_USCALED, .aliases[FORMAT_ALIAS_SSCALED] = VK_FORMAT_R8_SSCALED,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R8_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R8_SINT);
|
||||
case VK_FORMAT_R8G8_UNORM:
|
||||
case VK_FORMAT_R8G8_SNORM:
|
||||
case VK_FORMAT_R8G8_USCALED:
|
||||
case VK_FORMAT_R8G8_SSCALED:
|
||||
case VK_FORMAT_R8G8_UINT:
|
||||
case VK_FORMAT_R8G8_SINT:
|
||||
case VK_FORMAT_R8G8_SRGB:
|
||||
GROUP(2, .aliases[FORMAT_ALIAS_SRGB] = VK_FORMAT_R8G8_SRGB,
|
||||
.aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R8G8_UNORM, .aliases[FORMAT_ALIAS_SNORM] = VK_FORMAT_R8G8_SNORM,
|
||||
.aliases[FORMAT_ALIAS_USCALED] = VK_FORMAT_R8G8_USCALED, .aliases[FORMAT_ALIAS_SSCALED] = VK_FORMAT_R8G8_SSCALED,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R8G8_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R8G8_SINT);
|
||||
case VK_FORMAT_R8G8B8_UNORM:
|
||||
case VK_FORMAT_R8G8B8_SNORM:
|
||||
case VK_FORMAT_R8G8B8_USCALED:
|
||||
case VK_FORMAT_R8G8B8_SSCALED:
|
||||
case VK_FORMAT_R8G8B8_UINT:
|
||||
case VK_FORMAT_R8G8B8_SINT:
|
||||
case VK_FORMAT_R8G8B8_SRGB:
|
||||
GROUP(3, .aliases[FORMAT_ALIAS_SRGB] = VK_FORMAT_R8G8B8_SRGB,
|
||||
.aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R8G8B8_UNORM, .aliases[FORMAT_ALIAS_SNORM] = VK_FORMAT_R8G8B8_SNORM,
|
||||
.aliases[FORMAT_ALIAS_USCALED] = VK_FORMAT_R8G8B8_USCALED, .aliases[FORMAT_ALIAS_SSCALED] = VK_FORMAT_R8G8B8_SSCALED,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R8G8B8_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R8G8B8_SINT);
|
||||
case VK_FORMAT_B8G8R8_UNORM:
|
||||
case VK_FORMAT_B8G8R8_SNORM:
|
||||
case VK_FORMAT_B8G8R8_USCALED:
|
||||
case VK_FORMAT_B8G8R8_SSCALED:
|
||||
case VK_FORMAT_B8G8R8_UINT:
|
||||
case VK_FORMAT_B8G8R8_SINT:
|
||||
case VK_FORMAT_B8G8R8_SRGB:
|
||||
GROUP(3, .aliases[FORMAT_ALIAS_SRGB] = VK_FORMAT_B8G8R8_SRGB,
|
||||
.aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_B8G8R8_UNORM, .aliases[FORMAT_ALIAS_SNORM] = VK_FORMAT_B8G8R8_SNORM,
|
||||
.aliases[FORMAT_ALIAS_USCALED] = VK_FORMAT_B8G8R8_USCALED, .aliases[FORMAT_ALIAS_SSCALED] = VK_FORMAT_B8G8R8_SSCALED,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_B8G8R8_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_B8G8R8_SINT);
|
||||
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||
case VK_FORMAT_R8G8B8A8_SNORM:
|
||||
case VK_FORMAT_R8G8B8A8_USCALED:
|
||||
case VK_FORMAT_R8G8B8A8_SSCALED:
|
||||
case VK_FORMAT_R8G8B8A8_UINT:
|
||||
case VK_FORMAT_R8G8B8A8_SINT:
|
||||
case VK_FORMAT_R8G8B8A8_SRGB:
|
||||
GROUP(4, .aliases[FORMAT_ALIAS_SRGB] = VK_FORMAT_R8G8B8A8_SRGB,
|
||||
.aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R8G8B8A8_UNORM, .aliases[FORMAT_ALIAS_SNORM] = VK_FORMAT_R8G8B8A8_SNORM,
|
||||
.aliases[FORMAT_ALIAS_USCALED] = VK_FORMAT_R8G8B8A8_USCALED, .aliases[FORMAT_ALIAS_SSCALED] = VK_FORMAT_R8G8B8A8_SSCALED,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R8G8B8A8_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R8G8B8A8_SINT);
|
||||
case VK_FORMAT_B8G8R8A8_UNORM:
|
||||
case VK_FORMAT_B8G8R8A8_SNORM:
|
||||
case VK_FORMAT_B8G8R8A8_USCALED:
|
||||
case VK_FORMAT_B8G8R8A8_SSCALED:
|
||||
case VK_FORMAT_B8G8R8A8_UINT:
|
||||
case VK_FORMAT_B8G8R8A8_SINT:
|
||||
case VK_FORMAT_B8G8R8A8_SRGB:
|
||||
GROUP(4, .aliases[FORMAT_ALIAS_SRGB] = VK_FORMAT_B8G8R8A8_SRGB,
|
||||
.aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_B8G8R8A8_UNORM, .aliases[FORMAT_ALIAS_SNORM] = VK_FORMAT_B8G8R8A8_SNORM,
|
||||
.aliases[FORMAT_ALIAS_USCALED] = VK_FORMAT_B8G8R8A8_USCALED, .aliases[FORMAT_ALIAS_SSCALED] = VK_FORMAT_B8G8R8A8_SSCALED,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_B8G8R8A8_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_B8G8R8A8_SINT);
|
||||
case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_USCALED_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_SSCALED_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_UINT_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_SINT_PACK32:
|
||||
case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
|
||||
GROUP(4, .aliases[FORMAT_ALIAS_SRGB] = VK_FORMAT_A8B8G8R8_SRGB_PACK32,
|
||||
.aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_A8B8G8R8_UNORM_PACK32, .aliases[FORMAT_ALIAS_SNORM] = VK_FORMAT_A8B8G8R8_SNORM_PACK32,
|
||||
.aliases[FORMAT_ALIAS_USCALED] = VK_FORMAT_A8B8G8R8_USCALED_PACK32, .aliases[FORMAT_ALIAS_SSCALED] = VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_A8B8G8R8_UINT_PACK32, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_A8B8G8R8_SINT_PACK32);
|
||||
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
|
||||
case VK_FORMAT_A2R10G10B10_SNORM_PACK32:
|
||||
case VK_FORMAT_A2R10G10B10_USCALED_PACK32:
|
||||
case VK_FORMAT_A2R10G10B10_SSCALED_PACK32:
|
||||
case VK_FORMAT_A2R10G10B10_UINT_PACK32:
|
||||
case VK_FORMAT_A2R10G10B10_SINT_PACK32:
|
||||
GROUP(4,
|
||||
.aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_A2R10G10B10_UNORM_PACK32, .aliases[FORMAT_ALIAS_SNORM] = VK_FORMAT_A2R10G10B10_SNORM_PACK32,
|
||||
.aliases[FORMAT_ALIAS_USCALED] = VK_FORMAT_A2R10G10B10_USCALED_PACK32, .aliases[FORMAT_ALIAS_SSCALED] = VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_A2R10G10B10_UINT_PACK32, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_A2R10G10B10_SINT_PACK32);
|
||||
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
|
||||
case VK_FORMAT_A2B10G10R10_SNORM_PACK32:
|
||||
case VK_FORMAT_A2B10G10R10_USCALED_PACK32:
|
||||
case VK_FORMAT_A2B10G10R10_SSCALED_PACK32:
|
||||
case VK_FORMAT_A2B10G10R10_UINT_PACK32:
|
||||
case VK_FORMAT_A2B10G10R10_SINT_PACK32:
|
||||
GROUP(4,
|
||||
.aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_A2B10G10R10_UNORM_PACK32, .aliases[FORMAT_ALIAS_SNORM] = VK_FORMAT_A2B10G10R10_SNORM_PACK32,
|
||||
.aliases[FORMAT_ALIAS_USCALED] = VK_FORMAT_A2B10G10R10_USCALED_PACK32, .aliases[FORMAT_ALIAS_SSCALED] = VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_A2B10G10R10_UINT_PACK32, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_A2B10G10R10_SINT_PACK32);
|
||||
case VK_FORMAT_R16_UNORM:
|
||||
case VK_FORMAT_R16_SNORM:
|
||||
case VK_FORMAT_R16_USCALED:
|
||||
case VK_FORMAT_R16_SSCALED:
|
||||
case VK_FORMAT_R16_UINT:
|
||||
case VK_FORMAT_R16_SINT:
|
||||
case VK_FORMAT_R16_SFLOAT:
|
||||
GROUP(2, .aliases[FORMAT_ALIAS_SFLOAT] = VK_FORMAT_R16_SFLOAT,
|
||||
.aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R16_UNORM, .aliases[FORMAT_ALIAS_SNORM] = VK_FORMAT_R16_SNORM,
|
||||
.aliases[FORMAT_ALIAS_USCALED] = VK_FORMAT_R16_USCALED, .aliases[FORMAT_ALIAS_SSCALED] = VK_FORMAT_R16_SSCALED,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R16_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R16_SINT);
|
||||
case VK_FORMAT_R16G16_UNORM:
|
||||
case VK_FORMAT_R16G16_SNORM:
|
||||
case VK_FORMAT_R16G16_USCALED:
|
||||
case VK_FORMAT_R16G16_SSCALED:
|
||||
case VK_FORMAT_R16G16_UINT:
|
||||
case VK_FORMAT_R16G16_SINT:
|
||||
case VK_FORMAT_R16G16_SFLOAT:
|
||||
GROUP(4, .aliases[FORMAT_ALIAS_SFLOAT] = VK_FORMAT_R16G16_SFLOAT,
|
||||
.aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R16G16_UNORM, .aliases[FORMAT_ALIAS_SNORM] = VK_FORMAT_R16G16_SNORM,
|
||||
.aliases[FORMAT_ALIAS_USCALED] = VK_FORMAT_R16G16_USCALED, .aliases[FORMAT_ALIAS_SSCALED] = VK_FORMAT_R16G16_SSCALED,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R16G16_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R16G16_SINT);
|
||||
case VK_FORMAT_R16G16B16_UNORM:
|
||||
case VK_FORMAT_R16G16B16_SNORM:
|
||||
case VK_FORMAT_R16G16B16_USCALED:
|
||||
case VK_FORMAT_R16G16B16_SSCALED:
|
||||
case VK_FORMAT_R16G16B16_UINT:
|
||||
case VK_FORMAT_R16G16B16_SINT:
|
||||
case VK_FORMAT_R16G16B16_SFLOAT:
|
||||
GROUP(6, .aliases[FORMAT_ALIAS_SFLOAT] = VK_FORMAT_R16G16B16_SFLOAT,
|
||||
.aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R16G16B16_UNORM, .aliases[FORMAT_ALIAS_SNORM] = VK_FORMAT_R16G16B16_SNORM,
|
||||
.aliases[FORMAT_ALIAS_USCALED] = VK_FORMAT_R16G16B16_USCALED, .aliases[FORMAT_ALIAS_SSCALED] = VK_FORMAT_R16G16B16_SSCALED,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R16G16B16_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R16G16B16_SINT);
|
||||
case VK_FORMAT_R16G16B16A16_UNORM:
|
||||
case VK_FORMAT_R16G16B16A16_SNORM:
|
||||
case VK_FORMAT_R16G16B16A16_USCALED:
|
||||
case VK_FORMAT_R16G16B16A16_SSCALED:
|
||||
case VK_FORMAT_R16G16B16A16_UINT:
|
||||
case VK_FORMAT_R16G16B16A16_SINT:
|
||||
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
||||
GROUP(8, .aliases[FORMAT_ALIAS_SFLOAT] = VK_FORMAT_R16G16B16A16_SFLOAT,
|
||||
.aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R16G16B16A16_UNORM, .aliases[FORMAT_ALIAS_SNORM] = VK_FORMAT_R16G16B16A16_SNORM,
|
||||
.aliases[FORMAT_ALIAS_USCALED] = VK_FORMAT_R16G16B16A16_USCALED, .aliases[FORMAT_ALIAS_SSCALED] = VK_FORMAT_R16G16B16A16_SSCALED,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R16G16B16A16_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R16G16B16A16_SINT);
|
||||
case VK_FORMAT_R32_UINT:
|
||||
case VK_FORMAT_R32_SINT:
|
||||
case VK_FORMAT_R32_SFLOAT:
|
||||
GROUP(4, .aliases[FORMAT_ALIAS_SFLOAT] = VK_FORMAT_R32_SFLOAT,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R32_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R32_SINT);
|
||||
case VK_FORMAT_R32G32_UINT:
|
||||
case VK_FORMAT_R32G32_SINT:
|
||||
case VK_FORMAT_R32G32_SFLOAT:
|
||||
GROUP(8, .aliases[FORMAT_ALIAS_SFLOAT] = VK_FORMAT_R32G32_SFLOAT,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R32G32_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R32G32_SINT);
|
||||
case VK_FORMAT_R32G32B32_UINT:
|
||||
case VK_FORMAT_R32G32B32_SINT:
|
||||
case VK_FORMAT_R32G32B32_SFLOAT:
|
||||
GROUP(12, .aliases[FORMAT_ALIAS_SFLOAT] = VK_FORMAT_R32G32B32_SFLOAT,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R32G32B32_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R32G32B32_SINT);
|
||||
case VK_FORMAT_R32G32B32A32_UINT:
|
||||
case VK_FORMAT_R32G32B32A32_SINT:
|
||||
case VK_FORMAT_R32G32B32A32_SFLOAT:
|
||||
GROUP(16, .aliases[FORMAT_ALIAS_SFLOAT] = VK_FORMAT_R32G32B32A32_SFLOAT,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R32G32B32A32_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R32G32B32A32_SINT);
|
||||
case VK_FORMAT_R64_UINT:
|
||||
case VK_FORMAT_R64_SINT:
|
||||
case VK_FORMAT_R64_SFLOAT:
|
||||
GROUP(8, .aliases[FORMAT_ALIAS_SFLOAT] = VK_FORMAT_R64_SFLOAT,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R64_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R64_SINT);
|
||||
case VK_FORMAT_R64G64_UINT:
|
||||
case VK_FORMAT_R64G64_SINT:
|
||||
case VK_FORMAT_R64G64_SFLOAT:
|
||||
GROUP(16, .aliases[FORMAT_ALIAS_SFLOAT] = VK_FORMAT_R64G64_SFLOAT,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R64G64_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R64G64_SINT);
|
||||
case VK_FORMAT_R64G64B64_UINT:
|
||||
case VK_FORMAT_R64G64B64_SINT:
|
||||
case VK_FORMAT_R64G64B64_SFLOAT:
|
||||
GROUP(24, .aliases[FORMAT_ALIAS_SFLOAT] = VK_FORMAT_R64G64B64_SFLOAT,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R64G64B64_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R64G64B64_SINT);
|
||||
case VK_FORMAT_R64G64B64A64_UINT:
|
||||
case VK_FORMAT_R64G64B64A64_SINT:
|
||||
case VK_FORMAT_R64G64B64A64_SFLOAT:
|
||||
GROUP(32, .aliases[FORMAT_ALIAS_SFLOAT] = VK_FORMAT_R64G64B64A64_SFLOAT,
|
||||
.aliases[FORMAT_ALIAS_UINT] = VK_FORMAT_R64G64B64A64_UINT, .aliases[FORMAT_ALIAS_SINT] = VK_FORMAT_R64G64B64A64_SINT);
|
||||
case VK_FORMAT_R10X6_UNORM_PACK16: GROUP(2, .aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R10X6_UNORM_PACK16);
|
||||
case VK_FORMAT_R10X6G10X6_UNORM_2PACK16: GROUP(4, .aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R10X6G10X6_UNORM_2PACK16);
|
||||
case VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16: GROUP(8, .aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16);
|
||||
case VK_FORMAT_R12X4_UNORM_PACK16: GROUP(2, .aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R12X4_UNORM_PACK16);
|
||||
case VK_FORMAT_R12X4G12X4_UNORM_2PACK16: GROUP(4, .aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R12X4G12X4_UNORM_2PACK16);
|
||||
case VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16: GROUP(8, .aliases[FORMAT_ALIAS_UNORM] = VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16);
|
||||
default: GROUP(0);
|
||||
}
|
||||
#undef GROUP
|
||||
}
|
||||
|
||||
void VKUtil_LogResultError(const char* string, VkResult result) {
|
||||
const char* r;
|
||||
switch (result) {
|
||||
|
||||
@@ -69,13 +69,37 @@ inline VkBool32 VKUtil_CheckError(VkResult result, const char* errorMessage) {
|
||||
#define VK_UNHANDLED_ERROR() VK_FATAL_ERROR("Unhandled Vulkan error")
|
||||
#define VK_RUNTIME_ASSERT(...) if (!(__VA_ARGS__)) VK_FATAL_ERROR("Vulkan assertion failed: " #__VA_ARGS__)
|
||||
|
||||
typedef enum {
|
||||
FORMAT_ALIAS_ORIGINAL = 0,
|
||||
FORMAT_ALIAS_UNORM = 1,
|
||||
FORMAT_ALIAS_SNORM = 2,
|
||||
FORMAT_ALIAS_USCALED = 3,
|
||||
FORMAT_ALIAS_SSCALED = 4,
|
||||
FORMAT_ALIAS_UINT = 5,
|
||||
FORMAT_ALIAS_SINT = 6,
|
||||
FORMAT_ALIAS_SFLOAT = 7,
|
||||
FORMAT_ALIAS_SRGB = 8,
|
||||
FORMAT_ALIAS_COUNT = 9
|
||||
} FormatAlias;
|
||||
|
||||
/**
|
||||
* Group of format aliases. Use FormatAlias enum values to index into FormatGroup.aliases.
|
||||
*/
|
||||
typedef struct {
|
||||
VkFormat aliases[FORMAT_ALIAS_COUNT];
|
||||
uint bytes;
|
||||
} FormatGroup;
|
||||
|
||||
/**
|
||||
* Vulkan expects linear colors.
|
||||
* However Java2D expects legacy behavior, as if colors were blended in sRGB color space.
|
||||
* Therefore this function just remaps color components from [0, 255] to [0, 1] range,
|
||||
* they still represent sRGB color.
|
||||
* Therefore this function converts straight-alpha Java color in range [0, 255]
|
||||
* to pre-multiplied alpha normalized [0, 1] color, still representing sRGB color.
|
||||
* This is also accounted for in VKSD_ConfigureWindowSurface, so that Vulkan doesn't do any
|
||||
* color space conversions on its own, as the colors we are drawing are already in sRGB.
|
||||
*
|
||||
* Note: we receive colors from Java with straight (non-premultiplied) alpha, which is done to prevent precision loss.
|
||||
* This is controlled by PixelConverter parameter of SurfaceType, see VKSurfaceData.java.
|
||||
*/
|
||||
Color VKUtil_DecodeJavaColor(uint32_t color);
|
||||
|
||||
@@ -84,6 +108,11 @@ Color VKUtil_DecodeJavaColor(uint32_t color);
|
||||
*/
|
||||
uint32_t VKUtil_Log2(uint64_t i);
|
||||
|
||||
/**
|
||||
* Get group of formats with the same component layout.
|
||||
*/
|
||||
FormatGroup VKUtil_GetFormatGroup(VkFormat format);
|
||||
|
||||
/*
|
||||
* The following macros allow the caller to return (or continue) if the
|
||||
* provided value is NULL. (The strange else clause is included below to
|
||||
|
||||
@@ -82,25 +82,6 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.awt.wl.focus.WLComponentPeer");
|
||||
private static final PlatformLogger popupLog = PlatformLogger.getLogger("sun.awt.wl.popup.WLComponentPeer");
|
||||
|
||||
// mapping of AWT cursor types to X cursor names
|
||||
// multiple variants can be specified, that will be tried in order
|
||||
private static final String[][] CURSOR_NAMES = {
|
||||
{"default", "arrow", "left_ptr", "left_arrow"}, // DEFAULT_CURSOR
|
||||
{"crosshair"}, // CROSSHAIR_CURSOR
|
||||
{"text", "xterm"}, // TEXT_CURSOR
|
||||
{"wait", "watch"}, // WAIT_CURSOR
|
||||
{"sw-resize", "bottom_left_corner"}, // SW_RESIZE_CURSOR
|
||||
{"se-resize", "bottom_right_corner"}, // SE_RESIZE_CURSOR
|
||||
{"nw-resize", "top_left_corner"}, // NW_RESIZE_CURSOR
|
||||
{"ne-resize", "top_right_corner"}, // NE_RESIZE_CURSOR
|
||||
{"n-resize", "top_side"}, // N_RESIZE_CURSOR
|
||||
{"s-resize", "bottom_side"}, // S_RESIZE_CURSOR
|
||||
{"w-resize", "left_side"}, // W_RESIZE_CURSOR
|
||||
{"e-resize", "right_side"}, // E_RESIZE_CURSOR
|
||||
{"hand"}, // HAND_CURSOR
|
||||
{"move"}, // MOVE_CURSOR
|
||||
};
|
||||
|
||||
private static final int MINIMUM_WIDTH = 1;
|
||||
private static final int MINIMUM_HEIGHT = 1;
|
||||
|
||||
@@ -123,6 +104,7 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
int displayScale; // protected by dataLock
|
||||
double effectiveScale; // protected by dataLock
|
||||
private final WLSize wlSize = new WLSize();
|
||||
boolean repositionPopup = false; // protected by dataLock
|
||||
|
||||
static {
|
||||
initIDs();
|
||||
@@ -278,6 +260,12 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
return null;
|
||||
}
|
||||
|
||||
private static Component realParentFor(Component c) {
|
||||
return (c instanceof Window window && isWlPopup(window))
|
||||
? AWTAccessor.getWindowAccessor().getPopupParent(window)
|
||||
: c.getParent();
|
||||
}
|
||||
|
||||
static Point getRelativeLocation(Component c, Window toplevel) {
|
||||
Objects.requireNonNull(c);
|
||||
|
||||
@@ -286,26 +274,24 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
|
||||
int x = 0, y = 0;
|
||||
while (c != null) {
|
||||
if (c instanceof Window window) {
|
||||
// The location of non-popup windows has no relevance since
|
||||
// there are no absolute coordinates in Wayland.
|
||||
// The popup windows position, on the other hand, is set relative to their
|
||||
// parent toplevel.
|
||||
if (isWlPopup(window)) {
|
||||
x += c.getX();
|
||||
y += c.getY();
|
||||
}
|
||||
break;
|
||||
}
|
||||
while (c != null && c != toplevel) {
|
||||
x += c.getX();
|
||||
y += c.getY();
|
||||
c = c.getParent();
|
||||
c = realParentFor(c);
|
||||
}
|
||||
|
||||
return new Point(x, y);
|
||||
}
|
||||
|
||||
Point nativeLocationForPopup(Window popup, Component popupParent, Window toplevel) {
|
||||
// We need to provide popup's "parent" location relative to the surface this parent is painted upon:
|
||||
Point parentLocation = javaUnitsToSurfaceUnits(getRelativeLocation(popupParent, toplevel));
|
||||
|
||||
// Offset is relative to the top-left corner of the "parent".
|
||||
Point offsetFromParent = javaUnitsToSurfaceUnits(popup.getLocation());
|
||||
return new Point(parentLocation.x + offsetFromParent.x, parentLocation.y + offsetFromParent.y);
|
||||
}
|
||||
|
||||
protected void wlSetVisible(boolean v) {
|
||||
synchronized (getStateLock()) {
|
||||
if (this.visible == v) return;
|
||||
@@ -327,30 +313,12 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
performLocked(() -> {
|
||||
if (isWlPopup) {
|
||||
Window popup = (Window) target;
|
||||
final Component popupParent = AWTAccessor.getWindowAccessor().getPopupParent(popup);
|
||||
final Window toplevel = getToplevelFor(popupParent);
|
||||
// We need to provide popup "parent" location relative to
|
||||
// the surface it is painted upon:
|
||||
final Point toplevelLocation = getRelativeLocation(popupParent, toplevel);
|
||||
final int parentX = javaUnitsToSurfaceUnits(toplevelLocation.x);
|
||||
final int parentY = javaUnitsToSurfaceUnits(toplevelLocation.y);
|
||||
|
||||
// Offset must be relative to the top-left corner of the "parent".
|
||||
final Point offsetFromParent = popup.getLocation();
|
||||
final int offsetX = javaUnitsToSurfaceUnits(offsetFromParent.x);
|
||||
final int offsetY = javaUnitsToSurfaceUnits(offsetFromParent.y);
|
||||
|
||||
if (popupLog.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
popupLog.fine("New popup: " + popup);
|
||||
popupLog.fine("\tparent:" + popupParent);
|
||||
popupLog.fine("\ttoplevel: " + toplevel);
|
||||
popupLog.fine("\toffset of anchor from toplevel: " + toplevelLocation);
|
||||
popupLog.fine("\toffset from anchor: " + offsetFromParent);
|
||||
}
|
||||
|
||||
Component popupParent = AWTAccessor.getWindowAccessor().getPopupParent(popup);
|
||||
Window toplevel = getToplevelFor(popupParent);
|
||||
Point nativeLocation = nativeLocationForPopup(popup, popupParent, toplevel);
|
||||
nativeCreateWLPopup(nativePtr, getNativePtrFor(toplevel),
|
||||
thisWidth, thisHeight,
|
||||
parentX + offsetX, parentY + offsetY);
|
||||
nativeLocation.x, nativeLocation.y);
|
||||
} else {
|
||||
int xNative = javaUnitsToSurfaceUnits(target.getX());
|
||||
int yNative = javaUnitsToSurfaceUnits(target.getY());
|
||||
@@ -421,6 +389,18 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
if (surfaceMaxSize != null) {
|
||||
nativeSetMaximumSize(nativePtr, surfaceMaxSize.width, surfaceMaxSize.height);
|
||||
}
|
||||
|
||||
if (popupNeedsReposition()) {
|
||||
popupRepositioned();
|
||||
|
||||
// Since popup's reposition request includes both its size and location, the request
|
||||
// needs to be in sync with all the other sizes this method is responsible for updating.
|
||||
Window popup = (Window) target;
|
||||
final Component popupParent = AWTAccessor.getWindowAccessor().getPopupParent(popup);
|
||||
final Window toplevel = getToplevelFor(popupParent);
|
||||
Point nativeLocation = nativeLocationForPopup(popup, popupParent, toplevel);
|
||||
nativeRepositionWLPopup(nativePtr, surfaceWidth, surfaceHeight, nativeLocation.x, nativeLocation.y);
|
||||
}
|
||||
}
|
||||
|
||||
void configureWLSurface() {
|
||||
@@ -505,11 +485,28 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
}
|
||||
|
||||
private void setLocationTo(int newX, int newY) {
|
||||
private void resetTargetLocationTo(int newX, int newY) {
|
||||
var acc = AWTAccessor.getComponentAccessor();
|
||||
acc.setLocation(target, newX, newY);
|
||||
}
|
||||
|
||||
private boolean popupNeedsReposition() {
|
||||
synchronized (dataLock) {
|
||||
return repositionPopup;
|
||||
}
|
||||
}
|
||||
private void markPopupNeedsReposition() {
|
||||
synchronized (dataLock) {
|
||||
repositionPopup = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void popupRepositioned() {
|
||||
synchronized (dataLock) {
|
||||
repositionPopup = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void setBounds(int newX, int newY, int newWidth, int newHeight, int op) {
|
||||
Dimension newSize = constrainSize(newWidth, newHeight);
|
||||
boolean positionChanged = (op == SET_BOUNDS || op == SET_LOCATION);
|
||||
@@ -527,9 +524,7 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
if ((positionChanged || sizeChanged) && isPopup && visible) {
|
||||
// Need to update the location and size even if does not (yet) have a surface
|
||||
// as the initial configure event needs to have the latest data on the location/size.
|
||||
repositionWlPopup(newX, newY, newSize.width, newSize.height);
|
||||
// the location will be updated in notifyConfigured() following
|
||||
// the xdg_popup::repositioned event
|
||||
markPopupNeedsReposition();
|
||||
}
|
||||
|
||||
if (positionChanged) {
|
||||
@@ -546,9 +541,9 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
layout();
|
||||
|
||||
WLToolkit.postEvent(new ComponentEvent(getTarget(), ComponentEvent.COMPONENT_RESIZED));
|
||||
}
|
||||
|
||||
postPaintEvent();
|
||||
postPaintEvent(); // no need to repaint after being moved, only when resized
|
||||
}
|
||||
}
|
||||
|
||||
boolean isSizeBeingConfigured() {
|
||||
@@ -564,43 +559,17 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
|
||||
private void setSizeTo(int newWidth, int newHeight) {
|
||||
Dimension newSize = constrainSize(newWidth, newHeight);
|
||||
if (isSizeBeingConfigured() && wlSize.hasPixelSizeSet()) {
|
||||
// Must be careful not to override the size of the Wayland surface because
|
||||
// some implementations (Weston) react badly when the size of the surface
|
||||
// mismatches the configured size. We can't always precisely derive the surface
|
||||
// size from the Java (client) size because of scaling rounding errors.
|
||||
wlSize.setJavaSize(newSize.width, newSize.height);
|
||||
wlSize.setJavaSize(newWidth, newHeight);
|
||||
} else {
|
||||
wlSize.deriveFromJavaSize(newSize.width, newSize.height);
|
||||
wlSize.deriveFromJavaSize(newWidth, newHeight);
|
||||
}
|
||||
}
|
||||
|
||||
private void repositionWlPopup(int newX, int newY, int newWidth, int newHeight) {
|
||||
performLocked(() -> {
|
||||
Window popup = (Window) target;
|
||||
final Component popupParent = AWTAccessor.getWindowAccessor().getPopupParent(popup);
|
||||
final Window toplevel = getToplevelFor(popupParent);
|
||||
// We need to provide popup "parent" location relative to
|
||||
// the surface it is painted upon:
|
||||
final Point toplevelLocation = getRelativeLocation(popupParent, toplevel);
|
||||
final int parentX = javaUnitsToSurfaceUnits(toplevelLocation.x);
|
||||
final int parentY = javaUnitsToSurfaceUnits(toplevelLocation.y);
|
||||
int newXNative = javaUnitsToSurfaceUnits(newX);
|
||||
int newYNative = javaUnitsToSurfaceUnits(newY);
|
||||
int newWidthNative = javaUnitsToSurfaceUnits(newWidth);
|
||||
int newHeightNative = javaUnitsToSurfaceUnits(newHeight);
|
||||
if (popupLog.isLoggable(Level.FINE)) {
|
||||
popupLog.fine("Repositioning popup: " + popup);
|
||||
popupLog.fine("\tparent:" + popupParent);
|
||||
popupLog.fine("\ttoplevel: " + toplevel);
|
||||
popupLog.fine("\toffset of anchor from toplevel: " + toplevelLocation);
|
||||
popupLog.fine("\toffset from anchor: " + newX + ", " + newY);
|
||||
}
|
||||
nativeRepositionWLPopup(nativePtr, newWidthNative, newHeightNative, parentX + newXNative, parentY + newYNative);
|
||||
} );
|
||||
}
|
||||
|
||||
public int getBufferWidth() {
|
||||
return wlSize.getPixelWidth();
|
||||
}
|
||||
@@ -645,12 +614,23 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
try {
|
||||
return WLRobotPeer.getLocationOfWLSurface(wlSurfacePtr);
|
||||
} catch (UnsupportedOperationException ignore) {
|
||||
return new Point();
|
||||
return getFakeLocationOnScreen();
|
||||
}
|
||||
} else {
|
||||
return new Point();
|
||||
return getFakeLocationOnScreen();
|
||||
}
|
||||
}, Point::new);
|
||||
}, this::getFakeLocationOnScreen);
|
||||
}
|
||||
|
||||
private Point getFakeLocationOnScreen() {
|
||||
// If we can't learn the real location from WLRobotPeer, we can at least
|
||||
// return a reasonable fake. This fake location places all windows in the top-left
|
||||
// corner of their respective screen.
|
||||
GraphicsConfiguration graphicsConfig = target.getGraphicsConfiguration();
|
||||
if (graphicsConfig != null) {
|
||||
return graphicsConfig.getBounds().getLocation();
|
||||
}
|
||||
return new Point();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -858,17 +838,10 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
|
||||
public void updateCursorImmediately() {
|
||||
updateCursorImmediately(WLToolkit.getInputState());
|
||||
WLToolkit.updateCursorImmediatelyFor(this);
|
||||
}
|
||||
|
||||
private void updateCursorImmediately(WLInputState inputState) {
|
||||
WLComponentPeer peer = inputState.peerForPointerEvents();
|
||||
if (peer == null) return;
|
||||
Cursor cursor = peer.getCursor(inputState.getPointerX(), inputState.getPointerY());
|
||||
setCursor(cursor, getGraphicsDevice() != null ? getGraphicsDevice().getDisplayScale() : 1);
|
||||
}
|
||||
|
||||
Cursor getCursor(int x, int y) {
|
||||
Cursor cursorAt(int x, int y) {
|
||||
Component target = this.target;
|
||||
if (target instanceof Container) {
|
||||
Component c = AWTAccessor.getContainerAccessor().findComponentAt((Container) target, x, y, false);
|
||||
@@ -879,56 +852,6 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
return AWTAccessor.getComponentAccessor().getCursor(target);
|
||||
}
|
||||
|
||||
private static void setCursor(Cursor c, int scale) {
|
||||
long serial = WLToolkit.getInputState().pointerEnterSerial();
|
||||
if (serial == 0) {
|
||||
if (log.isLoggable(Level.WARNING)) {
|
||||
log.warning("setCursor aborted due to missing event serial");
|
||||
}
|
||||
return; // Wayland will ignore the request anyway
|
||||
}
|
||||
|
||||
Cursor cursor;
|
||||
if (c.getType() == Cursor.CUSTOM_CURSOR && !(c instanceof WLCustomCursor)) {
|
||||
cursor = Cursor.getDefaultCursor();
|
||||
} else {
|
||||
cursor = c;
|
||||
}
|
||||
performLockedGlobal(() -> {
|
||||
long pData = AWTAccessor.getCursorAccessor().getPData(cursor, scale);
|
||||
if (pData == 0) {
|
||||
// instead of destroying and creating new cursor after changing scale could be used caching
|
||||
long oldPData = AWTAccessor.getCursorAccessor().getPData(cursor);
|
||||
if (oldPData != 0 && oldPData != -1) {
|
||||
nativeDestroyPredefinedCursor(oldPData);
|
||||
}
|
||||
|
||||
pData = createNativeCursor(cursor.getType(), scale);
|
||||
if (pData == 0) {
|
||||
pData = createNativeCursor(Cursor.DEFAULT_CURSOR, scale);
|
||||
}
|
||||
if (pData == 0) {
|
||||
pData = -1; // mark as unavailable
|
||||
}
|
||||
AWTAccessor.getCursorAccessor().setPData(cursor, scale, pData);
|
||||
}
|
||||
nativeSetCursor(pData, scale, serial);
|
||||
});
|
||||
}
|
||||
|
||||
private static long createNativeCursor(int type, int scale) {
|
||||
if (type < Cursor.DEFAULT_CURSOR || type > Cursor.MOVE_CURSOR) {
|
||||
type = Cursor.DEFAULT_CURSOR;
|
||||
}
|
||||
for (String name : CURSOR_NAMES[type]) {
|
||||
long pData = nativeGetPredefinedCursor(name, scale);
|
||||
if (pData != 0) {
|
||||
return pData;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image createImage(int width, int height) {
|
||||
WLGraphicsConfig graphicsConfig = (WLGraphicsConfig) target.getGraphicsConfiguration();
|
||||
@@ -1094,9 +1017,6 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
private native void nativeSetWindowGeometry(long ptr, int x, int y, int width, int height);
|
||||
private native void nativeSetMinimumSize(long ptr, int width, int height);
|
||||
private native void nativeSetMaximumSize(long ptr, int width, int height);
|
||||
private static native void nativeSetCursor(long pData, int scale, long pointerEnterSerial);
|
||||
private static native long nativeGetPredefinedCursor(String name, int scale);
|
||||
private static native long nativeDestroyPredefinedCursor(long pData);
|
||||
private native void nativeShowWindowMenu(long serial, long ptr, int x, int y);
|
||||
private native void nativeActivate(long serial, long ptr, long activatingSurfacePtr);
|
||||
|
||||
@@ -1139,7 +1059,7 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
final long timestamp = newInputState.getTimestamp();
|
||||
|
||||
if (e.hasEnterEvent()) {
|
||||
performUnlocked(() -> updateCursorImmediately(newInputState));
|
||||
updateCursorImmediately();
|
||||
final MouseEvent mouseEvent = new MouseEvent(getTarget(), MouseEvent.MOUSE_ENTERED,
|
||||
timestamp,
|
||||
newInputState.getModifiers(),
|
||||
@@ -1548,23 +1468,34 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
}
|
||||
}
|
||||
|
||||
Point javaUnitsToSurfaceUnits(Point p) {
|
||||
return new Point(javaUnitsToSurfaceUnits(p.x), javaUnitsToSurfaceUnits(p.y));
|
||||
}
|
||||
|
||||
Dimension javaUnitsToSurfaceUnits(Dimension d) {
|
||||
return new Dimension(javaUnitsToSurfaceUnits(d.width), javaUnitsToSurfaceUnits(d.height));
|
||||
}
|
||||
|
||||
void notifyConfigured(int newSurfaceX, int newSurfaceY, int newSurfaceWidth, int newSurfaceHeight, boolean active, boolean maximized) {
|
||||
// NB: The width and height, as well as X and Y arguments specify the size and the location
|
||||
// NB: The width and height, as well as X and Y arguments, specify the size and the location
|
||||
// of the window in surface-local coordinates.
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
log.fine(String.format("%s configured to %dx%d surface units", this, newSurfaceWidth, newSurfaceHeight));
|
||||
}
|
||||
|
||||
boolean isWlPopup = targetIsWlPopup();
|
||||
|
||||
if (isWlPopup) { // Only popups provide (relative) location
|
||||
int newX = surfaceUnitsToJavaUnits(newSurfaceX);
|
||||
int newY = surfaceUnitsToJavaUnits(newSurfaceY);
|
||||
setLocationTo(newX, newY);
|
||||
|
||||
// The popup itself stores its location relative to its parent, but what we've got is
|
||||
// the location relative to the toplevel. Let's convert:
|
||||
Window popup = (Window) target;
|
||||
Component popupParent = AWTAccessor.getWindowAccessor().getPopupParent(popup);
|
||||
Window toplevel = getToplevelFor(popupParent);
|
||||
Point parentLocation = getRelativeLocation(popupParent, toplevel);
|
||||
Point locationRelativeToParent = new Point(newX - parentLocation.x, newY - parentLocation.y);
|
||||
resetTargetLocationTo(locationRelativeToParent.x, locationRelativeToParent.y);
|
||||
}
|
||||
|
||||
// From xdg-shell.xml: "If the width or height arguments are zero,
|
||||
@@ -1721,15 +1652,6 @@ public class WLComponentPeer implements ComponentPeer {
|
||||
// done using these methods. Then one can be sure that native data is not changed concurrently in any way while the
|
||||
// specified task is executed.
|
||||
|
||||
static void performLockedGlobal(Runnable task) {
|
||||
WLToolkit.awtLock();
|
||||
try {
|
||||
task.run();
|
||||
} finally {
|
||||
WLToolkit.awtUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
void performLocked(Runnable task) {
|
||||
WLToolkit.awtLock();
|
||||
try {
|
||||
|
||||
@@ -144,12 +144,12 @@ public abstract class WLDecoratedPeer extends WLWindowPeer {
|
||||
}
|
||||
|
||||
@Override
|
||||
Cursor getCursor(int x, int y) {
|
||||
Cursor cursorAt(int x, int y) {
|
||||
Cursor cursor = decoration.getCursor(x, y);
|
||||
if (cursor != null) {
|
||||
return cursor;
|
||||
} else {
|
||||
return super.getCursor(x, y);
|
||||
return super.cursorAt(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,17 +39,27 @@ public abstract class WLGraphicsConfig extends GraphicsConfiguration {
|
||||
private final WLGraphicsDevice device;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int xLogical; // logical (scaled) horizontal location; optional, could be zero
|
||||
private final int yLogical; // logical (scaled) vertical location; optional, could be zero
|
||||
private final int width;
|
||||
private final int height;
|
||||
private final int widthLogical; // logical (scaled) width; optional, could be zero
|
||||
private final int heightLogical;// logical (scaled) height; optional, could be zero
|
||||
private final int displayScale; // as reported by Wayland
|
||||
private final double effectiveScale; // as enforced by Java
|
||||
|
||||
protected WLGraphicsConfig(WLGraphicsDevice device, int x, int y, int width, int height, int displayScale) {
|
||||
protected WLGraphicsConfig(WLGraphicsDevice device, int x, int y, int xLogical, int yLogical,
|
||||
int width, int height, int widthLogical, int heightLogical,
|
||||
int displayScale) {
|
||||
this.device = device;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.xLogical = xLogical;
|
||||
this.yLogical = yLogical;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.widthLogical = widthLogical;
|
||||
this.heightLogical = heightLogical;
|
||||
this.displayScale = displayScale;
|
||||
this.effectiveScale = WLGraphicsEnvironment.effectiveScaleFrom(displayScale);
|
||||
}
|
||||
@@ -86,10 +96,13 @@ public abstract class WLGraphicsConfig extends GraphicsConfiguration {
|
||||
|
||||
@Override
|
||||
public Rectangle getBounds() {
|
||||
// NB: despite the claims of GraphicsConfiguration.getBounds()'s javadoc,
|
||||
// the value returned is expected to be in user-space coordinates,
|
||||
// same as windows sizes, offsets, components' coordinates, etc.
|
||||
return new Rectangle(x, y, (int) (width / effectiveScale), (int) (height / effectiveScale));
|
||||
return (widthLogical > 0 && heightLogical > 0)
|
||||
? new Rectangle(xLogical, yLogical, widthLogical, heightLogical)
|
||||
: new Rectangle(x, y, width, height);
|
||||
}
|
||||
|
||||
public Rectangle getRealBounds() {
|
||||
return new Rectangle(x, y, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -65,6 +65,9 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
*/
|
||||
private volatile int y; // only changes when the device gets invalidated
|
||||
|
||||
private volatile int xLogical; // logical (scaled) horizontal location; optional, could be zero
|
||||
private volatile int yLogical; // logical (scaled) vertical location; optional, could be zero
|
||||
|
||||
private final int widthMm;
|
||||
private final int heightMm;
|
||||
|
||||
@@ -78,10 +81,12 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
// and get their graphics configuration from it
|
||||
private final Set<WLComponentPeer> toplevels = new HashSet<>(); // guarded by 'this'
|
||||
|
||||
private WLGraphicsDevice(int id, int x, int y, int widthMm, int heightMm) {
|
||||
private WLGraphicsDevice(int id, int x, int y, int xLogical, int yLogical, int widthMm, int heightMm) {
|
||||
this.wlID = id;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.xLogical = xLogical;
|
||||
this.yLogical = yLogical;
|
||||
this.widthMm = widthMm;
|
||||
this.heightMm = heightMm;
|
||||
}
|
||||
@@ -90,7 +95,7 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
return wlID;
|
||||
}
|
||||
|
||||
void updateConfiguration(String name, int width, int height, int scale) {
|
||||
void updateConfiguration(String name, int width, int height, int widthLogical, int heightLogical, int scale) {
|
||||
this.name = name;
|
||||
|
||||
WLGraphicsConfig config = defaultConfig;
|
||||
@@ -101,16 +106,16 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
// It is necessary to create a new object whenever config changes as its
|
||||
// identity is used to detect changes in scale, among other things.
|
||||
if (VKInstance.isVulkanEnabled()) {
|
||||
newDefaultConfig = WLVKGraphicsConfig.getConfig(this, x, y, width, height, scale);
|
||||
newDefaultConfig = WLVKGraphicsConfig.getConfig(this, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale);
|
||||
newConfigs = new GraphicsConfiguration[1];
|
||||
newConfigs[0] = newDefaultConfig;
|
||||
} else {
|
||||
// TODO: Actually, Wayland may support a lot more shared memory buffer configurations, need to
|
||||
// subscribe to the wl_shm:format event and get the list from there.
|
||||
newDefaultConfig = WLSMGraphicsConfig.getConfig(this, x, y, width, height, scale, false);
|
||||
newDefaultConfig = WLSMGraphicsConfig.getConfig(this, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale, false);
|
||||
newConfigs = new GraphicsConfiguration[2];
|
||||
newConfigs[0] = newDefaultConfig;
|
||||
newConfigs[1] = WLSMGraphicsConfig.getConfig(this, x, y, width, height, scale, true);
|
||||
newConfigs[1] = WLSMGraphicsConfig.getConfig(this, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale, true);
|
||||
}
|
||||
|
||||
configs = newConfigs;
|
||||
@@ -145,19 +150,22 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
this.wlID = similarDevice.wlID;
|
||||
this.x = similarDevice.x;
|
||||
this.y = similarDevice.y;
|
||||
this.xLogical = similarDevice.xLogical;
|
||||
this.yLogical = similarDevice.yLogical;
|
||||
|
||||
int newScale = similarDevice.getDisplayScale();
|
||||
Rectangle newBounds = similarDevice.defaultConfig.getBounds();
|
||||
updateConfiguration(similarDevice.name, newBounds.width, newBounds.height, newScale);
|
||||
Rectangle newRealBounds = similarDevice.defaultConfig.getRealBounds();
|
||||
updateConfiguration(similarDevice.name, newRealBounds.width, newRealBounds.height, newBounds.width, newBounds.height, newScale);
|
||||
}
|
||||
|
||||
public static WLGraphicsDevice createWithConfiguration(int id, String name,
|
||||
int x, int y,
|
||||
int width, int height,
|
||||
int x, int y, int xLogical, int yLogical,
|
||||
int width, int height, int widthLogical, int heightLogical,
|
||||
int widthMm, int heightMm,
|
||||
int scale) {
|
||||
WLGraphicsDevice device = new WLGraphicsDevice(id, x, y, widthMm, heightMm);
|
||||
device.updateConfiguration(name, width, height, scale);
|
||||
WLGraphicsDevice device = new WLGraphicsDevice(id, x, y, xLogical, yLogical, widthMm, heightMm);
|
||||
device.updateConfiguration(name, width, height, widthLogical, heightLogical, scale);
|
||||
return device;
|
||||
}
|
||||
|
||||
@@ -165,8 +173,8 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
* Compares the identity of this device with the given attributes
|
||||
* and returns true iff the attributes identify the same device.
|
||||
*/
|
||||
boolean isSameDeviceAs(int wlID, int x, int y) {
|
||||
return this.wlID == wlID && this.x == x && this.y == y;
|
||||
boolean isSameDeviceAs(int wlID, int x, int y, int xLogical, int yLogical) {
|
||||
return this.wlID == wlID && this.x == x && this.y == y && this.xLogical == xLogical && this.yLogical == yLogical;
|
||||
}
|
||||
|
||||
boolean hasSameNameAs(WLGraphicsDevice otherDevice) {
|
||||
@@ -286,8 +294,8 @@ public class WLGraphicsDevice extends GraphicsDevice {
|
||||
@Override
|
||||
public String toString() {
|
||||
var config = defaultConfig;
|
||||
return String.format("WLGraphicsDevice: '%s' id=%d at (%d, %d) with %s",
|
||||
name, wlID, x, y,
|
||||
return String.format("WLGraphicsDevice: '%s' id=%d at (%d, %d) ((%d, %d) logical) with %s",
|
||||
name, wlID, x, y, xLogical, yLogical,
|
||||
config != null ? config : "<no configs>");
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,15 @@ import sun.util.logging.PlatformLogger;
|
||||
import sun.util.logging.PlatformLogger.Level;
|
||||
|
||||
public class WLGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
public static final int WL_OUTPUT_TRANSFORM_NORMAL = 0;
|
||||
public static final int WL_OUTPUT_TRANSFORM_90 = 1;
|
||||
public static final int WL_OUTPUT_TRANSFORM_180 = 2;
|
||||
public static final int WL_OUTPUT_TRANSFORM_270 = 3;
|
||||
public static final int WL_OUTPUT_TRANSFORM_FLIPPED = 4;
|
||||
public static final int WL_OUTPUT_TRANSFORM_FLIPPED_90 = 5;
|
||||
public static final int WL_OUTPUT_TRANSFORM_FLIPPED_180 = 6;
|
||||
public static final int WL_OUTPUT_TRANSFORM_FLIPPED_270 = 7;
|
||||
|
||||
private static final PlatformLogger log = PlatformLogger.getLogger("sun.awt.wl.WLGraphicsEnvironment");
|
||||
|
||||
private static final boolean debugScaleEnabled;
|
||||
@@ -90,12 +99,16 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
private final List<WLGraphicsDevice> devices = new ArrayList<>(5);
|
||||
|
||||
private void notifyOutputConfigured(String name, String make, String model, int wlID,
|
||||
int x, int y, int width, int height, int widthMm, int heightMm,
|
||||
int x, int y, int xLogical, int yLogical,
|
||||
int width, int height,
|
||||
int widthLogical, int heightLogical,
|
||||
int widthMm, int heightMm,
|
||||
int subpixel, int transform, int scale) {
|
||||
// Called from native code whenever a new output appears or an existing one changes its properties
|
||||
// NB: initially called during WLToolkit.initIDs() on the main thread; later on EDT.
|
||||
if (log.isLoggable(Level.FINE)) {
|
||||
log.fine(String.format("Output configured id=%d at (%d, %d) %dx%d %dx scale", wlID, x, y, width, height, scale));
|
||||
log.fine(String.format("Output configured id=%d at (%d, %d) (%d, %d logical) %dx%d (%dx%d logical) %dx scale",
|
||||
wlID, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale));
|
||||
}
|
||||
|
||||
String humanID =
|
||||
@@ -108,12 +121,13 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
final WLGraphicsDevice gd = devices.get(i);
|
||||
if (gd.getID() == wlID) {
|
||||
newOutput = false;
|
||||
if (gd.isSameDeviceAs(wlID, x, y)) {
|
||||
if (gd.isSameDeviceAs(wlID, x, y, xLogical, yLogical)) {
|
||||
// These coordinates and the size are not scaled.
|
||||
gd.updateConfiguration(humanID, width, height, scale);
|
||||
gd.updateConfiguration(humanID, width, height, widthLogical, heightLogical, scale);
|
||||
} else {
|
||||
final WLGraphicsDevice updatedDevice = WLGraphicsDevice.createWithConfiguration(wlID, humanID,
|
||||
x, y, width, height, widthMm, heightMm, scale);
|
||||
x, y, xLogical, yLogical, width, height, widthLogical, heightLogical,
|
||||
widthMm, heightMm, scale);
|
||||
devices.set(i, updatedDevice);
|
||||
gd.invalidate(updatedDevice);
|
||||
}
|
||||
@@ -121,8 +135,9 @@ public class WLGraphicsEnvironment extends SunGraphicsEnvironment {
|
||||
}
|
||||
}
|
||||
if (newOutput) {
|
||||
final WLGraphicsDevice gd = WLGraphicsDevice.createWithConfiguration(wlID, humanID, x, y,
|
||||
width, height, widthMm, heightMm, scale);
|
||||
final WLGraphicsDevice gd = WLGraphicsDevice.createWithConfiguration(wlID, humanID,
|
||||
x, y, xLogical, yLogical, width, height, widthLogical, heightLogical,
|
||||
widthMm, heightMm, scale);
|
||||
devices.add(gd);
|
||||
}
|
||||
if (LogDisplay.ENABLED) {
|
||||
|
||||
@@ -55,11 +55,15 @@ public class WLSMGraphicsConfig extends WLGraphicsConfig {
|
||||
private WLSMGraphicsConfig(WLGraphicsDevice device,
|
||||
int x,
|
||||
int y,
|
||||
int xLogical,
|
||||
int yLogical,
|
||||
int width,
|
||||
int height,
|
||||
int widthLogical,
|
||||
int heightLogical,
|
||||
int scale,
|
||||
boolean translucencyCapable) {
|
||||
super(device, x, y, width, height, scale);
|
||||
super(device, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale);
|
||||
this.translucencyCapable = translucencyCapable;
|
||||
this.colorModel = colorModelFor(translucencyCapable ? Transparency.TRANSLUCENT : Transparency.OPAQUE);
|
||||
// Note: GNOME Shell definitely expects alpha values to be pre-multiplied
|
||||
@@ -69,11 +73,15 @@ public class WLSMGraphicsConfig extends WLGraphicsConfig {
|
||||
public static WLSMGraphicsConfig getConfig(WLGraphicsDevice device,
|
||||
int x,
|
||||
int y,
|
||||
int xLogical,
|
||||
int yLogical,
|
||||
int width,
|
||||
int height,
|
||||
int widthLogical,
|
||||
int heightLogical,
|
||||
int scale,
|
||||
boolean translucencyCapable) {
|
||||
var newConfig = new WLSMGraphicsConfig(device, x, y, width, height, scale, translucencyCapable);
|
||||
var newConfig = new WLSMGraphicsConfig(device, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale, translucencyCapable);
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
log.fine("New shared memory config " + newConfig);
|
||||
}
|
||||
|
||||
@@ -133,11 +133,33 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
private static final int MOUSE_BUTTONS_COUNT = 7;
|
||||
private static final int AWT_MULTICLICK_DEFAULT_TIME_MS = 500;
|
||||
|
||||
// mapping of AWT cursor types to X cursor names
|
||||
// multiple variants can be specified, that will be tried in order
|
||||
// See https://freedesktop.org/wiki/Specifications/cursor-spec/
|
||||
private static final String[][] CURSOR_NAMES = {
|
||||
{"default", "arrow", "left_ptr", "left_arrow"}, // DEFAULT_CURSOR
|
||||
{"crosshair", "cross"}, // CROSSHAIR_CURSOR
|
||||
{"text", "xterm"}, // TEXT_CURSOR
|
||||
{"wait", "watch", "progress"}, // WAIT_CURSOR
|
||||
{"sw-resize", "bottom_left_corner"}, // SW_RESIZE_CURSOR
|
||||
{"se-resize", "bottom_right_corner"}, // SE_RESIZE_CURSOR
|
||||
{"nw-resize", "top_left_corner"}, // NW_RESIZE_CURSOR
|
||||
{"ne-resize", "top_right_corner"}, // NE_RESIZE_CURSOR
|
||||
{"n-resize", "top_side"}, // N_RESIZE_CURSOR
|
||||
{"s-resize", "bottom_side"}, // S_RESIZE_CURSOR
|
||||
{"w-resize", "left_side"}, // W_RESIZE_CURSOR
|
||||
{"e-resize", "right_side"}, // E_RESIZE_CURSOR
|
||||
{"pointer", "pointing_hand", "hand1", "hand2"}, // HAND_CURSOR
|
||||
{"move"}, // MOVE_CURSOR
|
||||
};
|
||||
|
||||
private static boolean initialized = false;
|
||||
private static Thread toolkitThread;
|
||||
private final WLClipboard clipboard;
|
||||
private final WLClipboard selection;
|
||||
|
||||
private static Cursor currentCursor;
|
||||
|
||||
private static native void initIDs(long displayPtr);
|
||||
|
||||
static {
|
||||
@@ -300,6 +322,10 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
final WLInputState oldInputState = inputState;
|
||||
final WLInputState newInputState = oldInputState.updatedFromPointerEvent(e);
|
||||
inputState = newInputState;
|
||||
if (e.hasLeaveEvent() || e.hasEnterEvent()) {
|
||||
// We've lost the control over the cursor, assume no knowledge about it
|
||||
currentCursor = null;
|
||||
}
|
||||
final WLComponentPeer peer = newInputState.peerForPointerEvents();
|
||||
if (peer == null) {
|
||||
// We don't know whom to notify of the event; may happen when
|
||||
@@ -1064,4 +1090,80 @@ public class WLToolkit extends UNIXToolkit implements Runnable {
|
||||
static boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
static void performLockedGlobal(Runnable task) {
|
||||
WLToolkit.awtLock();
|
||||
try {
|
||||
task.run();
|
||||
} finally {
|
||||
WLToolkit.awtUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
static void updateCursorImmediatelyFor(WLComponentPeer peer) {
|
||||
Cursor cursor = peer.cursorAt(inputState.getPointerX(), inputState.getPointerY());
|
||||
GraphicsConfiguration gc = peer.getGraphicsConfiguration();
|
||||
int scale = gc instanceof WLGraphicsConfig wlGC ? wlGC.getDisplayScale() : 1;
|
||||
setCursorTo(cursor, scale);
|
||||
}
|
||||
|
||||
static void setCursorTo(Cursor c, int scale) {
|
||||
long serial = inputState.pointerEnterSerial();
|
||||
if (serial == 0) {
|
||||
if (log.isLoggable(PlatformLogger.Level.FINE)) {
|
||||
log.fine("setCursor aborted due to missing event serial");
|
||||
}
|
||||
return; // Wayland will ignore the request anyway
|
||||
}
|
||||
|
||||
Cursor cursor;
|
||||
if (c.getType() == Cursor.CUSTOM_CURSOR && !(c instanceof WLCustomCursor)) {
|
||||
cursor = Cursor.getDefaultCursor();
|
||||
} else {
|
||||
cursor = c;
|
||||
}
|
||||
|
||||
performLockedGlobal(() -> {
|
||||
// Cursors may get updated very often; prevent vacuous updates from reaching the native code so
|
||||
// as not to overwhelm the Wayland server.
|
||||
if (cursor == currentCursor) return;
|
||||
currentCursor = cursor;
|
||||
|
||||
long pData = AWTAccessor.getCursorAccessor().getPData(cursor, scale);
|
||||
if (pData == 0) {
|
||||
// instead of destroying and creating new cursor after changing scale could be used caching
|
||||
long oldPData = AWTAccessor.getCursorAccessor().getPData(cursor);
|
||||
if (oldPData != 0 && oldPData != -1) {
|
||||
nativeDestroyPredefinedCursor(oldPData);
|
||||
}
|
||||
|
||||
pData = createNativeCursor(cursor.getType(), scale);
|
||||
if (pData == 0) {
|
||||
pData = createNativeCursor(Cursor.DEFAULT_CURSOR, scale);
|
||||
}
|
||||
if (pData == 0) {
|
||||
pData = -1; // mark as unavailable
|
||||
}
|
||||
AWTAccessor.getCursorAccessor().setPData(cursor, scale, pData);
|
||||
}
|
||||
nativeSetCursor(pData, scale, serial);
|
||||
});
|
||||
}
|
||||
|
||||
private static long createNativeCursor(int type, int scale) {
|
||||
if (type < Cursor.DEFAULT_CURSOR || type > Cursor.MOVE_CURSOR) {
|
||||
type = Cursor.DEFAULT_CURSOR;
|
||||
}
|
||||
for (String name : CURSOR_NAMES[type]) {
|
||||
long pData = nativeGetPredefinedCursor(name, scale);
|
||||
if (pData != 0) {
|
||||
return pData;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static native void nativeSetCursor(long pData, int scale, long pointerEnterSerial);
|
||||
private static native long nativeGetPredefinedCursor(String name, int scale);
|
||||
private static native long nativeDestroyPredefinedCursor(long pData);
|
||||
}
|
||||
|
||||
@@ -78,8 +78,11 @@ public final class WLVKGraphicsConfig extends WLGraphicsConfig
|
||||
|
||||
private static native long getVKConfigInfo();
|
||||
|
||||
public WLVKGraphicsConfig(WLGraphicsDevice device, int x, int y, int width, int height, int scale, ContextCapabilities vkCaps) {
|
||||
super(device, x, y, width, height, scale);
|
||||
public WLVKGraphicsConfig(WLGraphicsDevice device,
|
||||
int x, int y, int xLogical, int yLogical,
|
||||
int width, int height, int widthLogical, int heightLogical,
|
||||
int scale, ContextCapabilities vkCaps) {
|
||||
super(device, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale);
|
||||
this.vkCaps = vkCaps;
|
||||
context = new VKContext(VKRenderQueue.getInstance());
|
||||
}
|
||||
@@ -89,13 +92,16 @@ public final class WLVKGraphicsConfig extends WLGraphicsConfig
|
||||
return surfaceDataProxyCache;
|
||||
}
|
||||
|
||||
public static WLVKGraphicsConfig getConfig(WLGraphicsDevice device, int x, int y, int width, int height, int scale)
|
||||
public static WLVKGraphicsConfig getConfig(WLGraphicsDevice device,
|
||||
int x, int y, int xLogical, int yLogical,
|
||||
int width, int height, int widthLogical, int heightLogical,
|
||||
int scale)
|
||||
{
|
||||
ContextCapabilities caps = new VKContext.VKContextCaps(
|
||||
CAPS_PS30 | CAPS_PS20 | CAPS_RT_TEXTURE_ALPHA |
|
||||
CAPS_RT_TEXTURE_OPAQUE | CAPS_MULTITEXTURE | CAPS_TEXNONPOW2 |
|
||||
CAPS_TEXNONSQUARE, null);
|
||||
return new WLVKGraphicsConfig(device, x, y, width, height, scale, caps);
|
||||
return new WLVKGraphicsConfig(device, x, y, xLogical, yLogical, width, height, widthLogical, heightLogical, scale, caps);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -513,7 +513,7 @@ newPositioner
|
||||
xdg_positioner_set_size(xdg_positioner, width, height);
|
||||
xdg_positioner_set_anchor_rect(xdg_positioner, offsetX, offsetY, 1, 1);
|
||||
xdg_positioner_set_offset(xdg_positioner, 0, 0);
|
||||
xdg_positioner_set_anchor(xdg_positioner, XDG_POSITIONER_ANCHOR_BOTTOM_LEFT);
|
||||
xdg_positioner_set_anchor(xdg_positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT);
|
||||
xdg_positioner_set_gravity(xdg_positioner, XDG_POSITIONER_GRAVITY_BOTTOM_RIGHT);
|
||||
xdg_positioner_set_constraint_adjustment(xdg_positioner,
|
||||
XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y
|
||||
|
||||
@@ -58,7 +58,7 @@ Java_java_awt_Cursor_finalizeImpl
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jlong JNICALL Java_sun_awt_wl_WLComponentPeer_nativeGetPredefinedCursor
|
||||
JNIEXPORT jlong JNICALL Java_sun_awt_wl_WLToolkit_nativeGetPredefinedCursor
|
||||
(JNIEnv *env, jclass cls, jstring name, jint scale)
|
||||
{
|
||||
struct wl_cursor_theme *cursor_theme = getCursorTheme(scale);
|
||||
@@ -91,7 +91,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_wl_WLComponentPeer_nativeGetPredefinedCurso
|
||||
return ptr_to_jlong(cursor);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_sun_awt_wl_WLComponentPeer_nativeDestroyPredefinedCursor
|
||||
JNIEXPORT void JNICALL Java_sun_awt_wl_WLToolkit_nativeDestroyPredefinedCursor
|
||||
(JNIEnv *env, jclass cls, struct WLCursor *cursor)
|
||||
{
|
||||
free(cursor);
|
||||
@@ -140,7 +140,7 @@ JNIEXPORT jlong JNICALL Java_sun_awt_wl_WLCustomCursor_nativeCreateCustomCursor
|
||||
return ptr_to_jlong(cursor);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL Java_sun_awt_wl_WLComponentPeer_nativeSetCursor
|
||||
JNIEXPORT void JNICALL Java_sun_awt_wl_WLToolkit_nativeSetCursor
|
||||
(JNIEnv *env, jclass cls, jlong pData, jint scale, jlong pointerEnterSerial)
|
||||
{
|
||||
struct wl_buffer *buffer = NULL;
|
||||
|
||||
@@ -25,8 +25,10 @@
|
||||
*/
|
||||
#ifndef HEADLESS
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <Trace.h>
|
||||
|
||||
#include "JNIUtilities.h"
|
||||
@@ -36,12 +38,17 @@ typedef struct WLOutput {
|
||||
struct WLOutput * next;
|
||||
|
||||
struct wl_output * wl_output;
|
||||
struct zxdg_output_v1 * zxdg_output;
|
||||
uint32_t id;
|
||||
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
int32_t x_logical;
|
||||
int32_t y_logical;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t width_logical;
|
||||
int32_t height_logical;
|
||||
int32_t width_mm;
|
||||
int32_t height_mm;
|
||||
|
||||
@@ -137,12 +144,8 @@ wl_output_scale(
|
||||
}
|
||||
|
||||
static void
|
||||
wl_output_done(
|
||||
void *data,
|
||||
struct wl_output *wl_output)
|
||||
NotifyOutputConfigured(WLOutput* output)
|
||||
{
|
||||
WLOutput * output = data;
|
||||
|
||||
JNIEnv *env = getEnv();
|
||||
jobject obj = (*env)->CallStaticObjectMethod(env, geClass, getSingleInstanceMID);
|
||||
JNU_CHECK_EXCEPTION(env);
|
||||
@@ -158,8 +161,12 @@ wl_output_done(
|
||||
output->id,
|
||||
output->x,
|
||||
output->y,
|
||||
output->x_logical,
|
||||
output->y_logical,
|
||||
output->width,
|
||||
output->height,
|
||||
output->width_logical,
|
||||
output->height_logical,
|
||||
output->width_mm,
|
||||
output->height_mm,
|
||||
(jint)output->subpixel,
|
||||
@@ -168,6 +175,17 @@ wl_output_done(
|
||||
JNU_CHECK_EXCEPTION(env);
|
||||
}
|
||||
|
||||
static void
|
||||
wl_output_done(void *data, struct wl_output *wl_output)
|
||||
{
|
||||
WLOutput * output = data;
|
||||
// When the manager is present we'll wait for another 'done' event (see zxdg_output_done()).
|
||||
bool wait_for_zxdg_output_done = zxdg_output_manager_v1 != NULL;
|
||||
if (!wait_for_zxdg_output_done) {
|
||||
NotifyOutputConfigured(output);
|
||||
}
|
||||
}
|
||||
|
||||
struct wl_output_listener wl_output_listener = {
|
||||
.geometry = &wl_output_geometry,
|
||||
.mode = &wl_output_mode,
|
||||
@@ -181,6 +199,49 @@ struct wl_output_listener wl_output_listener = {
|
||||
.scale = &wl_output_scale
|
||||
};
|
||||
|
||||
static void
|
||||
zxdg_output_logical_size(void *data, struct zxdg_output_v1 *zxdg_output_v1, int32_t width, int32_t height)
|
||||
{
|
||||
WLOutput * output = data;
|
||||
output->width_logical = width;
|
||||
output->height_logical = height;
|
||||
}
|
||||
|
||||
static void
|
||||
zxdg_output_done(void *data, struct zxdg_output_v1 *zxdg_output_v1)
|
||||
{
|
||||
WLOutput * output = data;
|
||||
NotifyOutputConfigured(output);
|
||||
}
|
||||
|
||||
static void
|
||||
zxdg_output_logical_position(void *data, struct zxdg_output_v1 *zxdg_output_v1, int32_t x, int32_t y)
|
||||
{
|
||||
WLOutput * output = data;
|
||||
output->x_logical = x;
|
||||
output->y_logical = y;
|
||||
}
|
||||
|
||||
static void
|
||||
zxdg_output_description(void *data, struct zxdg_output_v1 *zxdg_output_v1, const char *description)
|
||||
{
|
||||
// Ignored
|
||||
}
|
||||
|
||||
static void
|
||||
zxdg_output_name(void *data, struct zxdg_output_v1 *zxdg_output_v1, const char *name)
|
||||
{
|
||||
// Ignored
|
||||
}
|
||||
|
||||
struct zxdg_output_v1_listener zxdg_output_listener = {
|
||||
.logical_position = zxdg_output_logical_position,
|
||||
.logical_size = zxdg_output_logical_size,
|
||||
.description = zxdg_output_description,
|
||||
.name = zxdg_output_name,
|
||||
.done = zxdg_output_done
|
||||
};
|
||||
|
||||
jboolean
|
||||
WLGraphicsEnvironment_initIDs
|
||||
(JNIEnv *env, jclass clazz)
|
||||
@@ -196,7 +257,7 @@ WLGraphicsEnvironment_initIDs
|
||||
CHECK_NULL_RETURN(
|
||||
notifyOutputConfiguredMID = (*env)->GetMethodID(env, clazz,
|
||||
"notifyOutputConfigured",
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIIIIII)V"),
|
||||
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IIIIIIIIIIIIII)V"),
|
||||
JNI_FALSE);
|
||||
CHECK_NULL_RETURN(
|
||||
notifyOutputDestroyedMID = (*env)->GetMethodID(env, clazz,
|
||||
@@ -206,6 +267,17 @@ WLGraphicsEnvironment_initIDs
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
static void RegisterXdgOutput(WLOutput* output)
|
||||
{
|
||||
assert(zxdg_output_manager_v1 != NULL);
|
||||
|
||||
if (output->zxdg_output == NULL) {
|
||||
output->zxdg_output = zxdg_output_manager_v1_get_xdg_output(zxdg_output_manager_v1, output->wl_output);
|
||||
CHECK_NULL(output->zxdg_output);
|
||||
zxdg_output_v1_add_listener(output->zxdg_output, &zxdg_output_listener, output);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WLOutputRegister(struct wl_registry *wl_registry, uint32_t id)
|
||||
{
|
||||
@@ -217,10 +289,25 @@ WLOutputRegister(struct wl_registry *wl_registry, uint32_t id)
|
||||
output->wl_output = wl_registry_bind(wl_registry, id, &wl_output_interface, 2);
|
||||
if (output->wl_output == NULL) {
|
||||
JNU_ThrowByName(env, "java/awt/AWTError", "wl_registry_bind() failed");
|
||||
return;
|
||||
}
|
||||
wl_output_add_listener(output->wl_output, &wl_output_listener, output);
|
||||
output->next = outputList;
|
||||
outputList = output;
|
||||
|
||||
if (zxdg_output_manager_v1 != NULL) {
|
||||
RegisterXdgOutput(output);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WLOutputXdgOutputManagerBecameAvailable(void)
|
||||
{
|
||||
assert(zxdg_output_manager_v1 != NULL);
|
||||
|
||||
for (WLOutput* output = outputList; output; output = output->next) {
|
||||
RegisterXdgOutput(output);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -236,6 +323,9 @@ WLOutputDeregister(struct wl_registry *wl_registry, uint32_t id)
|
||||
} else {
|
||||
outputList = cur->next;
|
||||
}
|
||||
if (cur->zxdg_output != NULL) {
|
||||
zxdg_output_v1_destroy(cur->zxdg_output);
|
||||
}
|
||||
wl_output_destroy(cur->wl_output);
|
||||
WLOutput * next = cur->next;
|
||||
free(cur->name);
|
||||
|
||||
@@ -30,3 +30,4 @@ void WLOutputRegister(struct wl_registry *wl_registry, uint32_t id);
|
||||
void WLOutputDeregister(struct wl_registry *wl_registry, uint32_t id);
|
||||
uint32_t WLOutputID(struct wl_output *wlOutput);
|
||||
struct wl_output* WLOutputByID(uint32_t id);
|
||||
void WLOutputXdgOutputManagerBecameAvailable(void);
|
||||
|
||||
@@ -80,6 +80,7 @@ struct wl_cursor_theme *cursor_themes[MAX_CURSOR_SCALE] = {NULL};
|
||||
|
||||
struct wl_data_device_manager *wl_ddm = NULL;
|
||||
struct zwp_primary_selection_device_manager_v1 *zwp_selection_dm = NULL; // optional, check for NULL before use
|
||||
struct zxdg_output_manager_v1 *zxdg_output_manager_v1 = NULL; // optional, check for NULL before use
|
||||
|
||||
static uint32_t num_of_outstanding_sync = 0;
|
||||
|
||||
@@ -557,6 +558,12 @@ registry_global(void *data, struct wl_registry *wl_registry,
|
||||
zwp_selection_dm = wl_registry_bind(wl_registry, name, &zwp_primary_selection_device_manager_v1_interface, 1);
|
||||
} else if (strcmp(interface, wp_viewporter_interface.name) == 0) {
|
||||
wp_viewporter = wl_registry_bind(wl_registry, name, &wp_viewporter_interface, 1);
|
||||
} else if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0) {
|
||||
zxdg_output_manager_v1 = wl_registry_bind(wl_registry, name, &zxdg_output_manager_v1_interface, 2);
|
||||
if (zxdg_output_manager_v1 != NULL) {
|
||||
WLOutputXdgOutputManagerBecameAvailable();
|
||||
process_new_listener_before_end_of_init();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WAKEFIELD_ROBOT
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <wayland-cursor.h>
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
#include "xdg-activation-v1-client-protocol.h"
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
#include "primary-selection-client-protocol.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
#include "jvm_md.h"
|
||||
@@ -62,6 +63,7 @@ extern struct gtk_shell1* gtk_shell1; // optional, check for NULL before use
|
||||
extern struct wl_cursor_theme *wl_cursor_theme;
|
||||
extern struct wl_data_device_manager *wl_ddm;
|
||||
extern struct zwp_primary_selection_device_manager_v1 *zwp_selection_dm; // optional, check for NULL before use
|
||||
extern struct zxdg_output_manager_v1 *zxdg_output_manager_v1; // optional, check for NULL before use
|
||||
|
||||
JNIEnv *getEnv();
|
||||
|
||||
|
||||
@@ -0,0 +1,418 @@
|
||||
/* Generated by wayland-scanner 1.19.0 */
|
||||
|
||||
#ifndef XDG_OUTPUT_UNSTABLE_V1_CLIENT_PROTOCOL_H
|
||||
#define XDG_OUTPUT_UNSTABLE_V1_CLIENT_PROTOCOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "wayland-client.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @page page_xdg_output_unstable_v1 The xdg_output_unstable_v1 protocol
|
||||
* Protocol to describe output regions
|
||||
*
|
||||
* @section page_desc_xdg_output_unstable_v1 Description
|
||||
*
|
||||
* This protocol aims at describing outputs in a way which is more in line
|
||||
* with the concept of an output on desktop oriented systems.
|
||||
*
|
||||
* Some information are more specific to the concept of an output for
|
||||
* a desktop oriented system and may not make sense in other applications,
|
||||
* such as IVI systems for example.
|
||||
*
|
||||
* Typically, the global compositor space on a desktop system is made of
|
||||
* a contiguous or overlapping set of rectangular regions.
|
||||
*
|
||||
* The logical_position and logical_size events defined in this protocol
|
||||
* might provide information identical to their counterparts already
|
||||
* available from wl_output, in which case the information provided by this
|
||||
* protocol should be preferred to their equivalent in wl_output. The goal is
|
||||
* to move the desktop specific concepts (such as output location within the
|
||||
* global compositor space, etc.) out of the core wl_output protocol.
|
||||
*
|
||||
* Warning! The protocol described in this file is experimental and
|
||||
* backward incompatible changes may be made. Backward compatible
|
||||
* changes may be added together with the corresponding interface
|
||||
* version bump.
|
||||
* Backward incompatible changes are done by bumping the version
|
||||
* number in the protocol and interface names and resetting the
|
||||
* interface version. Once the protocol is to be declared stable,
|
||||
* the 'z' prefix and the version number in the protocol and
|
||||
* interface names are removed and the interface version number is
|
||||
* reset.
|
||||
*
|
||||
* @section page_ifaces_xdg_output_unstable_v1 Interfaces
|
||||
* - @subpage page_iface_zxdg_output_manager_v1 - manage xdg_output objects
|
||||
* - @subpage page_iface_zxdg_output_v1 - compositor logical output region
|
||||
* @section page_copyright_xdg_output_unstable_v1 Copyright
|
||||
* <pre>
|
||||
*
|
||||
* Copyright © 2017 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE 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. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
* </pre>
|
||||
*/
|
||||
struct wl_output;
|
||||
struct zxdg_output_manager_v1;
|
||||
struct zxdg_output_v1;
|
||||
|
||||
#ifndef ZXDG_OUTPUT_MANAGER_V1_INTERFACE
|
||||
#define ZXDG_OUTPUT_MANAGER_V1_INTERFACE
|
||||
/**
|
||||
* @page page_iface_zxdg_output_manager_v1 zxdg_output_manager_v1
|
||||
* @section page_iface_zxdg_output_manager_v1_desc Description
|
||||
*
|
||||
* A global factory interface for xdg_output objects.
|
||||
* @section page_iface_zxdg_output_manager_v1_api API
|
||||
* See @ref iface_zxdg_output_manager_v1.
|
||||
*/
|
||||
/**
|
||||
* @defgroup iface_zxdg_output_manager_v1 The zxdg_output_manager_v1 interface
|
||||
*
|
||||
* A global factory interface for xdg_output objects.
|
||||
*/
|
||||
extern const struct wl_interface zxdg_output_manager_v1_interface;
|
||||
#endif
|
||||
#ifndef ZXDG_OUTPUT_V1_INTERFACE
|
||||
#define ZXDG_OUTPUT_V1_INTERFACE
|
||||
/**
|
||||
* @page page_iface_zxdg_output_v1 zxdg_output_v1
|
||||
* @section page_iface_zxdg_output_v1_desc Description
|
||||
*
|
||||
* An xdg_output describes part of the compositor geometry.
|
||||
*
|
||||
* This typically corresponds to a monitor that displays part of the
|
||||
* compositor space.
|
||||
*
|
||||
* For objects version 3 onwards, after all xdg_output properties have been
|
||||
* sent (when the object is created and when properties are updated), a
|
||||
* wl_output.done event is sent. This allows changes to the output
|
||||
* properties to be seen as atomic, even if they happen via multiple events.
|
||||
* @section page_iface_zxdg_output_v1_api API
|
||||
* See @ref iface_zxdg_output_v1.
|
||||
*/
|
||||
/**
|
||||
* @defgroup iface_zxdg_output_v1 The zxdg_output_v1 interface
|
||||
*
|
||||
* An xdg_output describes part of the compositor geometry.
|
||||
*
|
||||
* This typically corresponds to a monitor that displays part of the
|
||||
* compositor space.
|
||||
*
|
||||
* For objects version 3 onwards, after all xdg_output properties have been
|
||||
* sent (when the object is created and when properties are updated), a
|
||||
* wl_output.done event is sent. This allows changes to the output
|
||||
* properties to be seen as atomic, even if they happen via multiple events.
|
||||
*/
|
||||
extern const struct wl_interface zxdg_output_v1_interface;
|
||||
#endif
|
||||
|
||||
#define ZXDG_OUTPUT_MANAGER_V1_DESTROY 0
|
||||
#define ZXDG_OUTPUT_MANAGER_V1_GET_XDG_OUTPUT 1
|
||||
|
||||
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_manager_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_MANAGER_V1_DESTROY_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_manager_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_MANAGER_V1_GET_XDG_OUTPUT_SINCE_VERSION 1
|
||||
|
||||
/** @ingroup iface_zxdg_output_manager_v1 */
|
||||
static inline void
|
||||
zxdg_output_manager_v1_set_user_data(struct zxdg_output_manager_v1 *zxdg_output_manager_v1, void *user_data)
|
||||
{
|
||||
wl_proxy_set_user_data((struct wl_proxy *) zxdg_output_manager_v1, user_data);
|
||||
}
|
||||
|
||||
/** @ingroup iface_zxdg_output_manager_v1 */
|
||||
static inline void *
|
||||
zxdg_output_manager_v1_get_user_data(struct zxdg_output_manager_v1 *zxdg_output_manager_v1)
|
||||
{
|
||||
return wl_proxy_get_user_data((struct wl_proxy *) zxdg_output_manager_v1);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
zxdg_output_manager_v1_get_version(struct zxdg_output_manager_v1 *zxdg_output_manager_v1)
|
||||
{
|
||||
return wl_proxy_get_version((struct wl_proxy *) zxdg_output_manager_v1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_manager_v1
|
||||
*
|
||||
* Using this request a client can tell the server that it is not
|
||||
* going to use the xdg_output_manager object anymore.
|
||||
*
|
||||
* Any objects already created through this instance are not affected.
|
||||
*/
|
||||
static inline void
|
||||
zxdg_output_manager_v1_destroy(struct zxdg_output_manager_v1 *zxdg_output_manager_v1)
|
||||
{
|
||||
wl_proxy_marshal((struct wl_proxy *) zxdg_output_manager_v1,
|
||||
ZXDG_OUTPUT_MANAGER_V1_DESTROY);
|
||||
|
||||
wl_proxy_destroy((struct wl_proxy *) zxdg_output_manager_v1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_manager_v1
|
||||
*
|
||||
* This creates a new xdg_output object for the given wl_output.
|
||||
*/
|
||||
static inline struct zxdg_output_v1 *
|
||||
zxdg_output_manager_v1_get_xdg_output(struct zxdg_output_manager_v1 *zxdg_output_manager_v1, struct wl_output *output)
|
||||
{
|
||||
struct wl_proxy *id;
|
||||
|
||||
id = wl_proxy_marshal_constructor((struct wl_proxy *) zxdg_output_manager_v1,
|
||||
ZXDG_OUTPUT_MANAGER_V1_GET_XDG_OUTPUT, &zxdg_output_v1_interface, NULL, output);
|
||||
|
||||
return (struct zxdg_output_v1 *) id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
* @struct zxdg_output_v1_listener
|
||||
*/
|
||||
struct zxdg_output_v1_listener {
|
||||
/**
|
||||
* position of the output within the global compositor space
|
||||
*
|
||||
* The position event describes the location of the wl_output
|
||||
* within the global compositor space.
|
||||
*
|
||||
* The logical_position event is sent after creating an xdg_output
|
||||
* (see xdg_output_manager.get_xdg_output) and whenever the
|
||||
* location of the output changes within the global compositor
|
||||
* space.
|
||||
* @param x x position within the global compositor space
|
||||
* @param y y position within the global compositor space
|
||||
*/
|
||||
void (*logical_position)(void *data,
|
||||
struct zxdg_output_v1 *zxdg_output_v1,
|
||||
int32_t x,
|
||||
int32_t y);
|
||||
/**
|
||||
* size of the output in the global compositor space
|
||||
*
|
||||
* The logical_size event describes the size of the output in the
|
||||
* global compositor space.
|
||||
*
|
||||
* Most regular Wayland clients should not pay attention to the
|
||||
* logical size and would rather rely on xdg_shell interfaces.
|
||||
*
|
||||
* Some clients such as Xwayland, however, need this to configure
|
||||
* their surfaces in the global compositor space as the compositor
|
||||
* may apply a different scale from what is advertised by the
|
||||
* output scaling property (to achieve fractional scaling, for
|
||||
* example).
|
||||
*
|
||||
* For example, for a wl_output mode 3840×2160 and a scale factor
|
||||
* 2:
|
||||
*
|
||||
* - A compositor not scaling the monitor viewport in its
|
||||
* compositing space will advertise a logical size of 3840×2160,
|
||||
*
|
||||
* - A compositor scaling the monitor viewport with scale factor 2
|
||||
* will advertise a logical size of 1920×1080,
|
||||
*
|
||||
* - A compositor scaling the monitor viewport using a fractional
|
||||
* scale of 1.5 will advertise a logical size of 2560×1440.
|
||||
*
|
||||
* For example, for a wl_output mode 1920×1080 and a 90 degree
|
||||
* rotation, the compositor will advertise a logical size of
|
||||
* 1080x1920.
|
||||
*
|
||||
* The logical_size event is sent after creating an xdg_output (see
|
||||
* xdg_output_manager.get_xdg_output) and whenever the logical size
|
||||
* of the output changes, either as a result of a change in the
|
||||
* applied scale or because of a change in the corresponding output
|
||||
* mode(see wl_output.mode) or transform (see wl_output.transform).
|
||||
* @param width width in global compositor space
|
||||
* @param height height in global compositor space
|
||||
*/
|
||||
void (*logical_size)(void *data,
|
||||
struct zxdg_output_v1 *zxdg_output_v1,
|
||||
int32_t width,
|
||||
int32_t height);
|
||||
/**
|
||||
* all information about the output have been sent
|
||||
*
|
||||
* This event is sent after all other properties of an xdg_output
|
||||
* have been sent.
|
||||
*
|
||||
* This allows changes to the xdg_output properties to be seen as
|
||||
* atomic, even if they happen via multiple events.
|
||||
*
|
||||
* For objects version 3 onwards, this event is deprecated.
|
||||
* Compositors are not required to send it anymore and must send
|
||||
* wl_output.done instead.
|
||||
*/
|
||||
void (*done)(void *data,
|
||||
struct zxdg_output_v1 *zxdg_output_v1);
|
||||
/**
|
||||
* name of this output
|
||||
*
|
||||
* Many compositors will assign names to their outputs, show them
|
||||
* to the user, allow them to be configured by name, etc. The
|
||||
* client may wish to know this name as well to offer the user
|
||||
* similar behaviors.
|
||||
*
|
||||
* The naming convention is compositor defined, but limited to
|
||||
* alphanumeric characters and dashes (-). Each name is unique
|
||||
* among all wl_output globals, but if a wl_output global is
|
||||
* destroyed the same name may be reused later. The names will also
|
||||
* remain consistent across sessions with the same hardware and
|
||||
* software configuration.
|
||||
*
|
||||
* Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc.
|
||||
* However, do not assume that the name is a reflection of an
|
||||
* underlying DRM connector, X11 connection, etc.
|
||||
*
|
||||
* The name event is sent after creating an xdg_output (see
|
||||
* xdg_output_manager.get_xdg_output). This event is only sent once
|
||||
* per xdg_output, and the name does not change over the lifetime
|
||||
* of the wl_output global.
|
||||
*
|
||||
* This event is deprecated, instead clients should use
|
||||
* wl_output.name. Compositors must still support this event.
|
||||
* @param name output name
|
||||
* @since 2
|
||||
*/
|
||||
void (*name)(void *data,
|
||||
struct zxdg_output_v1 *zxdg_output_v1,
|
||||
const char *name);
|
||||
/**
|
||||
* human-readable description of this output
|
||||
*
|
||||
* Many compositors can produce human-readable descriptions of
|
||||
* their outputs. The client may wish to know this description as
|
||||
* well, to communicate the user for various purposes.
|
||||
*
|
||||
* The description is a UTF-8 string with no convention defined for
|
||||
* its contents. Examples might include 'Foocorp 11" Display' or
|
||||
* 'Virtual X11 output via :1'.
|
||||
*
|
||||
* The description event is sent after creating an xdg_output (see
|
||||
* xdg_output_manager.get_xdg_output) and whenever the description
|
||||
* changes. The description is optional, and may not be sent at
|
||||
* all.
|
||||
*
|
||||
* For objects of version 2 and lower, this event is only sent once
|
||||
* per xdg_output, and the description does not change over the
|
||||
* lifetime of the wl_output global.
|
||||
*
|
||||
* This event is deprecated, instead clients should use
|
||||
* wl_output.description. Compositors must still support this
|
||||
* event.
|
||||
* @param description output description
|
||||
* @since 2
|
||||
*/
|
||||
void (*description)(void *data,
|
||||
struct zxdg_output_v1 *zxdg_output_v1,
|
||||
const char *description);
|
||||
};
|
||||
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*/
|
||||
static inline int
|
||||
zxdg_output_v1_add_listener(struct zxdg_output_v1 *zxdg_output_v1,
|
||||
const struct zxdg_output_v1_listener *listener, void *data)
|
||||
{
|
||||
return wl_proxy_add_listener((struct wl_proxy *) zxdg_output_v1,
|
||||
(void (**)(void)) listener, data);
|
||||
}
|
||||
|
||||
#define ZXDG_OUTPUT_V1_DESTROY 0
|
||||
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_V1_LOGICAL_POSITION_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_V1_LOGICAL_SIZE_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_V1_DONE_SINCE_VERSION 1
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_V1_NAME_SINCE_VERSION 2
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_V1_DESCRIPTION_SINCE_VERSION 2
|
||||
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*/
|
||||
#define ZXDG_OUTPUT_V1_DESTROY_SINCE_VERSION 1
|
||||
|
||||
/** @ingroup iface_zxdg_output_v1 */
|
||||
static inline void
|
||||
zxdg_output_v1_set_user_data(struct zxdg_output_v1 *zxdg_output_v1, void *user_data)
|
||||
{
|
||||
wl_proxy_set_user_data((struct wl_proxy *) zxdg_output_v1, user_data);
|
||||
}
|
||||
|
||||
/** @ingroup iface_zxdg_output_v1 */
|
||||
static inline void *
|
||||
zxdg_output_v1_get_user_data(struct zxdg_output_v1 *zxdg_output_v1)
|
||||
{
|
||||
return wl_proxy_get_user_data((struct wl_proxy *) zxdg_output_v1);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
zxdg_output_v1_get_version(struct zxdg_output_v1 *zxdg_output_v1)
|
||||
{
|
||||
return wl_proxy_get_version((struct wl_proxy *) zxdg_output_v1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @ingroup iface_zxdg_output_v1
|
||||
*
|
||||
* Using this request a client can tell the server that it is not
|
||||
* going to use the xdg_output object anymore.
|
||||
*/
|
||||
static inline void
|
||||
zxdg_output_v1_destroy(struct zxdg_output_v1 *zxdg_output_v1)
|
||||
{
|
||||
wl_proxy_marshal((struct wl_proxy *) zxdg_output_v1,
|
||||
ZXDG_OUTPUT_V1_DESTROY);
|
||||
|
||||
wl_proxy_destroy((struct wl_proxy *) zxdg_output_v1);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,78 @@
|
||||
/* Generated by wayland-scanner 1.19.0 */
|
||||
|
||||
/*
|
||||
* Copyright © 2017 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE 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. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include "wayland-util.h"
|
||||
|
||||
#ifndef __has_attribute
|
||||
# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
|
||||
#endif
|
||||
|
||||
#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
|
||||
#define WL_PRIVATE __attribute__ ((visibility("hidden")))
|
||||
#else
|
||||
#define WL_PRIVATE
|
||||
#endif
|
||||
|
||||
extern const struct wl_interface wl_output_interface;
|
||||
extern const struct wl_interface zxdg_output_v1_interface;
|
||||
|
||||
static const struct wl_interface *xdg_output_unstable_v1_types[] = {
|
||||
NULL,
|
||||
NULL,
|
||||
&zxdg_output_v1_interface,
|
||||
&wl_output_interface,
|
||||
};
|
||||
|
||||
static const struct wl_message zxdg_output_manager_v1_requests[] = {
|
||||
{ "destroy", "", xdg_output_unstable_v1_types + 0 },
|
||||
{ "get_xdg_output", "no", xdg_output_unstable_v1_types + 2 },
|
||||
};
|
||||
|
||||
WL_PRIVATE const struct wl_interface zxdg_output_manager_v1_interface = {
|
||||
"zxdg_output_manager_v1", 3,
|
||||
2, zxdg_output_manager_v1_requests,
|
||||
0, NULL,
|
||||
};
|
||||
|
||||
static const struct wl_message zxdg_output_v1_requests[] = {
|
||||
{ "destroy", "", xdg_output_unstable_v1_types + 0 },
|
||||
};
|
||||
|
||||
static const struct wl_message zxdg_output_v1_events[] = {
|
||||
{ "logical_position", "ii", xdg_output_unstable_v1_types + 0 },
|
||||
{ "logical_size", "ii", xdg_output_unstable_v1_types + 0 },
|
||||
{ "done", "", xdg_output_unstable_v1_types + 0 },
|
||||
{ "name", "2s", xdg_output_unstable_v1_types + 0 },
|
||||
{ "description", "2s", xdg_output_unstable_v1_types + 0 },
|
||||
};
|
||||
|
||||
WL_PRIVATE const struct wl_interface zxdg_output_v1_interface = {
|
||||
"zxdg_output_v1", 3,
|
||||
1, zxdg_output_v1_requests,
|
||||
5, zxdg_output_v1_events,
|
||||
};
|
||||
|
||||
@@ -1082,6 +1082,9 @@ jdk_swing_wayland= \
|
||||
jb/javax/swing/Popup/WLPopupAsParent.java \
|
||||
jb/javax/swing/Popup/WLPopupMinSize.java \
|
||||
jb/javax/swing/Popup/WLPopupResize.java \
|
||||
jb/javax/swing/Popup/WLPopupLocation.java \
|
||||
jb/javax/swing/Popup/WLPopupMoves.java \
|
||||
jb/javax/swing/Popup/WLPopupVisibility.java \
|
||||
-com/sun/java/swing/plaf/gtk/TestBackSpaceAction.java \
|
||||
-com/sun/java/swing/plaf/gtk/TestFileChooserCtrlASelection.java \
|
||||
-com/sun/java/swing/plaf/gtk/TestFileChooserSingleDirectorySelection.java \
|
||||
|
||||
@@ -41,6 +41,10 @@ import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
|
||||
* @key headful
|
||||
* @modules java.desktop/sun.awt
|
||||
* @run main WLPopupAsParent
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 WLPopupAsParent
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 WLPopupAsParent
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.5 WLPopupAsParent
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.0 WLPopupAsParent
|
||||
*/
|
||||
public class WLPopupAsParent {
|
||||
private static JFrame frame;
|
||||
|
||||
125
test/jdk/jb/javax/swing/Popup/WLPopupLocation.java
Normal file
125
test/jdk/jb/javax/swing/Popup/WLPopupLocation.java
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright 2024 JetBrains s.r.o.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Verifies that the popup-style window can change it's size and location
|
||||
* @requires os.family == "linux"
|
||||
* @key headful
|
||||
* @modules java.desktop/sun.awt
|
||||
* @run main/othervm WLPopupLocation
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 WLPopupLocation
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 WLPopupLocation
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.5 WLPopupLocation
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.0 WLPopupLocation
|
||||
*/
|
||||
public class WLPopupLocation {
|
||||
|
||||
private static JFrame frame;
|
||||
private static JWindow popup;
|
||||
|
||||
private static void createAndShowUI() {
|
||||
frame = new JFrame("WLPopupLocation Test");
|
||||
frame.setSize(300, 200);
|
||||
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static void initPopup() {
|
||||
JPanel popupContents = new JPanel();
|
||||
popupContents.add(new JLabel("test popup"));
|
||||
popup = new JWindow(frame);
|
||||
popup.setType(Window.Type.POPUP);
|
||||
sun.awt.AWTAccessor.getWindowAccessor().setPopupParent(popup, frame);
|
||||
popup.add(popupContents);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
if (!toolkit.getClass().getName().equals("sun.awt.wl.WLToolkit")) {
|
||||
System.out.println("The test makes sense only for WLToolkit. Exiting...");
|
||||
return;
|
||||
}
|
||||
|
||||
Robot robot = new Robot();
|
||||
|
||||
SwingUtilities.invokeAndWait(WLPopupLocation::createAndShowUI);
|
||||
pause(robot);
|
||||
|
||||
SwingUtilities.invokeAndWait(WLPopupLocation::initPopup);
|
||||
pause(robot);
|
||||
|
||||
int w1 = 150, h1 = 200;
|
||||
int x1 = 100, y1 = 100;
|
||||
System.out.printf("Action: locate to (%d, %d), set size (%d, %d)\n", x1, y1, w1, h1);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setVisible(true);
|
||||
popup.setSize(w1, h1);
|
||||
popup.setLocation(x1, y1);
|
||||
});
|
||||
if (popup.getSize().width != w1 || popup.getSize().height != h1) {
|
||||
throw new RuntimeException(String.format("Incorrect size (%d, %d), expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
|
||||
}
|
||||
if (popup.getBounds().x != x1 || popup.getBounds().y != y1) {
|
||||
throw new RuntimeException(String.format("Wrong location (via getBounds()): (%d, %d). Expected: (%d, %d)", popup.getBounds().x, popup.getBounds().y, x1, y1));
|
||||
}
|
||||
pause(robot);
|
||||
if (popup.getSize().width != h1 || popup.getSize().height != h1) {
|
||||
throw new RuntimeException(String.format("Incorrect size (%d, %d) after robot's wait for idle, expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
|
||||
}
|
||||
if (popup.getBounds().x != x1 || popup.getBounds().y != y1) {
|
||||
throw new RuntimeException(String.format("Wrong location (via getBounds()) after robot's wait for idle: (%d, %d). Expected: (%d, %d)", popup.getBounds().x, popup.getBounds().y, x1, y1));
|
||||
}
|
||||
|
||||
int x2 = 200, y2 = 200;
|
||||
System.out.printf("Action: set popup size to (%d, %d)\n", x2, y2);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setLocation(x2, y2);
|
||||
});
|
||||
if (popup.getSize().width != w1 || popup.getSize().height != h1) {
|
||||
throw new RuntimeException(String.format("Incorrect size (%d, %d), expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
|
||||
}
|
||||
if (popup.getBounds().x != x2 || popup.getBounds().y != y2) {
|
||||
throw new RuntimeException(String.format("Wrong location (via getBounds()): (%d, %d). Expected: (%x, %d)", popup.getBounds().x, popup.getBounds().y, x2, y2));
|
||||
}
|
||||
pause(robot);
|
||||
if (popup.getSize().width != w1 || popup.getSize().height != h1) {
|
||||
throw new RuntimeException(String.format("Incorrect size (%d, %d) after robot's wait for idle, expected (%d, %d)", popup.getSize().width, popup.getSize().height, w1, h1));
|
||||
}
|
||||
if (popup.getBounds().x != x2 || popup.getBounds().y != y2) {
|
||||
throw new RuntimeException(String.format("Wrong location (via getBounds()) after robot's wait for idle: (%d, %d). Expected: (%d, %d)", popup.getBounds().x, popup.getBounds().y, x2, y2));
|
||||
}
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
}
|
||||
|
||||
private static void pause(Robot robot) {
|
||||
robot.waitForIdle();
|
||||
robot.delay(500);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,7 +38,11 @@ import java.awt.Window;
|
||||
* @requires os.family == "linux"
|
||||
* @key headful
|
||||
* @modules java.desktop/sun.awt
|
||||
* @run main WLPopupMinSize
|
||||
* @run main/othervm WLPopupMinSize
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 WLPopupMinSize
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 WLPopupMinSize
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.5 WLPopupMinSize
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.0 WLPopupMinSize
|
||||
*/
|
||||
public class WLPopupMinSize {
|
||||
private static JFrame frame;
|
||||
|
||||
171
test/jdk/jb/javax/swing/Popup/WLPopupMoves.java
Normal file
171
test/jdk/jb/javax/swing/Popup/WLPopupMoves.java
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright 2024 JetBrains s.r.o.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
||||
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Verifies that the popup-style window can move under Wayland
|
||||
* @requires os.family == "linux"
|
||||
* @key headful
|
||||
* @modules java.desktop/sun.awt
|
||||
* @run main/othervm WLPopupMoves
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 WLPopupMoves
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 WLPopupMoves
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.5 WLPopupMoves
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.0 WLPopupMoves
|
||||
*/
|
||||
public class WLPopupMoves {
|
||||
|
||||
private static JFrame frame;
|
||||
private static JWindow popup;
|
||||
|
||||
private static void createAndShowUI() {
|
||||
frame = new JFrame("WLPopupMoves Test");
|
||||
frame.setSize(300, 200);
|
||||
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static void initPopup() {
|
||||
JPanel popupContents = new JPanel();
|
||||
popupContents.add(new JLabel("test popup"));
|
||||
popup = new JWindow(frame);
|
||||
popup.setType(Window.Type.POPUP);
|
||||
sun.awt.AWTAccessor.getWindowAccessor().setPopupParent(popup, frame);
|
||||
popup.add(popupContents);
|
||||
}
|
||||
|
||||
public static void main(String... args) throws Exception {
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
if (!toolkit.getClass().getName().equals("sun.awt.wl.WLToolkit")) {
|
||||
System.out.println("The test makes sense only for WLToolkit. Exiting...");
|
||||
return;
|
||||
}
|
||||
|
||||
Robot robot = new Robot();
|
||||
|
||||
SwingUtilities.invokeAndWait(WLPopupMoves::createAndShowUI);
|
||||
pause(robot);
|
||||
|
||||
SwingUtilities.invokeAndWait(WLPopupMoves::initPopup);
|
||||
pause(robot);
|
||||
|
||||
double uiScale = getUiScale();
|
||||
System.out.printf("UI scale: %.2f.\n", uiScale);
|
||||
int pixelThreshold = uiScale == 1.0 ? 0 : (int) Math.ceil(uiScale);
|
||||
System.out.printf("Pixel threshold for verifications: %d\n", pixelThreshold);
|
||||
|
||||
int w = 120, h = 200;
|
||||
System.out.println("Set popup to (50, 50)");
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(50, 50, w, h);
|
||||
popup.setVisible(true);
|
||||
});
|
||||
verifyBounds("Popup position after setting to (50, 50)\n", 50, 50, w, h, pixelThreshold);
|
||||
pause(robot);
|
||||
verifyBounds("Popup position (50, 50) after robot's pause\n", 50, 50, w, h, pixelThreshold);
|
||||
|
||||
System.out.println("Set popup to (100, 100)");
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(100, 100, w, h);
|
||||
});
|
||||
verifyBounds("Popup position after setting to (100, 100)\n", 100, 100, w, h, pixelThreshold);
|
||||
pause(robot);
|
||||
verifyBounds("Popup position (100, 100) after robot's pause\n", 100, 100, w, h, pixelThreshold);
|
||||
|
||||
int x1 = (int) (toolkit.getScreenSize().width / (2 * uiScale));
|
||||
int y1 = (int) (toolkit.getScreenSize().height / (2 * uiScale));
|
||||
System.out.printf("Set popup to (%d, %d)\n", x1, y1);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(x1, y1, w, h);
|
||||
});
|
||||
verifyBounds(String.format("Popup position after setting to (%d, %d)\n", x1, y1), x1, y1, w, h, pixelThreshold);
|
||||
pause(robot);
|
||||
verifyBounds(String.format("Popup position (%d, %d) after robot's pause\n", x1, y1), x1, y1, w, h, pixelThreshold);
|
||||
|
||||
int x2 = (int) (toolkit.getScreenSize().width / uiScale - 10 - w);
|
||||
int y2 = (int) (toolkit.getScreenSize().height / uiScale - 10 - h);
|
||||
System.out.printf("Set popup to (%d, %d). (to the bottom right corner) \n", x2, y2);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(x2, y2, w, h);
|
||||
});
|
||||
verifyBounds(String.format("Popup position after setting to (%d, %d)\n", x2, y2), x2, y2, w, h, pixelThreshold);
|
||||
pause(robot);
|
||||
verifyBounds(String.format("Popup position (%d, %d) after robot's pause\n", x2, y2), x2, y2, w, h, pixelThreshold);
|
||||
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
GraphicsDevice device = ge.getDefaultScreenDevice();
|
||||
GraphicsConfiguration gc = device.getDefaultConfiguration();
|
||||
Insets insets = toolkit.getScreenInsets(gc);
|
||||
int x3 = (int) (toolkit.getScreenSize().width / uiScale - 10 - insets.right);
|
||||
int y3 = (int) (toolkit.getScreenSize().height / uiScale - 10 - insets.bottom);
|
||||
System.out.printf("Set popup to (%d, %d). (to the bottom right corner) \n", x3, y3);
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(x2, y2, w, h);
|
||||
});
|
||||
int x3Relocated = x3 - w;
|
||||
int y3Relocated = y3 - h;
|
||||
verifyBounds(String.format("Popup position after setting to (%d, %d)\n", x3, y3), x3Relocated, y3Relocated, w, h, pixelThreshold);
|
||||
pause(robot);
|
||||
verifyBounds(String.format("Popup position (%d, %d) after robot's pause\n", x3, y3), x3Relocated, y3Relocated, w, h, pixelThreshold);
|
||||
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
}
|
||||
|
||||
private static Double getUiScale() {
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
GraphicsDevice device = ge.getDefaultScreenDevice();
|
||||
GraphicsConfiguration gc = device.getDefaultConfiguration();
|
||||
AffineTransform transform = gc.getDefaultTransform();
|
||||
double scaleX = transform.getScaleX();
|
||||
double scaleY = transform.getScaleY();
|
||||
if (scaleX != scaleY) {
|
||||
System.out.println("Skip test due to non-uniform display scale");
|
||||
System.exit(0);
|
||||
}
|
||||
return scaleX;
|
||||
}
|
||||
|
||||
private static void verifyBounds(String message, int x, int y, int w, int h, int pixelThreshold) {
|
||||
Rectangle bounds = popup.getBounds();
|
||||
System.out.printf("Check %s for bounds: %s\n", message, bounds);
|
||||
boolean isCorrectPosition = x - pixelThreshold <= bounds.x && bounds.x <= x + pixelThreshold &&
|
||||
y - pixelThreshold <= bounds.y && bounds.y <= y + pixelThreshold;
|
||||
if (!isCorrectPosition) {
|
||||
throw new RuntimeException(String.format("%s has wrong position. Expected: (%d, %d). Actual: (%d, %d)", message, x, y, bounds.x, bounds.y));
|
||||
}
|
||||
if (bounds.width != w || bounds.height != h) {
|
||||
throw new RuntimeException(String.format("%s has wrong size. Expected: (%d, %d). Actual: (%d, %d)", message, w, h, bounds.width, bounds.height));
|
||||
}
|
||||
}
|
||||
|
||||
private static void pause(Robot robot) {
|
||||
robot.waitForIdle();
|
||||
robot.delay(500);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,26 @@
|
||||
/*
|
||||
* Copyright 2024 JetBrains s.r.o.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, JetBrains s.r.o.. All rights reserved.
|
||||
@@ -27,10 +50,8 @@ import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JWindow;
|
||||
import javax.swing.SwingUtilities;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Robot;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.Window;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.AffineTransform;
|
||||
|
||||
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
|
||||
|
||||
@@ -41,7 +62,11 @@ import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
|
||||
* @requires os.family == "linux"
|
||||
* @key headful
|
||||
* @modules java.desktop/sun.awt
|
||||
* @run main WLPopupResize
|
||||
* @run main/othervm WLPopupResize
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 WLPopupResize
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.25 WLPopupResize
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.5 WLPopupResize
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.0 WLPopupResize
|
||||
*/
|
||||
public class WLPopupResize {
|
||||
private static JFrame frame;
|
||||
@@ -80,15 +105,51 @@ public class WLPopupResize {
|
||||
SwingUtilities.invokeAndWait(WLPopupResize::showPopup);
|
||||
pause(robot);
|
||||
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(10, 20, 120, 80);
|
||||
});
|
||||
pause(robot);
|
||||
double uiScale = getUiScale();
|
||||
System.out.printf("UI scale: %.2f.\n", uiScale);
|
||||
int pixelThreshold = uiScale == 1.0 ? 0 : (int) Math.ceil(uiScale);
|
||||
System.out.printf("Pixel threshold for verifications: %d\n", pixelThreshold);
|
||||
|
||||
Dimension newSize = popup.getSize();
|
||||
if (newSize.width != 120 || newSize.height != 80) {
|
||||
throw new RuntimeException("Wrong popup size: " + newSize.width + ", " + newSize.height);
|
||||
int x = 10, y = 20, w = 120, h = 80;
|
||||
System.out.println("Set popup size to (120, 80)");
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setBounds(x, y, w, h);
|
||||
});
|
||||
Rectangle bounds = popup.getBounds();
|
||||
boolean isCorrectPosition = x - pixelThreshold <= bounds.x && bounds.x <= x + pixelThreshold &&
|
||||
y - pixelThreshold <= bounds.y && bounds.y <= y + pixelThreshold;
|
||||
if (!isCorrectPosition) {
|
||||
throw new RuntimeException("Popup position has unexpectedly changed. Bounds: " + popup.getBounds());
|
||||
}
|
||||
if (popup.getBounds().width != w || popup.getBounds().height != h) {
|
||||
throw new RuntimeException("Popup size wasn't correctly changed. Bounds: " + popup.getBounds());
|
||||
}
|
||||
pause(robot);
|
||||
System.out.println("Next checks after robot's waiting for idle.");
|
||||
|
||||
isCorrectPosition = x - pixelThreshold <= bounds.x && bounds.x <= x + pixelThreshold &&
|
||||
y - pixelThreshold <= bounds.y && bounds.y <= y + pixelThreshold;
|
||||
if (!isCorrectPosition) {
|
||||
throw new RuntimeException("Popup position has unexpectedly changed. Bounds: " + popup.getBounds());
|
||||
}
|
||||
if (popup.getBounds().width != w || popup.getBounds().height != h) {
|
||||
throw new RuntimeException("Popup size wasn't correctly changed. Bounds: " + popup.getBounds());
|
||||
}
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
}
|
||||
|
||||
private static Double getUiScale() {
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
GraphicsDevice device = ge.getDefaultScreenDevice();
|
||||
GraphicsConfiguration gc = device.getDefaultConfiguration();
|
||||
AffineTransform transform = gc.getDefaultTransform();
|
||||
double scaleX = transform.getScaleX();
|
||||
double scaleY = transform.getScaleY();
|
||||
if (scaleX != scaleY) {
|
||||
System.out.println("Skip test due to non-uniform display scale");
|
||||
System.exit(0);
|
||||
}
|
||||
return scaleX;
|
||||
}
|
||||
|
||||
private static void pause(Robot robot) {
|
||||
|
||||
133
test/jdk/jb/javax/swing/Popup/WLPopupVisibility.java
Normal file
133
test/jdk/jb/javax/swing/Popup/WLPopupVisibility.java
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2024 JetBrains s.r.o.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
|
||||
import static javax.swing.WindowConstants.EXIT_ON_CLOSE;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @summary Verifies that the popup-style window can change its visibility
|
||||
* @requires os.family == "linux"
|
||||
* @key headful
|
||||
* @modules java.desktop/sun.awt
|
||||
* @run main/othervm WLPopupVisibility
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=1.0 WLPopupVisibility
|
||||
* @run main/othervm -Dsun.java2d.uiScale.enabled=true -Dsun.java2d.uiScale=2.0 WLPopupVisibility
|
||||
*/
|
||||
public class WLPopupVisibility {
|
||||
|
||||
private static JFrame frame;
|
||||
private static JWindow popup;
|
||||
|
||||
private static void createAndShowUI() {
|
||||
frame = new JFrame("WLPopupVisibility Test");
|
||||
frame.setSize(300, 200);
|
||||
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
private static void initPopup() {
|
||||
JPanel popupContents = new JPanel();
|
||||
popupContents.add(new JLabel("test popup"));
|
||||
popup = new JWindow(frame);
|
||||
popup.setType(Window.Type.POPUP);
|
||||
sun.awt.AWTAccessor.getWindowAccessor().setPopupParent(popup, frame);
|
||||
popup.add(popupContents);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
Toolkit toolkit = Toolkit.getDefaultToolkit();
|
||||
if (!toolkit.getClass().getName().equals("sun.awt.wl.WLToolkit")) {
|
||||
System.out.println("The test makes sense only for WLToolkit. Exiting...");
|
||||
return;
|
||||
}
|
||||
|
||||
Robot robot = new Robot();
|
||||
|
||||
SwingUtilities.invokeAndWait(WLPopupVisibility::createAndShowUI);
|
||||
pause(robot);
|
||||
|
||||
SwingUtilities.invokeAndWait(WLPopupVisibility::initPopup);
|
||||
pause(robot);
|
||||
|
||||
System.out.println("Action: set the popup visible");
|
||||
SwingUtilities.invokeAndWait(() -> popup.setVisible(true));
|
||||
boolean isVisible1 = popup.isVisible();
|
||||
pause(robot);
|
||||
boolean isVisible2 = popup.isVisible();
|
||||
|
||||
if (!isVisible1 || !isVisible2) {
|
||||
throw new RuntimeException("Expected result: popup is visible");
|
||||
}
|
||||
|
||||
System.out.println("Action: set the popup disabled");
|
||||
SwingUtilities.invokeAndWait(() -> popup.setEnabled(false));
|
||||
boolean isEnabled3 = popup.isEnabled();
|
||||
boolean isVisible3 = popup.isVisible();
|
||||
pause(robot);
|
||||
boolean isEnabled4 = popup.isEnabled();
|
||||
boolean isVisible4 = popup.isVisible();
|
||||
if (isEnabled3 || isEnabled4) {
|
||||
throw new RuntimeException("Expected result: popup is disabled");
|
||||
}
|
||||
if (!isVisible3 || !isVisible4) {
|
||||
throw new RuntimeException("Expected result: disabled popup remains visible");
|
||||
}
|
||||
|
||||
System.out.println("Action: set the popup invisible");
|
||||
SwingUtilities.invokeAndWait(() -> popup.setVisible(false));
|
||||
boolean isVisible5 = popup.isVisible();
|
||||
pause(robot);
|
||||
boolean isVisible6 = popup.isVisible();
|
||||
if (isVisible5 && isVisible6) {
|
||||
throw new RuntimeException("Expected result: disabled popup remains visible");
|
||||
}
|
||||
|
||||
System.out.println("Action: set popup enabled and visible");
|
||||
SwingUtilities.invokeAndWait(() -> {
|
||||
popup.setVisible(true);
|
||||
popup.setEnabled(true);
|
||||
});
|
||||
boolean isEnabled7 = popup.isEnabled();
|
||||
boolean isVisible7 = popup.isVisible();
|
||||
pause(robot);
|
||||
boolean isEnabled8 = popup.isEnabled();
|
||||
boolean isVisible8 = popup.isVisible();
|
||||
if (!isEnabled7 || !isEnabled8) {
|
||||
throw new RuntimeException("Expected result: popup is enabled");
|
||||
}
|
||||
if (!isVisible7 || !isVisible8) {
|
||||
throw new RuntimeException("Expected result: popup becoming visible");
|
||||
}
|
||||
|
||||
SwingUtilities.invokeAndWait(frame::dispose);
|
||||
}
|
||||
|
||||
private static void pause(Robot robot) {
|
||||
robot.waitForIdle();
|
||||
robot.delay(500);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
java/awt/Choice/ChoiceHandleMouseEvent.java
|
||||
java/awt/Choice/ChoiceHandleMouseEvent_2.java JBR-7174 windows-all
|
||||
java/awt/dnd/RecognizedActionTest/RecognizedActionTest.java JBR-8017 windows-x64
|
||||
java/awt/Graphics/XORPaint.java#id0 JBR-7499 windows-x64
|
||||
java/awt/Toolkit/LWCToolkitInvokeAndWaitTest.java nobug macosx-all,linux-all,windows-all
|
||||
java/awt/Toolkit/AWTThreadingTest.java nobug macosx-all,linux-all,windows-all
|
||||
@@ -125,6 +126,7 @@ java/awt/Choice/ChoiceConsumeMouseEvents.java JBR-6951 windows-x64
|
||||
java/awt/Choice/ChoiceFreezeTest.java JBR-6952 windows-x64
|
||||
java/awt/Choice/ChoiceMouseEventOutbounds.java TBD windows-x64
|
||||
java/awt/Choice/ChoicePopupLocation/ChoicePopupLocation.java JBR-6857,JBR-5505 macosx-all,windows-all
|
||||
java/awt/Choice/NonFocusablePopupMenuTest.java JBR-7961 windows-x64
|
||||
java/awt/Choice/RemoveAllShrinkTest/RemoveAllShrinkTest.java JBR-5510,8310487,JBR-6950 linux-5.18.2-arch1-1,linux-all,windows-x64
|
||||
java/awt/Choice/ResizeAutoClosesChoice/ResizeAutoClosesChoice.java JBR-5510,JBR-5905 linux-5.18.2-arch1-1,linux-all,windows-x64
|
||||
java/awt/Component/NativeInLightShow/NativeInLightShow.java JBR-7715 windows-x64
|
||||
|
||||
@@ -130,7 +130,7 @@ java/awt/TextArea/UsingWithMouse/SelectionAutoscrollTest.java JBR-7779 linux-all
|
||||
javax/swing/JEditorPane/TestBrowserBGColor.java JBR-6697 linux-aarch64
|
||||
javax/swing/plaf/nimbus/8041642/ScrollBarThumbVisibleTest.java JBR-6485 linux-all
|
||||
javax/swing/plaf/nimbus/8041642/bug8041642.java JBR-6698 linux-all
|
||||
javax/swing/UI/UnninstallUIMemoryLeaks/UnninstallUIMemoryLeaks.java JBR-5952,JBR-6274 windows-x64,macosx-all
|
||||
javax/swing/UI/UnninstallUIMemoryLeaks/UnninstallUIMemoryLeaks.java JBR-5952,JBR-6274 windows-all,macosx-all
|
||||
|
||||
jb/java/awt/Focus/PopupIncomingFocusTest.java JBR-2651 generic-all
|
||||
jb/java/awt/Window/UndecoratedDialogInTransientsChain.java JBR-6924 windows-all
|
||||
@@ -155,7 +155,7 @@ java/awt/Frame/8158918/SetExtendedState.java JBR-6408 linux-all
|
||||
java/awt/Frame/GetGraphicsStressTest/GetGraphicsStressTest.java JBR-6509 generic-all
|
||||
java/awt/Frame/MaximizedUndecorated/MaximizedUndecorated.java 8022302 generic-all
|
||||
java/awt/Frame/MaximizedToIconified/MaximizedToIconified.java 8296972 macosx-all
|
||||
java/awt/Frame/MaximizedToMaximized/MaximizedToMaximized.java 8340595,JBR-7786 macosx-15.0,linux-all
|
||||
java/awt/Frame/MaximizedToMaximized/MaximizedToMaximized.java JBR-7786,JBR-7947 linux-all,macosx-15.0,macosx-15.0.1,macosx-15.1.1
|
||||
java/awt/Frame/MaximizedToOppositeScreen/MaximizedToOppositeScreenBig.java JBR-5303 windows-all
|
||||
java/awt/Frame/RestoreToOppositeScreen/RestoreToOppositeScreen.java 8286840 linux-all
|
||||
java/awt/dnd/AcceptDropMultipleTimes/AcceptDropMultipleTimes.java JBR-4880,JBR-6683 windows-all,linux-all
|
||||
@@ -255,7 +255,7 @@ java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java JBR-
|
||||
java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.java 8073636,JBR-4211 macosx-all,linux-all
|
||||
java/awt/EventDispatchThread/PropertyPermissionOnEDT/PropertyPermissionOnEDT.java JBR-5225 windows-all
|
||||
java/awt/FullScreen/AltTabCrashTest/AltTabCrashTest.java JBR-4905 windows-all,linux-all
|
||||
java/awt/FullScreen/FullScreenInsets/FullScreenInsets.java 7019055,8266245 windows-all,linux-all,macosx-aarch64
|
||||
java/awt/FullScreen/FullScreenInsets/FullScreenInsets.java 7019055,8266245 windows-all,linux-all,macosx-all
|
||||
java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java JBR-4275,JBR-4880 linux-all,windows-all
|
||||
java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java 7188711,8253184 linux-all,windows-all
|
||||
java/awt/FullScreen/UninitializedDisplayModeChangeTest/UninitializedDisplayModeChangeTest.java 7188711,8273617,JBR-4880,8253184 macosx-all,linux-all,windows-all
|
||||
@@ -393,7 +393,7 @@ java/awt/Frame/MiscUndecorated/ActiveSwingWindowTest.java JBR-5210 windows-all
|
||||
java/awt/Frame/MiscUndecorated/FrameCloseTest.java JBR-5210 windows-all
|
||||
java/awt/Frame/MiscUndecorated/RepaintTest.java 8266244,JBR-5786 macosx-aarch64,generic-all
|
||||
java/awt/Robot/HiDPIMouseClick/HiDPIRobotMouseClick.java 8253184 windows-all
|
||||
java/awt/Robot/NonEmptyErrorStream.java 8340330,JBR-5510 macosx-15.0,linux-5.18.2-arch1-1
|
||||
java/awt/Robot/NonEmptyErrorStream.java 8340330,JBR-5510 macosx-15.0.1,macosx-15.1.1,linux-5.18.2-arch1-1
|
||||
java/awt/Robot/RobotExtraButton/RobotExtraButton.java JBR-6554 linux-all
|
||||
java/awt/Modal/FileDialog/FileDialogAppModal1Test.java 7186009,8253184 macosx-all,windows-all
|
||||
java/awt/Modal/FileDialog/FileDialogAppModal2Test.java 7186009,8253184 macosx-all,windows-all
|
||||
@@ -709,7 +709,7 @@ java/awt/PopupMenu/PopupMenuLocation.java 8238720,JBR-7035 windows-all,macosx-al
|
||||
java/awt/GridBagLayout/GridBagLayoutIpadXYTest/GridBagLayoutIpadXYTest.java 8253184 windows-all
|
||||
java/awt/GridLayout/ChangeGridSize/ChangeGridSize.java 8238720,8324782 windows-all,macosx-all
|
||||
java/awt/GridLayout/ComponentPreferredSize/ComponentPreferredSize.java 8238720,8324782 windows-all,macosx-all
|
||||
java/awt/GridLayout/LayoutExtraGaps/LayoutExtraGaps.java JBR-7847 linux-aarch64
|
||||
java/awt/GridLayout/LayoutExtraGaps/LayoutExtraGaps.java JBR-7847 linux-all
|
||||
java/awt/event/MouseEvent/FrameMouseEventAbsoluteCoordsTest/FrameMouseEventAbsoluteCoordsTest.java 8238720 windows-all
|
||||
|
||||
java/awt/wakefield/RobotKeyboard.java JBR-5653 linux-all
|
||||
@@ -943,7 +943,7 @@ javax/swing/JButton/4368790/bug4368790.java JBR-5210 windows-all
|
||||
javax/swing/JButton/4659800/SpaceKeyActivatesButton.java JBR-4949 linux-all,windows-all
|
||||
javax/swing/JButton/8151303/PressedIconTest.java JBR-5210,JBR-5510 windows-all,linux-5.18.2-arch1-1
|
||||
javax/swing/JButton/PressedButtonRightClickTest.java JBR-5210 windows-all
|
||||
javax/swing/JButton/TestMnemonicAction.java JBR-6508 windows-x64,linux-all
|
||||
javax/swing/JButton/TestMnemonicAction.java JBR-6508 windows-all,linux-all
|
||||
javax/swing/JColorChooser/Test6524757.java JBR-5210 windows-all
|
||||
javax/swing/JColorChooser/Test6827032.java JBR-5210 windows-all
|
||||
javax/swing/JComboBox/4199622/bug4199622.java JBR-6751 winows-x64
|
||||
@@ -983,7 +983,7 @@ javax/swing/JOptionPane/8081019/bug8081019.java JBR-5767 windows-all
|
||||
javax/swing/JPopupMenu/4634626/bug4634626.java 8253184 windows-all
|
||||
javax/swing/JPopupMenu/4760494/bug4760494.java 8253184 windows-all
|
||||
javax/swing/JPopupMenu/4870644/bug4870644.java 8194130 macosx-all,linux-all
|
||||
javax/swing/JPopupMenu/4966112/bug4966112.java 8253184 windows-all
|
||||
javax/swing/JPopupMenu/4966112/bug4966112.java 8253184,JBR-7946 windows-all,linux-all
|
||||
javax/swing/JPopupMenu/6415145/bug6415145.java 8197552 windows-all
|
||||
javax/swing/JPopupMenu/6495920/bug6495920.java JBR-6928 linux-all
|
||||
javax/swing/JPopupMenu/6515446/bug6515446.java 8197552,JBR-6531 windows-all,linux-all
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
java/awt/Choice/ChoiceMouseEventOutbounds.java JBR-7980 windows-all
|
||||
java/awt/Choice/ChoiceMoveTest.java JBR-7980 windows-all
|
||||
java/awt/Dialog/DialogLocationTest.java JBR-6090 windows-all
|
||||
java/awt/datatransfer/DragUnicodeBetweenJVMTest/DragUnicodeBetweenJVMTest.java JBR-5538 windows-all
|
||||
java/awt/datatransfer/MissedHtmlAndRtfBug/MissedHtmlAndRtfBug.java JBR-6027 windows-all
|
||||
|
||||
Reference in New Issue
Block a user