Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
pirvi-public
glfw
Commits
25204b1e
Commit
25204b1e
authored
Sep 09, 2014
by
Ricardo Vieira
Committed by
Camilla Berglund
Sep 09, 2014
Browse files
wayland: Support for setting a cursor image
Closes #346.
parent
8d170c7f
Changes
4
Hide whitespace changes
Inline
Side-by-side
CMake/modules/FindWayland.cmake
View file @
25204b1e
...
...
@@ -27,21 +27,23 @@ IF (NOT WIN32)
# Use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
FIND_PACKAGE
(
PkgConfig
)
PKG_CHECK_MODULES
(
PKG_WAYLAND QUIET wayland-client wayland-server wayland-egl
)
PKG_CHECK_MODULES
(
PKG_WAYLAND QUIET wayland-client wayland-server wayland-egl
wayland-cursor
)
SET
(
WAYLAND_DEFINITIONS
${
PKG_WAYLAND_CFLAGS
}
)
FIND_PATH
(
WAYLAND_CLIENT_INCLUDE_DIR NAMES wayland-client.h HINTS
${
PKG_WAYLAND_INCLUDE_DIRS
}
)
FIND_PATH
(
WAYLAND_SERVER_INCLUDE_DIR NAMES wayland-server.h HINTS
${
PKG_WAYLAND_INCLUDE_DIRS
}
)
FIND_PATH
(
WAYLAND_EGL_INCLUDE_DIR NAMES wayland-egl.h HINTS
${
PKG_WAYLAND_INCLUDE_DIRS
}
)
FIND_PATH
(
WAYLAND_CURSOR_INCLUDE_DIR NAMES wayland-cursor.h HINTS
${
PKG_WAYLAND_INCLUDE_DIRS
}
)
FIND_LIBRARY
(
WAYLAND_CLIENT_LIBRARIES NAMES wayland-client HINTS
${
PKG_WAYLAND_LIBRARY_DIRS
}
)
FIND_LIBRARY
(
WAYLAND_SERVER_LIBRARIES NAMES wayland-server HINTS
${
PKG_WAYLAND_LIBRARY_DIRS
}
)
FIND_LIBRARY
(
WAYLAND_EGL_LIBRARIES NAMES wayland-egl HINTS
${
PKG_WAYLAND_LIBRARY_DIRS
}
)
FIND_LIBRARY
(
WAYLAND_CURSOR_LIBRARIES NAMES wayland-cursor HINTS
${
PKG_WAYLAND_LIBRARY_DIRS
}
)
set
(
WAYLAND_INCLUDE_DIR
${
WAYLAND_CLIENT_INCLUDE_DIR
}
${
WAYLAND_SERVER_INCLUDE_DIR
}
${
WAYLAND_EGL_INCLUDE_DIR
}
)
set
(
WAYLAND_INCLUDE_DIR
${
WAYLAND_CLIENT_INCLUDE_DIR
}
${
WAYLAND_SERVER_INCLUDE_DIR
}
${
WAYLAND_EGL_INCLUDE_DIR
}
${
WAYLAND_CURSOR_INCLUDE_DIR
}
)
set
(
WAYLAND_LIBRARIES
${
WAYLAND_CLIENT_LIBRARIES
}
${
WAYLAND_SERVER_LIBRARIES
}
${
WAYLAND_EGL_LIBRARIES
}
)
set
(
WAYLAND_LIBRARIES
${
WAYLAND_CLIENT_LIBRARIES
}
${
WAYLAND_SERVER_LIBRARIES
}
${
WAYLAND_EGL_LIBRARIES
}
${
WAYLAND_CURSOR_LIBRARIES
}
)
list
(
REMOVE_DUPLICATES WAYLAND_INCLUDE_DIR
)
...
...
@@ -50,6 +52,7 @@ IF (NOT WIN32)
FIND_PACKAGE_HANDLE_STANDARD_ARGS
(
WAYLAND_CLIENT DEFAULT_MSG WAYLAND_CLIENT_LIBRARIES WAYLAND_CLIENT_INCLUDE_DIR
)
FIND_PACKAGE_HANDLE_STANDARD_ARGS
(
WAYLAND_SERVER DEFAULT_MSG WAYLAND_SERVER_LIBRARIES WAYLAND_SERVER_INCLUDE_DIR
)
FIND_PACKAGE_HANDLE_STANDARD_ARGS
(
WAYLAND_EGL DEFAULT_MSG WAYLAND_EGL_LIBRARIES WAYLAND_EGL_INCLUDE_DIR
)
FIND_PACKAGE_HANDLE_STANDARD_ARGS
(
WAYLAND_EGL DEFAULT_MSG WAYLAND_CURSOR_LIBRARIES WAYLAND_CURSOR_INCLUDE_DIR
)
FIND_PACKAGE_HANDLE_STANDARD_ARGS
(
WAYLAND DEFAULT_MSG WAYLAND_LIBRARIES WAYLAND_INCLUDE_DIR
)
MARK_AS_ADVANCED
(
...
...
@@ -57,6 +60,7 @@ IF (NOT WIN32)
WAYLAND_CLIENT_INCLUDE_DIR WAYLAND_CLIENT_LIBRARIES
WAYLAND_SERVER_INCLUDE_DIR WAYLAND_SERVER_LIBRARIES
WAYLAND_EGL_INCLUDE_DIR WAYLAND_EGL_LIBRARIES
WAYLAND_CURSOR_INCLUDE_DIR WAYLAND_CURSOR_LIBRARIES
)
ENDIF
()
src/wl_init.c
View file @
25204b1e
...
...
@@ -46,7 +46,10 @@ static void pointerHandleEnter(void* data,
{
_GLFWwindow
*
window
=
wl_surface_get_user_data
(
surface
);
_glfw
.
wl
.
pointerSerial
=
serial
;
_glfw
.
wl
.
pointerFocus
=
window
;
_glfwPlatformSetCursor
(
window
,
window
->
wl
.
currentCursor
);
_glfwInputCursorEnter
(
window
,
GL_TRUE
);
}
...
...
@@ -60,6 +63,7 @@ static void pointerHandleLeave(void* data,
if
(
!
window
)
return
;
_glfw
.
wl
.
pointerSerial
=
serial
;
_glfw
.
wl
.
pointerFocus
=
NULL
;
_glfwInputCursorEnter
(
window
,
GL_FALSE
);
}
...
...
@@ -491,6 +495,11 @@ static void registryHandleGlobal(void* data,
_glfw
.
wl
.
compositor
=
wl_registry_bind
(
registry
,
name
,
&
wl_compositor_interface
,
1
);
}
else
if
(
strcmp
(
interface
,
"wl_shm"
)
==
0
)
{
_glfw
.
wl
.
shm
=
wl_registry_bind
(
registry
,
name
,
&
wl_shm_interface
,
1
);
}
else
if
(
strcmp
(
interface
,
"wl_shell"
)
==
0
)
{
_glfw
.
wl
.
shell
=
...
...
@@ -564,6 +573,20 @@ int _glfwPlatformInit(void)
_glfwInitTimer
();
_glfwInitJoysticks
();
if
(
_glfw
.
wl
.
pointer
&&
_glfw
.
wl
.
shm
){
_glfw
.
wl
.
cursorTheme
=
wl_cursor_theme_load
(
NULL
,
24
,
_glfw
.
wl
.
shm
);
if
(
!
_glfw
.
wl
.
cursorTheme
)
{
_glfwInputError
(
GLFW_PLATFORM_ERROR
,
"Wayland: Unable to load default cursor theme
\n
"
);
return
GL_FALSE
;
}
_glfw
.
wl
.
defaultCursor
=
wl_cursor_theme_get_cursor
(
_glfw
.
wl
.
cursorTheme
,
"left_ptr"
);
if
(
!
_glfw
.
wl
.
defaultCursor
)
{
_glfwInputError
(
GLFW_PLATFORM_ERROR
,
"Wayland: Unable to load default left pointer
\n
"
);
return
GL_FALSE
;
}
_glfw
.
wl
.
cursorSurface
=
wl_compositor_create_surface
(
_glfw
.
wl
.
compositor
);
}
return
GL_TRUE
;
}
...
...
@@ -571,6 +594,10 @@ void _glfwPlatformTerminate(void)
{
_glfwTerminateContextAPI
();
if
(
_glfw
.
wl
.
cursorTheme
)
wl_cursor_theme_destroy
(
_glfw
.
wl
.
cursorTheme
);
if
(
_glfw
.
wl
.
cursorSurface
)
wl_surface_destroy
(
_glfw
.
wl
.
cursorSurface
);
if
(
_glfw
.
wl
.
registry
)
wl_registry_destroy
(
_glfw
.
wl
.
registry
);
if
(
_glfw
.
wl
.
display
)
...
...
src/wl_platform.h
View file @
25204b1e
...
...
@@ -66,7 +66,7 @@ typedef struct _GLFWwindowWayland
struct
wl_shell_surface
*
shell_surface
;
EGLSurface
egl_surface
;
struct
wl_callback
*
callback
;
_GLFWcursor
*
currentCursor
;
}
_GLFWwindowWayland
;
...
...
@@ -78,10 +78,16 @@ typedef struct _GLFWlibraryWayland
struct
wl_registry
*
registry
;
struct
wl_compositor
*
compositor
;
struct
wl_shell
*
shell
;
struct
wl_shm
*
shm
;
struct
wl_seat
*
seat
;
struct
wl_pointer
*
pointer
;
struct
wl_keyboard
*
keyboard
;
struct
wl_cursor_theme
*
cursorTheme
;
struct
wl_cursor
*
defaultCursor
;
struct
wl_surface
*
cursorSurface
;
uint32_t
pointerSerial
;
_GLFWmonitor
**
monitors
;
int
monitorsCount
;
int
monitorsSize
;
...
...
@@ -124,8 +130,9 @@ typedef struct _GLFWmonitorWayland
//
typedef
struct
_GLFWcursorWayland
{
int
dummy
;
struct
wl_buffer
*
buffer
;
int
width
,
height
;
int
xhot
,
yhot
;
}
_GLFWcursorWayland
;
...
...
src/wl_window.c
View file @
25204b1e
...
...
@@ -27,9 +27,16 @@
#include
"internal.h"
#include
<stdio.h>
#include
<stdlib.h>
#include
<errno.h>
#include
<unistd.h>
#include
<string.h>
#include
<fcntl.h>
#include
<sys/mman.h>
#include
<poll.h>
#include
<GL/gl.h>
#include
<wayland-egl.h>
#include
<wayland-cursor.h>
static
void
handlePing
(
void
*
data
,
...
...
@@ -93,6 +100,105 @@ static GLboolean createSurface(_GLFWwindow* window,
return
GL_TRUE
;
}
static
int
set_cloexec_or_close
(
int
fd
)
{
long
flags
;
if
(
fd
==
-
1
)
return
-
1
;
flags
=
fcntl
(
fd
,
F_GETFD
);
if
(
flags
==
-
1
)
goto
err
;
if
(
fcntl
(
fd
,
F_SETFD
,
flags
|
FD_CLOEXEC
)
==
-
1
)
goto
err
;
return
fd
;
err:
close
(
fd
);
return
-
1
;
}
static
int
create_tmpfile_cloexec
(
char
*
tmpname
)
{
int
fd
;
#ifdef HAVE_MKOSTEMP
fd
=
mkostemp
(
tmpname
,
O_CLOEXEC
);
if
(
fd
>=
0
)
unlink
(
tmpname
);
#else
fd
=
mkstemp
(
tmpname
);
if
(
fd
>=
0
)
{
fd
=
set_cloexec_or_close
(
fd
);
unlink
(
tmpname
);
}
#endif
return
fd
;
}
/*
* Create a new, unique, anonymous file of the given size, and
* return the file descriptor for it. The file descriptor is set
* CLOEXEC. The file is immediately suitable for mmap()'ing
* the given size at offset zero.
*
* The file should not have a permanent backing store like a disk,
* but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
*
* The file name is deleted from the file system.
*
* The file is suitable for buffer sharing between processes by
* transmitting the file descriptor over Unix sockets using the
* SCM_RIGHTS methods.
*
* If the C library implements posix_fallocate(), it is used to
* guarantee that disk space is available for the file at the
* given size. If disk space is insufficent, errno is set to ENOSPC.
* If posix_fallocate() is not supported, program may receive
* SIGBUS on accessing mmap()'ed file contents instead.
*/
int
os_create_anonymous_file
(
off_t
size
)
{
static
const
char
template
[]
=
"/glfw-shared-XXXXXX"
;
const
char
*
path
;
char
*
name
;
int
fd
;
int
ret
;
path
=
getenv
(
"XDG_RUNTIME_DIR"
);
if
(
!
path
)
{
errno
=
ENOENT
;
return
-
1
;
}
name
=
malloc
(
strlen
(
path
)
+
sizeof
(
template
));
if
(
!
name
)
return
-
1
;
strcpy
(
name
,
path
);
strcat
(
name
,
template
);
fd
=
create_tmpfile_cloexec
(
name
);
free
(
name
);
if
(
fd
<
0
)
return
-
1
;
ret
=
posix_fallocate
(
fd
,
0
,
size
);
if
(
ret
!=
0
)
{
close
(
fd
);
errno
=
ret
;
return
-
1
;
}
return
fd
;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
...
...
@@ -122,6 +228,8 @@ int _glfwPlatformCreateWindow(_GLFWwindow* window,
wl_shell_surface_set_toplevel
(
window
->
wl
.
shell_surface
);
}
window
->
wl
.
currentCursor
=
NULL
;
return
GL_TRUE
;
}
...
...
@@ -279,37 +387,116 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
void
_glfwPlatformApplyCursorMode
(
_GLFWwindow
*
window
)
{
fprintf
(
stderr
,
"_glfwPlatformApplyCursorMode not implemented yet
\n
"
);
switch
(
window
->
cursorMode
)
{
case
GLFW_CURSOR_NORMAL
:
// TODO: enable showing cursor
break
;
case
GLFW_CURSOR_HIDDEN
:
// TODO: enable not showing cursor
break
;
case
GLFW_CURSOR_DISABLED
:
// TODO: enable pointer lock and hide cursor
break
;
}
_glfwPlatformSetCursor
(
window
,
window
->
wl
.
currentCursor
);
}
int
_glfwPlatformCreateCursor
(
_GLFWcursor
*
cursor
,
const
GLFWimage
*
image
,
int
xhot
,
int
yhot
)
{
fprintf
(
stderr
,
"_glfwPlatformCreateCursor not implemented yet
\n
"
);
return
GL_FALSE
;
struct
wl_shm_pool
*
pool
;
int
stride
=
image
->
width
*
4
;
int
length
=
image
->
width
*
image
->
height
*
4
;
void
*
data
;
int
fd
,
i
;
fd
=
os_create_anonymous_file
(
length
);
if
(
fd
<
0
)
{
_glfwInputError
(
GLFW_PLATFORM_ERROR
,
"Wayland: Creating a buffer file for %d B failed: %m
\n
"
,
length
);
return
GL_FALSE
;
}
data
=
mmap
(
NULL
,
length
,
PROT_READ
|
PROT_WRITE
,
MAP_SHARED
,
fd
,
0
);
if
(
data
==
MAP_FAILED
)
{
_glfwInputError
(
GLFW_PLATFORM_ERROR
,
"Wayland: Cursor mmap failed: %m
\n
"
);
close
(
fd
);
return
GL_FALSE
;
}
pool
=
wl_shm_create_pool
(
_glfw
.
wl
.
shm
,
fd
,
length
);
close
(
fd
);
unsigned
char
*
source
=
(
unsigned
char
*
)
image
->
pixels
;
unsigned
char
*
target
=
data
;
for
(
i
=
0
;
i
<
image
->
width
*
image
->
height
;
i
++
,
source
+=
4
)
{
*
target
++
=
source
[
2
];
*
target
++
=
source
[
1
];
*
target
++
=
source
[
0
];
*
target
++
=
source
[
3
];
}
cursor
->
wl
.
buffer
=
wl_shm_pool_create_buffer
(
pool
,
0
,
image
->
width
,
image
->
height
,
stride
,
WL_SHM_FORMAT_ARGB8888
);
munmap
(
data
,
length
);
wl_shm_pool_destroy
(
pool
);
cursor
->
wl
.
width
=
image
->
width
;
cursor
->
wl
.
height
=
image
->
height
;
cursor
->
wl
.
xhot
=
xhot
;
cursor
->
wl
.
yhot
=
yhot
;
return
GL_TRUE
;
}
void
_glfwPlatformDestroyCursor
(
_GLFWcursor
*
cursor
)
{
fprintf
(
stderr
,
"_glfwPlatformD
estroy
C
ursor
not implemented yet
\n
"
);
wl_buffer_d
estroy
(
c
ursor
->
wl
.
buffer
);
}
void
_glfwPlatformSetCursor
(
_GLFWwindow
*
window
,
_GLFWcursor
*
cursor
)
{
fprintf
(
stderr
,
"_glfwPlatformSetCursor not implemented yet
\n
"
);
struct
wl_buffer
*
buffer
;
struct
wl_cursor_image
*
image
;
struct
wl_surface
*
surface
=
_glfw
.
wl
.
cursorSurface
;
if
(
!
_glfw
.
wl
.
pointer
)
return
;
window
->
wl
.
currentCursor
=
cursor
;
// If we're not in the correct window just save the cursor
// the next time the pointer enters the window the cursor will change
if
(
window
!=
_glfw
.
wl
.
pointerFocus
)
return
;
if
(
window
->
cursorMode
==
GLFW_CURSOR_NORMAL
)
{
if
(
cursor
==
NULL
)
{
image
=
_glfw
.
wl
.
defaultCursor
->
images
[
0
];
buffer
=
wl_cursor_image_get_buffer
(
image
);
if
(
!
buffer
)
return
;
wl_pointer_set_cursor
(
_glfw
.
wl
.
pointer
,
_glfw
.
wl
.
pointerSerial
,
surface
,
image
->
hotspot_x
,
image
->
hotspot_y
);
wl_surface_attach
(
surface
,
buffer
,
0
,
0
);
wl_surface_damage
(
surface
,
0
,
0
,
image
->
width
,
image
->
height
);
wl_surface_commit
(
surface
);
}
else
{
wl_pointer_set_cursor
(
_glfw
.
wl
.
pointer
,
_glfw
.
wl
.
pointerSerial
,
surface
,
cursor
->
wl
.
xhot
,
cursor
->
wl
.
yhot
);
wl_surface_attach
(
surface
,
cursor
->
wl
.
buffer
,
0
,
0
);
wl_surface_damage
(
surface
,
0
,
0
,
cursor
->
wl
.
width
,
cursor
->
wl
.
height
);
wl_surface_commit
(
surface
);
}
}
else
/* Cursor is hidden set cursor surface to NULL */
{
wl_pointer_set_cursor
(
_glfw
.
wl
.
pointer
,
_glfw
.
wl
.
pointerSerial
,
NULL
,
0
,
0
);
}
}
void
_glfwPlatformSetClipboardString
(
_GLFWwindow
*
window
,
const
char
*
string
)
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment