Add wayland support to devdraw.

This commit is contained in:
Ethan Burns 2024-08-18 09:21:03 -04:00
parent a2567fcac9
commit 5f20010eb6
10 changed files with 4770 additions and 3 deletions

View file

@ -29,6 +29,8 @@ if [ "x$WSYSTYPE" = "x" ]; then
exit 1
fi
WSYSTYPE=mac
elif [ "x$XDG_SESSION_TYPE" = "xwayland" ]; then
WSYSTYPE=wayland
elif [ -d "$X11" ]; then
WSYSTYPE=x11
else
@ -58,6 +60,12 @@ elif [ $WSYSTYPE = mac ]; then
echo 'WSYSOFILES=$WSYSOFILES mac-draw.o mac-screen.o'
echo 'WSYSHFILES='
echo 'MACARGV=macargv.o'
elif [ $WSYSTYPE = wayland ]; then
echo 'LDFLAGS=$LDFLAGS -lwayland-client -lxkbcommon'
XO=`ls wayland*.c 2>/dev/null | sed 's/\.c/\.o/'`
echo 'WSYSOFILES=$WSYSOFILES '$XO
XH=`ls wayland*.h 2>/dev/null`
echo 'WSYSHFILES='$XH
elif [ $WSYSTYPE = nowsys ]; then
echo 'WSYSOFILES=nowsys.o'
fi

View file

