JBR-7158 Wayland: scale with wp_viewport instead of buffer scale

This commit is contained in:
Maxim Kartashev
2024-05-08 12:05:29 +04:00
committed by Maxim Kartashёv
parent 56bd776f20
commit 1e3fb0289d
10 changed files with 527 additions and 33 deletions

View File

@@ -119,8 +119,8 @@ public class WLComponentPeer implements ComponentPeer {
boolean visible = false;
private final Object dataLock = new Object();
int width; // protected by dataLock
int height; // protected by dataLock
int width; // in native pixels, protected by dataLock
int height; // in native pixels, protected by dataLock
int wlBufferScale; // protected by dataLock
double effectiveScale; // protected by dataLock
@@ -306,6 +306,7 @@ public class WLComponentPeer implements ComponentPeer {
nativeCreateWLPopup(nativePtr, getParentNativePtr(target),
thisWidth, thisHeight,
parentX + offsetX, parentY + offsetY);
nativeSetSurfaceSize(nativePtr, thisWidth, thisHeight);
} else {
int xNative = javaUnitsToSurfaceUnits(target.getX());
int yNative = javaUnitsToSurfaceUnits(target.getY());
@@ -314,6 +315,7 @@ public class WLComponentPeer implements ComponentPeer {
xNative, yNative,
isModal, isMaximized, isMinimized,
title, WLToolkit.getApplicationID());
nativeSetSurfaceSize(nativePtr, thisWidth, thisHeight);
}
final long wlSurfacePtr = getWLSurface(nativePtr);
WLToolkit.registerWLSurface(wlSurfacePtr, this);
@@ -483,6 +485,9 @@ public class WLComponentPeer implements ComponentPeer {
private void setSizeTo(int newWidth, int newHeight) {
Dimension newSize = constrainSize(newWidth, newHeight);
performLocked(() -> {
nativeSetSurfaceSize(nativePtr, javaUnitsToSurfaceUnits(newSize.width), javaUnitsToSurfaceUnits(newSize.height));
});
synchronized (dataLock) {
this.width = newSize.width;
this.height = newSize.height;
@@ -523,11 +528,10 @@ public class WLComponentPeer implements ComponentPeer {
}
/**
* Returns the scale of wl_buffer attached to this component's wl_surface.
* Buffer coordinate space is linearly scaled wrt the component (or surface)
* coordinate space, so component's coordinates have to be translated
* to buffers' whenever Wayland protocol requires "buffer-local" coordinates.
* See wl_surface.set_buffer_scale in wayland.xml for more details.
* Represents the scale ratio of Wayland's backing buffer in pixel units
* to surface units. Wayland events are generated in surface units, while
* painting should be performed in pixel units.
* The ratio is enforced with nativeSetSize().
*/
int getBufferScale() {
synchronized(dataLock) {
@@ -1023,6 +1027,7 @@ public class WLComponentPeer implements ComponentPeer {
private native void nativeRequestFullScreen(long ptr, int wlID);
private native void nativeRequestUnsetFullScreen(long ptr);
private native void nativeSetSurfaceSize(long ptr, int width, int height);
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);

View File

@@ -49,14 +49,14 @@ public class WLSMSurfaceData extends SurfaceData implements WLSurfaceDataExt {
public native void assignSurface(long surfacePtr);
private native void initOps(int width, int height, int scale, int backgroundRGB, int wlShmFormat, boolean perfCountersEnabled);
private native void initOps(int width, int height, int backgroundRGB, int wlShmFormat, boolean perfCountersEnabled);
private static native void initIDs();
static {
initIDs();
}
private WLSMSurfaceData(WLComponentPeer peer, SurfaceType surfaceType, ColorModel colorModel, int scale, int wlShmFormat, boolean perfCountersEnabled) {
private WLSMSurfaceData(WLComponentPeer peer, SurfaceType surfaceType, ColorModel colorModel, int wlShmFormat, boolean perfCountersEnabled) {
super(surfaceType, colorModel);
this.peer = peer;
@@ -68,10 +68,10 @@ public class WLSMSurfaceData extends SurfaceData implements WLSurfaceDataExt {
int height = peer.getBufferHeight();
if (log.isLoggable(PlatformLogger.Level.FINE)) {
log.fine(String.format("Shared memory surface data %dx%d x%d scale, format %d", width, height, scale, wlShmFormat));
log.fine(String.format("Shared memory surface data %dx%d, format %d", width, height, wlShmFormat));
}
initOps(width, height, scale, backgroundPixel, wlShmFormat, perfCountersEnabled);
initOps(width, height, backgroundPixel, wlShmFormat, perfCountersEnabled);
}
/**
@@ -85,7 +85,7 @@ public class WLSMSurfaceData extends SurfaceData implements WLSurfaceDataExt {
SurfaceType surfaceType = graphicsConfig.getSurfaceType();
Window target = peer.getTarget() instanceof Window ? (Window)peer.getTarget() : null;
boolean perfCountersEnabled = target != null && AWTAccessor.getWindowAccessor().countersEnabled(target);
return new WLSMSurfaceData(peer, surfaceType, cm, graphicsConfig.getWlScale(), graphicsConfig.getWlShmFormat(), perfCountersEnabled);
return new WLSMSurfaceData(peer, surfaceType, cm, graphicsConfig.getWlShmFormat(), perfCountersEnabled);
}
@Override

View File

@@ -270,9 +270,6 @@ struct WLSurfaceBufferManager {
/// Does not exceed MAX_BUFFERS_IN_USE elements.
WLSurfaceBuffer * buffersInUse; // only accessed under showLock
/// The scale of wl_surface (see Wayland docs for more info on that).
jint scale; // only accessed under showLock
pthread_mutex_t drawLock;
/**
@@ -760,7 +757,7 @@ SendShowBufferToWayland(WLSurfaceBufferManager * manager)
// wl_buffer_listener will release bufferForShow when Wayland's done with it
wl_surface_attach(manager->wlSurface, buffer->wlBuffer, 0, 0);
wl_surface_set_buffer_scale(manager->wlSurface, manager->scale);
//NB: do not specify scale for the buffer; we scale with wp_viewporter
// Better wait for the frame event so as not to overwhelm Wayland with
// frequent surface updates that it cannot deliver to the screen anyway.
@@ -935,7 +932,6 @@ HaveEnoughMemoryForWindow(jint width, jint height)
WLSurfaceBufferManager *
WLSBM_Create(jint width,
jint height,
jint scale,
jint bgPixel,
jint wlShmFormat,
jobject surfaceDataWeakRef,
@@ -955,7 +951,6 @@ WLSBM_Create(jint width,
manager->bufferForDraw.width = width;
manager->bufferForDraw.height = height;
manager->scale = scale;
manager->bgPixel = bgPixel;
manager->format = wlShmFormat;
manager->surfaceDataWeakRef = surfaceDataWeakRef;
@@ -1116,7 +1111,7 @@ WLSB_DataGet(WLDrawBuffer * buffer)
}
void
WLSBM_SizeChangeTo(WLSurfaceBufferManager * manager, jint width, jint height, jint scale)
WLSBM_SizeChangeTo(WLSurfaceBufferManager * manager, jint width, jint height)
{
if (!HaveEnoughMemoryForWindow(width, height)) {
JNU_ThrowOutOfMemoryError(getEnv(), "Wayland surface buffer too large");
@@ -1125,13 +1120,7 @@ WLSBM_SizeChangeTo(WLSurfaceBufferManager * manager, jint width, jint height, ji
MUTEX_LOCK(manager->drawLock);
MUTEX_LOCK(manager->showLock);
const bool change_needed =
manager->bufferForDraw.width != width
|| manager->bufferForDraw.height != height
|| manager->scale != scale;
manager->scale = scale;
if (change_needed) {
if (manager->bufferForDraw.width != width || manager->bufferForDraw.height != height) {
manager->bufferForDraw.width = width;
manager->bufferForDraw.height = height;
manager->bufferForDraw.resizePending = true;

View File

@@ -63,7 +63,7 @@ typedef void (*FrameCounterCallback)(jobject);
* the drawing to displaying buffer, synchronization, and sending
* the appropriate notifications to Wayland.
*/
WLSurfaceBufferManager * WLSBM_Create(jint width, jint height, jint scale, jint bgPixel, jint wlShmFormat,
WLSurfaceBufferManager * WLSBM_Create(jint width, jint height, jint bgPixel, jint wlShmFormat,
jobject surfaceDataWeakRef,
FrameCounterCallback frameSentCallback,
FrameCounterCallback frameDroppedCallback);
@@ -113,7 +113,7 @@ jint WLSBM_HeightGet(WLSurfaceBufferManager *);
* displays things will change later, but before the changes in drawing buffer
* are propagated to the display buffer.
*/
void WLSBM_SizeChangeTo(WLSurfaceBufferManager *, jint width, jint height, jint scale);
void WLSBM_SizeChangeTo(WLSurfaceBufferManager *, jint width, jint height);
/**
* Returns a buffer managed by the WayLand Surface Buffer Manager

View File

@@ -130,7 +130,7 @@ Java_sun_java2d_wl_WLSMSurfaceData_revalidate(JNIEnv *env, jobject wsd,
return;
}
WLSBM_SizeChangeTo(wsdo->bufferManager, width, height, scale);
WLSBM_SizeChangeTo(wsdo->bufferManager, width, height);
#endif /* !HEADLESS */
}
@@ -364,7 +364,6 @@ JNIEXPORT void JNICALL
Java_sun_java2d_wl_WLSMSurfaceData_initOps(JNIEnv *env, jobject wsd,
jint width,
jint height,
jint scale,
jint backgroundRGB,
jint wlShmFormat,
jboolean perfCountersEnabled)
@@ -394,7 +393,7 @@ Java_sun_java2d_wl_WLSMSurfaceData_initOps(JNIEnv *env, jobject wsd,
wsdo->sdOps.Unlock = WLSD_Unlock;
wsdo->sdOps.GetRasInfo = WLSD_GetRasInfo;
wsdo->sdOps.Dispose = WLSD_Dispose;
wsdo->bufferManager = WLSBM_Create(width, height, scale, backgroundRGB, wlShmFormat,
wsdo->bufferManager = WLSBM_Create(width, height, backgroundRGB, wlShmFormat,
surfaceDataWeakRef,
perfCountersEnabled ? CountFrameSent : NULL,
perfCountersEnabled ? CountFrameDropped : NULL);

View File

@@ -90,6 +90,7 @@ static void delete_all_tokens(struct activation_token_list_item *list) {
struct WLFrame {
jobject nativeFramePeer; // weak reference
struct wl_surface *wl_surface;
struct wp_viewport *wp_viewport;
struct xdg_surface *xdg_surface;
struct gtk_surface1 *gtk_surface;
struct WLFrame *parent;
@@ -451,13 +452,14 @@ Java_sun_awt_wl_WLComponentPeer_nativeCreateWLSurface
if (frame->wl_surface) return;
frame->wl_surface = wl_compositor_create_surface(wl_compositor);
CHECK_NULL(frame->wl_surface);
frame->wp_viewport = wp_viewporter_get_viewport(wp_viewporter, frame->wl_surface);
CHECK_NULL(frame->wp_viewport);
frame->xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, frame->wl_surface);
CHECK_NULL(frame->xdg_surface);
if (gtk_shell1 != NULL) {
frame->gtk_surface = gtk_shell1_get_gtk_surface(gtk_shell1, frame->wl_surface);
CHECK_NULL(frame->gtk_surface);
}
wl_surface_add_listener(frame->wl_surface, &wl_surface_listener, frame);
xdg_surface_add_listener(frame->xdg_surface, &xdg_surface_listener, frame);
frame->toplevel = JNI_TRUE;
@@ -530,6 +532,8 @@ Java_sun_awt_wl_WLComponentPeer_nativeCreateWLPopup
if (frame->wl_surface) return;
frame->wl_surface = wl_compositor_create_surface(wl_compositor);
CHECK_NULL(frame->wl_surface);
frame->wp_viewport = wp_viewporter_get_viewport(wp_viewporter, frame->wl_surface);
CHECK_NULL(frame->wp_viewport);
frame->xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, frame->wl_surface);
CHECK_NULL(frame->xdg_surface);
@@ -544,7 +548,6 @@ Java_sun_awt_wl_WLComponentPeer_nativeCreateWLPopup
CHECK_NULL(frame->xdg_popup);
xdg_popup_add_listener(frame->xdg_popup, &xdg_popup_listener, frame);
xdg_positioner_destroy(xdg_positioner);
// From xdg-shell.xml: "After creating a role-specific object and
// setting it up, the client must perform an initial commit
// without any buffer attached"
@@ -586,6 +589,7 @@ DoHide(JNIEnv *env, struct WLFrame *frame)
if (frame->gtk_surface != NULL) {
gtk_surface1_destroy(frame->gtk_surface);
}
wp_viewport_destroy(frame->wp_viewport);
xdg_surface_destroy(frame->xdg_surface);
wl_surface_destroy(frame->wl_surface);
delete_all_tokens(frame->activation_token_list);
@@ -596,6 +600,7 @@ DoHide(JNIEnv *env, struct WLFrame *frame)
frame->xdg_surface = NULL;
frame->xdg_toplevel = NULL;
frame->xdg_popup = NULL;
frame->wp_viewport = NULL;
frame->toplevel = JNI_FALSE;
}
}
@@ -644,6 +649,21 @@ JNIEXPORT void JNICALL Java_sun_awt_wl_WLComponentPeer_nativeStartResize
}
}
/**
* Specifies the size of the Wayland's surface in surface units.
* For the resulting image on the screen to look sharp this size should be
* multiple of backing buffer's size with the ratio matching the display scale.
*/
JNIEXPORT void JNICALL Java_sun_awt_wl_WLComponentPeer_nativeSetSurfaceSize
(JNIEnv *env, jobject obj, jlong ptr, jint width, jint height)
{
struct WLFrame *frame = jlong_to_ptr(ptr);
if (frame->wp_viewport != NULL) {
wp_viewport_set_destination(frame->wp_viewport, width, height);
}
}
JNIEXPORT void JNICALL Java_sun_awt_wl_WLComponentPeer_nativeSetWindowGeometry
(JNIEnv *env, jobject obj, jlong ptr, jint x, jint y, jint width, jint height)
{

View File

@@ -64,6 +64,7 @@ struct wl_display *wl_display = NULL;
struct wl_shm *wl_shm = NULL;
struct wl_compositor *wl_compositor = NULL;
struct xdg_wm_base *xdg_wm_base = NULL;
struct wp_viewporter *wp_viewporter = NULL;
struct xdg_activation_v1 *xdg_activation_v1 = NULL;
struct gtk_shell1* gtk_shell1 = NULL;
struct wl_seat *wl_seat = NULL;
@@ -524,6 +525,8 @@ registry_global(void *data, struct wl_registry *wl_registry,
wl_ddm = wl_registry_bind(wl_registry, name,&wl_data_device_manager_interface, 3);
} else if (strcmp(interface, zwp_primary_selection_device_manager_v1_interface.name) == 0) {
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);
}
#ifdef WAKEFIELD_ROBOT

View File

@@ -28,6 +28,7 @@
#include "xdg-shell-client-protocol.h"
#include "xdg-activation-v1-client-protocol.h"
#include "primary-selection-client-protocol.h"
#include "viewporter-client-protocol.h"
#include "jvm_md.h"
#include "jni_util.h"
@@ -54,6 +55,7 @@ extern struct wl_display *wl_display;
extern struct wl_pointer *wl_pointer;
extern struct wl_compositor *wl_compositor;
extern struct xdg_wm_base *xdg_wm_base;
extern struct wp_viewporter *wp_viewporter;
extern struct xdg_activation_v1 *xdg_activation_v1;
extern struct gtk_shell1* gtk_shell1; // optional, check for NULL before use

View File

@@ -0,0 +1,74 @@
/* Generated by wayland-scanner 1.19.0 */
/*
* Copyright © 2013-2016 Collabora, Ltd.
*
* 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_surface_interface;
extern const struct wl_interface wp_viewport_interface;
static const struct wl_interface *viewporter_types[] = {
NULL,
NULL,
NULL,
NULL,
&wp_viewport_interface,
&wl_surface_interface,
};
static const struct wl_message wp_viewporter_requests[] = {
{ "destroy", "", viewporter_types + 0 },
{ "get_viewport", "no", viewporter_types + 4 },
};
WL_PRIVATE const struct wl_interface wp_viewporter_interface = {
"wp_viewporter", 1,
2, wp_viewporter_requests,
0, NULL,
};
static const struct wl_message wp_viewport_requests[] = {
{ "destroy", "", viewporter_types + 0 },
{ "set_source", "ffff", viewporter_types + 0 },
{ "set_destination", "ii", viewporter_types + 0 },
};
WL_PRIVATE const struct wl_interface wp_viewport_interface = {
"wp_viewport", 1,
3, wp_viewport_requests,
0, NULL,
};

View File

@@ -0,0 +1,402 @@
/* Generated by wayland-scanner 1.19.0 */
#ifndef VIEWPORTER_CLIENT_PROTOCOL_H
#define VIEWPORTER_CLIENT_PROTOCOL_H
#include <stdint.h>
#include <stddef.h>
#include "wayland-client.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @page page_viewporter The viewporter protocol
* @section page_ifaces_viewporter Interfaces
* - @subpage page_iface_wp_viewporter - surface cropping and scaling
* - @subpage page_iface_wp_viewport - crop and scale interface to a wl_surface
* @section page_copyright_viewporter Copyright
* <pre>
*
* Copyright © 2013-2016 Collabora, Ltd.
*
* 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_surface;
struct wp_viewport;
struct wp_viewporter;
#ifndef WP_VIEWPORTER_INTERFACE
#define WP_VIEWPORTER_INTERFACE
/**
* @page page_iface_wp_viewporter wp_viewporter
* @section page_iface_wp_viewporter_desc Description
*
* The global interface exposing surface cropping and scaling
* capabilities is used to instantiate an interface extension for a
* wl_surface object. This extended interface will then allow
* cropping and scaling the surface contents, effectively
* disconnecting the direct relationship between the buffer and the
* surface size.
* @section page_iface_wp_viewporter_api API
* See @ref iface_wp_viewporter.
*/
/**
* @defgroup iface_wp_viewporter The wp_viewporter interface
*
* The global interface exposing surface cropping and scaling
* capabilities is used to instantiate an interface extension for a
* wl_surface object. This extended interface will then allow
* cropping and scaling the surface contents, effectively
* disconnecting the direct relationship between the buffer and the
* surface size.
*/
extern const struct wl_interface wp_viewporter_interface;
#endif
#ifndef WP_VIEWPORT_INTERFACE
#define WP_VIEWPORT_INTERFACE
/**
* @page page_iface_wp_viewport wp_viewport
* @section page_iface_wp_viewport_desc Description
*
* An additional interface to a wl_surface object, which allows the
* client to specify the cropping and scaling of the surface
* contents.
*
* This interface works with two concepts: the source rectangle (src_x,
* src_y, src_width, src_height), and the destination size (dst_width,
* dst_height). The contents of the source rectangle are scaled to the
* destination size, and content outside the source rectangle is ignored.
* This state is double-buffered, and is applied on the next
* wl_surface.commit.
*
* The two parts of crop and scale state are independent: the source
* rectangle, and the destination size. Initially both are unset, that
* is, no scaling is applied. The whole of the current wl_buffer is
* used as the source, and the surface size is as defined in
* wl_surface.attach.
*
* If the destination size is set, it causes the surface size to become
* dst_width, dst_height. The source (rectangle) is scaled to exactly
* this size. This overrides whatever the attached wl_buffer size is,
* unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface
* has no content and therefore no size. Otherwise, the size is always
* at least 1x1 in surface local coordinates.
*
* If the source rectangle is set, it defines what area of the wl_buffer is
* taken as the source. If the source rectangle is set and the destination
* size is not set, then src_width and src_height must be integers, and the
* surface size becomes the source rectangle size. This results in cropping
* without scaling. If src_width or src_height are not integers and
* destination size is not set, the bad_size protocol error is raised when
* the surface state is applied.
*
* The coordinate transformations from buffer pixel coordinates up to
* the surface-local coordinates happen in the following order:
* 1. buffer_transform (wl_surface.set_buffer_transform)
* 2. buffer_scale (wl_surface.set_buffer_scale)
* 3. crop and scale (wp_viewport.set*)
* This means, that the source rectangle coordinates of crop and scale
* are given in the coordinates after the buffer transform and scale,
* i.e. in the coordinates that would be the surface-local coordinates
* if the crop and scale was not applied.
*
* If src_x or src_y are negative, the bad_value protocol error is raised.
* Otherwise, if the source rectangle is partially or completely outside of
* the non-NULL wl_buffer, then the out_of_buffer protocol error is raised
* when the surface state is applied. A NULL wl_buffer does not raise the
* out_of_buffer error.
*
* If the wl_surface associated with the wp_viewport is destroyed,
* all wp_viewport requests except 'destroy' raise the protocol error
* no_surface.
*
* If the wp_viewport object is destroyed, the crop and scale
* state is removed from the wl_surface. The change will be applied
* on the next wl_surface.commit.
* @section page_iface_wp_viewport_api API
* See @ref iface_wp_viewport.
*/
/**
* @defgroup iface_wp_viewport The wp_viewport interface
*
* An additional interface to a wl_surface object, which allows the
* client to specify the cropping and scaling of the surface
* contents.
*
* This interface works with two concepts: the source rectangle (src_x,
* src_y, src_width, src_height), and the destination size (dst_width,
* dst_height). The contents of the source rectangle are scaled to the
* destination size, and content outside the source rectangle is ignored.
* This state is double-buffered, and is applied on the next
* wl_surface.commit.
*
* The two parts of crop and scale state are independent: the source
* rectangle, and the destination size. Initially both are unset, that
* is, no scaling is applied. The whole of the current wl_buffer is
* used as the source, and the surface size is as defined in
* wl_surface.attach.
*
* If the destination size is set, it causes the surface size to become
* dst_width, dst_height. The source (rectangle) is scaled to exactly
* this size. This overrides whatever the attached wl_buffer size is,
* unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface
* has no content and therefore no size. Otherwise, the size is always
* at least 1x1 in surface local coordinates.
*
* If the source rectangle is set, it defines what area of the wl_buffer is
* taken as the source. If the source rectangle is set and the destination
* size is not set, then src_width and src_height must be integers, and the
* surface size becomes the source rectangle size. This results in cropping
* without scaling. If src_width or src_height are not integers and
* destination size is not set, the bad_size protocol error is raised when
* the surface state is applied.
*
* The coordinate transformations from buffer pixel coordinates up to
* the surface-local coordinates happen in the following order:
* 1. buffer_transform (wl_surface.set_buffer_transform)
* 2. buffer_scale (wl_surface.set_buffer_scale)
* 3. crop and scale (wp_viewport.set*)
* This means, that the source rectangle coordinates of crop and scale
* are given in the coordinates after the buffer transform and scale,
* i.e. in the coordinates that would be the surface-local coordinates
* if the crop and scale was not applied.
*
* If src_x or src_y are negative, the bad_value protocol error is raised.
* Otherwise, if the source rectangle is partially or completely outside of
* the non-NULL wl_buffer, then the out_of_buffer protocol error is raised
* when the surface state is applied. A NULL wl_buffer does not raise the
* out_of_buffer error.
*
* If the wl_surface associated with the wp_viewport is destroyed,
* all wp_viewport requests except 'destroy' raise the protocol error
* no_surface.
*
* If the wp_viewport object is destroyed, the crop and scale
* state is removed from the wl_surface. The change will be applied
* on the next wl_surface.commit.
*/
extern const struct wl_interface wp_viewport_interface;
#endif
#ifndef WP_VIEWPORTER_ERROR_ENUM
#define WP_VIEWPORTER_ERROR_ENUM
enum wp_viewporter_error {
/**
* the surface already has a viewport object associated
*/
WP_VIEWPORTER_ERROR_VIEWPORT_EXISTS = 0,
};
#endif /* WP_VIEWPORTER_ERROR_ENUM */
#define WP_VIEWPORTER_DESTROY 0
#define WP_VIEWPORTER_GET_VIEWPORT 1
/**
* @ingroup iface_wp_viewporter
*/
#define WP_VIEWPORTER_DESTROY_SINCE_VERSION 1
/**
* @ingroup iface_wp_viewporter
*/
#define WP_VIEWPORTER_GET_VIEWPORT_SINCE_VERSION 1
/** @ingroup iface_wp_viewporter */
static inline void
wp_viewporter_set_user_data(struct wp_viewporter *wp_viewporter, void *user_data)
{
wl_proxy_set_user_data((struct wl_proxy *) wp_viewporter, user_data);
}
/** @ingroup iface_wp_viewporter */
static inline void *
wp_viewporter_get_user_data(struct wp_viewporter *wp_viewporter)
{
return wl_proxy_get_user_data((struct wl_proxy *) wp_viewporter);
}
static inline uint32_t
wp_viewporter_get_version(struct wp_viewporter *wp_viewporter)
{
return wl_proxy_get_version((struct wl_proxy *) wp_viewporter);
}
/**
* @ingroup iface_wp_viewporter
*
* Informs the server that the client will not be using this
* protocol object anymore. This does not affect any other objects,
* wp_viewport objects included.
*/
static inline void
wp_viewporter_destroy(struct wp_viewporter *wp_viewporter)
{
wl_proxy_marshal((struct wl_proxy *) wp_viewporter,
WP_VIEWPORTER_DESTROY);
wl_proxy_destroy((struct wl_proxy *) wp_viewporter);
}
/**
* @ingroup iface_wp_viewporter
*
* Instantiate an interface extension for the given wl_surface to
* crop and scale its content. If the given wl_surface already has
* a wp_viewport object associated, the viewport_exists
* protocol error is raised.
*/
static inline struct wp_viewport *
wp_viewporter_get_viewport(struct wp_viewporter *wp_viewporter, struct wl_surface *surface)
{
struct wl_proxy *id;
id = wl_proxy_marshal_constructor((struct wl_proxy *) wp_viewporter,
WP_VIEWPORTER_GET_VIEWPORT, &wp_viewport_interface, NULL, surface);
return (struct wp_viewport *) id;
}
#ifndef WP_VIEWPORT_ERROR_ENUM
#define WP_VIEWPORT_ERROR_ENUM
enum wp_viewport_error {
/**
* negative or zero values in width or height
*/
WP_VIEWPORT_ERROR_BAD_VALUE = 0,
/**
* destination size is not integer
*/
WP_VIEWPORT_ERROR_BAD_SIZE = 1,
/**
* source rectangle extends outside of the content area
*/
WP_VIEWPORT_ERROR_OUT_OF_BUFFER = 2,
/**
* the wl_surface was destroyed
*/
WP_VIEWPORT_ERROR_NO_SURFACE = 3,
};
#endif /* WP_VIEWPORT_ERROR_ENUM */
#define WP_VIEWPORT_DESTROY 0
#define WP_VIEWPORT_SET_SOURCE 1
#define WP_VIEWPORT_SET_DESTINATION 2
/**
* @ingroup iface_wp_viewport
*/
#define WP_VIEWPORT_DESTROY_SINCE_VERSION 1
/**
* @ingroup iface_wp_viewport
*/
#define WP_VIEWPORT_SET_SOURCE_SINCE_VERSION 1
/**
* @ingroup iface_wp_viewport
*/
#define WP_VIEWPORT_SET_DESTINATION_SINCE_VERSION 1
/** @ingroup iface_wp_viewport */
static inline void
wp_viewport_set_user_data(struct wp_viewport *wp_viewport, void *user_data)
{
wl_proxy_set_user_data((struct wl_proxy *) wp_viewport, user_data);
}
/** @ingroup iface_wp_viewport */
static inline void *
wp_viewport_get_user_data(struct wp_viewport *wp_viewport)
{
return wl_proxy_get_user_data((struct wl_proxy *) wp_viewport);
}
static inline uint32_t
wp_viewport_get_version(struct wp_viewport *wp_viewport)
{
return wl_proxy_get_version((struct wl_proxy *) wp_viewport);
}
/**
* @ingroup iface_wp_viewport
*
* The associated wl_surface's crop and scale state is removed.
* The change is applied on the next wl_surface.commit.
*/
static inline void
wp_viewport_destroy(struct wp_viewport *wp_viewport)
{
wl_proxy_marshal((struct wl_proxy *) wp_viewport,
WP_VIEWPORT_DESTROY);
wl_proxy_destroy((struct wl_proxy *) wp_viewport);
}
/**
* @ingroup iface_wp_viewport
*
* Set the source rectangle of the associated wl_surface. See
* wp_viewport for the description, and relation to the wl_buffer
* size.
*
* If all of x, y, width and height are -1.0, the source rectangle is
* unset instead. Any other set of values where width or height are zero
* or negative, or x or y are negative, raise the bad_value protocol
* error.
*
* The crop and scale state is double-buffered state, and will be
* applied on the next wl_surface.commit.
*/
static inline void
wp_viewport_set_source(struct wp_viewport *wp_viewport, wl_fixed_t x, wl_fixed_t y, wl_fixed_t width, wl_fixed_t height)
{
wl_proxy_marshal((struct wl_proxy *) wp_viewport,
WP_VIEWPORT_SET_SOURCE, x, y, width, height);
}
/**
* @ingroup iface_wp_viewport
*
* Set the destination size of the associated wl_surface. See
* wp_viewport for the description, and relation to the wl_buffer
* size.
*
* If width is -1 and height is -1, the destination size is unset
* instead. Any other pair of values for width and height that
* contains zero or negative values raises the bad_value protocol
* error.
*
* The crop and scale state is double-buffered state, and will be
* applied on the next wl_surface.commit.
*/
static inline void
wp_viewport_set_destination(struct wp_viewport *wp_viewport, int32_t width, int32_t height)
{
wl_proxy_marshal((struct wl_proxy *) wp_viewport,
WP_VIEWPORT_SET_DESTINATION, width, height);
}
#ifdef __cplusplus
}
#endif
#endif