mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-23 09:54:26 +08:00
Integrate UWAC in to the FreeRDP source tree
So the wayland client can still be built without installing UWAC as a dependency.
This commit is contained in:
parent
bc31c00865
commit
87d6caa69a
@ -789,6 +789,10 @@ include_directories("${CMAKE_BINARY_DIR}/rdtk/include")
|
||||
|
||||
add_subdirectory(rdtk)
|
||||
|
||||
if(WAYLAND_FOUND)
|
||||
add_subdirectory(uwac)
|
||||
endif()
|
||||
|
||||
if(BSD)
|
||||
if(IS_DIRECTORY /usr/local/include)
|
||||
include_directories(/usr/local/include)
|
||||
|
@ -19,7 +19,7 @@
|
||||
set(MODULE_NAME "wlfreerdp")
|
||||
set(MODULE_PREFIX "FREERDP_CLIENT_WAYLAND")
|
||||
|
||||
include_directories(${UWAC_INCLUDE_DIRS})
|
||||
include_directories(${CMAKE_SOURCE_DIR}/uwac/include)
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
wlfreerdp.c
|
||||
@ -31,7 +31,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${CMAKE_DL_LIBS})
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${UWAC_LIBS} freerdp-client freerdp)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-client freerdp uwac)
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)
|
||||
|
@ -1,10 +1,12 @@
|
||||
# - Finds UWAC
|
||||
# Find the UWAC libraries and its dependencies
|
||||
# - Finds Wayland
|
||||
# Find the Wayland libraries that are needed for UWAC
|
||||
#
|
||||
# This module defines the following variables:
|
||||
# UWAC_FOUND - true if UWAC has been found
|
||||
# UWAC_LIBS - Set to the full path to UWAC libraries and its dependencies
|
||||
# UWAC_INCLUDE_DIRS - Set to the include directories for UWAC
|
||||
# WAYLAND_FOUND - true if UWAC has been found
|
||||
# WAYLAND_LIBS - Set to the full path to wayland client libraries
|
||||
# WAYLAND_INCLUDE_DIR - Set to the include directories for wayland
|
||||
# XKBCOMMON_LIBS - Set to the full path to xkbcommon libraries
|
||||
# XKBCOMMON_INCLUDE_DIR - Set to the include directories for xkbcommon
|
||||
#
|
||||
|
||||
#=============================================================================
|
||||
@ -26,28 +28,32 @@
|
||||
include(FindPkgConfig)
|
||||
|
||||
if(PKG_CONFIG_FOUND)
|
||||
pkg_check_modules(UWAC uwac)
|
||||
|
||||
# find the complete path to each dependant library
|
||||
set(UWAC_LIBS, "")
|
||||
foreach(libname ${UWAC_LIBRARIES})
|
||||
find_library(FOUND_LIB NAMES ${libname}
|
||||
PATHS ${UWAC_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
if (FOUND_LIB)
|
||||
list(APPEND UWAC_LIBS ${FOUND_LIB})
|
||||
endif()
|
||||
unset(FOUND_LIB CACHE)
|
||||
endforeach()
|
||||
|
||||
|
||||
find_path(UWAC_INCLUDE_DIR NAMES uwac/uwac.h
|
||||
PATHS ${UWAC_INCLUDE_DIRS}
|
||||
DOC "The UWAC include directory"
|
||||
)
|
||||
|
||||
pkg_check_modules(WAYLAND_SCANNER_PKG wayland-scanner)
|
||||
pkg_check_modules(WAYLAND_CLIENT wayland-client)
|
||||
pkg_check_modules(XKBCOMMON xkbcommon)
|
||||
endif()
|
||||
|
||||
find_program(WAYLAND_SCANNER wayland-scanner
|
||||
HINTS "${WAYLAND_SCANNER_PREFIX}/bin"
|
||||
)
|
||||
|
||||
find_path(WAYLAND_INCLUDE_DIR wayland-client.h
|
||||
HINTS ${WAYLAND_CLIENT_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(WAYLAND_LIBS
|
||||
NAMES "wayland-client"
|
||||
HINTS "${WAYLAND_CLIENT_LIBRARIES}"
|
||||
)
|
||||
|
||||
find_path(XKBCOMMON_INCLUDE_DIR xkbcommon/xkbcommon.h
|
||||
HINTS ${XKBCOMMON_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
find_library(XKBCOMMON_LIBS
|
||||
NAMES xkbcommon
|
||||
HINTS "${XKBCOMMON_LIBRARIES}"
|
||||
)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG UWAC_LIBS UWAC_INCLUDE_DIR)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_SCANNER WAYLAND_INCLUDE_DIR WAYLAND_LIBS XKBCOMMON_INCLUDE_DIR XKBCOMMON_LIBS)
|
||||
|
20
uwac/CMakeLists.txt
Normal file
20
uwac/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
||||
# UWAC: Using Wayland As Client
|
||||
# cmake build script
|
||||
#
|
||||
# Copyright 2015 David FORT <contact@hardening-consulting.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(libuwac)
|
||||
|
20
uwac/include/CMakeLists.txt
Normal file
20
uwac/include/CMakeLists.txt
Normal file
@ -0,0 +1,20 @@
|
||||
# UWAC: Using Wayland As Client
|
||||
# cmake build script
|
||||
#
|
||||
# Copyright 2015 David FORT <contact@hardening-consulting.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
file(GLOB UWAC_HEADERS "uwac/*.h")
|
||||
install(FILES ${UWAC_HEADERS} DESTINATION include/uwac COMPONENT headers)
|
||||
|
60
uwac/include/uwac/uwac-tools.h
Normal file
60
uwac/include/uwac/uwac-tools.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright © 2015 David FORT <contact@hardening-consulting.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __UWAC_TOOLS_H_
|
||||
#define __UWAC_TOOLS_H_
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <uwac/uwac.h>
|
||||
|
||||
/** @brief */
|
||||
struct uwac_touch_point {
|
||||
uint32_t id;
|
||||
wl_fixed_t x, y;
|
||||
};
|
||||
typedef struct uwac_touch_point UwacTouchPoint;
|
||||
|
||||
struct uwac_touch_automata;
|
||||
typedef struct uwac_touch_automata UwacTouchAutomata;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param automata
|
||||
*/
|
||||
void UwacTouchAutomataInit(UwacTouchAutomata *automata);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param automata
|
||||
*/
|
||||
void UwacTouchAutomataReset(UwacTouchAutomata *automata);
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param automata
|
||||
* @param event
|
||||
* @return
|
||||
*/
|
||||
bool UwacTouchAutomataInjectEvent(UwacTouchAutomata *automata, UwacEvent *event);
|
||||
|
||||
#endif /* __UWAC_TOOLS_H_ */
|
480
uwac/include/uwac/uwac.h
Normal file
480
uwac/include/uwac/uwac.h
Normal file
@ -0,0 +1,480 @@
|
||||
/*
|
||||
* Copyright © 2014-2015 David FORT <contact@hardening-consulting.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __UWAC_H_
|
||||
#define __UWAC_H_
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct uwac_size UwacSize;
|
||||
typedef struct uwac_display UwacDisplay;
|
||||
typedef struct uwac_output UwacOutput;
|
||||
typedef struct uwac_window UwacWindow;
|
||||
typedef struct uwac_seat UwacSeat;
|
||||
|
||||
|
||||
/** @brief error codes */
|
||||
typedef enum {
|
||||
UWAC_SUCCESS = 0,
|
||||
UWAC_ERROR_NOMEMORY,
|
||||
UWAC_ERROR_UNABLE_TO_CONNECT,
|
||||
UWAC_ERROR_INVALID_DISPLAY,
|
||||
UWAC_NOT_ENOUGH_RESOURCES,
|
||||
UWAC_TIMEDOUT,
|
||||
UWAC_NOT_FOUND,
|
||||
UWAC_ERROR_CLOSED,
|
||||
UWAC_ERROR_INTERNAL,
|
||||
|
||||
UWAC_ERROR_LAST,
|
||||
} UwacReturnCode;
|
||||
|
||||
/** @brief input modifiers */
|
||||
enum {
|
||||
UWAC_MOD_SHIFT_MASK = 0x01,
|
||||
UWAC_MOD_ALT_MASK = 0x02,
|
||||
UWAC_MOD_CONTROL_MASK = 0x04,
|
||||
};
|
||||
|
||||
/** @brief a rectangle size measure */
|
||||
struct uwac_size {
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
|
||||
/** @brief event types */
|
||||
enum {
|
||||
UWAC_EVENT_NEW_SEAT = 0,
|
||||
UWAC_EVENT_REMOVED_SEAT,
|
||||
UWAC_EVENT_NEW_OUTPUT,
|
||||
UWAC_EVENT_CONFIGURE,
|
||||
UWAC_EVENT_POINTER_ENTER,
|
||||
UWAC_EVENT_POINTER_LEAVE,
|
||||
UWAC_EVENT_POINTER_MOTION,
|
||||
UWAC_EVENT_POINTER_BUTTONS,
|
||||
UWAC_EVENT_POINTER_AXIS,
|
||||
UWAC_EVENT_KEYBOARD_ENTER,
|
||||
UWAC_EVENT_KEY,
|
||||
UWAC_EVENT_TOUCH_FRAME_BEGIN,
|
||||
UWAC_EVENT_TOUCH_UP,
|
||||
UWAC_EVENT_TOUCH_DOWN,
|
||||
UWAC_EVENT_TOUCH_MOTION,
|
||||
UWAC_EVENT_TOUCH_CANCEL,
|
||||
UWAC_EVENT_TOUCH_FRAME_END,
|
||||
UWAC_EVENT_FRAME_DONE,
|
||||
UWAC_EVENT_CLOSE,
|
||||
};
|
||||
|
||||
/** @brief window states */
|
||||
enum {
|
||||
UWAC_WINDOW_MAXIMIZED = 0x1,
|
||||
UWAC_WINDOW_RESIZING = 0x2,
|
||||
UWAC_WINDOW_FULLSCREEN = 0x4,
|
||||
UWAC_WINDOW_ACTIVATED = 0x8,
|
||||
};
|
||||
|
||||
struct uwac_new_output_event {
|
||||
int type;
|
||||
UwacOutput *output;
|
||||
};
|
||||
typedef struct uwac_new_output_event UwacOutputNewEvent;
|
||||
|
||||
struct uwac_new_seat_event {
|
||||
int type;
|
||||
UwacSeat *seat;
|
||||
};
|
||||
typedef struct uwac_new_seat_event UwacSeatNewEvent;
|
||||
|
||||
typedef struct uwac_new_seat_event UwacSeatRemovedEvent;
|
||||
|
||||
struct uwac_keyboard_enter_event {
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacSeat *seat;
|
||||
};
|
||||
typedef struct uwac_keyboard_enter_event UwacKeyboardEnterLeaveEvent;
|
||||
|
||||
struct uwac_pointer_enter_event {
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacSeat *seat;
|
||||
uint32_t x, y;
|
||||
};
|
||||
typedef struct uwac_pointer_enter_event UwacPointerEnterLeaveEvent;
|
||||
|
||||
struct uwac_pointer_motion_event {
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacSeat *seat;
|
||||
uint32_t x, y;
|
||||
};
|
||||
typedef struct uwac_pointer_motion_event UwacPointerMotionEvent;
|
||||
|
||||
struct uwac_pointer_button_event {
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacSeat *seat;
|
||||
uint32_t x, y;
|
||||
uint32_t button;
|
||||
enum wl_pointer_button_state state;
|
||||
};
|
||||
typedef struct uwac_pointer_button_event UwacPointerButtonEvent;
|
||||
|
||||
struct uwac_pointer_axis_event {
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacSeat *seat;
|
||||
uint32_t x, y;
|
||||
uint32_t axis;
|
||||
wl_fixed_t value;
|
||||
};
|
||||
typedef struct uwac_pointer_axis_event UwacPointerAxisEvent;
|
||||
|
||||
struct uwac_touch_frame_event {
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacSeat *seat;
|
||||
};
|
||||
typedef struct uwac_touch_frame_event UwacTouchFrameBegin;
|
||||
typedef struct uwac_touch_frame_event UwacTouchFrameEnd;
|
||||
typedef struct uwac_touch_frame_event UwacTouchCancel;
|
||||
|
||||
struct uwac_touch_data {
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
UwacSeat *seat;
|
||||
int32_t id;
|
||||
wl_fixed_t x;
|
||||
wl_fixed_t y;
|
||||
};
|
||||
typedef struct uwac_touch_data UwacTouchUp;
|
||||
typedef struct uwac_touch_data UwacTouchDown;
|
||||
typedef struct uwac_touch_data UwacTouchMotion;
|
||||
|
||||
struct uwac_frame_done_event {
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
};
|
||||
typedef struct uwac_frame_done_event UwacFrameDoneEvent;
|
||||
|
||||
struct uwac_configure_event {
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int states;
|
||||
};
|
||||
typedef struct uwac_configure_event UwacConfigureEvent;
|
||||
|
||||
struct uwac_key_event {
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
uint32_t raw_key;
|
||||
uint32_t sym;
|
||||
bool pressed;
|
||||
};
|
||||
typedef struct uwac_key_event UwacKeyEvent;
|
||||
|
||||
struct uwac_close_event {
|
||||
int type;
|
||||
UwacWindow *window;
|
||||
};
|
||||
typedef struct uwac_close_event UwacCloseEvent;
|
||||
|
||||
|
||||
/** @brief */
|
||||
union uwac_event {
|
||||
int type;
|
||||
UwacOutputNewEvent output_new;
|
||||
UwacSeatNewEvent seat_new;
|
||||
UwacPointerEnterLeaveEvent mouse_enter_leave;
|
||||
UwacPointerMotionEvent mouse_motion;
|
||||
UwacPointerButtonEvent mouse_button;
|
||||
UwacPointerAxisEvent mouse_axis;
|
||||
UwacKeyboardEnterLeaveEvent keyboard_enter_leave;
|
||||
UwacKeyEvent key;
|
||||
UwacTouchFrameBegin touchFrameBegin;
|
||||
UwacTouchUp touchUp;
|
||||
UwacTouchDown touchDown;
|
||||
UwacTouchMotion touchMotion;
|
||||
UwacTouchFrameEnd touchFrameEnd;
|
||||
UwacTouchCancel touchCancel;
|
||||
UwacFrameDoneEvent frame_done;
|
||||
UwacConfigureEvent configure;
|
||||
UwacCloseEvent close;
|
||||
};
|
||||
typedef union uwac_event UwacEvent;
|
||||
|
||||
typedef bool (*UwacErrorHandler)(UwacDisplay *d, UwacReturnCode code, const char *msg, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* install a handler that will be called when UWAC encounter internal errors. The
|
||||
* handler is supposed to answer if the execution can continue. I can also be used
|
||||
* to log things.
|
||||
*
|
||||
* @param handler
|
||||
*/
|
||||
void UwacInstallErrorHandler(UwacErrorHandler handler);
|
||||
|
||||
|
||||
/**
|
||||
* Opens the corresponding wayland display, using NULL you will open the default
|
||||
* display.
|
||||
*
|
||||
* @param name the name of the display to open
|
||||
* @return the created UwacDisplay object
|
||||
*/
|
||||
UwacDisplay *UwacOpenDisplay(const char *name, UwacReturnCode *err);
|
||||
|
||||
/**
|
||||
* closes the corresponding UwacDisplay
|
||||
*
|
||||
* @param pdisplay a pointer on the display to close
|
||||
* @return UWAC_SUCCESS if the operation was successful, the corresponding error otherwise
|
||||
*/
|
||||
UwacReturnCode UwacCloseDisplay(UwacDisplay **pdisplay);
|
||||
|
||||
/**
|
||||
* Returns the file descriptor associated with the UwacDisplay, this is useful when
|
||||
* you want to poll that file descriptor for activity.
|
||||
*
|
||||
* @param display an opened UwacDisplay
|
||||
* @return the corresponding descriptor
|
||||
*/
|
||||
int UwacDisplayGetFd(UwacDisplay *display);
|
||||
|
||||
/**
|
||||
* Returns a human readable form of a Uwac error code
|
||||
*
|
||||
* @param error the error number
|
||||
* @return the associated string
|
||||
*/
|
||||
const char *UwacErrorString(UwacReturnCode error);
|
||||
|
||||
/**
|
||||
* returns the last error that occurred on a display
|
||||
*
|
||||
* @param display the display
|
||||
* @return the last error that have been set for this display
|
||||
*/
|
||||
UwacReturnCode UwacDisplayGetLastError(const UwacDisplay *display);
|
||||
|
||||
/**
|
||||
* retrieves the version of a given interface
|
||||
*
|
||||
* @param display the display connection
|
||||
* @param name the name of the interface
|
||||
* @param version the output variable for the version
|
||||
* @return UWAC_SUCCESS if the interface was found, UWAC_NOT_FOUND otherwise
|
||||
*/
|
||||
UwacReturnCode UwacDisplayQueryInterfaceVersion(const UwacDisplay *display, const char *name, uint32_t *version);
|
||||
|
||||
/**
|
||||
* returns the number SHM formats that have been reported by the compositor
|
||||
*
|
||||
* @param display a connected UwacDisplay
|
||||
* @return the number of SHM formats supported
|
||||
*/
|
||||
uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay *display);
|
||||
|
||||
/**
|
||||
* returns the supported ShmFormats
|
||||
*
|
||||
* @param display a connected UwacDisplay
|
||||
* @param formats a pointer on an array of wl_shm_format with enough place for formats_size items
|
||||
* @param formats_size the size of the formats array
|
||||
* @param filled the number of filled entries in the formats array
|
||||
* @return UWAC_SUCCESS on success, an error otherwise
|
||||
*/
|
||||
UwacReturnCode UwacDisplayQueryShmFormats(const UwacDisplay *display, enum wl_shm_format *formats, int formats_size, int *filled);
|
||||
|
||||
/**
|
||||
* returns the number of registered outputs
|
||||
*
|
||||
* @param display the display to query
|
||||
* @return the number of outputs
|
||||
*/
|
||||
uint32_t UwacDisplayGetNbOutputs(UwacDisplay *display);
|
||||
|
||||
/**
|
||||
* retrieve a particular UwacOutput object
|
||||
*
|
||||
* @param display the display to query
|
||||
* @param index index of the output
|
||||
* @return the given UwacOutput, NULL if something failed (so you should query UwacDisplayGetLastError() to have the reason)
|
||||
*/
|
||||
UwacOutput *UwacDisplayGetOutput(UwacDisplay *display, int index);
|
||||
|
||||
/**
|
||||
* retrieve the resolution of a given UwacOutput
|
||||
*
|
||||
* @param output the UwacOutput
|
||||
* @param resolution a pointer on the
|
||||
* @return UWAC_SUCCESS on success
|
||||
*/
|
||||
UwacReturnCode UwacOutputGetResolution(UwacOutput *output, UwacSize *resolution);
|
||||
|
||||
|
||||
/**
|
||||
* creates a window using a SHM surface
|
||||
*
|
||||
* @param display the display to attach the window to
|
||||
* @param width the width of the window
|
||||
* @param height the heigh of the window
|
||||
* @param format format to use for the SHM surface
|
||||
* @return the created UwacWindow, NULL if something failed (use UwacDisplayGetLastError() to know more about this)
|
||||
*/
|
||||
UwacWindow *UwacCreateWindowShm(UwacDisplay *display, uint32_t width, uint32_t height, enum wl_shm_format format);
|
||||
|
||||
/**
|
||||
* destroys the corresponding UwacWindow
|
||||
*
|
||||
* @param window a pointer on the UwacWindow to destroy
|
||||
* @return if the operation completed successfully
|
||||
*/
|
||||
UwacReturnCode UwacDestroyWindow(UwacWindow **window);
|
||||
|
||||
/**
|
||||
* Sets the region that should be considered opaque to the compositor.
|
||||
*
|
||||
* @param window the UwacWindow
|
||||
* @param x
|
||||
* @param y
|
||||
* @param width
|
||||
* @param height
|
||||
* @return UWAC_SUCCESS on success, an error otherwise
|
||||
*/
|
||||
UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
|
||||
|
||||
/**
|
||||
* Sets the region of the window that can trigger input events
|
||||
*
|
||||
* @param window the UwacWindow
|
||||
* @param x
|
||||
* @param y
|
||||
* @param width
|
||||
* @param height
|
||||
* @return
|
||||
*/
|
||||
UwacReturnCode UwacWindowSetInputRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
|
||||
|
||||
/**
|
||||
* retrieves a pointer on the current window content to draw a frame
|
||||
* @param window the UwacWindow
|
||||
* @return a pointer on the current window content
|
||||
*/
|
||||
void *UwacWindowGetDrawingBuffer(UwacWindow *window);
|
||||
|
||||
/**
|
||||
* sets a rectangle as dirty for the next frame of a window
|
||||
*
|
||||
* @param window the UwacWindow
|
||||
* @param x left coordinate
|
||||
* @param y top coordinate
|
||||
* @param width the width of the dirty rectangle
|
||||
* @param height the height of the dirty rectangle
|
||||
* @return UWAC_SUCCESS on success, an Uwac error otherwise
|
||||
*/
|
||||
UwacReturnCode UwacWindowAddDamage(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height);
|
||||
|
||||
/**
|
||||
* Sends a frame to the compositor with the content of the drawing buffer
|
||||
*
|
||||
* @param window the UwacWindow to refresh
|
||||
* @param copyContentForNextFrame if true the content to display is copied in the next drawing buffer
|
||||
* @return UWAC_SUCCESS if the operation was successful
|
||||
*/
|
||||
UwacReturnCode UwacWindowSubmitBuffer(UwacWindow *window, bool copyContentForNextFrame);
|
||||
|
||||
/**
|
||||
* returns the geometry of the given UwacWindows
|
||||
*
|
||||
* @param window the UwacWindow
|
||||
* @param geometry the geometry to fill
|
||||
* @return UWAC_SUCCESS on success, an Uwac error otherwise
|
||||
*/
|
||||
UwacReturnCode UwacWindowGetGeometry(UwacWindow *window, UwacSize *geometry);
|
||||
|
||||
/**
|
||||
* Sets or unset the fact that the window is set fullscreen. After this call the
|
||||
* application should get prepared to receive a configure event. The output is used
|
||||
* only when going fullscreen, it is optional and not used when exiting fullscreen.
|
||||
*
|
||||
* @param window the UwacWindow
|
||||
* @param output an optional UwacOutput to put the window fullscreen on
|
||||
* @param isFullscreen set or unset fullscreen
|
||||
* @return UWAC_SUCCESS if the operation was a success
|
||||
*/
|
||||
UwacReturnCode UwacWindowSetFullscreenState(UwacWindow *window, UwacOutput *output, bool isFullscreen);
|
||||
|
||||
/**
|
||||
* When possible (depending on the shell) sets the title of the UwacWindow
|
||||
*
|
||||
* @param window the UwacWindow
|
||||
* @param name title
|
||||
*/
|
||||
void UwacWindowSetTitle(UwacWindow *window, const char *name);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param display
|
||||
* @param timeout
|
||||
* @return
|
||||
*/
|
||||
int UwacDisplayDispatch(UwacDisplay *display, int timeout);
|
||||
|
||||
/**
|
||||
* Returns if you have some pending events, and you can UwacNextEvent() without blocking
|
||||
*
|
||||
* @param display the UwacDisplay
|
||||
* @return if there's some pending events
|
||||
*/
|
||||
bool UwacHasEvent(UwacDisplay *display);
|
||||
|
||||
/** Waits until an event occurs, and when it's there copy the event from the queue to
|
||||
* event.
|
||||
*
|
||||
* @param display the Uwac display
|
||||
* @param event the event to fill
|
||||
* @return if the operation completed successfully
|
||||
*/
|
||||
UwacReturnCode UwacNextEvent(UwacDisplay *display, UwacEvent *event);
|
||||
|
||||
|
||||
/**
|
||||
* returns the name of the given UwacSeat
|
||||
*
|
||||
* @param seat the UwacSeat
|
||||
* @return the name of the seat
|
||||
*/
|
||||
const char *UwacSeatGetName(const UwacSeat *seat);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __UWAC_H_ */
|
7
uwac/libuwac/.gitignore
vendored
Normal file
7
uwac/libuwac/.gitignore
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
fullscreen-shell-client-protocol.h
|
||||
fullscreen-shell-protocol.c
|
||||
ivi-application-client-protocol.h
|
||||
ivi-application-protocol.c
|
||||
xdg-shell-client-protocol.h
|
||||
xdg-shell-protocol.c
|
||||
|
79
uwac/libuwac/CMakeLists.txt
Normal file
79
uwac/libuwac/CMakeLists.txt
Normal file
@ -0,0 +1,79 @@
|
||||
# UWAC: Using Wayland As Client
|
||||
#
|
||||
# Copyright 2015 David FORT <contact@hardening-consulting.com>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set(MODULE_NAME "uwac")
|
||||
set(MODULE_PREFIX "UWAC")
|
||||
|
||||
|
||||
set(GENERATED_SOURCES "")
|
||||
macro(generate_protocol_file PROTO)
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-protocol.c"
|
||||
COMMAND ${WAYLAND_SCANNER} code < ${CMAKE_SOURCE_DIR}/uwac/protocols/${PROTO}.xml > ${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-protocol.c
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/uwac/protocols/${PROTO}.xml
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-client-protocol.h"
|
||||
COMMAND ${WAYLAND_SCANNER} client-header < ${CMAKE_SOURCE_DIR}/uwac/protocols/${PROTO}.xml > ${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-client-protocol.h
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/uwac/protocols/${PROTO}.xml
|
||||
)
|
||||
|
||||
list(APPEND GENERATED_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-client-protocol.h)
|
||||
list(APPEND GENERATED_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-protocol.c)
|
||||
endmacro()
|
||||
|
||||
generate_protocol_file(xdg-shell)
|
||||
generate_protocol_file(ivi-application)
|
||||
generate_protocol_file(fullscreen-shell)
|
||||
|
||||
include_directories(${WAYLAND_INCLUDE_DIR})
|
||||
include_directories(${XKBCOMMON_INCLUDE_DIR})
|
||||
include_directories("${CMAKE_SOURCE_DIR}/uwac/include")
|
||||
include_directories("${CMAKE_BINARY_DIR}/uwac/include")
|
||||
|
||||
add_definitions(-DBUILD_IVI -DBUILD_FULLSCREEN_SHELL -DENABLE_XKBCOMMON)
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
${GENERATED_SOURCES}
|
||||
uwac-display.c
|
||||
uwac-input.c
|
||||
uwac-os.c
|
||||
uwac-os.h
|
||||
uwac-output.c
|
||||
uwac-priv.h
|
||||
uwac-tools.c
|
||||
uwac-utils.c
|
||||
uwac-window.c)
|
||||
|
||||
|
||||
add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
|
||||
if (WITH_LIBRARY_VERSIONING)
|
||||
#set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${UWAC_VERSION} SOVERSION ${UWAC_API_VERSION})
|
||||
endif()
|
||||
|
||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS} ${WAYLAND_LIBS} ${XKBCOMMON_LIBS})
|
||||
|
||||
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT Uwac)
|
||||
|
||||
|
||||
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "uwac")
|
||||
|
||||
if(BUILD_TESTING)
|
||||
# add_subdirectory(test)
|
||||
endif()
|
631
uwac/libuwac/uwac-display.c
Normal file
631
uwac/libuwac/uwac-display.c
Normal file
@ -0,0 +1,631 @@
|
||||
/*
|
||||
* Copyright © 2014 David FORT <contact@hardening-consulting.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
#include "uwac-priv.h"
|
||||
#include "uwac-utils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#include "uwac-os.h"
|
||||
|
||||
#define TARGET_COMPOSITOR_INTERFACE 3
|
||||
#define TARGET_SHM_INTERFACE 1
|
||||
#define TARGET_SHELL_INTERFACE 1
|
||||
#define TARGET_DDM_INTERFACE 1
|
||||
#define TARGET_SEAT_INTERFACE 5
|
||||
#define TARGET_XDG_VERSION 5 /* The version of xdg-shell that we implement */
|
||||
|
||||
static const char *event_names[] = {
|
||||
"new seat",
|
||||
"removed seat",
|
||||
"new output",
|
||||
"configure",
|
||||
"pointer enter",
|
||||
"pointer leave",
|
||||
"pointer motion",
|
||||
"pointer buttons",
|
||||
"pointer axis",
|
||||
"keyboard enter",
|
||||
"key",
|
||||
"touch frame begin",
|
||||
"touch up",
|
||||
"touch down",
|
||||
"touch motion",
|
||||
"touch cancel",
|
||||
"touch frame end",
|
||||
"frame done",
|
||||
"close",
|
||||
NULL
|
||||
};
|
||||
|
||||
bool uwac_default_error_handler(UwacDisplay *display, UwacReturnCode code, const char *msg, ...) {
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
|
||||
vfprintf(stderr, "%s", args);
|
||||
return false;
|
||||
}
|
||||
|
||||
UwacErrorHandler uwacErrorHandler = uwac_default_error_handler;
|
||||
|
||||
void UwacInstallErrorHandler(UwacErrorHandler handler) {
|
||||
if (handler)
|
||||
uwacErrorHandler = handler;
|
||||
else
|
||||
uwacErrorHandler = uwac_default_error_handler;
|
||||
}
|
||||
|
||||
|
||||
static void cb_shm_format(void *data, struct wl_shm *wl_shm, uint32_t format)
|
||||
{
|
||||
UwacDisplay *d = data;
|
||||
|
||||
if (format == WL_SHM_FORMAT_RGB565)
|
||||
d->has_rgb565 = true;
|
||||
|
||||
d->shm_formats_nb++;
|
||||
d->shm_formats = xrealloc((void *)d->shm_formats, sizeof(enum wl_shm_format) * d->shm_formats_nb);
|
||||
d->shm_formats[d->shm_formats_nb - 1] = format;
|
||||
}
|
||||
|
||||
|
||||
struct wl_shm_listener shm_listener = {
|
||||
cb_shm_format
|
||||
};
|
||||
|
||||
static void xdg_shell_ping(void *data, struct xdg_shell *shell, uint32_t serial)
|
||||
{
|
||||
xdg_shell_pong(shell, serial);
|
||||
}
|
||||
|
||||
static const struct xdg_shell_listener xdg_shell_listener = {
|
||||
xdg_shell_ping,
|
||||
};
|
||||
|
||||
#ifdef BUILD_FULLSCREEN_SHELL
|
||||
static void fullscreen_capability(void *data, struct _wl_fullscreen_shell *_wl_fullscreen_shell,
|
||||
uint32_t capabilty)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct _wl_fullscreen_shell_listener fullscreen_shell_listener = {
|
||||
fullscreen_capability,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
static UwacSeat *display_destroy_seat(UwacDisplay *d, uint32_t name)
|
||||
{
|
||||
UwacSeat *seat;
|
||||
|
||||
wl_list_for_each(seat, &d->seats, link) {
|
||||
if (seat->seat_id == name) {
|
||||
UwacSeatDestroy(seat);
|
||||
return seat;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t id,
|
||||
const char *interface, uint32_t version)
|
||||
{
|
||||
UwacDisplay *d = data;
|
||||
UwacGlobal *global;
|
||||
|
||||
global = xmalloc(sizeof *global);
|
||||
global->name = id;
|
||||
global->interface = xstrdup(interface);
|
||||
global->version = version;
|
||||
wl_list_insert(d->globals.prev, &global->link);
|
||||
|
||||
if (strcmp(interface, "wl_compositor") == 0) {
|
||||
d->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, min(TARGET_COMPOSITOR_INTERFACE, version));
|
||||
} else if (strcmp(interface, "wl_shm") == 0) {
|
||||
d->shm = wl_registry_bind(registry, id, &wl_shm_interface, min(TARGET_SHM_INTERFACE, version));
|
||||
wl_shm_add_listener(d->shm, &shm_listener, d);
|
||||
} else if (strcmp(interface, "wl_output") == 0) {
|
||||
UwacOutput *output;
|
||||
UwacOutputNewEvent *ev;
|
||||
|
||||
output = UwacCreateOutput(d, id, version);
|
||||
if (!output) {
|
||||
assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create output\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
ev = (UwacOutputNewEvent *)UwacDisplayNewEvent(d, UWAC_EVENT_NEW_OUTPUT);
|
||||
if (ev)
|
||||
ev->output = output;
|
||||
|
||||
} else if (strcmp(interface, "wl_seat") == 0) {
|
||||
UwacSeatNewEvent *ev;
|
||||
UwacSeat *seat;
|
||||
|
||||
seat = UwacSeatNew(d, id, min(version, TARGET_SEAT_INTERFACE));
|
||||
if (!seat) {
|
||||
assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create new seat\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
ev = (UwacSeatNewEvent *)UwacDisplayNewEvent(d, UWAC_EVENT_NEW_SEAT);
|
||||
if (!ev) {
|
||||
assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create new seat event\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
ev->seat = seat;
|
||||
} else if (strcmp(interface, "wl_data_device_manager") == 0) {
|
||||
d->data_device_manager = wl_registry_bind(registry, id, &wl_data_device_manager_interface, min(TARGET_DDM_INTERFACE, version));
|
||||
} else if (strcmp(interface, "wl_shell") == 0) {
|
||||
d->shell = wl_registry_bind(registry, id, &wl_shell_interface, min(TARGET_SHELL_INTERFACE, version));
|
||||
} else if (strcmp(interface, "xdg_shell") == 0) {
|
||||
d->xdg_shell = wl_registry_bind(registry, id, &xdg_shell_interface, 1);
|
||||
xdg_shell_use_unstable_version(d->xdg_shell, TARGET_XDG_VERSION);
|
||||
xdg_shell_add_listener(d->xdg_shell, &xdg_shell_listener, d);
|
||||
#if BUILD_IVI
|
||||
} else if (strcmp(interface, "ivi_application") == 0) {
|
||||
d->ivi_application = wl_registry_bind(registry, id, &ivi_application_interface, 1);
|
||||
#endif
|
||||
#if BUILD_FULLSCREEN_SHELL
|
||||
} else if (strcmp(interface, "_wl_fullscreen_shell") == 0) {
|
||||
d->fullscreen_shell = wl_registry_bind(registry, id, &_wl_fullscreen_shell_interface, 1);
|
||||
_wl_fullscreen_shell_add_listener(d->fullscreen_shell, &fullscreen_shell_listener, d);
|
||||
#endif
|
||||
#if 0
|
||||
} else if (strcmp(interface, "text_cursor_position") == 0) {
|
||||
d->text_cursor_position = wl_registry_bind(registry, id, &text_cursor_position_interface, 1);
|
||||
} else if (strcmp(interface, "workspace_manager") == 0) {
|
||||
//init_workspace_manager(d, id);
|
||||
} else if (strcmp(interface, "wl_subcompositor") == 0) {
|
||||
d->subcompositor = wl_registry_bind(registry, id, &wl_subcompositor_interface, 1);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) {
|
||||
UwacDisplay *d = data;
|
||||
UwacGlobal *global;
|
||||
UwacGlobal *tmp;
|
||||
|
||||
wl_list_for_each_safe(global, tmp, &d->globals, link) {
|
||||
if (global->name != name)
|
||||
continue;
|
||||
|
||||
#if 0
|
||||
if (strcmp(global->interface, "wl_output") == 0)
|
||||
display_destroy_output(d, name);
|
||||
#endif
|
||||
|
||||
if (strcmp(global->interface, "wl_seat") == 0) {
|
||||
UwacSeatRemovedEvent *ev;
|
||||
UwacSeat *seat;
|
||||
|
||||
seat = display_destroy_seat(d, name);
|
||||
ev = (UwacSeatRemovedEvent *)UwacDisplayNewEvent(d, UWAC_EVENT_REMOVED_SEAT);
|
||||
if (ev)
|
||||
ev->seat = seat;
|
||||
}
|
||||
|
||||
|
||||
wl_list_remove(&global->link);
|
||||
free(global->interface);
|
||||
free(global);
|
||||
}
|
||||
}
|
||||
|
||||
void UwacDestroyGlobal(UwacGlobal *global) {
|
||||
free(global->interface);
|
||||
wl_list_remove(&global->link);
|
||||
free(global);
|
||||
}
|
||||
|
||||
void *display_bind(UwacDisplay *display, uint32_t name, const struct wl_interface *interface, uint32_t version) {
|
||||
return wl_registry_bind(display->registry, name, interface, version);
|
||||
}
|
||||
|
||||
static const struct wl_registry_listener registry_listener = {
|
||||
registry_handle_global,
|
||||
registry_handle_global_remove
|
||||
};
|
||||
|
||||
|
||||
int UwacDisplayWatchFd(UwacDisplay *display, int fd, uint32_t events, UwacTask *task) {
|
||||
struct epoll_event ep;
|
||||
|
||||
ep.events = events;
|
||||
ep.data.ptr = task;
|
||||
return epoll_ctl(display->epoll_fd, EPOLL_CTL_ADD, fd, &ep);
|
||||
}
|
||||
|
||||
void UwacDisplayUnwatchFd(UwacDisplay *display, int fd) {
|
||||
epoll_ctl(display->epoll_fd, EPOLL_CTL_DEL, fd, NULL);
|
||||
}
|
||||
|
||||
static void display_exit(UwacDisplay *display) {
|
||||
display->running = false;
|
||||
}
|
||||
|
||||
static void display_dispatch_events(UwacTask *task, uint32_t events)
|
||||
{
|
||||
UwacDisplay *display = container_of(task, UwacDisplay, dispatch_fd_task);
|
||||
struct epoll_event ep;
|
||||
int ret;
|
||||
|
||||
display->display_fd_events = events;
|
||||
|
||||
if ((events & EPOLLERR) || (events & EPOLLHUP)) {
|
||||
display_exit(display);
|
||||
return;
|
||||
}
|
||||
|
||||
if (events & EPOLLIN) {
|
||||
ret = wl_display_dispatch(display->display);
|
||||
if (ret == -1) {
|
||||
display_exit(display);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (events & EPOLLOUT) {
|
||||
ret = wl_display_flush(display->display);
|
||||
if (ret == 0) {
|
||||
ep.events = EPOLLIN | EPOLLERR | EPOLLHUP;
|
||||
ep.data.ptr = &display->dispatch_fd_task;
|
||||
epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD, display->display_fd, &ep);
|
||||
} else if (ret == -1 && errno != EAGAIN) {
|
||||
display_exit(display);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
UwacDisplay *UwacOpenDisplay(const char *name, UwacReturnCode *err) {
|
||||
UwacDisplay *ret;
|
||||
|
||||
ret = (UwacDisplay *)calloc(1, sizeof(*ret));
|
||||
if (!ret) {
|
||||
*err = UWAC_ERROR_NOMEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wl_list_init(&ret->globals);
|
||||
wl_list_init(&ret->seats);
|
||||
wl_list_init(&ret->outputs);
|
||||
wl_list_init(&ret->windows);
|
||||
|
||||
ret->display = wl_display_connect(name);
|
||||
if (ret->display == NULL) {
|
||||
fprintf(stderr, "failed to connect to Wayland display %s: %m\n", name);
|
||||
*err = UWAC_ERROR_UNABLE_TO_CONNECT;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
ret->epoll_fd = uwac_os_epoll_create_cloexec();
|
||||
if (ret->epoll_fd < 0) {
|
||||
*err = UWAC_NOT_ENOUGH_RESOURCES;
|
||||
goto out_disconnect;
|
||||
}
|
||||
|
||||
ret->display_fd = wl_display_get_fd(ret->display);
|
||||
|
||||
ret->registry = wl_display_get_registry(ret->display);
|
||||
if (!ret->registry) {
|
||||
*err = UWAC_ERROR_NOMEMORY;
|
||||
goto out_close_epoll;
|
||||
}
|
||||
|
||||
wl_registry_add_listener(ret->registry, ®istry_listener, ret);
|
||||
|
||||
if ((wl_display_roundtrip(ret->display) < 0) || (wl_display_roundtrip(ret->display) < 0)) {
|
||||
uwacErrorHandler(ret, UWAC_ERROR_UNABLE_TO_CONNECT, "Failed to process Wayland connection: %m\n");
|
||||
*err = UWAC_ERROR_UNABLE_TO_CONNECT;
|
||||
goto out_free_registry;
|
||||
}
|
||||
|
||||
ret->dispatch_fd_task.run = display_dispatch_events;
|
||||
if (UwacDisplayWatchFd(ret, ret->display_fd, EPOLLIN | EPOLLERR | EPOLLHUP, &ret->dispatch_fd_task) < 0) {
|
||||
uwacErrorHandler(ret, UWAC_ERROR_INTERNAL, "unable to watch display fd: %m\n");
|
||||
*err = UWAC_ERROR_INTERNAL;
|
||||
goto out_free_registry;
|
||||
}
|
||||
|
||||
ret->running = true;
|
||||
ret->last_error = *err = UWAC_SUCCESS;
|
||||
return ret;
|
||||
|
||||
out_free_registry:
|
||||
wl_registry_destroy(ret->registry);
|
||||
out_close_epoll:
|
||||
close(ret->epoll_fd);
|
||||
out_disconnect:
|
||||
wl_display_disconnect(ret->display);
|
||||
out_free:
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int UwacDisplayDispatch(UwacDisplay *display, int timeout) {
|
||||
int ret, count, i;
|
||||
UwacTask *task;
|
||||
struct epoll_event ep[16];
|
||||
|
||||
wl_display_dispatch_pending(display->display);
|
||||
|
||||
if (!display->running)
|
||||
return 0;
|
||||
|
||||
ret = wl_display_flush(display->display);
|
||||
if (ret < 0 && errno == EAGAIN) {
|
||||
ep[0].events = (EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP);
|
||||
ep[0].data.ptr = &display->dispatch_fd_task;
|
||||
|
||||
epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD, display->display_fd, &ep[0]);
|
||||
} else if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
count = epoll_wait(display->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
|
||||
for (i = 0; i < count; i++) {
|
||||
task = ep[i].data.ptr;
|
||||
task->run(task, ep[i].events);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
UwacReturnCode UwacDisplayGetLastError(const UwacDisplay *display) {
|
||||
return display->last_error;
|
||||
}
|
||||
|
||||
UwacReturnCode UwacCloseDisplay(UwacDisplay **pdisplay) {
|
||||
UwacDisplay *display;
|
||||
UwacSeat *seat, *tmpSeat;
|
||||
UwacWindow *window, *tmpWindow;
|
||||
UwacOutput *output, *tmpOutput;
|
||||
UwacGlobal *global, *tmpGlobal;
|
||||
|
||||
assert(pdisplay);
|
||||
display = *pdisplay;
|
||||
if (!display)
|
||||
return UWAC_ERROR_INVALID_DISPLAY;
|
||||
|
||||
/* destroy windows */
|
||||
wl_list_for_each_safe(window, tmpWindow, &display->windows, link) {
|
||||
UwacDestroyWindow(&window);
|
||||
}
|
||||
|
||||
/* destroy seats */
|
||||
wl_list_for_each_safe(seat, tmpSeat, &display->seats, link) {
|
||||
UwacSeatDestroy(seat);
|
||||
}
|
||||
|
||||
/* destroy output */
|
||||
wl_list_for_each_safe(output, tmpOutput, &display->outputs, link) {
|
||||
UwacDestroyOutput(output);
|
||||
}
|
||||
|
||||
/* destroy globals */
|
||||
wl_list_for_each_safe(global, tmpGlobal, &display->globals, link) {
|
||||
UwacDestroyGlobal(global);
|
||||
}
|
||||
|
||||
if (display->compositor)
|
||||
wl_compositor_destroy(display->compositor);
|
||||
#ifdef BUILD_FULLSCREEN_SHELL
|
||||
if (display->fullscreen_shell)
|
||||
_wl_fullscreen_shell_destroy(display->fullscreen_shell);
|
||||
#endif
|
||||
#ifdef BUILD_IVI
|
||||
if (display->ivi_application)
|
||||
ivi_application_destroy(display->ivi_application);
|
||||
#endif
|
||||
if (display->xdg_shell)
|
||||
xdg_shell_destroy(display->xdg_shell);
|
||||
if (display->shell)
|
||||
wl_shell_destroy(display->shell);
|
||||
if (display->shm)
|
||||
wl_shm_destroy(display->shm);
|
||||
if (display->subcompositor)
|
||||
wl_subcompositor_destroy(display->subcompositor);
|
||||
if (display->data_device_manager)
|
||||
wl_data_device_manager_destroy(display->data_device_manager);
|
||||
|
||||
free(display->shm_formats);
|
||||
wl_registry_destroy(display->registry);
|
||||
|
||||
close(display->epoll_fd);
|
||||
|
||||
wl_display_disconnect(display->display);
|
||||
|
||||
/* cleanup the event queue */
|
||||
while (display->push_queue) {
|
||||
UwacEventListItem *item = display->push_queue;
|
||||
|
||||
display->push_queue = item->tail;
|
||||
free(item);
|
||||
}
|
||||
|
||||
free(display);
|
||||
*pdisplay = NULL;
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
int UwacDisplayGetFd(UwacDisplay *display) {
|
||||
return display->epoll_fd;
|
||||
}
|
||||
|
||||
static const char *errorStrings[] = {
|
||||
"success",
|
||||
"out of memory error",
|
||||
"unable to connect to wayland display",
|
||||
"invalid UWAC display",
|
||||
"not enough resources",
|
||||
"timed out",
|
||||
"not found",
|
||||
"closed connection",
|
||||
|
||||
"internal error",
|
||||
};
|
||||
|
||||
const char *UwacErrorString(UwacReturnCode error) {
|
||||
if (error < 0 || error >= UWAC_ERROR_LAST)
|
||||
return "invalid error code";
|
||||
|
||||
return errorStrings[error];
|
||||
}
|
||||
|
||||
UwacReturnCode UwacDisplayQueryInterfaceVersion(const UwacDisplay *display, const char *name, uint32_t *version) {
|
||||
const UwacGlobal *global;
|
||||
|
||||
if (!display)
|
||||
return UWAC_ERROR_INVALID_DISPLAY;
|
||||
|
||||
wl_list_for_each(global, &display->globals, link) {
|
||||
if (strcmp(global->interface, name) == 0) {
|
||||
if (version)
|
||||
*version = global->version;
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return UWAC_NOT_FOUND;
|
||||
}
|
||||
|
||||
uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay *display) {
|
||||
if (!display) {
|
||||
display->last_error = UWAC_ERROR_INVALID_DISPLAY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!display->shm) {
|
||||
display->last_error = UWAC_NOT_FOUND;
|
||||
return 0;
|
||||
}
|
||||
|
||||
display->last_error = UWAC_SUCCESS;
|
||||
return display->shm_formats_nb;
|
||||
}
|
||||
|
||||
|
||||
UwacReturnCode UwacDisplayQueryShmFormats(const UwacDisplay *display, enum wl_shm_format *formats, int formats_size, int *filled) {
|
||||
if (!display)
|
||||
return UWAC_ERROR_INVALID_DISPLAY;
|
||||
|
||||
*filled = min(display->shm_formats_nb, formats_size);
|
||||
memcpy(formats, (const void *)display->shm_formats, *filled * sizeof(enum wl_shm_format));
|
||||
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
uint32_t UwacDisplayGetNbOutputs(UwacDisplay *display) {
|
||||
return wl_list_length(&display->outputs);
|
||||
}
|
||||
|
||||
UwacOutput *UwacDisplayGetOutput(UwacDisplay *display, int index) {
|
||||
struct wl_list *l;
|
||||
int i;
|
||||
|
||||
for (i = 0, l = &display->outputs; l && i < index; i++, l = l->next)
|
||||
;
|
||||
|
||||
if (!l) {
|
||||
display->last_error = UWAC_NOT_FOUND;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
display->last_error = UWAC_SUCCESS;
|
||||
return container_of(l, UwacOutput, link);
|
||||
}
|
||||
|
||||
UwacReturnCode UwacOutputGetResolution(UwacOutput *output, UwacSize *resolution) {
|
||||
*resolution = output->resolution;
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
UwacEvent *UwacDisplayNewEvent(UwacDisplay *display, int type) {
|
||||
UwacEventListItem *ret;
|
||||
|
||||
if (!display) {
|
||||
display->last_error = UWAC_ERROR_INVALID_DISPLAY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = zalloc(sizeof(UwacEventListItem));
|
||||
if (!ret) {
|
||||
assert(uwacErrorHandler(display, UWAC_ERROR_NOMEMORY, "unable to allocate a '%s' event", event_names[type]));
|
||||
display->last_error = UWAC_ERROR_NOMEMORY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret->event.type = type;
|
||||
ret->tail = display->push_queue;
|
||||
if (ret->tail)
|
||||
ret->tail->head = ret;
|
||||
else
|
||||
display->pop_queue = ret;
|
||||
display->push_queue = ret;
|
||||
return &ret->event;
|
||||
}
|
||||
|
||||
bool UwacHasEvent(UwacDisplay *display) {
|
||||
return display->pop_queue != NULL;
|
||||
}
|
||||
|
||||
|
||||
UwacReturnCode UwacNextEvent(UwacDisplay *display, UwacEvent *event) {
|
||||
UwacEventListItem *prevItem;
|
||||
int ret;
|
||||
|
||||
if (!display)
|
||||
return UWAC_ERROR_INVALID_DISPLAY;
|
||||
|
||||
while (!display->pop_queue) {
|
||||
ret = UwacDisplayDispatch(display, 1 * 1000);
|
||||
if (ret < 0)
|
||||
return UWAC_ERROR_INTERNAL;
|
||||
else if (ret == 0)
|
||||
return UWAC_ERROR_CLOSED;
|
||||
}
|
||||
|
||||
prevItem = display->pop_queue->head;
|
||||
*event = display->pop_queue->event;
|
||||
free(display->pop_queue);
|
||||
display->pop_queue = prevItem;
|
||||
if (prevItem)
|
||||
prevItem->tail = NULL;
|
||||
else
|
||||
display->push_queue = NULL;
|
||||
return UWAC_SUCCESS;
|
||||
}
|
831
uwac/libuwac/uwac-input.c
Normal file
831
uwac/libuwac/uwac-input.c
Normal file
@ -0,0 +1,831 @@
|
||||
/*
|
||||
* Copyright © 2014-2015 David FORT <contact@hardening-consulting.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
#include "uwac-priv.h"
|
||||
#include "uwac-utils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/timerfd.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
|
||||
static void keyboard_repeat_func(UwacTask *task, uint32_t events)
|
||||
{
|
||||
UwacSeat *input = container_of(task, UwacSeat, repeat_task);
|
||||
UwacWindow *window = input->keyboard_focus;
|
||||
uint64_t exp;
|
||||
|
||||
if (read(input->repeat_timer_fd, &exp, sizeof exp) != sizeof exp)
|
||||
/* If we change the timer between the fd becoming
|
||||
* readable and getting here, there'll be nothing to
|
||||
* read and we get EAGAIN. */
|
||||
return;
|
||||
|
||||
if (window) {
|
||||
UwacKeyEvent *key;
|
||||
|
||||
key = (UwacKeyEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_KEY);
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
key->window = window;
|
||||
key->sym = input->repeat_sym;
|
||||
key->pressed = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
|
||||
uint32_t format, int fd, uint32_t size)
|
||||
{
|
||||
UwacSeat *input = data;
|
||||
struct xkb_keymap *keymap;
|
||||
struct xkb_state *state;
|
||||
char *map_str;
|
||||
|
||||
if (!data) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (map_str == MAP_FAILED) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
keymap = xkb_keymap_new_from_string(input->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0);
|
||||
munmap(map_str, size);
|
||||
close(fd);
|
||||
|
||||
if (!keymap) {
|
||||
assert(uwacErrorHandler(input->display, UWAC_ERROR_INTERNAL, "failed to compile keymap\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
state = xkb_state_new(keymap);
|
||||
if (!state) {
|
||||
assert(uwacErrorHandler(input->display, UWAC_ERROR_NOMEMORY, "failed to create XKB state\n"));
|
||||
xkb_keymap_unref(keymap);
|
||||
return;
|
||||
}
|
||||
|
||||
xkb_keymap_unref(input->xkb.keymap);
|
||||
xkb_state_unref(input->xkb.state);
|
||||
input->xkb.keymap = keymap;
|
||||
input->xkb.state = state;
|
||||
|
||||
input->xkb.control_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Control");
|
||||
input->xkb.alt_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Mod1");
|
||||
input->xkb.shift_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Shift");
|
||||
}
|
||||
|
||||
static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
|
||||
uint32_t serial, uint32_t time, uint32_t key,
|
||||
uint32_t state_w);
|
||||
|
||||
static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial,
|
||||
struct wl_surface *surface, struct wl_array *keys)
|
||||
{
|
||||
uint32_t *key, *pressedKey;
|
||||
UwacSeat *input = (UwacSeat *)data;
|
||||
int i, found;
|
||||
UwacKeyboardEnterLeaveEvent *event;
|
||||
|
||||
event = (UwacKeyboardEnterLeaveEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_KEYBOARD_ENTER);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
event->window = input->keyboard_focus = (UwacWindow *)wl_surface_get_user_data(surface);
|
||||
|
||||
/* look for keys that have been released */
|
||||
found = false;
|
||||
for (pressedKey = input->pressed_keys.data, i = 0; i < input->pressed_keys.size; i += sizeof(uint32_t)) {
|
||||
wl_array_for_each(key, keys) {
|
||||
if (*key == *pressedKey) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
keyboard_handle_key(data, keyboard, serial, 0, *pressedKey, WL_KEYBOARD_KEY_STATE_RELEASED);
|
||||
} else {
|
||||
pressedKey++;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle keys that are now pressed */
|
||||
wl_array_for_each(key, keys) {
|
||||
keyboard_handle_key(data, keyboard, serial, 0, *key, WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||
}
|
||||
}
|
||||
|
||||
static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial,
|
||||
struct wl_surface *surface)
|
||||
{
|
||||
struct itimerspec its;
|
||||
UwacSeat *input;
|
||||
UwacPointerEnterLeaveEvent *event;
|
||||
|
||||
input = (UwacSeat *)data;
|
||||
|
||||
its.it_interval.tv_sec = 0;
|
||||
its.it_interval.tv_nsec = 0;
|
||||
its.it_value.tv_sec = 0;
|
||||
its.it_value.tv_nsec = 0;
|
||||
timerfd_settime(input->repeat_timer_fd, 0, &its, NULL);
|
||||
|
||||
event = (UwacPointerEnterLeaveEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_LEAVE);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
event->window = input->keyboard_focus;
|
||||
}
|
||||
|
||||
static int update_key_pressed(UwacSeat *seat, uint32_t key) {
|
||||
uint32_t *keyPtr;
|
||||
|
||||
/* check if the key is not already pressed */
|
||||
wl_array_for_each(keyPtr, &seat->pressed_keys) {
|
||||
if (*keyPtr == key)
|
||||
return 1;
|
||||
}
|
||||
|
||||
keyPtr = wl_array_add(&seat->pressed_keys, sizeof(uint32_t));
|
||||
if (!keyPtr)
|
||||
return -1;
|
||||
|
||||
*keyPtr = key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int update_key_released(UwacSeat *seat, uint32_t key) {
|
||||
uint32_t *keyPtr;
|
||||
int i, toMove;
|
||||
bool found = false;
|
||||
|
||||
for (i = 0, keyPtr = seat->pressed_keys.data; i < seat->pressed_keys.size; i++, keyPtr++) {
|
||||
if (*keyPtr == key) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
toMove = seat->pressed_keys.size - ((i + 1) * sizeof(uint32_t));
|
||||
if (toMove)
|
||||
memmove(keyPtr, keyPtr+1, toMove);
|
||||
|
||||
seat->pressed_keys.size -= sizeof(uint32_t);
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
|
||||
uint32_t serial, uint32_t time, uint32_t key,
|
||||
uint32_t state_w)
|
||||
{
|
||||
UwacSeat *input = (UwacSeat *)data;
|
||||
UwacWindow *window = input->keyboard_focus;
|
||||
UwacKeyEvent *keyEvent;
|
||||
|
||||
uint32_t code, num_syms;
|
||||
enum wl_keyboard_key_state state = state_w;
|
||||
const xkb_keysym_t *syms;
|
||||
xkb_keysym_t sym;
|
||||
struct itimerspec its;
|
||||
|
||||
if (state_w == WL_KEYBOARD_KEY_STATE_PRESSED)
|
||||
update_key_pressed(input, key);
|
||||
else
|
||||
update_key_released(input, key);
|
||||
|
||||
input->display->serial = serial;
|
||||
code = key + 8;
|
||||
if (!window || !input->xkb.state)
|
||||
return;
|
||||
|
||||
/* We only use input grabs for pointer events for now, so just
|
||||
* ignore key presses if a grab is active. We expand the key
|
||||
* event delivery mechanism to route events to widgets to
|
||||
* properly handle key grabs. In the meantime, this prevents
|
||||
* key event delivery while a grab is active. */
|
||||
/*if (input->grab && input->grab_button == 0)
|
||||
return;*/
|
||||
|
||||
num_syms = xkb_state_key_get_syms(input->xkb.state, code, &syms);
|
||||
|
||||
sym = XKB_KEY_NoSymbol;
|
||||
if (num_syms == 1)
|
||||
sym = syms[0];
|
||||
|
||||
if (state == WL_KEYBOARD_KEY_STATE_RELEASED && key == input->repeat_key) {
|
||||
its.it_interval.tv_sec = 0;
|
||||
its.it_interval.tv_nsec = 0;
|
||||
its.it_value.tv_sec = 0;
|
||||
its.it_value.tv_nsec = 0;
|
||||
timerfd_settime(input->repeat_timer_fd, 0, &its, NULL);
|
||||
} else if (state == WL_KEYBOARD_KEY_STATE_PRESSED && xkb_keymap_key_repeats(input->xkb.keymap, code)) {
|
||||
input->repeat_sym = sym;
|
||||
input->repeat_key = key;
|
||||
input->repeat_time = time;
|
||||
its.it_interval.tv_sec = input->repeat_rate_sec;
|
||||
its.it_interval.tv_nsec = input->repeat_rate_nsec;
|
||||
its.it_value.tv_sec = input->repeat_delay_sec;
|
||||
its.it_value.tv_nsec = input->repeat_delay_nsec;
|
||||
timerfd_settime(input->repeat_timer_fd, 0, &its, NULL);
|
||||
}
|
||||
|
||||
keyEvent = (UwacKeyEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_KEY);
|
||||
if (!keyEvent)
|
||||
return;
|
||||
|
||||
keyEvent->window = window;
|
||||
keyEvent->sym = sym;
|
||||
keyEvent->raw_key = key;
|
||||
keyEvent->pressed = (state == WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||
}
|
||||
|
||||
static void keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial,
|
||||
uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
|
||||
{
|
||||
UwacSeat *input = data;
|
||||
xkb_mod_mask_t mask;
|
||||
|
||||
/* If we're not using a keymap, then we don't handle PC-style modifiers */
|
||||
if (!input->xkb.keymap)
|
||||
return;
|
||||
|
||||
xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched, mods_locked, 0, 0, group);
|
||||
mask = xkb_state_serialize_mods(input->xkb.state, XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED);
|
||||
input->modifiers = 0;
|
||||
if (mask & input->xkb.control_mask)
|
||||
input->modifiers |= UWAC_MOD_CONTROL_MASK;
|
||||
if (mask & input->xkb.alt_mask)
|
||||
input->modifiers |= UWAC_MOD_ALT_MASK;
|
||||
if (mask & input->xkb.shift_mask)
|
||||
input->modifiers |= UWAC_MOD_SHIFT_MASK;
|
||||
}
|
||||
|
||||
static void set_repeat_info(UwacSeat *input, int32_t rate, int32_t delay)
|
||||
{
|
||||
input->repeat_rate_sec = input->repeat_rate_nsec = 0;
|
||||
input->repeat_delay_sec = input->repeat_delay_nsec = 0;
|
||||
|
||||
/* a rate of zero disables any repeating, regardless of the delay's
|
||||
* value */
|
||||
if (rate == 0)
|
||||
return;
|
||||
|
||||
if (rate == 1)
|
||||
input->repeat_rate_sec = 1;
|
||||
else
|
||||
input->repeat_rate_nsec = 1000000000 / rate;
|
||||
|
||||
input->repeat_delay_sec = delay / 1000;
|
||||
delay -= (input->repeat_delay_sec * 1000);
|
||||
input->repeat_delay_nsec = delay * 1000 * 1000;
|
||||
}
|
||||
|
||||
|
||||
static void keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard,
|
||||
int32_t rate, int32_t delay)
|
||||
{
|
||||
UwacSeat *input = data;
|
||||
|
||||
set_repeat_info(input, rate, delay);
|
||||
}
|
||||
|
||||
static const struct wl_keyboard_listener keyboard_listener = {
|
||||
keyboard_handle_keymap,
|
||||
keyboard_handle_enter,
|
||||
keyboard_handle_leave,
|
||||
keyboard_handle_key,
|
||||
keyboard_handle_modifiers,
|
||||
keyboard_handle_repeat_info
|
||||
};
|
||||
|
||||
static bool touch_send_start_frame(UwacSeat *seat) {
|
||||
UwacTouchFrameBegin *ev;
|
||||
|
||||
ev = (UwacTouchFrameBegin *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_FRAME_BEGIN);
|
||||
if (!ev)
|
||||
return false;
|
||||
|
||||
seat->touch_frame_started = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void touch_handle_down(void *data, struct wl_touch *wl_touch,
|
||||
uint32_t serial, uint32_t time, struct wl_surface *surface,
|
||||
int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
|
||||
{
|
||||
UwacSeat *seat = data;
|
||||
UwacTouchDown *tdata;
|
||||
|
||||
seat->display->serial = serial;
|
||||
if (!seat->touch_frame_started && !touch_send_start_frame(seat))
|
||||
return;
|
||||
|
||||
tdata = (UwacTouchDown *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_DOWN);
|
||||
if (!tdata)
|
||||
return;
|
||||
|
||||
tdata->seat = seat;
|
||||
tdata->id = id;
|
||||
tdata->x = x_w;
|
||||
tdata->y = y_w;
|
||||
|
||||
#if 0
|
||||
struct widget *widget;
|
||||
float sx = wl_fixed_to_double(x);
|
||||
float sy = wl_fixed_to_double(y);
|
||||
|
||||
|
||||
input->touch_focus = wl_surface_get_user_data(surface);
|
||||
if (!input->touch_focus) {
|
||||
DBG("Failed to find to touch focus for surface %p\n", surface);
|
||||
return;
|
||||
}
|
||||
|
||||
if (surface != input->touch_focus->main_surface->surface) {
|
||||
DBG("Ignoring input event from subsurface %p\n", surface);
|
||||
input->touch_focus = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (input->grab)
|
||||
widget = input->grab;
|
||||
else
|
||||
widget = window_find_widget(input->touch_focus,
|
||||
wl_fixed_to_double(x),
|
||||
wl_fixed_to_double(y));
|
||||
if (widget) {
|
||||
struct touch_point *tp = xmalloc(sizeof *tp);
|
||||
if (tp) {
|
||||
tp->id = id;
|
||||
tp->widget = widget;
|
||||
tp->x = sx;
|
||||
tp->y = sy;
|
||||
wl_list_insert(&input->touch_point_list, &tp->link);
|
||||
|
||||
if (widget->touch_down_handler)
|
||||
(*widget->touch_down_handler)(widget, input,
|
||||
serial, time, id,
|
||||
sx, sy,
|
||||
widget->user_data);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void touch_handle_up(void *data, struct wl_touch *wl_touch,
|
||||
uint32_t serial, uint32_t time, int32_t id)
|
||||
{
|
||||
UwacSeat *seat = data;
|
||||
UwacTouchUp *tdata;
|
||||
|
||||
if (!seat->touch_frame_started && !touch_send_start_frame(seat))
|
||||
return;
|
||||
|
||||
tdata = (UwacTouchUp *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_UP);
|
||||
if (!tdata)
|
||||
return;
|
||||
|
||||
tdata->seat = seat;
|
||||
tdata->id = id;
|
||||
|
||||
|
||||
#if 0
|
||||
struct touch_point *tp, *tmp;
|
||||
|
||||
if (!input->touch_focus) {
|
||||
DBG("No touch focus found for touch up event!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) {
|
||||
if (tp->id != id)
|
||||
continue;
|
||||
|
||||
if (tp->widget->touch_up_handler)
|
||||
(*tp->widget->touch_up_handler)(tp->widget, input, serial,
|
||||
time, id,
|
||||
tp->widget->user_data);
|
||||
|
||||
wl_list_remove(&tp->link);
|
||||
free(tp);
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void touch_handle_motion(void *data, struct wl_touch *wl_touch,
|
||||
uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w)
|
||||
{
|
||||
UwacSeat *seat = data;
|
||||
UwacTouchMotion *tdata;
|
||||
|
||||
if (!seat->touch_frame_started && !touch_send_start_frame(seat))
|
||||
return;
|
||||
|
||||
tdata = (UwacTouchMotion *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_MOTION);
|
||||
if (!tdata)
|
||||
return;
|
||||
|
||||
tdata->seat = seat;
|
||||
tdata->id = id;
|
||||
tdata->x = x_w;
|
||||
tdata->y = y_w;
|
||||
|
||||
#if 0
|
||||
struct touch_point *tp;
|
||||
float sx = wl_fixed_to_double(x);
|
||||
float sy = wl_fixed_to_double(y);
|
||||
|
||||
DBG("touch_handle_motion: %i %i\n", id, wl_list_length(&seat->touch_point_list));
|
||||
|
||||
if (!seat->touch_focus) {
|
||||
DBG("No touch focus found for touch motion event!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wl_list_for_each(tp, &seat->touch_point_list, link) {
|
||||
if (tp->id != id)
|
||||
continue;
|
||||
|
||||
tp->x = sx;
|
||||
tp->y = sy;
|
||||
if (tp->widget->touch_motion_handler)
|
||||
(*tp->widget->touch_motion_handler)(tp->widget, seat, time,
|
||||
id, sx, sy,
|
||||
tp->widget->user_data);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void touch_handle_frame(void *data, struct wl_touch *wl_touch)
|
||||
{
|
||||
UwacSeat *seat = data;
|
||||
UwacTouchFrameEnd *ev;
|
||||
|
||||
ev = (UwacTouchFrameEnd *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_FRAME_END);
|
||||
if (!ev)
|
||||
return;
|
||||
|
||||
ev->seat = seat;
|
||||
seat->touch_frame_started = false;
|
||||
}
|
||||
|
||||
static void touch_handle_cancel(void *data, struct wl_touch *wl_touch)
|
||||
{
|
||||
UwacSeat *seat = data;
|
||||
UwacTouchCancel *ev;
|
||||
|
||||
ev = (UwacTouchCancel *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_CANCEL);
|
||||
if (!ev)
|
||||
return;
|
||||
|
||||
ev->seat = seat;
|
||||
seat->touch_frame_started = false;
|
||||
|
||||
#if 0
|
||||
struct touch_point *tp, *tmp;
|
||||
|
||||
DBG("touch_handle_cancel\n");
|
||||
|
||||
if (!input->touch_focus) {
|
||||
DBG("No touch focus found for touch cancel event!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) {
|
||||
if (tp->widget->touch_cancel_handler)
|
||||
(*tp->widget->touch_cancel_handler)(tp->widget, input,
|
||||
tp->widget->user_data);
|
||||
|
||||
wl_list_remove(&tp->link);
|
||||
free(tp);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static const struct wl_touch_listener touch_listener = {
|
||||
touch_handle_down,
|
||||
touch_handle_up,
|
||||
touch_handle_motion,
|
||||
touch_handle_frame,
|
||||
touch_handle_cancel,
|
||||
};
|
||||
|
||||
|
||||
static void pointer_handle_enter(void *data, struct wl_pointer *pointer, uint32_t serial,
|
||||
struct wl_surface *surface, wl_fixed_t sx_w, wl_fixed_t sy_w)
|
||||
{
|
||||
UwacSeat *input = data;
|
||||
UwacWindow *window;
|
||||
UwacPointerEnterLeaveEvent *event;
|
||||
|
||||
float sx = wl_fixed_to_double(sx_w);
|
||||
float sy = wl_fixed_to_double(sy_w);
|
||||
|
||||
if (!surface) {
|
||||
/* enter event for a window we've just destroyed */
|
||||
return;
|
||||
}
|
||||
|
||||
input->display->serial = serial;
|
||||
window = wl_surface_get_user_data(surface);
|
||||
if (window)
|
||||
window->pointer_enter_serial = serial;
|
||||
input->pointer_focus = window;
|
||||
input->sx = sx;
|
||||
input->sy = sy;
|
||||
|
||||
event = (UwacPointerEnterLeaveEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_ENTER);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
event->seat = input;
|
||||
event->window = window;
|
||||
event->x = sx;
|
||||
event->y = sy;
|
||||
}
|
||||
|
||||
static void pointer_handle_leave(void *data, struct wl_pointer *pointer, uint32_t serial,
|
||||
struct wl_surface *surface)
|
||||
{
|
||||
UwacPointerEnterLeaveEvent *event;
|
||||
UwacWindow *window;
|
||||
UwacSeat *input = data;
|
||||
|
||||
input->display->serial = serial;
|
||||
|
||||
event = (UwacPointerEnterLeaveEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_LEAVE);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
window = wl_surface_get_user_data(surface);
|
||||
|
||||
event->seat = input;
|
||||
event->window = window;
|
||||
|
||||
#if 0
|
||||
input_remove_pointer_focus(input);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void pointer_handle_motion(void *data, struct wl_pointer *pointer, uint32_t time,
|
||||
wl_fixed_t sx_w, wl_fixed_t sy_w)
|
||||
{
|
||||
UwacPointerMotionEvent *motion_event;
|
||||
UwacSeat *input = data;
|
||||
UwacWindow *window = input->pointer_focus;
|
||||
|
||||
float sx = wl_fixed_to_double(sx_w);
|
||||
float sy = wl_fixed_to_double(sy_w);
|
||||
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
input->sx = sx;
|
||||
input->sy = sy;
|
||||
|
||||
motion_event = (UwacPointerMotionEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_MOTION);
|
||||
if (!motion_event)
|
||||
return;
|
||||
|
||||
motion_event->seat = input;
|
||||
motion_event->window = window;
|
||||
motion_event->x = wl_fixed_to_int(sx_w);
|
||||
motion_event->y = wl_fixed_to_int(sy_w);
|
||||
}
|
||||
|
||||
static void pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
|
||||
uint32_t time, uint32_t button, uint32_t state_w)
|
||||
{
|
||||
UwacPointerButtonEvent *event;
|
||||
UwacSeat *seat = data;
|
||||
UwacWindow *window = seat->pointer_focus;
|
||||
|
||||
seat->display->serial = serial;
|
||||
|
||||
event = (UwacPointerButtonEvent *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_BUTTONS);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
event->seat = seat;
|
||||
event->window = window;
|
||||
event->x = seat->sx;
|
||||
event->y = seat->sy;
|
||||
event->button = button;
|
||||
event->state = (enum wl_pointer_button_state)state_w;
|
||||
}
|
||||
|
||||
static void pointer_handle_axis(void *data, struct wl_pointer *pointer, uint32_t time,
|
||||
uint32_t axis, wl_fixed_t value)
|
||||
{
|
||||
UwacPointerAxisEvent *event;
|
||||
UwacSeat *seat = data;
|
||||
UwacWindow *window = seat->pointer_focus;
|
||||
|
||||
if (!window)
|
||||
return;
|
||||
|
||||
event = (UwacPointerAxisEvent *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_AXIS);
|
||||
if (!event)
|
||||
return;
|
||||
|
||||
event->seat = seat;
|
||||
event->window = window;
|
||||
event->x = seat->sx;
|
||||
event->y = seat->sy;
|
||||
event->axis = axis;
|
||||
event->value = value;
|
||||
}
|
||||
|
||||
static const struct wl_pointer_listener pointer_listener = {
|
||||
pointer_handle_enter,
|
||||
pointer_handle_leave,
|
||||
pointer_handle_motion,
|
||||
pointer_handle_button,
|
||||
pointer_handle_axis,
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void seat_handle_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability caps)
|
||||
{
|
||||
UwacSeat *input = data;
|
||||
|
||||
if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
|
||||
input->pointer = wl_seat_get_pointer(seat);
|
||||
wl_pointer_set_user_data(input->pointer, input);
|
||||
wl_pointer_add_listener(input->pointer, &pointer_listener, input);
|
||||
} else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
|
||||
if (input->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION)
|
||||
wl_pointer_release(input->pointer);
|
||||
else
|
||||
wl_pointer_destroy(input->pointer);
|
||||
input->pointer = NULL;
|
||||
}
|
||||
|
||||
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
|
||||
input->keyboard = wl_seat_get_keyboard(seat);
|
||||
wl_keyboard_set_user_data(input->keyboard, input);
|
||||
wl_keyboard_add_listener(input->keyboard, &keyboard_listener, input);
|
||||
} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
|
||||
if (input->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION)
|
||||
wl_keyboard_release(input->keyboard);
|
||||
else
|
||||
wl_keyboard_destroy(input->keyboard);
|
||||
input->keyboard = NULL;
|
||||
}
|
||||
|
||||
if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) {
|
||||
input->touch = wl_seat_get_touch(seat);
|
||||
wl_touch_set_user_data(input->touch, input);
|
||||
wl_touch_add_listener(input->touch, &touch_listener, input);
|
||||
} else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch) {
|
||||
if (input->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION)
|
||||
wl_touch_release(input->touch);
|
||||
else
|
||||
wl_touch_destroy(input->touch);
|
||||
input->touch = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
seat_handle_name(void *data, struct wl_seat *seat, const char *name)
|
||||
{
|
||||
UwacSeat *input = data;
|
||||
if (input->name)
|
||||
free(input->name);
|
||||
|
||||
input->name = strdup(name);
|
||||
}
|
||||
|
||||
static const struct wl_seat_listener seat_listener = {
|
||||
seat_handle_capabilities,
|
||||
seat_handle_name,
|
||||
};
|
||||
|
||||
|
||||
UwacSeat *UwacSeatNew(UwacDisplay *d, uint32_t id, uint32_t version) {
|
||||
UwacSeat *ret;
|
||||
|
||||
ret = zalloc(sizeof(UwacSeat));
|
||||
ret->display = d;
|
||||
ret->seat_id = id;
|
||||
ret->seat_version = version;
|
||||
|
||||
wl_array_init(&ret->pressed_keys);
|
||||
ret->xkb_context = xkb_context_new(0);
|
||||
if (!ret->xkb_context) {
|
||||
fprintf(stderr, "%s: unable to allocate a xkb_context\n", __FUNCTION__);
|
||||
goto error_xkb_context;
|
||||
}
|
||||
|
||||
ret->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, version);
|
||||
wl_seat_add_listener(ret->seat, &seat_listener, ret);
|
||||
wl_seat_set_user_data(ret->seat, ret);
|
||||
|
||||
ret->repeat_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
|
||||
if (ret->repeat_timer_fd < 0) {
|
||||
fprintf(stderr, "%s: error creating repeat timer\n", __FUNCTION__);
|
||||
goto error_timer_fd;
|
||||
}
|
||||
ret->repeat_task.run = keyboard_repeat_func;
|
||||
if (UwacDisplayWatchFd(d, ret->repeat_timer_fd, EPOLLIN, &ret->repeat_task) < 0) {
|
||||
fprintf(stderr, "%s: error polling repeat timer\n", __FUNCTION__);
|
||||
goto error_watch_timerfd;
|
||||
}
|
||||
|
||||
wl_list_insert(d->seats.prev, &ret->link);
|
||||
return ret;
|
||||
|
||||
error_watch_timerfd:
|
||||
close(ret->repeat_timer_fd);
|
||||
error_timer_fd:
|
||||
wl_seat_destroy(ret->seat);
|
||||
error_xkb_context:
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void UwacSeatDestroy(UwacSeat *s) {
|
||||
if (s->seat) {
|
||||
if (s->seat_version >= WL_SEAT_RELEASE_SINCE_VERSION)
|
||||
wl_seat_release(s->seat);
|
||||
else
|
||||
wl_seat_destroy(s->seat);
|
||||
}
|
||||
s->seat = NULL;
|
||||
|
||||
free(s->name);
|
||||
wl_array_release(&s->pressed_keys);
|
||||
|
||||
xkb_state_unref(s->xkb.state);
|
||||
xkb_context_unref(s->xkb_context);
|
||||
|
||||
if (s->pointer) {
|
||||
if (s->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION)
|
||||
wl_pointer_release(s->pointer);
|
||||
else
|
||||
wl_pointer_destroy(s->pointer);
|
||||
}
|
||||
|
||||
if (s->touch) {
|
||||
if (s->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION)
|
||||
wl_touch_release(s->touch);
|
||||
else
|
||||
wl_touch_destroy(s->touch);
|
||||
}
|
||||
|
||||
if (s->keyboard) {
|
||||
if (s->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION)
|
||||
wl_keyboard_release(s->keyboard);
|
||||
else
|
||||
wl_keyboard_destroy(s->keyboard);
|
||||
}
|
||||
|
||||
wl_list_remove(&s->link);
|
||||
free(s);
|
||||
}
|
||||
|
||||
const char *UwacSeatGetName(const UwacSeat *seat) {
|
||||
return seat->name;
|
||||
}
|
236
uwac/libuwac/uwac-os.c
Normal file
236
uwac/libuwac/uwac-os.c
Normal file
@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright © 2012 Collabora, Ltd.
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is an adaptation of src/wayland-os.h from the wayland project and
|
||||
* shared/os-compatiblity.h from the weston project.
|
||||
*
|
||||
* Functions have been renamed just to prevent name clashes.
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/epoll.h>
|
||||
|
||||
#include "../config.h"
|
||||
#include "uwac-os.h"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
int uwac_os_socket_cloexec(int domain, int type, int protocol)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = socket(domain, type | SOCK_CLOEXEC, protocol);
|
||||
if (fd >= 0)
|
||||
return fd;
|
||||
if (errno != EINVAL)
|
||||
return -1;
|
||||
|
||||
fd = socket(domain, type, protocol);
|
||||
return set_cloexec_or_close(fd);
|
||||
}
|
||||
|
||||
int uwac_os_dupfd_cloexec(int fd, long minfd)
|
||||
{
|
||||
int newfd;
|
||||
|
||||
newfd = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
|
||||
if (newfd >= 0)
|
||||
return newfd;
|
||||
if (errno != EINVAL)
|
||||
return -1;
|
||||
|
||||
newfd = fcntl(fd, F_DUPFD, minfd);
|
||||
return set_cloexec_or_close(newfd);
|
||||
}
|
||||
|
||||
static ssize_t recvmsg_cloexec_fallback(int sockfd, struct msghdr *msg, int flags)
|
||||
{
|
||||
ssize_t len;
|
||||
struct cmsghdr *cmsg;
|
||||
unsigned char *data;
|
||||
int *fd;
|
||||
int *end;
|
||||
|
||||
len = recvmsg(sockfd, msg, flags);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
|
||||
if (!msg->msg_control || msg->msg_controllen == 0)
|
||||
return len;
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(msg);
|
||||
for (; cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) {
|
||||
if (cmsg->cmsg_level != SOL_SOCKET ||
|
||||
cmsg->cmsg_type != SCM_RIGHTS)
|
||||
continue;
|
||||
|
||||
data = CMSG_DATA(cmsg);
|
||||
end = (int *)(data + cmsg->cmsg_len - CMSG_LEN(0));
|
||||
for (fd = (int *)data; fd < end; ++fd)
|
||||
*fd = set_cloexec_or_close(*fd);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t uwac_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags)
|
||||
{
|
||||
ssize_t len;
|
||||
|
||||
len = recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC);
|
||||
if (len >= 0)
|
||||
return len;
|
||||
if (errno != EINVAL)
|
||||
return -1;
|
||||
|
||||
return recvmsg_cloexec_fallback(sockfd, msg, flags);
|
||||
}
|
||||
|
||||
int uwac_os_epoll_create_cloexec(void)
|
||||
{
|
||||
int fd;
|
||||
|
||||
#ifdef EPOLL_CLOEXEC
|
||||
fd = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (fd >= 0)
|
||||
return fd;
|
||||
if (errno != EINVAL)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
fd = epoll_create(1);
|
||||
return set_cloexec_or_close(fd);
|
||||
}
|
||||
|
||||
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 insufficient, errno is set to ENOSPC.
|
||||
* If posix_fallocate() is not supported, program may receive
|
||||
* SIGBUS on accessing mmap()'ed file contents instead.
|
||||
*/
|
||||
int uwac_create_anonymous_file(off_t size)
|
||||
{
|
||||
static const char template[] = "/weston-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;
|
||||
|
||||
#ifdef HAVE_POSIX_FALLOCATE
|
||||
ret = posix_fallocate(fd, 0, size);
|
||||
if (ret != 0) {
|
||||
close(fd);
|
||||
errno = ret;
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
ret = ftruncate(fd, size);
|
||||
if (ret < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return fd;
|
||||
}
|
45
uwac/libuwac/uwac-os.h
Normal file
45
uwac/libuwac/uwac-os.h
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright © 2012 Collabora, Ltd.
|
||||
* Copyright © 2014 David FORT <contact@hardening-consulting.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is an adaptation of src/wayland-os.h from the wayland project and
|
||||
* shared/os-compatiblity.h from the weston project.
|
||||
*
|
||||
* Functions have been renamed just to prevent name clashes.
|
||||
*/
|
||||
|
||||
#ifndef __UWAC_OS_H
|
||||
#define __UWAC_OS_H
|
||||
|
||||
#include <sys/socket.h>
|
||||
|
||||
int uwac_os_socket_cloexec(int domain, int type, int protocol);
|
||||
|
||||
int uwac_os_dupfd_cloexec(int fd, long minfd);
|
||||
|
||||
ssize_t uwac_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags);
|
||||
|
||||
int uwac_os_epoll_create_cloexec(void);
|
||||
|
||||
int uwac_create_anonymous_file(off_t size);
|
||||
#endif /* __UWAC_OS_H */
|
126
uwac/libuwac/uwac-output.c
Normal file
126
uwac/libuwac/uwac-output.c
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright © 2014 David FORT <contact@hardening-consulting.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
#include "uwac-priv.h"
|
||||
#include "uwac-utils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#define TARGET_OUTPUT_INTERFACE 2
|
||||
|
||||
static void output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
|
||||
int physical_width, int physical_height, int subpixel,
|
||||
const char *make, const char *model, int transform)
|
||||
{
|
||||
UwacOutput *output = data;
|
||||
|
||||
/* output->allocation.x = x;
|
||||
output->allocation.y = y;*/
|
||||
output->transform = transform;
|
||||
|
||||
if (output->make)
|
||||
free(output->make);
|
||||
output->make = strdup(make);
|
||||
if (!output->make) {
|
||||
assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY, "%s: unable to strdup make\n", __FUNCTION__));
|
||||
}
|
||||
|
||||
if (output->model)
|
||||
free(output->model);
|
||||
output->model = strdup(model);
|
||||
if (!output->model) {
|
||||
assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY, "%s: unable to strdup model\n", __FUNCTION__));
|
||||
}
|
||||
}
|
||||
|
||||
static void output_handle_done(void *data, struct wl_output *wl_output)
|
||||
{
|
||||
UwacOutput *output = data;
|
||||
|
||||
output->doneReceived = true;
|
||||
}
|
||||
|
||||
static void output_handle_scale(void *data, struct wl_output *wl_output, int32_t scale)
|
||||
{
|
||||
UwacOutput *output = data;
|
||||
|
||||
output->scale = scale;
|
||||
}
|
||||
|
||||
static void output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
|
||||
int width, int height, int refresh)
|
||||
{
|
||||
UwacOutput *output = data;
|
||||
//UwacDisplay *display = output->display;
|
||||
|
||||
if (output->doneNeeded && output->doneReceived) {
|
||||
/* TODO: we should clear the mode list */
|
||||
}
|
||||
|
||||
if (flags & WL_OUTPUT_MODE_CURRENT) {
|
||||
output->resolution.width = width;
|
||||
output->resolution.height = height;
|
||||
/* output->allocation.width = width;
|
||||
output->allocation.height = height;
|
||||
if (display->output_configure_handler)
|
||||
(*display->output_configure_handler)(
|
||||
output, display->user_data);*/
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_output_listener output_listener = {
|
||||
output_handle_geometry,
|
||||
output_handle_mode,
|
||||
output_handle_done,
|
||||
output_handle_scale
|
||||
};
|
||||
|
||||
UwacOutput *UwacCreateOutput(UwacDisplay *d, uint32_t id, uint32_t version) {
|
||||
UwacOutput *o;
|
||||
|
||||
o = zalloc(sizeof *o);
|
||||
if (!o)
|
||||
return NULL;
|
||||
|
||||
o->display = d;
|
||||
o->server_output_id = id;
|
||||
o->doneNeeded = (version > 1);
|
||||
o->doneReceived = false;
|
||||
o->output = wl_registry_bind(d->registry, id, &wl_output_interface, min(TARGET_OUTPUT_INTERFACE, version));
|
||||
wl_output_add_listener(o->output, &output_listener, o);
|
||||
|
||||
wl_list_insert(d->outputs.prev, &o->link);
|
||||
return o;
|
||||
}
|
||||
|
||||
int UwacDestroyOutput(UwacOutput *output) {
|
||||
free(output->make);
|
||||
free(output->model);
|
||||
|
||||
wl_output_destroy(output->output);
|
||||
wl_list_remove(&output->link);
|
||||
free(output);
|
||||
|
||||
return UWAC_SUCCESS;
|
||||
}
|
237
uwac/libuwac/uwac-priv.h
Normal file
237
uwac/libuwac/uwac-priv.h
Normal file
@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright © 2014 David FORT <contact@hardening-consulting.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __UWAC_PRIV_H_
|
||||
#define __UWAC_PRIV_H_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <wayland-client.h>
|
||||
#include "xdg-shell-client-protocol.h"
|
||||
#ifdef BUILD_IVI
|
||||
#include "ivi-application-client-protocol.h"
|
||||
#endif
|
||||
#ifdef BUILD_FULLSCREEN_SHELL
|
||||
#include "fullscreen-shell-client-protocol.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_PIXMAN_REGION
|
||||
#include <pixman-1/pixman.h>
|
||||
#else
|
||||
#include <freerdp/codec/region.h>
|
||||
#endif
|
||||
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
|
||||
#include <uwac/uwac.h>
|
||||
|
||||
|
||||
extern UwacErrorHandler uwacErrorHandler;
|
||||
|
||||
typedef struct uwac_task UwacTask;
|
||||
|
||||
/** @brief */
|
||||
struct uwac_task {
|
||||
void (*run)(UwacTask *task, uint32_t events);
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
/** @brief a global registry object */
|
||||
struct uwac_global {
|
||||
uint32_t name;
|
||||
char *interface;
|
||||
uint32_t version;
|
||||
struct wl_list link;
|
||||
};
|
||||
typedef struct uwac_global UwacGlobal;
|
||||
|
||||
struct uwac_event_list_item;
|
||||
typedef struct uwac_event_list_item UwacEventListItem;
|
||||
|
||||
/** @brief */
|
||||
struct uwac_event_list_item {
|
||||
UwacEvent event;
|
||||
UwacEventListItem *tail, *head;
|
||||
};
|
||||
|
||||
|
||||
/** @brief main connection object to a wayland display */
|
||||
struct uwac_display {
|
||||
struct wl_list globals;
|
||||
|
||||
struct wl_display *display;
|
||||
struct wl_registry *registry;
|
||||
struct wl_compositor *compositor;
|
||||
struct wl_subcompositor *subcompositor;
|
||||
struct wl_shell *shell;
|
||||
struct xdg_shell *xdg_shell;
|
||||
#ifdef BUILD_IVI
|
||||
struct ivi_application *ivi_application;
|
||||
#endif
|
||||
#ifdef BUILD_FULLSCREEN_SHELL
|
||||
struct _wl_fullscreen_shell *fullscreen_shell;
|
||||
#endif
|
||||
|
||||
struct wl_shm *shm;
|
||||
enum wl_shm_format *shm_formats;
|
||||
uint32_t shm_formats_nb;
|
||||
bool has_rgb565;
|
||||
|
||||
struct wl_data_device_manager *data_device_manager;
|
||||
struct text_cursor_position *text_cursor_position;
|
||||
struct workspace_manager *workspace_manager;
|
||||
|
||||
struct wl_list seats;
|
||||
|
||||
int display_fd;
|
||||
UwacReturnCode last_error;
|
||||
uint32_t display_fd_events;
|
||||
int epoll_fd;
|
||||
bool running;
|
||||
UwacTask dispatch_fd_task;
|
||||
uint32_t serial;
|
||||
|
||||
struct wl_cursor_theme *cursor_theme;
|
||||
struct wl_cursor **cursors;
|
||||
|
||||
struct wl_list windows;
|
||||
|
||||
struct wl_list outputs;
|
||||
|
||||
UwacEventListItem *push_queue, *pop_queue;
|
||||
};
|
||||
|
||||
/** @brief an output on a wayland display */
|
||||
struct uwac_output {
|
||||
UwacDisplay *display;
|
||||
|
||||
bool doneNeeded;
|
||||
bool doneReceived;
|
||||
|
||||
UwacSize resolution;
|
||||
int transform;
|
||||
int scale;
|
||||
char *make;
|
||||
char *model;
|
||||
uint32_t server_output_id;
|
||||
struct wl_output *output;
|
||||
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
/** @brief a seat attached to a wayland display */
|
||||
struct uwac_seat {
|
||||
UwacDisplay *display;
|
||||
char *name;
|
||||
struct wl_seat *seat;
|
||||
uint32_t seat_id;
|
||||
uint32_t seat_version;
|
||||
struct wl_pointer *pointer;
|
||||
struct wl_keyboard *keyboard;
|
||||
struct wl_touch *touch;
|
||||
struct xkb_context *xkb_context;
|
||||
|
||||
struct {
|
||||
struct xkb_keymap *keymap;
|
||||
struct xkb_state *state;
|
||||
xkb_mod_mask_t control_mask;
|
||||
xkb_mod_mask_t alt_mask;
|
||||
xkb_mod_mask_t shift_mask;
|
||||
} xkb;
|
||||
uint32_t modifiers;
|
||||
int32_t repeat_rate_sec, repeat_rate_nsec;
|
||||
int32_t repeat_delay_sec, repeat_delay_nsec;
|
||||
uint32_t repeat_sym, repeat_key, repeat_time;
|
||||
|
||||
struct wl_array pressed_keys;
|
||||
|
||||
UwacWindow *pointer_focus;
|
||||
|
||||
UwacWindow *keyboard_focus;
|
||||
|
||||
UwacWindow *touch_focus;
|
||||
bool touch_frame_started;
|
||||
|
||||
int repeat_timer_fd;
|
||||
UwacTask repeat_task;
|
||||
float sx, sy;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
|
||||
/** @brief a buffer used for drawing a surface frame */
|
||||
struct uwac_buffer {
|
||||
bool used;
|
||||
#ifdef HAVE_PIXMAN_REGION
|
||||
pixman_region32_t damage;
|
||||
#else
|
||||
REGION16 damage;
|
||||
#endif
|
||||
struct wl_buffer *wayland_buffer;
|
||||
void *data;
|
||||
};
|
||||
typedef struct uwac_buffer UwacBuffer;
|
||||
|
||||
|
||||
/** @brief a window */
|
||||
struct uwac_window {
|
||||
UwacDisplay *display;
|
||||
int width, height, stride;
|
||||
int surfaceStates;
|
||||
enum wl_shm_format format;
|
||||
|
||||
int nbuffers;
|
||||
UwacBuffer *buffers;
|
||||
|
||||
struct wl_region *opaque_region;
|
||||
struct wl_region *input_region;
|
||||
struct wl_callback *frame_callback;
|
||||
UwacBuffer *drawingBuffer, *pendingBuffer;
|
||||
struct wl_surface *surface;
|
||||
struct wl_shell_surface *shell_surface;
|
||||
struct xdg_surface *xdg_surface;
|
||||
#ifdef BUILD_IVI
|
||||
struct ivi_surface *ivi_surface;
|
||||
#endif
|
||||
struct wl_list link;
|
||||
|
||||
uint32_t pointer_enter_serial;
|
||||
uint32_t pointer_cursor_serial;
|
||||
int pointer_current_cursor;
|
||||
};
|
||||
|
||||
|
||||
/* in uwa-display.c */
|
||||
UwacEvent *UwacDisplayNewEvent(UwacDisplay *d, int type);
|
||||
int UwacDisplayWatchFd(UwacDisplay *display, int fd, uint32_t events, UwacTask *task);
|
||||
|
||||
|
||||
/* in uwac-input.c */
|
||||
UwacSeat *UwacSeatNew(UwacDisplay *d, uint32_t id, uint32_t version);
|
||||
void UwacSeatDestroy(UwacSeat *s);
|
||||
|
||||
/* in uwac-output.c */
|
||||
UwacOutput *UwacCreateOutput(UwacDisplay *d, uint32_t id, uint32_t version);
|
||||
int UwacDestroyOutput(UwacOutput *output);
|
||||
|
||||
#endif /* __UWAC_PRIV_H_ */
|
93
uwac/libuwac/uwac-tools.c
Normal file
93
uwac/libuwac/uwac-tools.c
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright © 2015 David FORT <contact@hardening-consulting.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <wayland-util.h>
|
||||
#include <string.h>
|
||||
#include <uwac/uwac-tools.h>
|
||||
|
||||
/** @brief */
|
||||
struct uwac_touch_automata {
|
||||
struct wl_array tp;
|
||||
};
|
||||
|
||||
void UwacTouchAutomataInit(UwacTouchAutomata *automata) {
|
||||
wl_array_init(&automata->tp);
|
||||
}
|
||||
|
||||
void UwacTouchAutomataReset(UwacTouchAutomata *automata) {
|
||||
automata->tp.size = 0;
|
||||
}
|
||||
|
||||
bool UwacTouchAutomataInjectEvent(UwacTouchAutomata *automata, UwacEvent *event) {
|
||||
|
||||
UwacTouchPoint *tp;
|
||||
|
||||
switch (event->type) {
|
||||
case UWAC_EVENT_TOUCH_FRAME_BEGIN:
|
||||
break;
|
||||
|
||||
case UWAC_EVENT_TOUCH_UP: {
|
||||
UwacTouchUp *touchUp = &event->touchUp;
|
||||
int toMove = automata->tp.size - sizeof(UwacTouchPoint);
|
||||
|
||||
wl_array_for_each(tp, &automata->tp) {
|
||||
if (tp->id == touchUp->id) {
|
||||
if (toMove)
|
||||
memmove(tp, tp+1, toMove);
|
||||
return true;
|
||||
}
|
||||
|
||||
toMove -= sizeof(UwacTouchPoint);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case UWAC_EVENT_TOUCH_DOWN: {
|
||||
UwacTouchDown *touchDown = &event->touchDown;
|
||||
|
||||
wl_array_for_each(tp, &automata->tp) {
|
||||
if (tp->id == touchDown->id) {
|
||||
tp->x = touchDown->x;
|
||||
tp->y = touchDown->y;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
tp = wl_array_add(&automata->tp, sizeof(UwacTouchPoint));
|
||||
if (!tp)
|
||||
return false;
|
||||
|
||||
tp->id = touchDown->id;
|
||||
tp->x = touchDown->x;
|
||||
tp->y = touchDown->y;
|
||||
break;
|
||||
}
|
||||
|
||||
case UWAC_EVENT_TOUCH_FRAME_END:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
63
uwac/libuwac/uwac-utils.c
Normal file
63
uwac/libuwac/uwac-utils.c
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright © 2012 Collabora, Ltd.
|
||||
* Copyright © 2008 Kristian Høgsberg
|
||||
* Copyright © 2014 David FORT <contact@hardening-consulting.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "uwac-utils.h"
|
||||
|
||||
/*
|
||||
* This part is an adaptation of client/window.c from the weston project.
|
||||
*/
|
||||
|
||||
void *fail_on_null(void *p) {
|
||||
if (p == NULL) {
|
||||
fprintf(stderr, "out of memory\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
void *xmalloc(size_t s) {
|
||||
return fail_on_null(malloc(s));
|
||||
}
|
||||
|
||||
void *xzalloc(size_t s) {
|
||||
return fail_on_null(zalloc(s));
|
||||
}
|
||||
|
||||
char *xstrdup(const char *s) {
|
||||
return fail_on_null(strdup(s));
|
||||
}
|
||||
|
||||
void *xrealloc(char *p, size_t s) {
|
||||
return fail_on_null(realloc(p, s));
|
||||
}
|
||||
|
||||
|
53
uwac/libuwac/uwac-utils.h
Normal file
53
uwac/libuwac/uwac-utils.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright © 2014 David FORT <contact@hardening-consulting.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __UWAC_UTILS_H_
|
||||
#define __UWAC_UTILS_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define min(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a < _b ? _a : _b; })
|
||||
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||
|
||||
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||
|
||||
|
||||
|
||||
void *xmalloc(size_t s);
|
||||
|
||||
static inline void *zalloc(size_t size) {
|
||||
return calloc(1, size);
|
||||
}
|
||||
|
||||
void *xzalloc(size_t s);
|
||||
|
||||
char *xstrdup(const char *s);
|
||||
|
||||
void *xrealloc(char *p, size_t s);
|
||||
|
||||
#endif /* __UWAC_UTILS_H_ */
|
616
uwac/libuwac/uwac-window.c
Normal file
616
uwac/libuwac/uwac-window.c
Normal file
@ -0,0 +1,616 @@
|
||||
/*
|
||||
* Copyright © 2014 David FORT <contact@hardening-consulting.com>
|
||||
*
|
||||
* Permission to use, copy, modify, distribute, and sell this software and its
|
||||
* documentation for any purpose is hereby granted without fee, provided that
|
||||
* the above copyright notice appear in all copies and that both that copyright
|
||||
* notice and this permission notice appear in supporting documentation, and
|
||||
* that the name of the copyright holders not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without specific,
|
||||
* written prior permission. The copyright holders make no representations
|
||||
* about the suitability of this software for any purpose. It is provided "as
|
||||
* is" without express or implied warranty.
|
||||
*
|
||||
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
|
||||
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
|
||||
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
|
||||
* OF THIS SOFTWARE.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "uwac-priv.h"
|
||||
#include "uwac-utils.h"
|
||||
#include "uwac-os.h"
|
||||
|
||||
|
||||
#define UWAC_INITIAL_BUFFERS 3
|
||||
|
||||
|
||||
static int bppFromShmFormat(enum wl_shm_format format) {
|
||||
switch (format) {
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void buffer_release(void *data, struct wl_buffer *buffer) {
|
||||
UwacBuffer *uwacBuffer = (UwacBuffer *)data;
|
||||
|
||||
uwacBuffer->used = false;
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener buffer_listener = {
|
||||
buffer_release
|
||||
};
|
||||
|
||||
void UwacWindowDestroyBuffers(UwacWindow *w) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < w->nbuffers; i++) {
|
||||
UwacBuffer *buffer = &w->buffers[i];
|
||||
#ifdef HAVE_PIXMAN_REGION
|
||||
pixman_region32_fini(&buffer->damage);
|
||||
#else
|
||||
region16_uninit(&buffer->damage);
|
||||
#endif
|
||||
wl_buffer_destroy(buffer->wayland_buffer);
|
||||
}
|
||||
|
||||
w->nbuffers = 0;
|
||||
free(w->buffers);
|
||||
w->buffers = NULL;
|
||||
}
|
||||
|
||||
|
||||
int UwacWindowShmAllocBuffers(UwacWindow *w, int nbuffers, int allocSize, uint32_t width,
|
||||
uint32_t height, enum wl_shm_format format);
|
||||
|
||||
static void xdg_handle_configure(void *data, struct xdg_surface *surface,
|
||||
int32_t width, int32_t height,
|
||||
struct wl_array *states, uint32_t serial)
|
||||
{
|
||||
UwacWindow *window = (UwacWindow *)data;
|
||||
UwacConfigureEvent *event;
|
||||
int ret, surfaceState;
|
||||
enum xdg_surface_state *state;
|
||||
|
||||
surfaceState = 0;
|
||||
wl_array_for_each(state, states) {
|
||||
switch (*state) {
|
||||
case XDG_SURFACE_STATE_MAXIMIZED:
|
||||
surfaceState |= UWAC_WINDOW_MAXIMIZED;
|
||||
break;
|
||||
case XDG_SURFACE_STATE_FULLSCREEN:
|
||||
surfaceState |= UWAC_WINDOW_FULLSCREEN;
|
||||
break;
|
||||
case XDG_SURFACE_STATE_ACTIVATED:
|
||||
surfaceState |= UWAC_WINDOW_ACTIVATED;
|
||||
break;
|
||||
case XDG_SURFACE_STATE_RESIZING:
|
||||
surfaceState |= UWAC_WINDOW_RESIZING;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
window->surfaceStates = surfaceState;
|
||||
|
||||
event = (UwacConfigureEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE);
|
||||
if(!event) {
|
||||
assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY, "failed to allocate a configure event\n"));
|
||||
goto ack;
|
||||
}
|
||||
|
||||
event->window = window;
|
||||
event->states = surfaceState;
|
||||
if (width && height) {
|
||||
event->width = width;
|
||||
event->height = height;
|
||||
|
||||
UwacWindowDestroyBuffers(window);
|
||||
|
||||
window->width = width;
|
||||
window->stride = width * bppFromShmFormat(window->format);
|
||||
window->height = height;
|
||||
|
||||
ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height,
|
||||
width, height, window->format);
|
||||
if (ret != UWAC_SUCCESS) {
|
||||
assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
|
||||
window->drawingBuffer = window->pendingBuffer = NULL;
|
||||
goto ack;
|
||||
}
|
||||
window->drawingBuffer = window->pendingBuffer = &window->buffers[0];
|
||||
} else {
|
||||
event->width = window->width;
|
||||
event->height = window->height;
|
||||
}
|
||||
|
||||
ack:
|
||||
xdg_surface_ack_configure(surface, serial);
|
||||
}
|
||||
|
||||
static void xdg_handle_close(void *data, struct xdg_surface *xdg_surface)
|
||||
{
|
||||
UwacCloseEvent *event;
|
||||
UwacWindow *window = (UwacWindow *)data;
|
||||
|
||||
event = (UwacCloseEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CLOSE);
|
||||
if(!event) {
|
||||
assert(uwacErrorHandler(window->display, UWAC_ERROR_INTERNAL, "failed to allocate a close event\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
event->window = window;
|
||||
}
|
||||
|
||||
static const struct xdg_surface_listener xdg_surface_listener = {
|
||||
xdg_handle_configure,
|
||||
xdg_handle_close,
|
||||
};
|
||||
|
||||
#if BUILD_IVI
|
||||
|
||||
static void ivi_handle_configure(void *data, struct ivi_surface *surface,
|
||||
int32_t width, int32_t height)
|
||||
{
|
||||
UwacWindow *window = (UwacWindow *)data;
|
||||
UwacConfigureEvent *event;
|
||||
int ret;
|
||||
|
||||
|
||||
event = (UwacConfigureEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE);
|
||||
if(!event) {
|
||||
assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY, "failed to allocate a configure event\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
event->window = window;
|
||||
event->states = 0;
|
||||
if (width && height) {
|
||||
event->width = width;
|
||||
event->height = height;
|
||||
|
||||
UwacWindowDestroyBuffers(window);
|
||||
|
||||
window->width = width;
|
||||
window->stride = width * bppFromShmFormat(window->format);
|
||||
window->height = height;
|
||||
|
||||
ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height,
|
||||
width, height, window->format);
|
||||
if (ret != UWAC_SUCCESS) {
|
||||
assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
|
||||
window->drawingBuffer = window->pendingBuffer = NULL;
|
||||
return;
|
||||
}
|
||||
window->drawingBuffer = window->pendingBuffer = &window->buffers[0];
|
||||
} else {
|
||||
event->width = window->width;
|
||||
event->height = window->height;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct ivi_surface_listener ivi_surface_listener = {
|
||||
ivi_handle_configure,
|
||||
};
|
||||
#endif
|
||||
|
||||
void shell_ping(void *data, struct wl_shell_surface *surface, uint32_t serial)
|
||||
{
|
||||
wl_shell_surface_pong(surface, serial);
|
||||
}
|
||||
|
||||
void shell_configure(void *data, struct wl_shell_surface *surface, uint32_t edges,
|
||||
int32_t width, int32_t height)
|
||||
{
|
||||
UwacWindow *window = (UwacWindow *)data;
|
||||
UwacConfigureEvent *event;
|
||||
int ret;
|
||||
|
||||
event = (UwacConfigureEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE);
|
||||
if(!event) {
|
||||
assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY, "failed to allocate a configure event\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
event->window = window;
|
||||
event->states = 0;
|
||||
if (width && height) {
|
||||
event->width = width;
|
||||
event->height = height;
|
||||
|
||||
UwacWindowDestroyBuffers(window);
|
||||
|
||||
window->width = width;
|
||||
window->stride = width * bppFromShmFormat(window->format);
|
||||
window->height = height;
|
||||
|
||||
ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height,
|
||||
width, height, window->format);
|
||||
if (ret != UWAC_SUCCESS) {
|
||||
assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n"));
|
||||
window->drawingBuffer = window->pendingBuffer = NULL;
|
||||
return;
|
||||
}
|
||||
window->drawingBuffer = window->pendingBuffer = &window->buffers[0];
|
||||
} else {
|
||||
event->width = window->width;
|
||||
event->height = window->height;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void shell_popup_done(void *data, struct wl_shell_surface *surface)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
static const struct wl_shell_surface_listener shell_listener = {
|
||||
shell_ping,
|
||||
shell_configure,
|
||||
shell_popup_done
|
||||
};
|
||||
|
||||
|
||||
int UwacWindowShmAllocBuffers(UwacWindow *w, int nbuffers, int allocSize, uint32_t width,
|
||||
uint32_t height, enum wl_shm_format format)
|
||||
{
|
||||
int ret = UWAC_SUCCESS;
|
||||
UwacBuffer *newBuffers;
|
||||
int i, fd;
|
||||
void *data;
|
||||
struct wl_shm_pool *pool;
|
||||
|
||||
newBuffers = realloc(w->buffers, (w->nbuffers + nbuffers) * sizeof(UwacBuffer));
|
||||
if (!newBuffers)
|
||||
return UWAC_ERROR_NOMEMORY;
|
||||
|
||||
w->buffers = newBuffers;
|
||||
|
||||
memset(w->buffers + w->nbuffers, 0, sizeof(UwacBuffer) * nbuffers);
|
||||
|
||||
fd = uwac_create_anonymous_file(allocSize * nbuffers);
|
||||
if (fd < 0) {
|
||||
return UWAC_ERROR_INTERNAL;
|
||||
}
|
||||
|
||||
data = mmap(NULL, allocSize * nbuffers, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
if (data == MAP_FAILED) {
|
||||
ret = UWAC_ERROR_NOMEMORY;
|
||||
goto error_mmap;
|
||||
}
|
||||
|
||||
pool = wl_shm_create_pool(w->display->shm, fd, allocSize * nbuffers);
|
||||
|
||||
for (i = 0; i < nbuffers; i++) {
|
||||
UwacBuffer *buffer = &w->buffers[w->nbuffers + i];
|
||||
#ifdef HAVE_PIXMAN_REGION
|
||||
pixman_region32_init(&buffer->damage);
|
||||
#else
|
||||
region16_init(&buffer->damage);
|
||||
#endif
|
||||
buffer->data = data + (allocSize * i);
|
||||
|
||||
buffer->wayland_buffer = wl_shm_pool_create_buffer(pool, allocSize * i, width, height, w->stride, format);
|
||||
wl_buffer_add_listener(buffer->wayland_buffer, &buffer_listener, buffer);
|
||||
|
||||
}
|
||||
|
||||
wl_shm_pool_destroy(pool);
|
||||
w->nbuffers += nbuffers;
|
||||
|
||||
error_mmap:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
UwacBuffer *UwacWindowFindFreeBuffer(UwacWindow *w) {
|
||||
int i, ret;
|
||||
|
||||
for (i = 0; i < w->nbuffers; i++) {
|
||||
if (!w->buffers[i].used) {
|
||||
w->buffers[i].used = true;
|
||||
return &w->buffers[i];
|
||||
}
|
||||
}
|
||||
|
||||
ret = UwacWindowShmAllocBuffers(w, 2, w->stride * w->height, w->width, w->height, w->format);
|
||||
if (ret != UWAC_SUCCESS) {
|
||||
w->display->last_error = ret;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
w->buffers[i].used = true;
|
||||
return &w->buffers[i];
|
||||
}
|
||||
|
||||
|
||||
UwacWindow *UwacCreateWindowShm(UwacDisplay *display, uint32_t width, uint32_t height, enum wl_shm_format format) {
|
||||
UwacWindow *w;
|
||||
int allocSize, ret;
|
||||
|
||||
if (!display) {
|
||||
display->last_error = UWAC_ERROR_INVALID_DISPLAY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
w = zalloc(sizeof(*w));
|
||||
if (!w) {
|
||||
display->last_error = UWAC_ERROR_NOMEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
w->display = display;
|
||||
w->format = format;
|
||||
w->width = width;
|
||||
w->height = height;
|
||||
w->stride = width * bppFromShmFormat(format);
|
||||
allocSize = w->stride * height;
|
||||
|
||||
ret = UwacWindowShmAllocBuffers(w, UWAC_INITIAL_BUFFERS, allocSize, width, height, format);
|
||||
if (ret != UWAC_SUCCESS) {
|
||||
display->last_error = ret;
|
||||
goto out_error_free;
|
||||
}
|
||||
|
||||
w->buffers[0].used = true;
|
||||
w->drawingBuffer = &w->buffers[0];
|
||||
|
||||
w->surface = wl_compositor_create_surface(display->compositor);
|
||||
if (!w->surface) {
|
||||
display->last_error = UWAC_ERROR_NOMEMORY;
|
||||
goto out_error_surface;
|
||||
}
|
||||
wl_surface_set_user_data(w->surface, w);
|
||||
|
||||
if (display->xdg_shell) {
|
||||
w->xdg_surface = xdg_shell_get_xdg_surface(display->xdg_shell, w->surface);
|
||||
if (!w->xdg_surface) {
|
||||
display->last_error = UWAC_ERROR_NOMEMORY;
|
||||
goto out_error_shell;
|
||||
}
|
||||
|
||||
assert(w->xdg_surface);
|
||||
|
||||
xdg_surface_add_listener(w->xdg_surface, &xdg_surface_listener, w);
|
||||
#if BUILD_IVI
|
||||
} else if (display->ivi_application) {
|
||||
w->ivi_surface = ivi_application_surface_create(display->ivi_application, 1, w->surface);
|
||||
|
||||
assert (w->ivi_surface);
|
||||
|
||||
ivi_surface_add_listener(w->ivi_surface, &ivi_surface_listener, w);
|
||||
#endif
|
||||
#if BUILD_FULLSCREEN_SHELL
|
||||
} else if (display->fullscreen_shell) {
|
||||
_wl_fullscreen_shell_present_surface(display->fullscreen_shell, w->surface,
|
||||
_WL_FULLSCREEN_SHELL_PRESENT_METHOD_CENTER, NULL);
|
||||
#endif
|
||||
} else {
|
||||
w->shell_surface = wl_shell_get_shell_surface(display->shell, w->surface);
|
||||
|
||||
assert(w->shell_surface);
|
||||
|
||||
wl_shell_surface_add_listener(w->shell_surface, &shell_listener, w);
|
||||
wl_shell_surface_set_toplevel(w->shell_surface);
|
||||
}
|
||||
|
||||
wl_list_insert(display->windows.prev, &w->link);
|
||||
|
||||
display->last_error = UWAC_SUCCESS;
|
||||
return w;
|
||||
|
||||
out_error_shell:
|
||||
wl_surface_destroy(w->surface);
|
||||
out_error_surface:
|
||||
UwacWindowDestroyBuffers(w);
|
||||
out_error_free:
|
||||
free(w);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
UwacReturnCode UwacDestroyWindow(UwacWindow **pwindow) {
|
||||
UwacWindow *w;
|
||||
|
||||
assert (pwindow);
|
||||
|
||||
w = *pwindow;
|
||||
UwacWindowDestroyBuffers(w);
|
||||
|
||||
if (w->frame_callback)
|
||||
wl_callback_destroy(w->frame_callback);
|
||||
|
||||
if (w->xdg_surface)
|
||||
xdg_surface_destroy(w->xdg_surface);
|
||||
#if BUILD_IVI
|
||||
if (w->ivi_surface)
|
||||
ivi_surface_destroy(w->ivi_surface);
|
||||
#endif
|
||||
|
||||
if (w->opaque_region)
|
||||
wl_region_destroy(w->opaque_region);
|
||||
|
||||
if (w->input_region)
|
||||
wl_region_destroy(w->opaque_region);
|
||||
|
||||
wl_surface_destroy(w->surface);
|
||||
wl_list_remove(&w->link);
|
||||
free(w);
|
||||
|
||||
*pwindow = NULL;
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width,
|
||||
uint32_t height)
|
||||
{
|
||||
assert(window);
|
||||
|
||||
if (window->opaque_region)
|
||||
wl_region_destroy(window->opaque_region);
|
||||
|
||||
window->opaque_region = wl_compositor_create_region(window->display->compositor);
|
||||
if (!window->opaque_region)
|
||||
return UWAC_ERROR_NOMEMORY;
|
||||
|
||||
wl_region_add(window->opaque_region, x, y, width, height);
|
||||
wl_surface_set_opaque_region(window->surface, window->opaque_region);
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
UwacReturnCode UwacWindowSetInputRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
|
||||
assert(window);
|
||||
|
||||
if (window->input_region)
|
||||
wl_region_destroy(window->input_region);
|
||||
|
||||
window->input_region = wl_compositor_create_region(window->display->compositor);
|
||||
if (!window->input_region)
|
||||
return UWAC_ERROR_NOMEMORY;
|
||||
|
||||
wl_region_add(window->input_region, x, y, width, height);
|
||||
wl_surface_set_input_region(window->surface, window->input_region);
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void *UwacWindowGetDrawingBuffer(UwacWindow *window) {
|
||||
return window->drawingBuffer->data;
|
||||
}
|
||||
|
||||
static void frame_done_cb(void *data, struct wl_callback *callback, uint32_t time);
|
||||
|
||||
static const struct wl_callback_listener frame_listener = {
|
||||
frame_done_cb
|
||||
};
|
||||
|
||||
|
||||
static void UwacSubmitBufferPtr(UwacWindow *window, UwacBuffer *buffer) {
|
||||
int nrects, i;
|
||||
#ifdef HAVE_PIXMAN_REGION
|
||||
const pixman_box32_t *box;
|
||||
#else
|
||||
const RECTANGLE_16 *box;
|
||||
#endif
|
||||
|
||||
wl_surface_attach(window->surface, buffer->wayland_buffer, 0, 0);
|
||||
|
||||
#ifdef HAVE_PIXMAN_REGION
|
||||
box = pixman_region32_rectangles(&buffer->damage, &nrects);
|
||||
for (i = 0; i < nrects; i++, box++)
|
||||
wl_surface_damage(window->surface, box->x1, box->y1, (box->x2 - box->x1), (box->y2 - box->y1));
|
||||
#else
|
||||
box = region16_rects(&buffer->damage, &nrects);
|
||||
for (i = 0; i < nrects; i++, box++)
|
||||
wl_surface_damage(window->surface, box->left, box->top, (box->right - box->left), (box->bottom - box->top));
|
||||
#endif
|
||||
|
||||
if (window->frame_callback)
|
||||
wl_callback_destroy(window->frame_callback);
|
||||
|
||||
window->frame_callback = wl_surface_frame(window->surface);
|
||||
wl_callback_add_listener(window->frame_callback, &frame_listener, window);
|
||||
|
||||
wl_surface_commit(window->surface);
|
||||
|
||||
#ifdef HAVE_PIXMAN_REGION
|
||||
pixman_region32_clear(&buffer->damage);
|
||||
#else
|
||||
region16_clear(&buffer->damage);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static void frame_done_cb(void *data, struct wl_callback *callback, uint32_t time) {
|
||||
UwacWindow *window = (UwacWindow *)data;
|
||||
UwacFrameDoneEvent *event;
|
||||
|
||||
window->pendingBuffer = NULL;
|
||||
event = (UwacFrameDoneEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_FRAME_DONE);
|
||||
if(event)
|
||||
event->window = window;
|
||||
}
|
||||
|
||||
|
||||
UwacReturnCode UwacWindowAddDamage(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height) {
|
||||
#ifdef HAVE_PIXMAN_REGION
|
||||
if (!pixman_region32_union_rect(&window->drawingBuffer->damage, &window->drawingBuffer->damage, x, y, width, height))
|
||||
#else
|
||||
RECTANGLE_16 box;
|
||||
box.left = x; box.top = y;
|
||||
box.right = x + width; box.bottom = y + height;
|
||||
|
||||
if (!region16_union_rect(&window->drawingBuffer->damage, &window->drawingBuffer->damage, &box))
|
||||
#endif
|
||||
return UWAC_ERROR_INTERNAL;
|
||||
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
UwacReturnCode UwacWindowSubmitBuffer(UwacWindow *window, bool copyContentForNextFrame) {
|
||||
UwacBuffer *drawingBuffer = window->drawingBuffer;
|
||||
|
||||
if (window->pendingBuffer) {
|
||||
/* we already have a pending frame, don't do anything*/
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
UwacSubmitBufferPtr(window, drawingBuffer);
|
||||
|
||||
window->pendingBuffer = window->drawingBuffer;
|
||||
window->drawingBuffer = UwacWindowFindFreeBuffer(window);
|
||||
if (!window->drawingBuffer)
|
||||
return UWAC_ERROR_NOMEMORY;
|
||||
|
||||
if (copyContentForNextFrame) {
|
||||
memcpy(window->drawingBuffer->data, window->pendingBuffer->data, window->stride * window->height);
|
||||
}
|
||||
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
UwacReturnCode UwacWindowGetGeometry(UwacWindow *window, UwacSize *geometry) {
|
||||
assert(window);
|
||||
assert(geometry);
|
||||
|
||||
geometry->width = window->width;
|
||||
geometry->height = window->height;
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
UwacReturnCode UwacWindowSetFullscreenState(UwacWindow *window, UwacOutput *output, bool isFullscreen) {
|
||||
if (window->xdg_surface) {
|
||||
if (isFullscreen) {
|
||||
xdg_surface_set_fullscreen(window->xdg_surface, output ? output->output : NULL);
|
||||
} else {
|
||||
xdg_surface_unset_fullscreen(window->xdg_surface);
|
||||
}
|
||||
}
|
||||
return UWAC_SUCCESS;
|
||||
}
|
||||
|
||||
void UwacWindowSetTitle(UwacWindow *window, const char *name) {
|
||||
if (window->xdg_surface)
|
||||
xdg_surface_set_title(window->xdg_surface, name);
|
||||
else if (window->shell_surface)
|
||||
wl_shell_surface_set_title(window->shell_surface, name);
|
||||
}
|
206
uwac/protocols/fullscreen-shell.xml
Normal file
206
uwac/protocols/fullscreen-shell.xml
Normal file
@ -0,0 +1,206 @@
|
||||
<protocol name="fullscreen_shell">
|
||||
<interface name="_wl_fullscreen_shell" version="1">
|
||||
<description summary="Displays a single surface per output">
|
||||
Displays a single surface per output.
|
||||
|
||||
This interface provides a mechanism for a single client to display
|
||||
simple full-screen surfaces. While there technically may be multiple
|
||||
clients bound to this interface, only one of those clients should be
|
||||
shown at a time.
|
||||
|
||||
To present a surface, the client uses either the present_surface or
|
||||
present_surface_for_mode requests. Presenting a surface takes effect
|
||||
on the next wl_surface.commit. See the individual requests for
|
||||
details about scaling and mode switches.
|
||||
|
||||
The client can have at most one surface per output at any time.
|
||||
Requesting a surface be presented on an output that already has a
|
||||
surface replaces the previously presented surface. Presenting a null
|
||||
surface removes its content and effectively disables the output.
|
||||
Exactly what happens when an output is "disabled" is
|
||||
compositor-specific. The same surface may be presented on multiple
|
||||
outputs simultaneously.
|
||||
|
||||
Once a surface is presented on an output, it stays on that output
|
||||
until either the client removes it or the compositor destroys the
|
||||
output. This way, the client can update the output's contents by
|
||||
simply attaching a new buffer.
|
||||
</description>
|
||||
|
||||
<request name="release" type="destructor">
|
||||
<description summary="release the wl_fullscreen_shell interface">
|
||||
Release the binding from the wl_fullscreen_shell interface
|
||||
|
||||
This destroys the server-side object and frees this binding. If
|
||||
the client binds to wl_fullscreen_shell multiple times, it may wish
|
||||
to free some of those bindings.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<enum name="capability">
|
||||
<description summary="capabilities advertised by the compositor">
|
||||
Various capabilities that can be advertised by the compositor. They
|
||||
are advertised one-at-a-time when the wl_fullscreen_shell interface is
|
||||
bound. See the wl_fullscreen_shell.capability event for more details.
|
||||
|
||||
ARBITRARY_MODE:
|
||||
This is a hint to the client that indicates that the compositor is
|
||||
capable of setting practically any mode on its outputs. If this
|
||||
capability is provided, wl_fullscreen_shell.present_surface_for_mode
|
||||
will almost never fail and clients should feel free to set whatever
|
||||
mode they like. If the compositor does not advertise this, it may
|
||||
still support some modes that are not advertised through wl_global.mode
|
||||
but it is less likely.
|
||||
|
||||
CURSOR_PLANE:
|
||||
This is a hint to the client that indicates that the compositor can
|
||||
handle a cursor surface from the client without actually compositing.
|
||||
This may be because of a hardware cursor plane or some other mechanism.
|
||||
If the compositor does not advertise this capability then setting
|
||||
wl_pointer.cursor may degrade performance or be ignored entirely. If
|
||||
CURSOR_PLANE is not advertised, it is recommended that the client draw
|
||||
its own cursor and set wl_pointer.cursor(NULL).
|
||||
</description>
|
||||
<entry name="arbitrary_modes" value="1" summary="compositor is capable of almost any output mode"/>
|
||||
<entry name="cursor_plane" value="2" summary="compositor has a separate cursor plane"/>
|
||||
</enum>
|
||||
|
||||
<event name="capability">
|
||||
<description summary="advertises a capability of the compositor">
|
||||
Advertises a single capability of the compositor.
|
||||
|
||||
When the wl_fullscreen_shell interface is bound, this event is emitted
|
||||
once for each capability advertised. Valid capabilities are given by
|
||||
the wl_fullscreen_shell.capability enum. If clients want to take
|
||||
advantage of any of these capabilities, they should use a
|
||||
wl_display.sync request immediately after binding to ensure that they
|
||||
receive all the capability events.
|
||||
</description>
|
||||
<arg name="capabilty" type="uint"/>
|
||||
</event>
|
||||
|
||||
<enum name="present_method">
|
||||
<description summary="different method to set the surface fullscreen">
|
||||
Hints to indicate to the compositor how to deal with a conflict
|
||||
between the dimensions of the surface and the dimensions of the
|
||||
output. The compositor is free to ignore this parameter.
|
||||
</description>
|
||||
<entry name="default" value="0" summary="no preference, apply default policy"/>
|
||||
<entry name="center" value="1" summary="center the surface on the output"/>
|
||||
<entry name="zoom" value="2" summary="scale the surface, preserving aspect ratio, to the largest size that will fit on the output" />
|
||||
<entry name="zoom_crop" value="3" summary="scale the surface, preserving aspect ratio, to fully fill the output cropping if needed" />
|
||||
<entry name="stretch" value="4" summary="scale the surface to the size of the output ignoring aspect ratio" />
|
||||
</enum>
|
||||
|
||||
<request name="present_surface">
|
||||
<description summary="present surface for display">
|
||||
Present a surface on the given output.
|
||||
|
||||
If the output is null, the compositor will present the surface on
|
||||
whatever display (or displays) it thinks best. In particular, this
|
||||
may replace any or all surfaces currently presented so it should
|
||||
not be used in combination with placing surfaces on specific
|
||||
outputs.
|
||||
|
||||
The method parameter is a hint to the compositor for how the surface
|
||||
is to be presented. In particular, it tells the compositor how to
|
||||
handle a size mismatch between the presented surface and the
|
||||
output. The compositor is free to ignore this parameter.
|
||||
|
||||
The "zoom", "zoom_crop", and "stretch" methods imply a scaling
|
||||
operation on the surface. This will override any kind of output
|
||||
scaling, so the buffer_scale property of the surface is effectively
|
||||
ignored.
|
||||
</description>
|
||||
<arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
|
||||
<arg name="method" type="uint"/>
|
||||
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
||||
</request>
|
||||
|
||||
<request name="present_surface_for_mode">
|
||||
<description summary="present surface for display at a particular mode">
|
||||
Presents a surface on the given output for a particular mode.
|
||||
|
||||
If the current size of the output differs from that of the surface,
|
||||
the compositor will attempt to change the size of the output to
|
||||
match the surface. The result of the mode-switch operation will be
|
||||
returned via the provided wl_fullscreen_shell_mode_feedback object.
|
||||
|
||||
If the current output mode matches the one requested or if the
|
||||
compositor successfully switches the mode to match the surface,
|
||||
then the mode_successful event will be sent and the output will
|
||||
contain the contents of the given surface. If the compositor
|
||||
cannot match the output size to the surface size, the mode_failed
|
||||
will be sent and the output will contain the contents of the
|
||||
previously presented surface (if any). If another surface is
|
||||
presented on the given output before either of these has a chance
|
||||
to happen, the present_cancelled event will be sent.
|
||||
|
||||
Due to race conditions and other issues unknown to the client, no
|
||||
mode-switch operation is guaranteed to succeed. However, if the
|
||||
mode is one advertised by wl_output.mode or if the compositor
|
||||
advertises the ARBITRARY_MODES capability, then the client should
|
||||
expect that the mode-switch operation will usually succeed.
|
||||
|
||||
If the size of the presented surface changes, the resulting output
|
||||
is undefined. The compositor may attempt to change the output mode
|
||||
to compensate. However, there is no guarantee that a suitable mode
|
||||
will be found and the client has no way to be notified of success
|
||||
or failure.
|
||||
|
||||
The framerate parameter specifies the desired framerate for the
|
||||
output in mHz. The compositor is free to ignore this parameter. A
|
||||
value of 0 indicates that the client has no preference.
|
||||
|
||||
If the value of wl_output.scale differs from wl_surface.buffer_scale,
|
||||
then the compositor may choose a mode that matches either the buffer
|
||||
size or the surface size. In either case, the surface will fill the
|
||||
output.
|
||||
</description>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="output" type="object" interface="wl_output"/>
|
||||
<arg name="framerate" type="int"/>
|
||||
<arg name="feedback" type="new_id" interface="_wl_fullscreen_shell_mode_feedback"/>
|
||||
</request>
|
||||
|
||||
<enum name="error">
|
||||
<description summary="wl_fullscreen_shell error values">
|
||||
These errors can be emitted in response to wl_fullscreen_shell requests
|
||||
</description>
|
||||
<entry name="invalid_method" value="0" summary="present_method is not known"/>
|
||||
</enum>
|
||||
</interface>
|
||||
|
||||
<interface name="_wl_fullscreen_shell_mode_feedback" version="1">
|
||||
<event name="mode_successful">
|
||||
<description summary="mode switch succeeded">
|
||||
This event indicates that the attempted mode switch operation was
|
||||
successful. A surface of the size requested in the mode switch
|
||||
will fill the output without scaling.
|
||||
|
||||
Upon receiving this event, the client should destroy the
|
||||
wl_fullscreen_shell_mode_feedback object.
|
||||
</description>
|
||||
</event>
|
||||
<event name="mode_failed">
|
||||
<description summary="mode switch failed">
|
||||
This event indicates that the attempted mode switch operation
|
||||
failed. This may be because the requested output mode is not
|
||||
possible or it may mean that the compositor does not want to allow it.
|
||||
|
||||
Upon receiving this event, the client should destroy the
|
||||
wl_fullscreen_shell_mode_feedback object.
|
||||
</description>
|
||||
</event>
|
||||
<event name="present_cancelled">
|
||||
<description summary="mode switch cancelled">
|
||||
This event indicates that the attempted mode switch operation was
|
||||
cancelled. Most likely this is because the client requested a
|
||||
second mode switch before the first one completed.
|
||||
|
||||
Upon receiving this event, the client should destroy the
|
||||
wl_fullscreen_shell_mode_feedback object.
|
||||
</description>
|
||||
</event>
|
||||
</interface>
|
||||
</protocol>
|
100
uwac/protocols/ivi-application.xml
Normal file
100
uwac/protocols/ivi-application.xml
Normal file
@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="ivi_application">
|
||||
|
||||
<copyright>
|
||||
Copyright (C) 2013 DENSO CORPORATION
|
||||
Copyright (c) 2013 BMW Car IT GmbH
|
||||
|
||||
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.
|
||||
</copyright>
|
||||
|
||||
<interface name="ivi_surface" version="1">
|
||||
<description summary="application interface to surface in ivi compositor"/>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy ivi_surface">
|
||||
This removes link from ivi_id to wl_surface and destroys ivi_surface.
|
||||
The ID, ivi_id, is free and can be used for surface_create again.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="configure">
|
||||
<description summary="suggest resize">
|
||||
The configure event asks the client to resize its surface.
|
||||
|
||||
The size is a hint, in the sense that the client is free to
|
||||
ignore it if it doesn't resize, pick a smaller size (to
|
||||
satisfy aspect ratio or resize in steps of NxM pixels).
|
||||
|
||||
The client is free to dismiss all but the last configure
|
||||
event it received.
|
||||
|
||||
The width and height arguments specify the size of the window
|
||||
in surface local coordinates.
|
||||
</description>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="ivi_application" version="1">
|
||||
<description summary="create ivi-style surfaces">
|
||||
This interface is exposed as a global singleton.
|
||||
This interface is implemented by servers that provide IVI-style user interfaces.
|
||||
It allows clients to associate a ivi_surface with wl_surface.
|
||||
</description>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="role" value="0" summary="given wl_surface has another role"/>
|
||||
<entry name="ivi_id" value="1" summary="given ivi_id is assigned to another wl_surface"/>
|
||||
</enum>
|
||||
|
||||
<request name="surface_create">
|
||||
<description summary="create ivi_surface with numeric ID in ivi compositor">
|
||||
This request gives the wl_surface the role of an IVI Surface. Creating more than
|
||||
one ivi_surface for a wl_surface is not allowed. Note, that this still allows the
|
||||
following example:
|
||||
|
||||
1. create a wl_surface
|
||||
2. create ivi_surface for the wl_surface
|
||||
3. destroy the ivi_surface
|
||||
4. create ivi_surface for the wl_surface (with the same or another ivi_id as before)
|
||||
|
||||
surface_create will create a interface:ivi_surface with numeric ID; ivi_id in
|
||||
ivi compositor. These ivi_ids are defined as unique in the system to identify
|
||||
it inside of ivi compositor. The ivi compositor implements business logic how to
|
||||
set properties of the surface with ivi_id according to status of the system.
|
||||
E.g. a unique ID for Car Navigation application is used for implementing special
|
||||
logic of the application about where it shall be located.
|
||||
The server regards following cases as protocol errors and disconnects the client.
|
||||
- wl_surface already has an nother role.
|
||||
- ivi_id is already assigned to an another wl_surface.
|
||||
|
||||
If client destroys ivi_surface or wl_surface which is assigne to the ivi_surface,
|
||||
ivi_id which is assigned to the ivi_surface is free for reuse.
|
||||
</description>
|
||||
<arg name="ivi_id" type="uint"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="id" type="new_id" interface="ivi_surface"/>
|
||||
</request>
|
||||
|
||||
</interface>
|
||||
|
||||
</protocol>
|
608
uwac/protocols/xdg-shell.xml
Normal file
608
uwac/protocols/xdg-shell.xml
Normal file
@ -0,0 +1,608 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="xdg_shell">
|
||||
|
||||
<copyright>
|
||||
Copyright © 2008-2013 Kristian Høgsberg
|
||||
Copyright © 2013 Rafael Antognolli
|
||||
Copyright © 2013 Jasper St. Pierre
|
||||
Copyright © 2010-2013 Intel Corporation
|
||||
|
||||
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.
|
||||
</copyright>
|
||||
|
||||
<interface name="xdg_shell" version="1">
|
||||
<description summary="create desktop-style surfaces">
|
||||
xdg_shell allows clients to turn a wl_surface into a "real window"
|
||||
which can be dragged, resized, stacked, and moved around by the
|
||||
user. Everything about this interface is suited towards traditional
|
||||
desktop environments.
|
||||
</description>
|
||||
|
||||
<enum name="version">
|
||||
<description summary="latest protocol version">
|
||||
The 'current' member of this enum gives the version of the
|
||||
protocol. Implementations can compare this to the version
|
||||
they implement using static_assert to ensure the protocol and
|
||||
implementation versions match.
|
||||
</description>
|
||||
<entry name="current" value="5" summary="Always the latest version"/>
|
||||
</enum>
|
||||
|
||||
<enum name="error">
|
||||
<entry name="role" value="0" summary="given wl_surface has another role"/>
|
||||
<entry name="defunct_surfaces" value="1" summary="xdg_shell was destroyed before children"/>
|
||||
<entry name="not_the_topmost_popup" value="2" summary="the client tried to map or destroy a non-topmost popup"/>
|
||||
<entry name="invalid_popup_parent" value="3" summary="the client specified an invalid popup parent surface"/>
|
||||
</enum>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy xdg_shell">
|
||||
Destroy this xdg_shell object.
|
||||
|
||||
Destroying a bound xdg_shell object while there are surfaces
|
||||
still alive created by this xdg_shell object instance is illegal
|
||||
and will result in a protocol error.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="use_unstable_version">
|
||||
<description summary="enable use of this unstable version">
|
||||
Negotiate the unstable version of the interface. This
|
||||
mechanism is in place to ensure client and server agree on the
|
||||
unstable versions of the protocol that they speak or exit
|
||||
cleanly if they don't agree. This request will go away once
|
||||
the xdg-shell protocol is stable.
|
||||
</description>
|
||||
<arg name="version" type="int"/>
|
||||
</request>
|
||||
|
||||
<request name="get_xdg_surface">
|
||||
<description summary="create a shell surface from a surface">
|
||||
This creates an xdg_surface for the given surface and gives it the
|
||||
xdg_surface role. A wl_surface can only be given an xdg_surface role
|
||||
once. If get_xdg_surface is called with a wl_surface that already has
|
||||
an active xdg_surface associated with it, or if it had any other role,
|
||||
an error is raised.
|
||||
|
||||
See the documentation of xdg_surface for more details about what an
|
||||
xdg_surface is and how it is used.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="xdg_surface"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
</request>
|
||||
|
||||
<request name="get_xdg_popup">
|
||||
<description summary="create a popup for a surface">
|
||||
This creates an xdg_popup for the given surface and gives it the
|
||||
xdg_popup role. A wl_surface can only be given an xdg_popup role
|
||||
once. If get_xdg_popup is called with a wl_surface that already has
|
||||
an active xdg_popup associated with it, or if it had any other role,
|
||||
an error is raised.
|
||||
|
||||
This request must be used in response to some sort of user action
|
||||
like a button press, key press, or touch down event.
|
||||
|
||||
See the documentation of xdg_popup for more details about what an
|
||||
xdg_popup is and how it is used.
|
||||
</description>
|
||||
<arg name="id" type="new_id" interface="xdg_popup"/>
|
||||
<arg name="surface" type="object" interface="wl_surface"/>
|
||||
<arg name="parent" type="object" interface="wl_surface"/>
|
||||
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
|
||||
<arg name="serial" type="uint" summary="the serial of the user event"/>
|
||||
<arg name="x" type="int"/>
|
||||
<arg name="y" type="int"/>
|
||||
</request>
|
||||
|
||||
<event name="ping">
|
||||
<description summary="check if the client is alive">
|
||||
The ping event asks the client if it's still alive. Pass the
|
||||
serial specified in the event back to the compositor by sending
|
||||
a "pong" request back with the specified serial.
|
||||
|
||||
Compositors can use this to determine if the client is still
|
||||
alive. It's unspecified what will happen if the client doesn't
|
||||
respond to the ping request, or in what timeframe. Clients should
|
||||
try to respond in a reasonable amount of time.
|
||||
|
||||
A compositor is free to ping in any way it wants, but a client must
|
||||
always respond to any xdg_shell object it created.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="pass this to the pong request"/>
|
||||
</event>
|
||||
|
||||
<request name="pong">
|
||||
<description summary="respond to a ping event">
|
||||
A client must respond to a ping event with a pong request or
|
||||
the client may be deemed unresponsive.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="serial of the ping event"/>
|
||||
</request>
|
||||
</interface>
|
||||
|
||||
<interface name="xdg_surface" version="1">
|
||||
<description summary="A desktop window">
|
||||
An interface that may be implemented by a wl_surface, for
|
||||
implementations that provide a desktop-style user interface.
|
||||
|
||||
It provides requests to treat surfaces like windows, allowing to set
|
||||
properties like maximized, fullscreen, minimized, and to move and resize
|
||||
them, and associate metadata like title and app id.
|
||||
|
||||
The client must call wl_surface.commit on the corresponding wl_surface
|
||||
for the xdg_surface state to take effect. Prior to committing the new
|
||||
state, it can set up initial configuration, such as maximizing or setting
|
||||
a window geometry.
|
||||
|
||||
Even without attaching a buffer the compositor must respond to initial
|
||||
committed configuration, for instance sending a configure event with
|
||||
expected window geometry if the client maximized its surface during
|
||||
initialization.
|
||||
|
||||
For a surface to be mapped by the compositor the client must have
|
||||
committed both an xdg_surface state and a buffer.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="Destroy the xdg_surface">
|
||||
Unmap and destroy the window. The window will be effectively
|
||||
hidden from the user's point of view, and all state like
|
||||
maximization, fullscreen, and so on, will be lost.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_parent">
|
||||
<description summary="set the parent of this surface">
|
||||
Set the "parent" of this surface. This window should be stacked
|
||||
above a parent. The parent surface must be mapped as long as this
|
||||
surface is mapped.
|
||||
|
||||
Parent windows should be set on dialogs, toolboxes, or other
|
||||
"auxiliary" surfaces, so that the parent is raised when the dialog
|
||||
is raised.
|
||||
</description>
|
||||
<arg name="parent" type="object" interface="xdg_surface" allow-null="true"/>
|
||||
</request>
|
||||
|
||||
<request name="set_title">
|
||||
<description summary="set surface title">
|
||||
Set a short title for the surface.
|
||||
|
||||
This string may be used to identify the surface in a task bar,
|
||||
window list, or other user interface elements provided by the
|
||||
compositor.
|
||||
|
||||
The string must be encoded in UTF-8.
|
||||
</description>
|
||||
<arg name="title" type="string"/>
|
||||
</request>
|
||||
|
||||
<request name="set_app_id">
|
||||
<description summary="set application ID">
|
||||
Set an application identifier for the surface.
|
||||
|
||||
The app ID identifies the general class of applications to which
|
||||
the surface belongs. The compositor can use this to group multiple
|
||||
surfaces together, or to determine how to launch a new application.
|
||||
|
||||
For D-Bus activatable applications, the app ID is used as the D-Bus
|
||||
service name.
|
||||
|
||||
The compositor shell will try to group application surfaces together
|
||||
by their app ID. As a best practice, it is suggested to select app
|
||||
ID's that match the basename of the application's .desktop file.
|
||||
For example, "org.freedesktop.FooViewer" where the .desktop file is
|
||||
"org.freedesktop.FooViewer.desktop".
|
||||
|
||||
See the desktop-entry specification [0] for more details on
|
||||
application identifiers and how they relate to well-known D-Bus
|
||||
names and .desktop files.
|
||||
|
||||
[0] http://standards.freedesktop.org/desktop-entry-spec/
|
||||
</description>
|
||||
<arg name="app_id" type="string"/>
|
||||
</request>
|
||||
|
||||
<request name="show_window_menu">
|
||||
<description summary="show the window menu">
|
||||
Clients implementing client-side decorations might want to show
|
||||
a context menu when right-clicking on the decorations, giving the
|
||||
user a menu that they can use to maximize or minimize the window.
|
||||
|
||||
This request asks the compositor to pop up such a window menu at
|
||||
the given position, relative to the local surface coordinates of
|
||||
the parent surface. There are no guarantees as to what menu items
|
||||
the window menu contains.
|
||||
|
||||
This request must be used in response to some sort of user action
|
||||
like a button press, key press, or touch down event.
|
||||
</description>
|
||||
|
||||
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
|
||||
<arg name="serial" type="uint" summary="the serial of the user event"/>
|
||||
<arg name="x" type="int" summary="the x position to pop up the window menu at"/>
|
||||
<arg name="y" type="int" summary="the y position to pop up the window menu at"/>
|
||||
</request>
|
||||
|
||||
<request name="move">
|
||||
<description summary="start an interactive move">
|
||||
Start an interactive, user-driven move of the surface.
|
||||
|
||||
This request must be used in response to some sort of user action
|
||||
like a button press, key press, or touch down event. The passed
|
||||
serial is used to determine the type of interactive move (touch,
|
||||
pointer, etc).
|
||||
|
||||
The server may ignore move requests depending on the state of
|
||||
the surface (e.g. fullscreen or maximized), or if the passed serial
|
||||
is no longer valid.
|
||||
|
||||
If triggered, the surface will lose the focus of the device
|
||||
(wl_pointer, wl_touch, etc) used for the move. It is up to the
|
||||
compositor to visually indicate that the move is taking place, such as
|
||||
updating a pointer cursor, during the move. There is no guarantee
|
||||
that the device focus will return when the move is completed.
|
||||
</description>
|
||||
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
|
||||
<arg name="serial" type="uint" summary="the serial of the user event"/>
|
||||
</request>
|
||||
|
||||
<enum name="resize_edge">
|
||||
<description summary="edge values for resizing">
|
||||
These values are used to indicate which edge of a surface
|
||||
is being dragged in a resize operation.
|
||||
</description>
|
||||
<entry name="none" value="0"/>
|
||||
<entry name="top" value="1"/>
|
||||
<entry name="bottom" value="2"/>
|
||||
<entry name="left" value="4"/>
|
||||
<entry name="top_left" value="5"/>
|
||||
<entry name="bottom_left" value="6"/>
|
||||
<entry name="right" value="8"/>
|
||||
<entry name="top_right" value="9"/>
|
||||
<entry name="bottom_right" value="10"/>
|
||||
</enum>
|
||||
|
||||
<request name="resize">
|
||||
<description summary="start an interactive resize">
|
||||
Start a user-driven, interactive resize of the surface.
|
||||
|
||||
This request must be used in response to some sort of user action
|
||||
like a button press, key press, or touch down event. The passed
|
||||
serial is used to determine the type of interactive resize (touch,
|
||||
pointer, etc).
|
||||
|
||||
The server may ignore resize requests depending on the state of
|
||||
the surface (e.g. fullscreen or maximized).
|
||||
|
||||
If triggered, the client will receive configure events with the
|
||||
"resize" state enum value and the expected sizes. See the "resize"
|
||||
enum value for more details about what is required. The client
|
||||
must also acknowledge configure events using "ack_configure". After
|
||||
the resize is completed, the client will receive another "configure"
|
||||
event without the resize state.
|
||||
|
||||
If triggered, the surface also will lose the focus of the device
|
||||
(wl_pointer, wl_touch, etc) used for the resize. It is up to the
|
||||
compositor to visually indicate that the resize is taking place,
|
||||
such as updating a pointer cursor, during the resize. There is no
|
||||
guarantee that the device focus will return when the resize is
|
||||
completed.
|
||||
|
||||
The edges parameter specifies how the surface should be resized,
|
||||
and is one of the values of the resize_edge enum. The compositor
|
||||
may use this information to update the surface position for
|
||||
example when dragging the top left corner. The compositor may also
|
||||
use this information to adapt its behavior, e.g. choose an
|
||||
appropriate cursor image.
|
||||
</description>
|
||||
<arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
|
||||
<arg name="serial" type="uint" summary="the serial of the user event"/>
|
||||
<arg name="edges" type="uint" summary="which edge or corner is being dragged"/>
|
||||
</request>
|
||||
|
||||
<enum name="state">
|
||||
<description summary="types of state on the surface">
|
||||
The different state values used on the surface. This is designed for
|
||||
state values like maximized, fullscreen. It is paired with the
|
||||
configure event to ensure that both the client and the compositor
|
||||
setting the state can be synchronized.
|
||||
|
||||
States set in this way are double-buffered. They will get applied on
|
||||
the next commit.
|
||||
|
||||
Desktop environments may extend this enum by taking up a range of
|
||||
values and documenting the range they chose in this description.
|
||||
They are not required to document the values for the range that they
|
||||
chose. Ideally, any good extensions from a desktop environment should
|
||||
make its way into standardization into this enum.
|
||||
|
||||
The current reserved ranges are:
|
||||
|
||||
0x0000 - 0x0FFF: xdg-shell core values, documented below.
|
||||
0x1000 - 0x1FFF: GNOME
|
||||
</description>
|
||||
<entry name="maximized" value="1" summary="the surface is maximized">
|
||||
The surface is maximized. The window geometry specified in the configure
|
||||
event must be obeyed by the client.
|
||||
</entry>
|
||||
<entry name="fullscreen" value="2" summary="the surface is fullscreen">
|
||||
The surface is fullscreen. The window geometry specified in the configure
|
||||
event must be obeyed by the client.
|
||||
</entry>
|
||||
<entry name="resizing" value="3">
|
||||
The surface is being resized. The window geometry specified in the
|
||||
configure event is a maximum; the client cannot resize beyond it.
|
||||
Clients that have aspect ratio or cell sizing configuration can use
|
||||
a smaller size, however.
|
||||
</entry>
|
||||
<entry name="activated" value="4">
|
||||
Client window decorations should be painted as if the window is
|
||||
active. Do not assume this means that the window actually has
|
||||
keyboard or pointer focus.
|
||||
</entry>
|
||||
</enum>
|
||||
|
||||
<event name="configure">
|
||||
<description summary="suggest a surface change">
|
||||
The configure event asks the client to resize its surface or to
|
||||
change its state.
|
||||
|
||||
The width and height arguments specify a hint to the window
|
||||
about how its surface should be resized in window geometry
|
||||
coordinates. See set_window_geometry.
|
||||
|
||||
If the width or height arguments are zero, it means the client
|
||||
should decide its own window dimension. This may happen when the
|
||||
compositor need to configure the state of the surface but doesn't
|
||||
have any information about any previous or expected dimension.
|
||||
|
||||
The states listed in the event specify how the width/height
|
||||
arguments should be interpreted, and possibly how it should be
|
||||
drawn.
|
||||
|
||||
Clients should arrange their surface for the new size and
|
||||
states, and then send a ack_configure request with the serial
|
||||
sent in this configure event at some point before committing
|
||||
the new surface.
|
||||
|
||||
If the client receives multiple configure events before it
|
||||
can respond to one, it is free to discard all but the last
|
||||
event it received.
|
||||
</description>
|
||||
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
<arg name="states" type="array"/>
|
||||
<arg name="serial" type="uint"/>
|
||||
</event>
|
||||
|
||||
<request name="ack_configure">
|
||||
<description summary="ack a configure event">
|
||||
When a configure event is received, if a client commits the
|
||||
surface in response to the configure event, then the client
|
||||
must make a ack_configure request before the commit request,
|
||||
passing along the serial of the configure event.
|
||||
|
||||
For instance, the compositor might use this information to move
|
||||
a surface to the top left only when the client has drawn itself
|
||||
for the maximized or fullscreen state.
|
||||
|
||||
If the client receives multiple configure events before it
|
||||
can respond to one, it only has to ack the last configure event.
|
||||
</description>
|
||||
<arg name="serial" type="uint" summary="the serial from the configure event"/>
|
||||
</request>
|
||||
|
||||
<request name="set_window_geometry">
|
||||
<description summary="set the new window geometry">
|
||||
The window geometry of a window is its "visible bounds" from the
|
||||
user's perspective. Client-side decorations often have invisible
|
||||
portions like drop-shadows which should be ignored for the
|
||||
purposes of aligning, placing and constraining windows.
|
||||
|
||||
The window geometry is double buffered, and will be applied at the
|
||||
time wl_surface.commit of the corresponding wl_surface is called.
|
||||
|
||||
Once the window geometry of the surface is set once, it is not
|
||||
possible to unset it, and it will remain the same until
|
||||
set_window_geometry is called again, even if a new subsurface or
|
||||
buffer is attached.
|
||||
|
||||
If never set, the value is the full bounds of the surface,
|
||||
including any subsurfaces. This updates dynamically on every
|
||||
commit. This unset mode is meant for extremely simple clients.
|
||||
|
||||
If responding to a configure event, the window geometry in here
|
||||
must respect the sizing negotiations specified by the states in
|
||||
the configure event.
|
||||
|
||||
The arguments are given in the surface local coordinate space of
|
||||
the wl_surface associated with this xdg_surface.
|
||||
|
||||
The width and height must be greater than zero.
|
||||
</description>
|
||||
<arg name="x" type="int"/>
|
||||
<arg name="y" type="int"/>
|
||||
<arg name="width" type="int"/>
|
||||
<arg name="height" type="int"/>
|
||||
</request>
|
||||
|
||||
<request name="set_maximized">
|
||||
<description summary="maximize the window">
|
||||
Maximize the surface.
|
||||
|
||||
After requesting that the surface should be maximized, the compositor
|
||||
will respond by emitting a configure event with the "maximized" state
|
||||
and the required window geometry. The client should then update its
|
||||
content, drawing it in a maximized state, i.e. without shadow or other
|
||||
decoration outside of the window geometry. The client must also
|
||||
acknowledge the configure when committing the new content (see
|
||||
ack_configure).
|
||||
|
||||
It is up to the compositor to decide how and where to maximize the
|
||||
surface, for example which output and what region of the screen should
|
||||
be used.
|
||||
|
||||
If the surface was already maximized, the compositor will still emit
|
||||
a configure event with the "maximized" state.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="unset_maximized">
|
||||
<description summary="unmaximize the window">
|
||||
Unmaximize the surface.
|
||||
|
||||
After requesting that the surface should be unmaximized, the compositor
|
||||
will respond by emitting a configure event without the "maximized"
|
||||
state. If available, the compositor will include the window geometry
|
||||
dimensions the window had prior to being maximized in the configure
|
||||
request. The client must then update its content, drawing it in a
|
||||
regular state, i.e. potentially with shadow, etc. The client must also
|
||||
acknowledge the configure when committing the new content (see
|
||||
ack_configure).
|
||||
|
||||
It is up to the compositor to position the surface after it was
|
||||
unmaximized; usually the position the surface had before maximizing, if
|
||||
applicable.
|
||||
|
||||
If the surface was already not maximized, the compositor will still
|
||||
emit a configure event without the "maximized" state.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="set_fullscreen">
|
||||
<description summary="set the window as fullscreen on a monitor">
|
||||
Make the surface fullscreen.
|
||||
|
||||
You can specify an output that you would prefer to be fullscreen.
|
||||
If this value is NULL, it's up to the compositor to choose which
|
||||
display will be used to map this surface.
|
||||
|
||||
If the surface doesn't cover the whole output, the compositor will
|
||||
position the surface in the center of the output and compensate with
|
||||
black borders filling the rest of the output.
|
||||
</description>
|
||||
<arg name="output" type="object" interface="wl_output" allow-null="true"/>
|
||||
</request>
|
||||
<request name="unset_fullscreen" />
|
||||
|
||||
<request name="set_minimized">
|
||||
<description summary="set the window as minimized">
|
||||
Request that the compositor minimize your surface. There is no
|
||||
way to know if the surface is currently minimized, nor is there
|
||||
any way to unset minimization on this surface.
|
||||
|
||||
If you are looking to throttle redrawing when minimized, please
|
||||
instead use the wl_surface.frame event for this, as this will
|
||||
also work with live previews on windows in Alt-Tab, Expose or
|
||||
similar compositor features.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="close">
|
||||
<description summary="surface wants to be closed">
|
||||
The close event is sent by the compositor when the user
|
||||
wants the surface to be closed. This should be equivalent to
|
||||
the user clicking the close button in client-side decorations,
|
||||
if your application has any...
|
||||
|
||||
This is only a request that the user intends to close your
|
||||
window. The client may choose to ignore this request, or show
|
||||
a dialog to ask the user to save their data...
|
||||
</description>
|
||||
</event>
|
||||
</interface>
|
||||
|
||||
<interface name="xdg_popup" version="1">
|
||||
<description summary="short-lived, popup surfaces for menus">
|
||||
A popup surface is a short-lived, temporary surface that can be
|
||||
used to implement menus. It takes an explicit grab on the surface
|
||||
that will be dismissed when the user dismisses the popup. This can
|
||||
be done by the user clicking outside the surface, using the keyboard,
|
||||
or even locking the screen through closing the lid or a timeout.
|
||||
|
||||
When the popup is dismissed, a popup_done event will be sent out,
|
||||
and at the same time the surface will be unmapped. The xdg_popup
|
||||
object is now inert and cannot be reactivated, so clients should
|
||||
destroy it. Explicitly destroying the xdg_popup object will also
|
||||
dismiss the popup and unmap the surface.
|
||||
|
||||
Clients will receive events for all their surfaces during this
|
||||
grab (which is an "owner-events" grab in X11 parlance). This is
|
||||
done so that users can navigate through submenus and other
|
||||
"nested" popup windows without having to dismiss the topmost
|
||||
popup.
|
||||
|
||||
Clients that want to dismiss the popup when another surface of
|
||||
their own is clicked should dismiss the popup using the destroy
|
||||
request.
|
||||
|
||||
The parent surface must have either an xdg_surface or xdg_popup
|
||||
role.
|
||||
|
||||
Specifying an xdg_popup for the parent means that the popups are
|
||||
nested, with this popup now being the topmost popup. Nested
|
||||
popups must be destroyed in the reverse order they were created
|
||||
in, e.g. the only popup you are allowed to destroy at all times
|
||||
is the topmost one.
|
||||
|
||||
If there is an existing popup when creating a new popup, the
|
||||
parent must be the current topmost popup.
|
||||
|
||||
A parent surface must be mapped before the new popup is mapped.
|
||||
|
||||
When compositors choose to dismiss a popup, they will likely
|
||||
dismiss every nested popup as well. When a compositor dismisses
|
||||
popups, it will follow the same dismissing order as required
|
||||
from the client.
|
||||
|
||||
The x and y arguments passed when creating the popup object specify
|
||||
where the top left of the popup should be placed, relative to the
|
||||
local surface coordinates of the parent surface. See
|
||||
xdg_shell.get_xdg_popup.
|
||||
|
||||
The client must call wl_surface.commit on the corresponding wl_surface
|
||||
for the xdg_popup state to take effect.
|
||||
|
||||
For a surface to be mapped by the compositor the client must have
|
||||
committed both the xdg_popup state and a buffer.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="remove xdg_popup interface">
|
||||
This destroys the popup. Explicitly destroying the xdg_popup
|
||||
object will also dismiss the popup, and unmap the surface.
|
||||
|
||||
If this xdg_popup is not the "topmost" popup, a protocol error
|
||||
will be sent.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<event name="popup_done">
|
||||
<description summary="popup interaction is done">
|
||||
The popup_done event is sent out when a popup is dismissed by the
|
||||
compositor. The client should destroy the xdg_popup object at this
|
||||
point.
|
||||
</description>
|
||||
</event>
|
||||
|
||||
</interface>
|
||||
</protocol>
|
Loading…
Reference in New Issue
Block a user