@ -0,0 +1,99 @@
/* Generated by wayland-scanner 1.23.0 */
/*
* Copyright © 2014 Jonas Ådahl
* Copyright © 2015 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 <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include "wayland-util.h"
extern const struct wl_interface wl_pointer_interface;
extern const struct wl_interface wl_region_interface;
extern const struct wl_interface wl_surface_interface;
extern const struct wl_interface zwp_confined_pointer_v1_interface;
extern const struct wl_interface zwp_locked_pointer_v1_interface;
static const struct wl_interface *pointer_constraints_unstable_v1_types[] = {
NULL,
NULL,
&zwp_locked_pointer_v1_interface,
&wl_surface_interface,
&wl_pointer_interface,
&wl_region_interface,
NULL,
&zwp_confined_pointer_v1_interface,
&wl_surface_interface,
&wl_pointer_interface,
&wl_region_interface,
NULL,
&wl_region_interface,
&wl_region_interface,
};
static const struct wl_message zwp_pointer_constraints_v1_requests[] = {
{ "destroy", "", pointer_constraints_unstable_v1_types + 0 },
{ "lock_pointer", "noo?ou", pointer_constraints_unstable_v1_types + 2 },
{ "confine_pointer", "noo?ou", pointer_constraints_unstable_v1_types + 7 },
};
WL_EXPORT const struct wl_interface zwp_pointer_constraints_v1_interface = {
"zwp_pointer_constraints_v1", 1,
3, zwp_pointer_constraints_v1_requests,
0, NULL,
};
static const struct wl_message zwp_locked_pointer_v1_requests[] = {
{ "destroy", "", pointer_constraints_unstable_v1_types + 0 },
{ "set_cursor_position_hint", "ff", pointer_constraints_unstable_v1_types + 0 },
{ "set_region", "?o", pointer_constraints_unstable_v1_types + 12 },
};
static const struct wl_message zwp_locked_pointer_v1_events[] = {
{ "locked", "", pointer_constraints_unstable_v1_types + 0 },
{ "unlocked", "", pointer_constraints_unstable_v1_types + 0 },
};
WL_EXPORT const struct wl_interface zwp_locked_pointer_v1_interface = {
"zwp_locked_pointer_v1", 1,
3, zwp_locked_pointer_v1_requests,
2, zwp_locked_pointer_v1_events,
};
static const struct wl_message zwp_confined_pointer_v1_requests[] = {
{ "destroy", "", pointer_constraints_unstable_v1_types + 0 },
{ "set_region", "?o", pointer_constraints_unstable_v1_types + 13 },
};
static const struct wl_message zwp_confined_pointer_v1_events[] = {
{ "confined", "", pointer_constraints_unstable_v1_types + 0 },
{ "unconfined", "", pointer_constraints_unstable_v1_types + 0 },
};
WL_EXPORT const struct wl_interface zwp_confined_pointer_v1_interface = {
"zwp_confined_pointer_v1", 1,
2, zwp_confined_pointer_v1_requests,
2, zwp_confined_pointer_v1_events,
};

View file

@ -0,0 +1,667 @@
/* Generated by wayland-scanner 1.23.0 */
#ifndef POINTER_CONSTRAINTS_UNSTABLE_V1_CLIENT_PROTOCOL_H
#define POINTER_CONSTRAINTS_UNSTABLE_V1_CLIENT_PROTOCOL_H
#include <stdint.h>
#include <stddef.h>
#include "wayland-client.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @page page_pointer_constraints_unstable_v1 The pointer_constraints_unstable_v1 protocol
* protocol for constraining pointer motions
*
* @section page_desc_pointer_constraints_unstable_v1 Description
*
* This protocol specifies a set of interfaces used for adding constraints to
* the motion of a pointer. Possible constraints include confining pointer
* motions to a given region, or locking it to its current position.
*
* In order to constrain the pointer, a client must first bind the global
* interface "wp_pointer_constraints" which, if a compositor supports pointer
* constraints, is exposed by the registry. Using the bound global object, the
* client uses the request that corresponds to the type of constraint it wants
* to make. See wp_pointer_constraints for more details.
*
* 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_pointer_constraints_unstable_v1 Interfaces
* - @subpage page_iface_zwp_pointer_constraints_v1 - constrain the movement of a pointer
* - @subpage page_iface_zwp_locked_pointer_v1 - receive relative pointer motion events
* - @subpage page_iface_zwp_confined_pointer_v1 - confined pointer object
* @section page_copyright_pointer_constraints_unstable_v1 Copyright
* <pre>
*
* Copyright © 2014 Jonas Ådahl
* Copyright © 2015 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_pointer;
struct wl_region;
struct wl_surface;
struct zwp_confined_pointer_v1;
struct zwp_locked_pointer_v1;
struct zwp_pointer_constraints_v1;
#ifndef ZWP_POINTER_CONSTRAINTS_V1_INTERFACE
#define ZWP_POINTER_CONSTRAINTS_V1_INTERFACE
/**
* @page page_iface_zwp_pointer_constraints_v1 zwp_pointer_constraints_v1
* @section page_iface_zwp_pointer_constraints_v1_desc Description
*
* The global interface exposing pointer constraining functionality. It
* exposes two requests: lock_pointer for locking the pointer to its
* position, and confine_pointer for locking the pointer to a region.
*
* The lock_pointer and confine_pointer requests create the objects
* wp_locked_pointer and wp_confined_pointer respectively, and the client can
* use these objects to interact with the lock.
*
* For any surface, only one lock or confinement may be active across all
* wl_pointer objects of the same seat. If a lock or confinement is requested
* when another lock or confinement is active or requested on the same surface
* and with any of the wl_pointer objects of the same seat, an
* 'already_constrained' error will be raised.
* @section page_iface_zwp_pointer_constraints_v1_api API
* See @ref iface_zwp_pointer_constraints_v1.
*/
/**
* @defgroup iface_zwp_pointer_constraints_v1 The zwp_pointer_constraints_v1 interface
*
* The global interface exposing pointer constraining functionality. It
* exposes two requests: lock_pointer for locking the pointer to its
* position, and confine_pointer for locking the pointer to a region.
*
* The lock_pointer and confine_pointer requests create the objects
* wp_locked_pointer and wp_confined_pointer respectively, and the client can
* use these objects to interact with the lock.
*
* For any surface, only one lock or confinement may be active across all
* wl_pointer objects of the same seat. If a lock or confinement is requested
* when another lock or confinement is active or requested on the same surface
* and with any of the wl_pointer objects of the same seat, an
* 'already_constrained' error will be raised.
*/
extern const struct wl_interface zwp_pointer_constraints_v1_interface;
#endif
#ifndef ZWP_LOCKED_POINTER_V1_INTERFACE
#define ZWP_LOCKED_POINTER_V1_INTERFACE
/**
* @page page_iface_zwp_locked_pointer_v1 zwp_locked_pointer_v1
* @section page_iface_zwp_locked_pointer_v1_desc Description
*
* The wp_locked_pointer interface represents a locked pointer state.
*
* While the lock of this object is active, the wl_pointer objects of the
* associated seat will not emit any wl_pointer.motion events.
*
* This object will send the event 'locked' when the lock is activated.
* Whenever the lock is activated, it is guaranteed that the locked surface
* will already have received pointer focus and that the pointer will be
* within the region passed to the request creating this object.
*
* To unlock the pointer, send the destroy request. This will also destroy
* the wp_locked_pointer object.
*
* If the compositor decides to unlock the pointer the unlocked event is
* sent. See wp_locked_pointer.unlock for details.
*
* When unlocking, the compositor may warp the cursor position to the set
* cursor position hint. If it does, it will not result in any relative
* motion events emitted via wp_relative_pointer.
*
* If the surface the lock was requested on is destroyed and the lock is not
* yet activated, the wp_locked_pointer object is now defunct and must be
* destroyed.
* @section page_iface_zwp_locked_pointer_v1_api API
* See @ref iface_zwp_locked_pointer_v1.
*/
/**
* @defgroup iface_zwp_locked_pointer_v1 The zwp_locked_pointer_v1 interface
*
* The wp_locked_pointer interface represents a locked pointer state.
*
* While the lock of this object is active, the wl_pointer objects of the
* associated seat will not emit any wl_pointer.motion events.
*
* This object will send the event 'locked' when the lock is activated.
* Whenever the lock is activated, it is guaranteed that the locked surface
* will already have received pointer focus and that the pointer will be
* within the region passed to the request creating this object.
*
* To unlock the pointer, send the destroy request. This will also destroy
* the wp_locked_pointer object.
*
* If the compositor decides to unlock the pointer the unlocked event is
* sent. See wp_locked_pointer.unlock for details.
*
* When unlocking, the compositor may warp the cursor position to the set
* cursor position hint. If it does, it will not result in any relative
* motion events emitted via wp_relative_pointer.
*
* If the surface the lock was requested on is destroyed and the lock is not
* yet activated, the wp_locked_pointer object is now defunct and must be
* destroyed.
*/
extern const struct wl_interface zwp_locked_pointer_v1_interface;
#endif
#ifndef ZWP_CONFINED_POINTER_V1_INTERFACE
#define ZWP_CONFINED_POINTER_V1_INTERFACE
/**
* @page page_iface_zwp_confined_pointer_v1 zwp_confined_pointer_v1
* @section page_iface_zwp_confined_pointer_v1_desc Description
*
* The wp_confined_pointer interface represents a confined pointer state.
*
* This object will send the event 'confined' when the confinement is
* activated. Whenever the confinement is activated, it is guaranteed that
* the surface the pointer is confined to will already have received pointer
* focus and that the pointer will be within the region passed to the request
* creating this object. It is up to the compositor to decide whether this
* requires some user interaction and if the pointer will warp to within the
* passed region if outside.
*
* To unconfine the pointer, send the destroy request. This will also destroy
* the wp_confined_pointer object.
*
* If the compositor decides to unconfine the pointer the unconfined event is
* sent. The wp_confined_pointer object is at this point defunct and should
* be destroyed.
* @section page_iface_zwp_confined_pointer_v1_api API
* See @ref iface_zwp_confined_pointer_v1.
*/
/**
* @defgroup iface_zwp_confined_pointer_v1 The zwp_confined_pointer_v1 interface
*
* The wp_confined_pointer interface represents a confined pointer state.
*
* This object will send the event 'confined' when the confinement is
* activated. Whenever the confinement is activated, it is guaranteed that
* the surface the pointer is confined to will already have received pointer
* focus and that the pointer will be within the region passed to the request
* creating this object. It is up to the compositor to decide whether this
* requires some user interaction and if the pointer will warp to within the
* passed region if outside.
*
* To unconfine the pointer, send the destroy request. This will also destroy
* the wp_confined_pointer object.
*
* If the compositor decides to unconfine the pointer the unconfined event is
* sent. The wp_confined_pointer object is at this point defunct and should
* be destroyed.
*/
extern const struct wl_interface zwp_confined_pointer_v1_interface;
#endif
#ifndef ZWP_POINTER_CONSTRAINTS_V1_ERROR_ENUM
#define ZWP_POINTER_CONSTRAINTS_V1_ERROR_ENUM
/**
* @ingroup iface_zwp_pointer_constraints_v1
* wp_pointer_constraints error values
*
* These errors can be emitted in response to wp_pointer_constraints
* requests.
*/
enum zwp_pointer_constraints_v1_error {
/**
* pointer constraint already requested on that surface
*/
ZWP_POINTER_CONSTRAINTS_V1_ERROR_ALREADY_CONSTRAINED = 1,
};
#endif /* ZWP_POINTER_CONSTRAINTS_V1_ERROR_ENUM */
#ifndef ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ENUM
#define ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ENUM
/**
* @ingroup iface_zwp_pointer_constraints_v1
* constraint lifetime
*
* These values represent different lifetime semantics. They are passed
* as arguments to the factory requests to specify how the constraint
* lifetimes should be managed.
*/
enum zwp_pointer_constraints_v1_lifetime {
/**
* the pointer constraint is defunct once deactivated
*
* A oneshot pointer constraint will never reactivate once it has
* been deactivated. See the corresponding deactivation event
* (wp_locked_pointer.unlocked and wp_confined_pointer.unconfined)
* for details.
*/
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT = 1,
/**
* the pointer constraint may reactivate
*
* A persistent pointer constraint may again reactivate once it
* has been deactivated. See the corresponding deactivation event
* (wp_locked_pointer.unlocked and wp_confined_pointer.unconfined)
* for details.
*/
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT = 2,
};
#endif /* ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ENUM */
#define ZWP_POINTER_CONSTRAINTS_V1_DESTROY 0
#define ZWP_POINTER_CONSTRAINTS_V1_LOCK_POINTER 1
#define ZWP_POINTER_CONSTRAINTS_V1_CONFINE_POINTER 2
/**
* @ingroup iface_zwp_pointer_constraints_v1
*/
#define ZWP_POINTER_CONSTRAINTS_V1_DESTROY_SINCE_VERSION 1
/**
* @ingroup iface_zwp_pointer_constraints_v1
*/
#define ZWP_POINTER_CONSTRAINTS_V1_LOCK_POINTER_SINCE_VERSION 1
/**
* @ingroup iface_zwp_pointer_constraints_v1
*/
#define ZWP_POINTER_CONSTRAINTS_V1_CONFINE_POINTER_SINCE_VERSION 1
/** @ingroup iface_zwp_pointer_constraints_v1 */
static inline void
zwp_pointer_constraints_v1_set_user_data(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1, void *user_data)
{
wl_proxy_set_user_data((struct wl_proxy *) zwp_pointer_constraints_v1, user_data);
}
/** @ingroup iface_zwp_pointer_constraints_v1 */
static inline void *
zwp_pointer_constraints_v1_get_user_data(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1)
{
return wl_proxy_get_user_data((struct wl_proxy *) zwp_pointer_constraints_v1);
}
static inline uint32_t
zwp_pointer_constraints_v1_get_version(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1)
{
return wl_proxy_get_version((struct wl_proxy *) zwp_pointer_constraints_v1);
}
/**
* @ingroup iface_zwp_pointer_constraints_v1
*
* Used by the client to notify the server that it will no longer use this
* pointer constraints object.
*/
static inline void
zwp_pointer_constraints_v1_destroy(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1)
{
wl_proxy_marshal_flags((struct wl_proxy *) zwp_pointer_constraints_v1,
ZWP_POINTER_CONSTRAINTS_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_pointer_constraints_v1), WL_MARSHAL_FLAG_DESTROY);
}
/**
* @ingroup iface_zwp_pointer_constraints_v1
*
* The lock_pointer request lets the client request to disable movements of
* the virtual pointer (i.e. the cursor), effectively locking the pointer
* to a position. This request may not take effect immediately; in the
* future, when the compositor deems implementation-specific constraints
* are satisfied, the pointer lock will be activated and the compositor
* sends a locked event.
*
* The protocol provides no guarantee that the constraints are ever
* satisfied, and does not require the compositor to send an error if the
* constraints cannot ever be satisfied. It is thus possible to request a
* lock that will never activate.
*
* There may not be another pointer constraint of any kind requested or
* active on the surface for any of the wl_pointer objects of the seat of
* the passed pointer when requesting a lock. If there is, an error will be
* raised. See general pointer lock documentation for more details.
*
* The intersection of the region passed with this request and the input
* region of the surface is used to determine where the pointer must be
* in order for the lock to activate. It is up to the compositor whether to
* warp the pointer or require some kind of user interaction for the lock
* to activate. If the region is null the surface input region is used.
*
* A surface may receive pointer focus without the lock being activated.
*
* The request creates a new object wp_locked_pointer which is used to
* interact with the lock as well as receive updates about its state. See
* the the description of wp_locked_pointer for further information.
*
* Note that while a pointer is locked, the wl_pointer objects of the
* corresponding seat will not emit any wl_pointer.motion events, but
* relative motion events will still be emitted via wp_relative_pointer
* objects of the same seat. wl_pointer.axis and wl_pointer.button events
* are unaffected.
*/
static inline struct zwp_locked_pointer_v1 *
zwp_pointer_constraints_v1_lock_pointer(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1, struct wl_surface *surface, struct wl_pointer *pointer, struct wl_region *region, uint32_t lifetime)
{
struct wl_proxy *id;
id = wl_proxy_marshal_flags((struct wl_proxy *) zwp_pointer_constraints_v1,
ZWP_POINTER_CONSTRAINTS_V1_LOCK_POINTER, &zwp_locked_pointer_v1_interface, wl_proxy_get_version((struct wl_proxy *) zwp_pointer_constraints_v1), 0, NULL, surface, pointer, region, lifetime);
return (struct zwp_locked_pointer_v1 *) id;
}
/**
* @ingroup iface_zwp_pointer_constraints_v1
*
* The confine_pointer request lets the client request to confine the
* pointer cursor to a given region. This request may not take effect
* immediately; in the future, when the compositor deems implementation-
* specific constraints are satisfied, the pointer confinement will be
* activated and the compositor sends a confined event.
*
* The intersection of the region passed with this request and the input
* region of the surface is used to determine where the pointer must be
* in order for the confinement to activate. It is up to the compositor
* whether to warp the pointer or require some kind of user interaction for
* the confinement to activate. If the region is null the surface input
* region is used.
*
* The request will create a new object wp_confined_pointer which is used
* to interact with the confinement as well as receive updates about its
* state. See the the description of wp_confined_pointer for further
* information.
*/
static inline struct zwp_confined_pointer_v1 *
zwp_pointer_constraints_v1_confine_pointer(struct zwp_pointer_constraints_v1 *zwp_pointer_constraints_v1, struct wl_surface *surface, struct wl_pointer *pointer, struct wl_region *region, uint32_t lifetime)
{
struct wl_proxy *id;
id = wl_proxy_marshal_flags((struct wl_proxy *) zwp_pointer_constraints_v1,
ZWP_POINTER_CONSTRAINTS_V1_CONFINE_POINTER, &zwp_confined_pointer_v1_interface, wl_proxy_get_version((struct wl_proxy *) zwp_pointer_constraints_v1), 0, NULL, surface, pointer, region, lifetime);
return (struct zwp_confined_pointer_v1 *) id;
}
/**
* @ingroup iface_zwp_locked_pointer_v1
* @struct zwp_locked_pointer_v1_listener
*/
struct zwp_locked_pointer_v1_listener {
/**
* lock activation event
*
* Notification that the pointer lock of the seat's pointer is
* activated.
*/
void (*locked)(void *data,
struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1);
/**
* lock deactivation event
*
* Notification that the pointer lock of the seat's pointer is no
* longer active. If this is a oneshot pointer lock (see
* wp_pointer_constraints.lifetime) this object is now defunct and
* should be destroyed. If this is a persistent pointer lock (see
* wp_pointer_constraints.lifetime) this pointer lock may again
* reactivate in the future.
*/
void (*unlocked)(void *data,
struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1);
};
/**
* @ingroup iface_zwp_locked_pointer_v1
*/
static inline int
zwp_locked_pointer_v1_add_listener(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1,
const struct zwp_locked_pointer_v1_listener *listener, void *data)
{
return wl_proxy_add_listener((struct wl_proxy *) zwp_locked_pointer_v1,
(void (**)(void)) listener, data);
}
#define ZWP_LOCKED_POINTER_V1_DESTROY 0
#define ZWP_LOCKED_POINTER_V1_SET_CURSOR_POSITION_HINT 1
#define ZWP_LOCKED_POINTER_V1_SET_REGION 2
/**
* @ingroup iface_zwp_locked_pointer_v1
*/
#define ZWP_LOCKED_POINTER_V1_LOCKED_SINCE_VERSION 1
/**
* @ingroup iface_zwp_locked_pointer_v1
*/
#define ZWP_LOCKED_POINTER_V1_UNLOCKED_SINCE_VERSION 1
/**
* @ingroup iface_zwp_locked_pointer_v1
*/
#define ZWP_LOCKED_POINTER_V1_DESTROY_SINCE_VERSION 1
/**
* @ingroup iface_zwp_locked_pointer_v1
*/
#define ZWP_LOCKED_POINTER_V1_SET_CURSOR_POSITION_HINT_SINCE_VERSION 1
/**
* @ingroup iface_zwp_locked_pointer_v1
*/
#define ZWP_LOCKED_POINTER_V1_SET_REGION_SINCE_VERSION 1
/** @ingroup iface_zwp_locked_pointer_v1 */
static inline void
zwp_locked_pointer_v1_set_user_data(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1, void *user_data)
{
wl_proxy_set_user_data((struct wl_proxy *) zwp_locked_pointer_v1, user_data);
}
/** @ingroup iface_zwp_locked_pointer_v1 */
static inline void *
zwp_locked_pointer_v1_get_user_data(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1)
{
return wl_proxy_get_user_data((struct wl_proxy *) zwp_locked_pointer_v1);
}
static inline uint32_t
zwp_locked_pointer_v1_get_version(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1)
{
return wl_proxy_get_version((struct wl_proxy *) zwp_locked_pointer_v1);
}
/**
* @ingroup iface_zwp_locked_pointer_v1
*
* Destroy the locked pointer object. If applicable, the compositor will
* unlock the pointer.
*/
static inline void
zwp_locked_pointer_v1_destroy(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1)
{
wl_proxy_marshal_flags((struct wl_proxy *) zwp_locked_pointer_v1,
ZWP_LOCKED_POINTER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_locked_pointer_v1), WL_MARSHAL_FLAG_DESTROY);
}
/**
* @ingroup iface_zwp_locked_pointer_v1
*
* Set the cursor position hint relative to the top left corner of the
* surface.
*
* If the client is drawing its own cursor, it should update the position
* hint to the position of its own cursor. A compositor may use this
* information to warp the pointer upon unlock in order to avoid pointer
* jumps.
*
* The cursor position hint is double buffered. The new hint will only take
* effect when the associated surface gets it pending state applied. See
* wl_surface.commit for details.
*/
static inline void
zwp_locked_pointer_v1_set_cursor_position_hint(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1, wl_fixed_t surface_x, wl_fixed_t surface_y)
{
wl_proxy_marshal_flags((struct wl_proxy *) zwp_locked_pointer_v1,
ZWP_LOCKED_POINTER_V1_SET_CURSOR_POSITION_HINT, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_locked_pointer_v1), 0, surface_x, surface_y);
}
/**
* @ingroup iface_zwp_locked_pointer_v1
*
* Set a new region used to lock the pointer.
*
* The new lock region is double-buffered. The new lock region will
* only take effect when the associated surface gets its pending state
* applied. See wl_surface.commit for details.
*
* For details about the lock region, see wp_locked_pointer.
*/
static inline void
zwp_locked_pointer_v1_set_region(struct zwp_locked_pointer_v1 *zwp_locked_pointer_v1, struct wl_region *region)
{
wl_proxy_marshal_flags((struct wl_proxy *) zwp_locked_pointer_v1,
ZWP_LOCKED_POINTER_V1_SET_REGION, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_locked_pointer_v1), 0, region);
}
/**
* @ingroup iface_zwp_confined_pointer_v1
* @struct zwp_confined_pointer_v1_listener
*/
struct zwp_confined_pointer_v1_listener {
/**
* pointer confined
*
* Notification that the pointer confinement of the seat's
* pointer is activated.
*/
void (*confined)(void *data,
struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1);
/**
* pointer unconfined
*
* Notification that the pointer confinement of the seat's
* pointer is no longer active. If this is a oneshot pointer
* confinement (see wp_pointer_constraints.lifetime) this object is
* now defunct and should be destroyed. If this is a persistent
* pointer confinement (see wp_pointer_constraints.lifetime) this
* pointer confinement may again reactivate in the future.
*/
void (*unconfined)(void *data,
struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1);
};
/**
* @ingroup iface_zwp_confined_pointer_v1
*/
static inline int
zwp_confined_pointer_v1_add_listener(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1,
const struct zwp_confined_pointer_v1_listener *listener, void *data)
{
return wl_proxy_add_listener((struct wl_proxy *) zwp_confined_pointer_v1,
(void (**)(void)) listener, data);
}
#define ZWP_CONFINED_POINTER_V1_DESTROY 0
#define ZWP_CONFINED_POINTER_V1_SET_REGION 1
/**
* @ingroup iface_zwp_confined_pointer_v1
*/
#define ZWP_CONFINED_POINTER_V1_CONFINED_SINCE_VERSION 1
/**
* @ingroup iface_zwp_confined_pointer_v1
*/
#define ZWP_CONFINED_POINTER_V1_UNCONFINED_SINCE_VERSION 1
/**
* @ingroup iface_zwp_confined_pointer_v1
*/
#define ZWP_CONFINED_POINTER_V1_DESTROY_SINCE_VERSION 1
/**
* @ingroup iface_zwp_confined_pointer_v1
*/
#define ZWP_CONFINED_POINTER_V1_SET_REGION_SINCE_VERSION 1
/** @ingroup iface_zwp_confined_pointer_v1 */
static inline void
zwp_confined_pointer_v1_set_user_data(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1, void *user_data)
{
wl_proxy_set_user_data((struct wl_proxy *) zwp_confined_pointer_v1, user_data);
}
/** @ingroup iface_zwp_confined_pointer_v1 */
static inline void *
zwp_confined_pointer_v1_get_user_data(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1)
{
return wl_proxy_get_user_data((struct wl_proxy *) zwp_confined_pointer_v1);
}
static inline uint32_t
zwp_confined_pointer_v1_get_version(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1)
{
return wl_proxy_get_version((struct wl_proxy *) zwp_confined_pointer_v1);
}
/**
* @ingroup iface_zwp_confined_pointer_v1
*
* Destroy the confined pointer object. If applicable, the compositor will
* unconfine the pointer.
*/
static inline void
zwp_confined_pointer_v1_destroy(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1)
{
wl_proxy_marshal_flags((struct wl_proxy *) zwp_confined_pointer_v1,
ZWP_CONFINED_POINTER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_confined_pointer_v1), WL_MARSHAL_FLAG_DESTROY);
}
/**
* @ingroup iface_zwp_confined_pointer_v1
*
* Set a new region used to confine the pointer.
*
* The new confine region is double-buffered. The new confine region will
* only take effect when the associated surface gets its pending state
* applied. See wl_surface.commit for details.
*
* If the confinement is active when the new confinement region is applied
* and the pointer ends up outside of newly applied region, the pointer may
* warped to a position within the new confinement region. If warped, a
* wl_pointer.motion event will be emitted, but no
* wp_relative_pointer.relative_motion event.
*
* The compositor may also, instead of using the new region, unconfine the
* pointer.
*
* For details about the confine region, see wp_confined_pointer.
*/
static inline void
zwp_confined_pointer_v1_set_region(struct zwp_confined_pointer_v1 *zwp_confined_pointer_v1, struct wl_region *region)
{
wl_proxy_marshal_flags((struct wl_proxy *) zwp_confined_pointer_v1,
ZWP_CONFINED_POINTER_V1_SET_REGION, NULL, wl_proxy_get_version((struct wl_proxy *) zwp_confined_pointer_v1), 0, region);
}
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,66 @@
/* Generated by wayland-scanner 1.23.0 */
/*
* Copyright © 2018 Simon Ser
*
* 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 <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include "wayland-util.h"
extern const struct wl_interface xdg_toplevel_interface;
extern const struct wl_interface zxdg_toplevel_decoration_v1_interface;
static const struct wl_interface *xdg_decoration_unstable_v1_types[] = {
NULL,
&zxdg_toplevel_decoration_v1_interface,
&xdg_toplevel_interface,
};
static const struct wl_message zxdg_decoration_manager_v1_requests[] = {
{ "destroy", "", xdg_decoration_unstable_v1_types + 0 },
{ "get_toplevel_decoration", "no", xdg_decoration_unstable_v1_types + 1 },
};
WL_EXPORT const struct wl_interface zxdg_decoration_manager_v1_interface = {
"zxdg_decoration_manager_v1", 1,
2, zxdg_decoration_manager_v1_requests,
0, NULL,
};
static const struct wl_message zxdg_toplevel_decoration_v1_requests[] = {
{ "destroy", "", xdg_decoration_unstable_v1_types + 0 },
{ "set_mode", "u", xdg_decoration_unstable_v1_types + 0 },
{ "unset_mode", "", xdg_decoration_unstable_v1_types + 0 },
};
static const struct wl_message zxdg_toplevel_decoration_v1_events[] = {
{ "configure", "u", xdg_decoration_unstable_v1_types + 0 },
};
WL_EXPORT const struct wl_interface zxdg_toplevel_decoration_v1_interface = {
"zxdg_toplevel_decoration_v1", 1,
3, zxdg_toplevel_decoration_v1_requests,
1, zxdg_toplevel_decoration_v1_events,
};

View file

@ -0,0 +1,377 @@
/* Generated by wayland-scanner 1.23.0 */
#ifndef XDG_DECORATION_UNSTABLE_V1_CLIENT_PROTOCOL_H
#define XDG_DECORATION_UNSTABLE_V1_CLIENT_PROTOCOL_H
#include <stdint.h>
#include <stddef.h>
#include "wayland-client.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @page page_xdg_decoration_unstable_v1 The xdg_decoration_unstable_v1 protocol
* @section page_ifaces_xdg_decoration_unstable_v1 Interfaces
* - @subpage page_iface_zxdg_decoration_manager_v1 - window decoration manager
* - @subpage page_iface_zxdg_toplevel_decoration_v1 - decoration object for a toplevel surface
* @section page_copyright_xdg_decoration_unstable_v1 Copyright
* <pre>
*
* Copyright © 2018 Simon Ser
*
* 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 xdg_toplevel;
struct zxdg_decoration_manager_v1;
struct zxdg_toplevel_decoration_v1;
#ifndef ZXDG_DECORATION_MANAGER_V1_INTERFACE
#define ZXDG_DECORATION_MANAGER_V1_INTERFACE
/**
* @page page_iface_zxdg_decoration_manager_v1 zxdg_decoration_manager_v1
* @section page_iface_zxdg_decoration_manager_v1_desc Description
*
* This interface allows a compositor to announce support for server-side
* decorations.
*
* A window decoration is a set of window controls as deemed appropriate by
* the party managing them, such as user interface components used to move,
* resize and change a window's state.
*
* A client can use this protocol to request being decorated by a supporting
* compositor.
*
* If compositor and client do not negotiate the use of a server-side
* decoration using this protocol, clients continue to self-decorate as they
* see fit.
*
* 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_iface_zxdg_decoration_manager_v1_api API
* See @ref iface_zxdg_decoration_manager_v1.
*/
/**
* @defgroup iface_zxdg_decoration_manager_v1 The zxdg_decoration_manager_v1 interface
*
* This interface allows a compositor to announce support for server-side
* decorations.
*
* A window decoration is a set of window controls as deemed appropriate by
* the party managing them, such as user interface components used to move,
* resize and change a window's state.
*
* A client can use this protocol to request being decorated by a supporting
* compositor.
*
* If compositor and client do not negotiate the use of a server-side
* decoration using this protocol, clients continue to self-decorate as they
* see fit.
*
* 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.
*/
extern const struct wl_interface zxdg_decoration_manager_v1_interface;
#endif
#ifndef ZXDG_TOPLEVEL_DECORATION_V1_INTERFACE
#define ZXDG_TOPLEVEL_DECORATION_V1_INTERFACE
/**
* @page page_iface_zxdg_toplevel_decoration_v1 zxdg_toplevel_decoration_v1
* @section page_iface_zxdg_toplevel_decoration_v1_desc Description
*
* The decoration object allows the compositor to toggle server-side window
* decorations for a toplevel surface. The client can request to switch to
* another mode.
*
* The xdg_toplevel_decoration object must be destroyed before its
* xdg_toplevel.
* @section page_iface_zxdg_toplevel_decoration_v1_api API
* See @ref iface_zxdg_toplevel_decoration_v1.
*/
/**
* @defgroup iface_zxdg_toplevel_decoration_v1 The zxdg_toplevel_decoration_v1 interface
*
* The decoration object allows the compositor to toggle server-side window
* decorations for a toplevel surface. The client can request to switch to
* another mode.
*
* The xdg_toplevel_decoration object must be destroyed before its
* xdg_toplevel.
*/
extern const struct wl_interface zxdg_toplevel_decoration_v1_interface;
#endif
#define ZXDG_DECORATION_MANAGER_V1_DESTROY 0
#define ZXDG_DECORATION_MANAGER_V1_GET_TOPLEVEL_DECORATION 1
/**
* @ingroup iface_zxdg_decoration_manager_v1
*/
#define ZXDG_DECORATION_MANAGER_V1_DESTROY_SINCE_VERSION 1
/**
* @ingroup iface_zxdg_decoration_manager_v1
*/
#define ZXDG_DECORATION_MANAGER_V1_GET_TOPLEVEL_DECORATION_SINCE_VERSION 1
/** @ingroup iface_zxdg_decoration_manager_v1 */
static inline void
zxdg_decoration_manager_v1_set_user_data(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1, void *user_data)
{
wl_proxy_set_user_data((struct wl_proxy *) zxdg_decoration_manager_v1, user_data);
}
/** @ingroup iface_zxdg_decoration_manager_v1 */
static inline void *
zxdg_decoration_manager_v1_get_user_data(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1)
{
return wl_proxy_get_user_data((struct wl_proxy *) zxdg_decoration_manager_v1);
}
static inline uint32_t
zxdg_decoration_manager_v1_get_version(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1)
{
return wl_proxy_get_version((struct wl_proxy *) zxdg_decoration_manager_v1);
}
/**
* @ingroup iface_zxdg_decoration_manager_v1
*
* Destroy the decoration manager. This doesn't destroy objects created
* with the manager.
*/
static inline void
zxdg_decoration_manager_v1_destroy(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1)
{
wl_proxy_marshal_flags((struct wl_proxy *) zxdg_decoration_manager_v1,
ZXDG_DECORATION_MANAGER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_decoration_manager_v1), WL_MARSHAL_FLAG_DESTROY);
}
/**
* @ingroup iface_zxdg_decoration_manager_v1
*
* Create a new decoration object associated with the given toplevel.
*
* Creating an xdg_toplevel_decoration from an xdg_toplevel which has a
* buffer attached or committed is a client error, and any attempts by a
* client to attach or manipulate a buffer prior to the first
* xdg_toplevel_decoration.configure event must also be treated as
* errors.
*/
static inline struct zxdg_toplevel_decoration_v1 *
zxdg_decoration_manager_v1_get_toplevel_decoration(struct zxdg_decoration_manager_v1 *zxdg_decoration_manager_v1, struct xdg_toplevel *toplevel)
{
struct wl_proxy *id;
id = wl_proxy_marshal_flags((struct wl_proxy *) zxdg_decoration_manager_v1,
ZXDG_DECORATION_MANAGER_V1_GET_TOPLEVEL_DECORATION, &zxdg_toplevel_decoration_v1_interface, wl_proxy_get_version((struct wl_proxy *) zxdg_decoration_manager_v1), 0, NULL, toplevel);
return (struct zxdg_toplevel_decoration_v1 *) id;
}
#ifndef ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ENUM
#define ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ENUM
enum zxdg_toplevel_decoration_v1_error {
/**
* xdg_toplevel has a buffer attached before configure
*/
ZXDG_TOPLEVEL_DECORATION_V1_ERROR_UNCONFIGURED_BUFFER = 0,
/**
* xdg_toplevel already has a decoration object
*/
ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ALREADY_CONSTRUCTED = 1,
/**
* xdg_toplevel destroyed before the decoration object
*/
ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ORPHANED = 2,
};
#endif /* ZXDG_TOPLEVEL_DECORATION_V1_ERROR_ENUM */
#ifndef ZXDG_TOPLEVEL_DECORATION_V1_MODE_ENUM
#define ZXDG_TOPLEVEL_DECORATION_V1_MODE_ENUM
/**
* @ingroup iface_zxdg_toplevel_decoration_v1
* window decoration modes
*
* These values describe window decoration modes.
*/
enum zxdg_toplevel_decoration_v1_mode {
/**
* no server-side window decoration
*/
ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE = 1,
/**
* server-side window decoration
*/
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE = 2,
};
#endif /* ZXDG_TOPLEVEL_DECORATION_V1_MODE_ENUM */
/**
* @ingroup iface_zxdg_toplevel_decoration_v1
* @struct zxdg_toplevel_decoration_v1_listener
*/
struct zxdg_toplevel_decoration_v1_listener {
/**
* notify a decoration mode change
*
* The configure event configures the effective decoration mode.
* The configured state should not be applied immediately. Clients
* must send an ack_configure in response to this event. See
* xdg_surface.configure and xdg_surface.ack_configure for details.
*
* A configure event can be sent at any time. The specified mode
* must be obeyed by the client.
* @param mode the decoration mode
*/
void (*configure)(void *data,
struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1,
uint32_t mode);
};
/**
* @ingroup iface_zxdg_toplevel_decoration_v1
*/
static inline int
zxdg_toplevel_decoration_v1_add_listener(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1,
const struct zxdg_toplevel_decoration_v1_listener *listener, void *data)
{
return wl_proxy_add_listener((struct wl_proxy *) zxdg_toplevel_decoration_v1,
(void (**)(void)) listener, data);
}
#define ZXDG_TOPLEVEL_DECORATION_V1_DESTROY 0
#define ZXDG_TOPLEVEL_DECORATION_V1_SET_MODE 1
#define ZXDG_TOPLEVEL_DECORATION_V1_UNSET_MODE 2
/**
* @ingroup iface_zxdg_toplevel_decoration_v1
*/
#define ZXDG_TOPLEVEL_DECORATION_V1_CONFIGURE_SINCE_VERSION 1
/**
* @ingroup iface_zxdg_toplevel_decoration_v1
*/
#define ZXDG_TOPLEVEL_DECORATION_V1_DESTROY_SINCE_VERSION 1
/**
* @ingroup iface_zxdg_toplevel_decoration_v1
*/
#define ZXDG_TOPLEVEL_DECORATION_V1_SET_MODE_SINCE_VERSION 1
/**
* @ingroup iface_zxdg_toplevel_decoration_v1
*/
#define ZXDG_TOPLEVEL_DECORATION_V1_UNSET_MODE_SINCE_VERSION 1
/** @ingroup iface_zxdg_toplevel_decoration_v1 */
static inline void
zxdg_toplevel_decoration_v1_set_user_data(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, void *user_data)
{
wl_proxy_set_user_data((struct wl_proxy *) zxdg_toplevel_decoration_v1, user_data);
}
/** @ingroup iface_zxdg_toplevel_decoration_v1 */
static inline void *
zxdg_toplevel_decoration_v1_get_user_data(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1)
{
return wl_proxy_get_user_data((struct wl_proxy *) zxdg_toplevel_decoration_v1);
}
static inline uint32_t
zxdg_toplevel_decoration_v1_get_version(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1)
{
return wl_proxy_get_version((struct wl_proxy *) zxdg_toplevel_decoration_v1);
}
/**
* @ingroup iface_zxdg_toplevel_decoration_v1
*
* Switch back to a mode without any server-side decorations at the next
* commit.
*/
static inline void
zxdg_toplevel_decoration_v1_destroy(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1)
{
wl_proxy_marshal_flags((struct wl_proxy *) zxdg_toplevel_decoration_v1,
ZXDG_TOPLEVEL_DECORATION_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_toplevel_decoration_v1), WL_MARSHAL_FLAG_DESTROY);
}
/**
* @ingroup iface_zxdg_toplevel_decoration_v1
*
* Set the toplevel surface decoration mode. This informs the compositor
* that the client prefers the provided decoration mode.
*
* After requesting a decoration mode, the compositor will respond by
* emitting an xdg_surface.configure event. The client should then update
* its content, drawing it without decorations if the received mode is
* server-side decorations. The client must also acknowledge the configure
* when committing the new content (see xdg_surface.ack_configure).
*
* The compositor can decide not to use the client's mode and enforce a
* different mode instead.
*
* Clients whose decoration mode depend on the xdg_toplevel state may send
* a set_mode request in response to an xdg_surface.configure event and wait
* for the next xdg_surface.configure event to prevent unwanted state.
* Such clients are responsible for preventing configure loops and must
* make sure not to send multiple successive set_mode requests with the
* same decoration mode.
*/
static inline void
zxdg_toplevel_decoration_v1_set_mode(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1, uint32_t mode)
{
wl_proxy_marshal_flags((struct wl_proxy *) zxdg_toplevel_decoration_v1,
ZXDG_TOPLEVEL_DECORATION_V1_SET_MODE, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_toplevel_decoration_v1), 0, mode);
}
/**
* @ingroup iface_zxdg_toplevel_decoration_v1
*
* Unset the toplevel surface decoration mode. This informs the compositor
* that the client doesn't prefer a particular decoration mode.
*
* This request has the same semantics as set_mode.
*/
static inline void
zxdg_toplevel_decoration_v1_unset_mode(struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1)
{
wl_proxy_marshal_flags((struct wl_proxy *) zxdg_toplevel_decoration_v1,
ZXDG_TOPLEVEL_DECORATION_V1_UNSET_MODE, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_toplevel_decoration_v1), 0);
}
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,174 @@
/* Generated by wayland-scanner 1.23.0 */
/*
* Copyright © 2008-2013 Kristian Høgsberg
* Copyright © 2013 Rafael Antognolli
* Copyright © 2013 Jasper St. Pierre
* Copyright © 2010-2013 Intel Corporation
* Copyright © 2015-2017 Samsung Electronics Co., Ltd
* Copyright © 2015-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 <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include "wayland-util.h"
extern const struct wl_interface wl_output_interface;
extern const struct wl_interface wl_seat_interface;
extern const struct wl_interface wl_surface_interface;
extern const struct wl_interface xdg_popup_interface;
extern const struct wl_interface xdg_positioner_interface;
extern const struct wl_interface xdg_surface_interface;
extern const struct wl_interface xdg_toplevel_interface;
static const struct wl_interface *xdg_shell_types[] = {
NULL,
NULL,
NULL,
NULL,
&xdg_positioner_interface,
&xdg_surface_interface,
&wl_surface_interface,
&xdg_toplevel_interface,
&xdg_popup_interface,
&xdg_surface_interface,
&xdg_positioner_interface,
&xdg_toplevel_interface,
&wl_seat_interface,
NULL,
NULL,
NULL,
&wl_seat_interface,
NULL,
&wl_seat_interface,
NULL,
NULL,
&wl_output_interface,
&wl_seat_interface,
NULL,
&xdg_positioner_interface,
NULL,
};
static const struct wl_message xdg_wm_base_requests[] = {
{ "destroy", "", xdg_shell_types + 0 },
{ "create_positioner", "n", xdg_shell_types + 4 },
{ "get_xdg_surface", "no", xdg_shell_types + 5 },
{ "pong", "u", xdg_shell_types + 0 },
};
static const struct wl_message xdg_wm_base_events[] = {
{ "ping", "u", xdg_shell_types + 0 },
};
WL_EXPORT const struct wl_interface xdg_wm_base_interface = {
"xdg_wm_base", 6,
4, xdg_wm_base_requests,
1, xdg_wm_base_events,
};
static const struct wl_message xdg_positioner_requests[] = {
{ "destroy", "", xdg_shell_types + 0 },
{ "set_size", "ii", xdg_shell_types + 0 },
{ "set_anchor_rect", "iiii", xdg_shell_types + 0 },
{ "set_anchor", "u", xdg_shell_types + 0 },
{ "set_gravity", "u", xdg_shell_types + 0 },
{ "set_constraint_adjustment", "u", xdg_shell_types + 0 },
{ "set_offset", "ii", xdg_shell_types + 0 },
{ "set_reactive", "3", xdg_shell_types + 0 },
{ "set_parent_size", "3ii", xdg_shell_types + 0 },
{ "set_parent_configure", "3u", xdg_shell_types + 0 },
};
WL_EXPORT const struct wl_interface xdg_positioner_interface = {
"xdg_positioner", 6,
10, xdg_positioner_requests,
0, NULL,
};
static const struct wl_message xdg_surface_requests[] = {
{ "destroy", "", xdg_shell_types + 0 },
{ "get_toplevel", "n", xdg_shell_types + 7 },
{ "get_popup", "n?oo", xdg_shell_types + 8 },
{ "set_window_geometry", "iiii", xdg_shell_types + 0 },
{ "ack_configure", "u", xdg_shell_types + 0 },
};
static const struct wl_message xdg_surface_events[] = {
{ "configure", "u", xdg_shell_types + 0 },
};
WL_EXPORT const struct wl_interface xdg_surface_interface = {
"xdg_surface", 6,
5, xdg_surface_requests,
1, xdg_surface_events,
};
static const struct wl_message xdg_toplevel_requests[] = {
{ "destroy", "", xdg_shell_types + 0 },
{ "set_parent", "?o", xdg_shell_types + 11 },
{ "set_title", "s", xdg_shell_types + 0 },
{ "set_app_id", "s", xdg_shell_types + 0 },
{ "show_window_menu", "ouii", xdg_shell_types + 12 },
{ "move", "ou", xdg_shell_types + 16 },
{ "resize", "ouu", xdg_shell_types + 18 },
{ "set_max_size", "ii", xdg_shell_types + 0 },
{ "set_min_size", "ii", xdg_shell_types + 0 },
{ "set_maximized", "", xdg_shell_types + 0 },
{ "unset_maximized", "", xdg_shell_types + 0 },
{ "set_fullscreen", "?o", xdg_shell_types + 21 },
{ "unset_fullscreen", "", xdg_shell_types + 0 },
{ "set_minimized", "", xdg_shell_types + 0 },
};
static const struct wl_message xdg_toplevel_events[] = {
{ "configure", "iia", xdg_shell_types + 0 },
{ "close", "", xdg_shell_types + 0 },
{ "configure_bounds", "4ii", xdg_shell_types + 0 },
{ "wm_capabilities", "5a", xdg_shell_types + 0 },
};
WL_EXPORT const struct wl_interface xdg_toplevel_interface = {
"xdg_toplevel", 6,
14, xdg_toplevel_requests,
4, xdg_toplevel_events,
};
static const struct wl_message xdg_popup_requests[] = {
{ "destroy", "", xdg_shell_types + 0 },
{ "grab", "ou", xdg_shell_types + 22 },
{ "reposition", "3ou", xdg_shell_types + 24 },
};
static const struct wl_message xdg_popup_events[] = {
{ "configure", "iiii", xdg_shell_types + 0 },
{ "popup_done", "", xdg_shell_types + 0 },
{ "repositioned", "3u", xdg_shell_types + 0 },
};
WL_EXPORT const struct wl_interface xdg_popup_interface = {
"xdg_popup", 6,
3, xdg_popup_requests,
3, xdg_popup_events,
};

File diff suppressed because it is too large Load diff

986
src/cmd/devdraw/wayland.c Normal file
View file

@ -0,0 +1,986 @@
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <memdraw.h>
#include <memlayer.h>
#include <keyboard.h>
#include <mouse.h>
#include <cursor.h>
#include <thread.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/input-event-codes.h>
#include <wayland-client.h>
#include <xkbcommon/xkbcommon.h>
#include "bigarrow.h"
#include "devdraw.h"
#include "wayland-pointer-constraints.h"
#include "wayland-xdg-decoration.h"
#include "wayland-xdg-shell.h"
// alt+click and ctl+click are mapped to mouse buttons
// to support single button mice.
#define ALT_BUTTON 1
#define CTL_BUTTON 2
struct WaylandBuffer {
int w;
int h;
int size;
char *data;
struct wl_buffer* wl_buffer;
};
typedef struct WaylandBuffer WaylandBuffer;
struct WaylandClient {
// The screen image written to by the client, and read by this driver.
Memimage *memimage;
// The current mouse coordinates and a bitmask of held buttons.
int mouse_x;
int mouse_y;
int buttons;
// Booleans indicating whether control or alt are currently held.
int ctl;
int alt;
// State for key repeat for keyboard keys.
int repeat_rune;
int repeat_next_ms;
// State for "key repeat" for the mouse scroll wheel.
// This allows touchpad devices to have accelerated scrolling.
int repeat_scroll_button;
int repeat_scroll_count;
int repeat_scroll_rate_ms;
int repeat_scroll_next_ms;
// The Wayland surface for this window
// and its corresponding xdg objects.
struct wl_surface *wl_surface;
struct xdg_surface *xdg_surface;
struct xdg_toplevel *xdg_toplevel;
// A callback when wl_surface is ready for the next frame.
// Currently this is not used for drawing,
// but as a hack for implementing key repeat
// without needing to implement our own timer thread/events.
struct wl_callback *wl_callback;
// The mouse pointer and the surface for the current cursor.
struct wl_pointer *wl_pointer;
struct wl_surface *wl_surface_cursor;
// The keyboard and xkb state used
// for mapping scan codes to key codes.
struct wl_keyboard *wl_keyboard;
struct xkb_context *xkb_context;
struct xkb_keymap *xkb_keymap;
struct xkb_state *xkb_state;
};
typedef struct WaylandClient WaylandClient;
static QLock wayland_lock;
// Required globals wayland objects.
static struct wl_display *wl_display;
static struct wl_output *wl_output;
static struct wl_registry *wl_registry;
static struct wl_shm *wl_shm;
static struct wl_compositor *wl_compositor;
static struct xdg_wm_base *xdg_wm_base;
static struct wl_seat *wl_seat;
// Optional global wayland objects.
// Need to NULL check them before using.
static struct zxdg_decoration_manager_v1 *decoration_manager;
static struct zwp_pointer_constraints_v1 *pointer_constraints;
// The wl output scale factor reported by wl_output.
// We only set it if we get th event before entering the graphics loop.
// Once we enter the loop, we never change it to avoid the need
// to reason about which scale a buffer was created with.
int wl_output_scale_factor = 1;
int entered_gfx_loop = 0;
// The delay in ms which a key must be held to begin repeating..
int key_repeat_delay_ms = 500;
// The number of ms between repeats of a repeating key.
int key_repeat_ms = 100;
// The maximum number of ms between repeats of a scroll.
// This is scaled by the number of repeating scrolls pending.
int scroll_repeat_ms = 100;
// A pool of xrgb888 buffers used for drawing to the screen.
// When drawing, we give ownership of the buffer's memory to the compositor.
// The compositor notifies us asynchronously when it is done reading the buffer.
// In the case that we need to draw (rpc_flush) before the buffer is ready,
// we will need to allocate a whole new buffer to draw to.
// We use this pool to avoid the need to setup a new shared memory buffer
// each time this happens.
#define N_XRGB8888_BUFFERS 3
struct WaylandBuffer *xrgb8888_buffers[N_XRGB8888_BUFFERS];
int wayland_debug = 0;
#define DEBUG(...) \
do { \
if (wayland_debug) { \
fprint(2, __VA_ARGS__); \
} \
} while(0)
static void registry_global(void *data, struct wl_registry *wl_registry,
uint32_t name, const char *interface, uint32_t version) {
if (strcmp(interface, wl_output_interface.name) == 0) {
wl_output = wl_registry_bind(wl_registry, name, &wl_output_interface, 2);
} else if (strcmp(interface, wl_shm_interface.name) == 0) {
wl_shm = wl_registry_bind(wl_registry, name, &wl_shm_interface, 1);
} else if (strcmp(interface, wl_compositor_interface.name) == 0) {
wl_compositor = wl_registry_bind(wl_registry, name,
&wl_compositor_interface, 4);
} else if (strcmp(interface, xdg_wm_base_interface.name) == 0) {
xdg_wm_base = wl_registry_bind(wl_registry, name,
&xdg_wm_base_interface, 1);
} else if (strcmp(interface, wl_seat_interface.name) == 0) {
wl_seat = wl_registry_bind(wl_registry, name, &wl_seat_interface, 1);
} else if (strcmp(interface, zxdg_decoration_manager_v1_interface.name) == 0) {
decoration_manager = wl_registry_bind(wl_registry, name,
&zxdg_decoration_manager_v1_interface, 1);
} else if (strcmp(interface, zwp_pointer_constraints_v1_interface.name) == 0) {
pointer_constraints = wl_registry_bind(wl_registry, name,
&zwp_pointer_constraints_v1_interface, 1);
}
}
static void registry_global_remove(void *data, struct wl_registry *wl_registry,
uint32_t name) {}
static const struct wl_registry_listener wl_registry_listener = {
.global = registry_global,
.global_remove = registry_global_remove,
};
void wl_output_geometry(void *data, struct wl_output *wl_output,
int32_t x, int32_t y, int32_t physical_width, int32_t physical_height,
int32_t subpixel, const char *make, const char *model, int32_t transform) {}
void wl_output_mode(void *data, struct wl_output *wl_output, uint32_t flags,
int32_t width, int32_t height, int32_t refresh) {}
void wl_output_done(void *data, struct wl_output *wl_output) {}
void wl_output_scale(void *data, struct wl_output *wl_output, int32_t factor) {
DEBUG("wl_output_scale(factor=%d)\n", factor);
qlock(&wayland_lock);
if (!entered_gfx_loop) {
wl_output_scale_factor = factor;
}
qunlock(&wayland_lock);
}
static const struct wl_output_listener wl_output_listener = {
.geometry = wl_output_geometry,
.mode = wl_output_mode,
.done = wl_output_done,
.scale = wl_output_scale,
};
static void xdg_wm_base_ping(void *data, struct xdg_wm_base *xdg_wm_base, uint32_t serial) {
xdg_wm_base_pong(xdg_wm_base, serial);
}
static const struct xdg_wm_base_listener xdg_wm_base_listener = {
.ping = xdg_wm_base_ping,
};
void delete_buffer(WaylandBuffer *b) {
munmap(b->data, b->size);
wl_buffer_destroy(b->wl_buffer);
free(b);
}
static void wl_buffer_release(void *data, struct wl_buffer *wl_buffer) {
if (data == NULL) {
wl_buffer_destroy(wl_buffer);
return;
}
for (int i = 0; i < N_XRGB8888_BUFFERS; i++) {
if (xrgb8888_buffers[i] == NULL) {
xrgb8888_buffers[i] = (WaylandBuffer*) data;
return;
}
}
delete_buffer((WaylandBuffer*) data);
}
static const struct wl_buffer_listener wl_buffer_listener = {
.release = wl_buffer_release,
};
static void xdg_surface_configure(void *data, struct xdg_surface *xdg_surface, uint32_t serial) {
DEBUG("xdg_surface_configure\n");
const Client* c = data;
const WaylandClient *wl = c->view;
qlock(&wayland_lock);
xdg_surface_ack_configure(wl->xdg_surface, serial);
qunlock(&wayland_lock);
DEBUG("xdg_surface_configure: returned\n");
}
static const struct xdg_surface_listener xdg_surface_listener = {
.configure = xdg_surface_configure,
};
void xdg_toplevel_configure(void *data, struct xdg_toplevel *xdg_toplevel,
int32_t width, int32_t height, struct wl_array *states) {
DEBUG("xdg_toplevel_configure(width=%d, height=%d)\n", width, height);
if (width == 0 || height == 0) {
return;
}
Client* c = data;
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
width *= wl_output_scale_factor;
height *= wl_output_scale_factor;
Rectangle r = Rect(0, 0, width, height);
if (eqrect(r, wl->memimage->r)) {
// The size didn't change, so nothing to do.
qunlock(&wayland_lock);
return;
}
// The size changed, so allocate a new Memimage and notify the client.
wl->memimage = _allocmemimage(r, XRGB32);
c->mouserect = r;
qunlock(&wayland_lock);
gfx_replacescreenimage(c, wl->memimage);
}
void xdg_toplevel_close(void *data, struct xdg_toplevel *xdg_toplevel) {
DEBUG("xdg_toplevel_close\n");
threadexitsall(nil);
}
static const struct xdg_toplevel_listener xdg_toplevel_listener = {
.configure = xdg_toplevel_configure,
.close = xdg_toplevel_close,
};
static const struct wl_callback_listener wl_callback_listener;
// The callback is called per-frame.
// It is currently only used to implement key repeat.
static void wl_callback_done(void *data, struct wl_callback *wl_callback, uint32_t time) {
Client* c = data;
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
// Request another callback for the next frame.
// TODO: Only request a callback if we are still repeating a key.
wl_callback_destroy(wl_callback);
wl_callback = wl_surface_frame(wl->wl_surface);
wl_callback_add_listener(wl_callback, &wl_callback_listener, c);
wl_surface_commit(wl->wl_surface);
int repeat_rune = 0;
if (wl->repeat_rune && time >= wl->repeat_next_ms) {
repeat_rune = wl->repeat_rune;
wl->repeat_next_ms = time + key_repeat_ms;
}
int x = wl->mouse_x;
int y = wl->mouse_y;
int repeat_scroll_button = 0;
if (wl->repeat_scroll_button && time >= wl->repeat_scroll_next_ms) {
repeat_scroll_button = wl->repeat_scroll_button | wl->buttons;
wl->repeat_scroll_count--;
if (wl->repeat_scroll_count == 0) {
wl->repeat_scroll_button = 0;
}
wl->repeat_scroll_next_ms = time + scroll_repeat_ms/wl->repeat_scroll_count;
}
qunlock(&wayland_lock);
if (repeat_rune) {
gfx_keystroke(c, repeat_rune);
}
if (repeat_scroll_button) {
gfx_mousetrack(c, x, y, repeat_scroll_button, (uint) time);
}
}
static const struct wl_callback_listener wl_callback_listener = {
.done = wl_callback_done,
};
void wl_pointer_enter(void *data,struct wl_pointer *wl_pointer, uint32_t serial,
struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
Client* c = data;
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
wl->mouse_x = wl_fixed_to_int(surface_x) * wl_output_scale_factor;
wl->mouse_y = wl_fixed_to_int(surface_y) * wl_output_scale_factor;
wl_pointer_set_cursor(wl->wl_pointer, serial, wl->wl_surface_cursor, 0, 0);
qunlock(&wayland_lock);
// We don't call gfx_mousetrack here, since we don't have the time.
}
void wl_pointer_leave(void *data, struct wl_pointer *wl_pointer,
uint32_t serial, struct wl_surface *surface) {
Client* c = data;
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
wl->buttons = 0;
wl->repeat_scroll_button = 0;
qunlock(&wayland_lock);
}
void wl_pointer_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time,
wl_fixed_t surface_x, wl_fixed_t surface_y){
Client* c = data;
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
wl->repeat_scroll_button = 0;
wl->repeat_scroll_count = 0;
wl->mouse_x = wl_fixed_to_int(surface_x) * wl_output_scale_factor;
wl->mouse_y = wl_fixed_to_int(surface_y) * wl_output_scale_factor;
int x = wl->mouse_x;
int y = wl->mouse_y;
int b = wl->buttons;
qunlock(&wayland_lock);
gfx_mousetrack(c, x, y, b, (uint) time);
}
void wl_pointer_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial,
uint32_t time, uint32_t button, uint32_t state) {
DEBUG("wl_pointer_button(button=%d)\n", (int) button);
Client* c = data;
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
wl->repeat_scroll_button = 0;
wl->repeat_scroll_count = 0;
int mask = 0;
switch (button) {
case BTN_LEFT:
mask = 1<<0;
break;
case BTN_MIDDLE:
mask = 1<<1;
break;
case BTN_RIGHT:
mask = 1<<2;
break;
case BTN_4:
mask = 1<<3;
break;
case BTN_5:
mask = 1<<4;
break;
default:
DEBUG("wl_pointer_button: unknown button: %d\n", button);
qunlock(&wayland_lock);
return;
}
if (button == BTN_LEFT) {
if (wl->ctl) {
mask = 1 << CTL_BUTTON;
} else if (wl->alt) {
mask = 1 << ALT_BUTTON;
}
}
DEBUG("wl_pointer_button: mask=%x\n", mask);
switch (state) {
case WL_POINTER_BUTTON_STATE_PRESSED:
wl->buttons |= mask;
break;
case WL_POINTER_BUTTON_STATE_RELEASED:
wl->buttons &= ~mask;
break;
default:
fprint(2, "Unknown button state: %d\n", state);
}
int x = wl->mouse_x;
int y = wl->mouse_y;
int b = wl->buttons;
qunlock(&wayland_lock);
DEBUG("wl_pointer_button: gfx_trackmouse(x=%d, y=%d, b=%d)\n", x, y, b);
gfx_mousetrack(c, x, y, b, (uint) time);
}
void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time,
uint32_t axis, wl_fixed_t value_fixed) {
double value = wl_fixed_to_double(value_fixed);
Client* c = data;
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
int x = wl->mouse_x;
int y = wl->mouse_y;
wl->repeat_scroll_button = 0;
wl->repeat_scroll_count = 0;
int b = 0;
if (value < 0) {
b |= 1 << 3;
} else if (value > 0) {
b |= 1 << 4;
}
int mag = fabs(value);
if (mag > 1) {
wl->repeat_scroll_button = b;
wl->repeat_scroll_count = mag;
wl->repeat_scroll_next_ms = time + scroll_repeat_ms/wl->repeat_scroll_count;
}
b |= wl->buttons;
qunlock(&wayland_lock);
gfx_mousetrack(c, x, y, b, (uint) time);
}
static const struct wl_pointer_listener pointer_listener = {
.enter = wl_pointer_enter,
.leave = wl_pointer_leave,
.motion = wl_pointer_motion,
.button = wl_pointer_button,
.axis = wl_pointer_axis,
};
void wl_keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
uint32_t format, int32_t fd, uint32_t size) {
DEBUG("wl_keyboard_keymap\n");
char *keymap = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
Client* c = data;
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
if (wl->xkb_keymap != NULL) {
xkb_keymap_unref(wl->xkb_keymap);
}
wl->xkb_keymap = xkb_keymap_new_from_string(wl->xkb_context, keymap,
XKB_KEYMAP_FORMAT_TEXT_V1,
XKB_KEYMAP_COMPILE_NO_FLAGS);
if (wl->xkb_state != NULL) {
xkb_state_unref(wl->xkb_state);
}
wl->xkb_state = xkb_state_new(wl->xkb_keymap);
qunlock(&wayland_lock);
munmap(keymap, size);
close(fd);
}
void wl_keyboard_enter(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, struct wl_surface *surface, struct wl_array *keys) {
DEBUG("wl_keyboard_enter\n");
}
void wl_keyboard_leave(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, struct wl_surface *surface) {
DEBUG("wl_keyboard_leave\n");
Client* c = data;
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
wl->ctl = 0;
wl->alt = 0;
wl->repeat_rune = 0;
qunlock(&wayland_lock);
}
void wl_keyboard_key(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, uint32_t time, uint32_t key, uint32_t state) {
Client* c = data;
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
wl->repeat_rune = 0;
wl->repeat_scroll_button = 0;
wl->repeat_scroll_count = 0;
key += 8; // Add 8 to translate Linux scan code to xkb code.
uint32_t rune = xkb_state_key_get_utf32(wl->xkb_state, key);
xkb_keysym_t keysym = xkb_state_key_get_one_sym(wl->xkb_state, key);
if (wayland_debug) {
char name[256];
xkb_keysym_get_name(keysym, &name[0], 256);
char *state_str = WL_KEYBOARD_KEY_STATE_PRESSED ? "down" : "up";
DEBUG("wl_keyboard_key: keysym=%s, rune=0x%x, state=%s\n",
name, rune, state_str);
}
switch (keysym) {
case XKB_KEY_Return:
rune = '\n';
break;
case XKB_KEY_Alt_L:
case XKB_KEY_Alt_R:
rune = Kalt;
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
wl->alt = 1;
} else {
wl->alt = 0;
}
if (wl->buttons) {
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
wl->buttons |= 1 << ALT_BUTTON;
} else {
wl->buttons &= ~(1 << ALT_BUTTON);
}
int x = wl->mouse_x;
int y = wl->mouse_y;
int b = wl->buttons;
qunlock(&wayland_lock);
gfx_mousetrack(c, x, y, b, (uint) time);
return;
}
break;
case XKB_KEY_Control_L:
case XKB_KEY_Control_R:
// For some reason, Kctl is not used;
// it results in drawing a replacement character.
// Common ctl combos still work.
// For example ctl+w sends rune 0x17
// which erases the previous word.
rune = 0; // Kctl;
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
wl->ctl = 1;
} else {
wl->ctl = 0;
}
if (wl->buttons) {
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
wl->buttons |= 1 << CTL_BUTTON;
} else {
wl->buttons &= ~(1 << CTL_BUTTON);
}
int x = wl->mouse_x;
int y = wl->mouse_y;
int b = wl->buttons;
qunlock(&wayland_lock);
gfx_mousetrack(c, x, y, b, (uint) time);
return;
}
break;
case XKB_KEY_Delete:
rune = Kdel;
break;
case XKB_KEY_Escape:
rune = Kesc;
break;
case XKB_KEY_Home:
rune = Khome;
break;
case XKB_KEY_End:
rune = Kend;
break;
case XKB_KEY_Prior:
rune = Kpgup;
break;
case XKB_KEY_Next:
rune = Kpgdown;
break;
case XKB_KEY_Up:
rune = Kup;
break;
case XKB_KEY_Down:
rune = Kdown;
break;
case XKB_KEY_Left:
rune = Kleft;
break;
case XKB_KEY_Right:
rune = Kright;
break;
}
qunlock(&wayland_lock);
if (state == WL_KEYBOARD_KEY_STATE_PRESSED && rune != 0) {
wl->repeat_rune = rune;
wl->repeat_next_ms = time + key_repeat_delay_ms;
gfx_keystroke(c, rune);
}
}
void wl_keyboard_modifiers(void *data, struct wl_keyboard *wl_keyboard,
uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched,
uint32_t mods_locked, uint32_t group) {
DEBUG("wl_keyboard_modifiers\n");
Client* c = data;
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
xkb_state_update_mask(wl->xkb_state, mods_depressed,
mods_latched, mods_locked, 0, 0, group);
qunlock(&wayland_lock);
}
// TODO: Use this to set key repeat.
// Currently we don't bind the keyboard with the correct version to get this event.
void wl_keyboard_repeat_info(void *data, struct wl_keyboard *wl_keyboard,
int32_t rate, int32_t delay) {
DEBUG("wl_keyboard_repeat_info(rate=%d, delay=%d)\n",
(int) rate, (int) delay);
}
static const struct wl_keyboard_listener keyboard_listener = {
.keymap = wl_keyboard_keymap,
.enter = wl_keyboard_enter,
.leave = wl_keyboard_leave,
.key = wl_keyboard_key,
.modifiers = wl_keyboard_modifiers,
.repeat_info = wl_keyboard_repeat_info,
};
void gfx_main(void) {
DEBUG("gfx_main called\n");
wl_display = wl_display_connect(NULL);
wl_registry = wl_display_get_registry(wl_display);
wl_registry_add_listener(wl_registry, &wl_registry_listener, NULL);
wl_display_roundtrip(wl_display);
// Ensure required globals were correctly bound.
if (wl_display == NULL) {
sysfatal("Unable to get Wayland display");
}
if (wl_registry == NULL) {
sysfatal("Unable to get Wayland registry");
}
if (wl_output == NULL) {
sysfatal("Unable to bind wl_output");
}
if (wl_shm == NULL) {
sysfatal("Unable to bind wl_shm");
}
if (wl_compositor == NULL) {
sysfatal("Unable to bind wl_compositor");
}
if (xdg_wm_base == NULL) {
sysfatal("Unable to bind xdg_wm_base");
}
if (wl_seat == NULL) {
sysfatal("Unable to bind wl_seat");
}
wl_output_add_listener(wl_output, &wl_output_listener, NULL);
xdg_wm_base_add_listener(xdg_wm_base, &xdg_wm_base_listener, NULL);
wl_display_roundtrip(wl_display);
entered_gfx_loop = 1;
gfx_started();
DEBUG("gfx_main: entering loop\n");
while (wl_display_dispatch(wl_display))
;
}
static void rpc_resizeimg(Client*) {
DEBUG("rpc_resizeimg\n");
}
static void rpc_resizewindow(Client*, Rectangle) {
DEBUG("rpc_resizewindow\n");
}
static int next_shm = 0;
WaylandBuffer *new_buffer(int w, int h, int format) {
int stride = w * 4;
int size = stride * h;
// Create an anonymous shared memory file.
char name[128];
snprintf(name, 128, "/acme_wl_shm-%d-%d", getpid(), next_shm++);
int fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
if (fd < 0) {
sysfatal("shm_open failed");
}
shm_unlink(name);
// Set the file's size.
int ret;
do {
ret = ftruncate(fd, size);
} while (ret < 0 && errno == EINTR);
if (ret < 0) {
sysfatal("ftruncate failed");
}
char *d = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (d == MAP_FAILED) {
sysfatal("mmap failed");
}
WaylandBuffer *b = malloc(sizeof(WaylandBuffer));
b->w = w;
b->h = h;
b->size = size;
b->data = d;
struct wl_shm_pool *p = wl_shm_create_pool(wl_shm, fd, size);
b->wl_buffer = wl_shm_pool_create_buffer(p, 0, w, h, stride, format);
wl_shm_pool_destroy(p);
close(fd);
return b;
}
void wayland_set_cursor(WaylandClient *wl, Cursor *cursor) {
// Convert bitmap to ARGB.
// Yes, this is super clunky. Sorry about that.
const uint32_t fg = 0xFF000000;
const uint32_t a = 0x00FFFFFF;
uint32_t data[8*32];
int j = 0;
for (int i = 0; i < 32; i++) {
char c = cursor->set[i];
data[j++] = (c >>7) & 1 == 1 ? fg : a;
data[j++] = (c >> 6) & 1 == 1 ? fg : a;
data[j++] = (c >> 5) & 1 == 1 ? fg : a;
data[j++] = (c >> 4) & 1 == 1 ? fg : a;
data[j++] = (c >> 3) & 1 == 1 ? fg : a;
data[j++] = (c >> 2) & 1 == 1 ? fg : a;
data[j++] = (c >> 1) & 1 == 1 ? fg : a;
data[j++] = (c >> 0) & 1 == 1 ? fg : a;
}
WaylandBuffer *b = new_buffer(16, 16, WL_SHM_FORMAT_ARGB8888);
memcpy(b->data, (char*) &data[0], b->size);
// We don't want to bother saving this buffer in xrgb8888_buffers.
// Unmap and use NULL for it's listener data.
// This will cause it to be destroyed when it is released.
munmap(b->data, b->size);
wl_buffer_add_listener(b->wl_buffer, &wl_buffer_listener, NULL);
wl_surface_attach(wl->wl_surface_cursor, b->wl_buffer, 0, 0);
wl_surface_damage_buffer(wl->wl_surface_cursor, 0, 0, 16, 16);
wl_surface_commit(wl->wl_surface_cursor);
}
static void rpc_setcursor(Client *c, Cursor *cursor, Cursor2*) {
DEBUG("rpc_setcursor\n");
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
if (cursor == NULL) {
cursor = &bigarrow;
}
wayland_set_cursor(wl, cursor);
qunlock(&wayland_lock);
}
static void rpc_setlabel(Client *c, char *label) {
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
xdg_toplevel_set_title(wl->xdg_toplevel, label);
qunlock(&wayland_lock);
}
static void rpc_setmouse(Client *c, Point p) {
if (pointer_constraints == NULL) {
// If there is no pointer constraints extension,
// we cannot warp the mouse.
return;
}
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
// Wayland does not directly support warping the pointer.
// Instead, we use (misuse?) the pointer constraints extension,
// which allows sending the compositor a new pointer location
// hint when the pointer is unlocked.
// We lock the pointer, and immediately unlock it with a hint
// of the desired wrap location.
struct zwp_locked_pointer_v1 *lock = zwp_pointer_constraints_v1_lock_pointer(
pointer_constraints, wl->wl_surface, wl->wl_pointer, NULL,
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_PERSISTENT);
int x = wl_fixed_from_int(p.x / wl_output_scale_factor);
int y = wl_fixed_from_int(p.y / wl_output_scale_factor);
zwp_locked_pointer_v1_set_cursor_position_hint(lock, x, y);
wl_surface_commit(wl->wl_surface);
zwp_locked_pointer_v1_destroy(lock);
qunlock(&wayland_lock);
}
static void rpc_topwin(Client*) {
DEBUG("rpc_topwin\n");
}
static void rpc_bouncemouse(Client*, Mouse) {
DEBUG("rpc_bouncemouse\n");
}
// Must be called with the lock held.
WaylandBuffer *get_xrgb8888_buffer(int w, int h) {
for (int i = 0; i < N_XRGB8888_BUFFERS; i++) {
if (xrgb8888_buffers[i] == NULL) {
continue;
}
// Delete any cached buffers that are not the right size.
if (xrgb8888_buffers[i]->w != w || xrgb8888_buffers[i]->h != h) {
delete_buffer(xrgb8888_buffers[i]);
xrgb8888_buffers[i] = NULL;
continue;
}
WaylandBuffer *b = xrgb8888_buffers[i];
xrgb8888_buffers[i] = NULL;
return b;
}
WaylandBuffer *b = new_buffer(w, h, WL_SHM_FORMAT_XRGB8888);
wl_buffer_add_listener(b->wl_buffer, &wl_buffer_listener, b);
return b;
}
static void rpc_flush(Client *c, Rectangle r) {
WaylandClient *wl = (WaylandClient*) c->view;
qlock(&wayland_lock);
int w = Dx(wl->memimage->r);
int h = Dy(wl->memimage->r);
WaylandBuffer *b = get_xrgb8888_buffer(w, h);
memcpy(b->data, (char*) wl->memimage->data->bdata, b->size);
wl_surface_attach(wl->wl_surface, b->wl_buffer, 0, 0);
wl_surface_damage_buffer(wl->wl_surface, r.min.x, r.min.y, Dx(r), Dy(r));
wl_surface_commit(wl->wl_surface);
wl_display_flush(wl_display);
qunlock(&wayland_lock);
}
static ClientImpl wayland_impl = {
rpc_resizeimg,
rpc_resizewindow,
rpc_setcursor,
rpc_setlabel,
rpc_setmouse,
rpc_topwin,
rpc_bouncemouse,
rpc_flush
};
Memimage *rpc_attach(Client *c, char *label, char *winsize) {
DEBUG("rpc_attach(%s)\n", label);
qlock(&wayland_lock);
WaylandClient *wl = calloc(1, sizeof(WaylandClient));
c->impl = &wayland_impl;
c->view = wl;
wl->wl_surface = wl_compositor_create_surface(wl_compositor);
wl->xdg_surface = xdg_wm_base_get_xdg_surface(xdg_wm_base, wl->wl_surface);
xdg_surface_add_listener(wl->xdg_surface, &xdg_surface_listener, c);
wl->xdg_toplevel = xdg_surface_get_toplevel(wl->xdg_surface);
xdg_toplevel_add_listener(wl->xdg_toplevel, &xdg_toplevel_listener, c);
xdg_toplevel_set_title(wl->xdg_toplevel, label);
wl->wl_callback = wl_surface_frame(wl->wl_surface);
wl_callback_add_listener(wl->wl_callback, &wl_callback_listener, c);
wl->wl_pointer = wl_seat_get_pointer(wl_seat);
wl_pointer_add_listener(wl->wl_pointer, &pointer_listener, c);
wl->wl_surface_cursor = wl_compositor_create_surface(wl_compositor);
wayland_set_cursor(wl, &bigarrow);
wl->wl_keyboard = wl_seat_get_keyboard(wl_seat);
wl_keyboard_add_listener(wl->wl_keyboard, &keyboard_listener, c);
wl->xkb_context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
// If the xdg decorations extension is available,
// enable server-side decorations.
// Otherwise there will be no window decorations
// (title, resize, buttons, etc.).
if (decoration_manager != NULL) {
struct zxdg_toplevel_decoration_v1 *d =
zxdg_decoration_manager_v1_get_toplevel_decoration(
decoration_manager, wl->xdg_toplevel);
zxdg_toplevel_decoration_v1_set_mode(d,
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
}
// TODO: parse winsize.
int w = 640*wl_output_scale_factor;
int h = 480*wl_output_scale_factor;
Rectangle r = Rect(0, 0, w, h);
wl->memimage = _allocmemimage(r, XRGB32);
c->mouserect = r;
c->displaydpi = 110 * wl_output_scale_factor;
wl_surface_set_buffer_scale(wl->wl_surface, wl_output_scale_factor);
wl_surface_commit(wl->wl_surface);
qunlock(&wayland_lock);
return wl->memimage;
}
char *rpc_getsnarf(void) {
DEBUG("rpc_getsnarf\n");
return NULL;
}
void rpc_putsnarf(char*) {
DEBUG("rpc_putsnarf\n");
}
void rpc_shutdown(void) {
DEBUG("rpc_shutdown\n");
}
void rpc_gfxdrawlock(void) {
qlock(&wayland_lock);
}
void rpc_gfxdrawunlock(void) {
qunlock(&wayland_lock);
}
int cloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) {
return _cloadmemimage(i, r, data, ndata);
}
int loadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) {
return _loadmemimage(i, r, data, ndata);
}
int unloadmemimage(Memimage *i, Rectangle r, uchar *data, int ndata) {
return _unloadmemimage(i, r, data, ndata);
}

View file

@ -1,6 +1,6 @@
<$PLAN9/src/mkhdr
<|osxvers
<|sh ../devdraw/mkwsysrules.sh
<|sh mkwsysrules.sh
<|sh freetyperules.sh $WSYSTYPE $X11H
TARG=fontsrv

View file

@ -0,0 +1,63 @@
#!/bin/sh
[ -f $PLAN9/config ] && . $PLAN9/config
if [ "x$X11" = "x" ]; then
if [ -d /usr/X11R6 ]; then
X11=/usr/X11R6
elif [ -d /usr/local/X11R6 ]; then
X11=/usr/local/X11R6
elif [ -d /usr/X11R7 ]; then
X11=/usr/X11R7
elif [ -d /usr/X ]; then
X11=/usr/X
elif [ -d /usr/openwin ]; then # for Sun
X11=/usr/openwin
elif [ -d /usr/include/X11 ]; then
X11=/usr
elif [ -d /usr/local/include/X11 ]; then
X11=/usr/local
else
X11=noX11dir
fi
fi
if [ "x$WSYSTYPE" = "x" ]; then
if [ "x`uname`" = "xDarwin" ]; then
if sw_vers | egrep 'ProductVersion: (10\.[0-9]\.|10\.1[012])$' >/dev/null; then
echo 1>&2 'OS X 10.12 and older are not supported'
exit 1
fi
WSYSTYPE=mac
elif [ -d "$X11" ]; then
WSYSTYPE=x11
else
WSYSTYPE=nowsys
fi
fi
if [ "x$WSYSTYPE" = "xx11" -a "x$X11H" = "x" ]; then
if [ -d "$X11/include" ]; then
X11H="-I$X11/include"
else
X11H=""
fi
fi
echo 'WSYSTYPE='$WSYSTYPE
echo 'X11='$X11
echo 'X11H='$X11H
if [ $WSYSTYPE = x11 ]; then
echo 'CFLAGS=$CFLAGS '$X11H
echo 'HFILES=$HFILES $XHFILES'
XO=`ls x11-*.c 2>/dev/null | sed 's/\.c$/.o/'`
echo 'WSYSOFILES=$WSYSOFILES '$XO
echo 'WSYSHFILES=x11-inc.h x11-keysym2ucs.h x11-memdraw.h'
elif [ $WSYSTYPE = mac ]; then
echo 'WSYSOFILES=$WSYSOFILES mac-draw.o mac-screen.o'
echo 'WSYSHFILES='
echo 'MACARGV=macargv.o'
elif [ $WSYSTYPE = nowsys ]; then
echo 'WSYSOFILES=nowsys.o'
fi