xwayland: Separate Xwayland screen code
Move Xwayland screen related code to a separate source file and header. Signed-off-by: Olivier Fourdan <ofourdan@redhat.com> Reviewed-by: Michel Dänzer <mdaenzer@redhat.com>
This commit is contained in:
parent
211609a938
commit
0617c635fa
|
@ -19,6 +19,8 @@ Xwayland_SOURCES = \
|
|||
xwayland-pixmap.c \
|
||||
xwayland-pixmap.h \
|
||||
xwayland-present.h \
|
||||
xwayland-screen.c \
|
||||
xwayland-screen.h \
|
||||
xwayland-shm.c \
|
||||
xwayland-shm.h \
|
||||
xwayland-types.h \
|
||||
|
|
|
@ -8,6 +8,8 @@ srcs = [
|
|||
'xwayland-pixmap.c',
|
||||
'xwayland-pixmap.h',
|
||||
'xwayland-present.h',
|
||||
'xwayland-screen.c',
|
||||
'xwayland-screen.h',
|
||||
'xwayland-shm.c',
|
||||
'xwayland-shm.h',
|
||||
'xwayland-types.h',
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include "xwayland.h"
|
||||
#include "xwayland-cursor.h"
|
||||
#include "xwayland-input.h"
|
||||
#include "xwayland-screen.h"
|
||||
#include "xwayland-shm.h"
|
||||
#include "xwayland-types.h"
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "xwayland.h"
|
||||
#include "xwayland-glamor.h"
|
||||
#include "xwayland-pixmap.h"
|
||||
#include "xwayland-screen.h"
|
||||
|
||||
#include "wayland-eglstream-client-protocol.h"
|
||||
#include "wayland-eglstream-controller-client-protocol.h"
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "xwayland.h"
|
||||
#include "xwayland-glamor.h"
|
||||
#include "xwayland-pixmap.h"
|
||||
#include "xwayland-screen.h"
|
||||
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
|
||||
#include "xwayland.h"
|
||||
#include "xwayland-glamor.h"
|
||||
#include "xwayland-screen.h"
|
||||
#include "xwayland-window.h"
|
||||
|
||||
static void
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include "glamor_context.h"
|
||||
#include "glamor.h"
|
||||
|
||||
#include "xwayland-screen.h"
|
||||
|
||||
/* Can't get these from <GL/glx.h> since it pulls in client headers */
|
||||
#define GLX_RGBA_BIT 0x00000001
|
||||
#define GLX_WINDOW_BIT 0x00000001
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "xwayland-cursor.h"
|
||||
#include "xwayland-input.h"
|
||||
#include "xwayland-window.h"
|
||||
#include "xwayland-screen.h"
|
||||
|
||||
#include "pointer-constraints-unstable-v1-client-protocol.h"
|
||||
#include "relative-pointer-unstable-v1-client-protocol.h"
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "xwayland.h"
|
||||
#include "xwayland-output.h"
|
||||
#include "xwayland-screen.h"
|
||||
#include "xwayland-window.h"
|
||||
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include "xwayland.h"
|
||||
#include "xwayland-present.h"
|
||||
#include "xwayland-screen.h"
|
||||
#include "xwayland-window.h"
|
||||
#include "xwayland-pixmap.h"
|
||||
#include "glamor.h"
|
||||
|
|
|
@ -0,0 +1,641 @@
|
|||
/*
|
||||
* Copyright © 2011-2014 Intel Corporation
|
||||
*
|
||||
* 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 <xwayland-config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <X11/Xatom.h>
|
||||
#include <micmap.h>
|
||||
#include <misyncshm.h>
|
||||
#include <os.h>
|
||||
#include <fb.h>
|
||||
#include <dixstruct.h>
|
||||
#include <propertyst.h>
|
||||
#include <inputstr.h>
|
||||
#include <xserver_poll.h>
|
||||
|
||||
#include "xwayland-cursor.h"
|
||||
#include "xwayland-screen.h"
|
||||
#include "xwayland-window.h"
|
||||
#include "xwayland-input.h"
|
||||
#include "xwayland-output.h"
|
||||
#include "xwayland-pixmap.h"
|
||||
#include "xwayland-present.h"
|
||||
#include "xwayland-shm.h"
|
||||
#include "xwayland.h"
|
||||
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
|
||||
static DevPrivateKeyRec xwl_screen_private_key;
|
||||
static DevPrivateKeyRec xwl_client_private_key;
|
||||
|
||||
_X_NORETURN
|
||||
static void _X_ATTRIBUTE_PRINTF(1, 2)
|
||||
xwl_give_up(const char *f, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, f);
|
||||
VErrorFSigSafe(f, args);
|
||||
va_end(args);
|
||||
|
||||
CloseWellKnownConnections();
|
||||
OsCleanup(TRUE);
|
||||
fflush(stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct xwl_client *
|
||||
xwl_client_get(ClientPtr client)
|
||||
{
|
||||
return dixLookupPrivate(&client->devPrivates, &xwl_client_private_key);
|
||||
}
|
||||
|
||||
struct xwl_screen *
|
||||
xwl_screen_get(ScreenPtr screen)
|
||||
{
|
||||
return dixLookupPrivate(&screen->devPrivates, &xwl_screen_private_key);
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_screen_has_viewport_support(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
return wl_compositor_get_version(xwl_screen->compositor) >=
|
||||
WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION &&
|
||||
xwl_screen->viewporter != NULL;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
/* Resolution change emulation is only supported in rootless mode and
|
||||
* it requires viewport support.
|
||||
*/
|
||||
return xwl_screen->rootless && xwl_screen_has_viewport_support(xwl_screen);
|
||||
}
|
||||
|
||||
/* Return the output @ 0x0, falling back to the first output in the list */
|
||||
struct xwl_output *
|
||||
xwl_screen_get_first_output(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
struct xwl_output *xwl_output;
|
||||
|
||||
xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) {
|
||||
if (xwl_output->x == 0 && xwl_output->y == 0)
|
||||
return xwl_output;
|
||||
}
|
||||
|
||||
if (xorg_list_is_empty(&xwl_screen->output_list))
|
||||
return NULL;
|
||||
|
||||
return xorg_list_first_entry(&xwl_screen->output_list, struct xwl_output, link);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_property_callback(CallbackListPtr *pcbl, void *closure,
|
||||
void *calldata)
|
||||
{
|
||||
ScreenPtr screen = closure;
|
||||
PropertyStateRec *rec = calldata;
|
||||
struct xwl_screen *xwl_screen;
|
||||
struct xwl_window *xwl_window;
|
||||
|
||||
if (rec->win->drawable.pScreen != screen)
|
||||
return;
|
||||
|
||||
xwl_window = xwl_window_get(rec->win);
|
||||
if (!xwl_window)
|
||||
return;
|
||||
|
||||
xwl_screen = xwl_screen_get(screen);
|
||||
|
||||
if (rec->prop->propertyName == xwl_screen->allow_commits_prop)
|
||||
xwl_window_update_property(xwl_window, rec);
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_close_screen(ScreenPtr screen)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
struct xwl_output *xwl_output, *next_xwl_output;
|
||||
struct xwl_seat *xwl_seat, *next_xwl_seat;
|
||||
|
||||
DeleteCallback(&PropertyStateCallback, xwl_property_callback, screen);
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_output, next_xwl_output,
|
||||
&xwl_screen->output_list, link)
|
||||
xwl_output_destroy(xwl_output);
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_seat, next_xwl_seat,
|
||||
&xwl_screen->seat_list, link)
|
||||
xwl_seat_destroy(xwl_seat);
|
||||
|
||||
xwl_screen_release_tablet_manager(xwl_screen);
|
||||
|
||||
RemoveNotifyFd(xwl_screen->wayland_fd);
|
||||
|
||||
wl_display_disconnect(xwl_screen->display);
|
||||
|
||||
screen->CloseScreen = xwl_screen->CloseScreen;
|
||||
free(xwl_screen);
|
||||
|
||||
return screen->CloseScreen(screen);
|
||||
}
|
||||
|
||||
static struct xwl_seat *
|
||||
xwl_screen_get_default_seat(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
if (xorg_list_is_empty(&xwl_screen->seat_list))
|
||||
return NULL;
|
||||
|
||||
return container_of(xwl_screen->seat_list.prev,
|
||||
struct xwl_seat,
|
||||
link);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_cursor_warped_to(DeviceIntPtr device,
|
||||
ScreenPtr screen,
|
||||
ClientPtr client,
|
||||
WindowPtr window,
|
||||
SpritePtr sprite,
|
||||
int x, int y)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
struct xwl_seat *xwl_seat = device->public.devicePrivate;
|
||||
struct xwl_window *xwl_window;
|
||||
WindowPtr focus;
|
||||
|
||||
if (!xwl_seat)
|
||||
xwl_seat = xwl_screen_get_default_seat(xwl_screen);
|
||||
|
||||
if (!window)
|
||||
window = XYToWindow(sprite, x, y);
|
||||
|
||||
xwl_window = xwl_window_from_window(window);
|
||||
if (!xwl_window && xwl_seat->focus_window) {
|
||||
focus = xwl_seat->focus_window->window;
|
||||
|
||||
/* Warps on non wl_surface backed Windows are only allowed
|
||||
* as long as the pointer stays within the focus window.
|
||||
*/
|
||||
if (x >= focus->drawable.x &&
|
||||
y >= focus->drawable.y &&
|
||||
x < focus->drawable.x + focus->drawable.width &&
|
||||
y < focus->drawable.y + focus->drawable.height) {
|
||||
if (!window) {
|
||||
DebugF("Warp relative to pointer, assuming pointer focus\n");
|
||||
xwl_window = xwl_seat->focus_window;
|
||||
} else if (window == screen->root) {
|
||||
DebugF("Warp on root window, assuming pointer focus\n");
|
||||
xwl_window = xwl_seat->focus_window;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!xwl_window)
|
||||
return;
|
||||
|
||||
xwl_seat_emulate_pointer_warp(xwl_seat, xwl_window, sprite, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_cursor_confined_to(DeviceIntPtr device,
|
||||
ScreenPtr screen,
|
||||
WindowPtr window)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
struct xwl_seat *xwl_seat = device->public.devicePrivate;
|
||||
struct xwl_window *xwl_window;
|
||||
|
||||
if (!xwl_seat)
|
||||
xwl_seat = xwl_screen_get_default_seat(xwl_screen);
|
||||
|
||||
/* xwl_seat hasn't been setup yet, don't do anything just yet */
|
||||
if (!xwl_seat)
|
||||
return;
|
||||
|
||||
if (window == screen->root) {
|
||||
xwl_seat_unconfine_pointer(xwl_seat);
|
||||
return;
|
||||
}
|
||||
|
||||
xwl_window = xwl_window_from_window(window);
|
||||
if (!xwl_window && xwl_seat->focus_window) {
|
||||
/* Allow confining on InputOnly windows, but only if the geometry
|
||||
* is the same than the focus window.
|
||||
*/
|
||||
if (window->drawable.class == InputOnly) {
|
||||
DebugF("Confine on InputOnly window, assuming pointer focus\n");
|
||||
xwl_window = xwl_seat->focus_window;
|
||||
}
|
||||
}
|
||||
if (!xwl_window)
|
||||
return;
|
||||
|
||||
xwl_seat_confine_pointer(xwl_seat, xwl_window);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
struct xwl_window *xwl_window;
|
||||
|
||||
xorg_list_for_each_entry(xwl_window, &xwl_screen->window_list, link_window)
|
||||
xwl_window_check_resolution_change_emulation(xwl_window);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_screen_post_damage(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
struct xwl_window *xwl_window, *next_xwl_window;
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_window, next_xwl_window,
|
||||
&xwl_screen->damage_window_list, link_damage) {
|
||||
/* If we're waiting on a frame callback from the server,
|
||||
* don't attach a new buffer. */
|
||||
if (xwl_window->frame_callback)
|
||||
continue;
|
||||
|
||||
if (!xwl_window->allow_commits)
|
||||
continue;
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (xwl_screen->glamor && !xwl_glamor_allow_commits(xwl_window))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
xwl_window_post_damage(xwl_window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
registry_global(void *data, struct wl_registry *registry, uint32_t id,
|
||||
const char *interface, uint32_t version)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = data;
|
||||
|
||||
if (strcmp(interface, "wl_compositor") == 0) {
|
||||
uint32_t request_version = 1;
|
||||
|
||||
if (version >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)
|
||||
request_version = WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION;
|
||||
|
||||
xwl_screen->compositor =
|
||||
wl_registry_bind(registry, id, &wl_compositor_interface, request_version);
|
||||
}
|
||||
else if (strcmp(interface, "wl_shm") == 0) {
|
||||
xwl_screen->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
|
||||
}
|
||||
else if (strcmp(interface, "wl_shell") == 0) {
|
||||
xwl_screen->shell =
|
||||
wl_registry_bind(registry, id, &wl_shell_interface, 1);
|
||||
}
|
||||
else if (strcmp(interface, "wl_output") == 0 && version >= 2) {
|
||||
if (xwl_output_create(xwl_screen, id))
|
||||
xwl_screen->expecting_event++;
|
||||
}
|
||||
else if (strcmp(interface, "zxdg_output_manager_v1") == 0) {
|
||||
/* We support xdg-output from version 1 to version 3 */
|
||||
version = min(version, 3);
|
||||
xwl_screen->xdg_output_manager =
|
||||
wl_registry_bind(registry, id, &zxdg_output_manager_v1_interface, version);
|
||||
xwl_screen_init_xdg_output(xwl_screen);
|
||||
}
|
||||
else if (strcmp(interface, "wp_viewporter") == 0) {
|
||||
xwl_screen->viewporter = wl_registry_bind(registry, id, &wp_viewporter_interface, 1);
|
||||
}
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
else if (xwl_screen->glamor) {
|
||||
xwl_glamor_init_wl_registry(xwl_screen, registry, id, interface,
|
||||
version);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
global_remove(void *data, struct wl_registry *registry, uint32_t name)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = data;
|
||||
struct xwl_output *xwl_output, *tmp_xwl_output;
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_output, tmp_xwl_output,
|
||||
&xwl_screen->output_list, link) {
|
||||
if (xwl_output->server_output_id == name) {
|
||||
xwl_output_remove(xwl_output);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_registry_listener registry_listener = {
|
||||
registry_global,
|
||||
global_remove
|
||||
};
|
||||
|
||||
static void
|
||||
xwl_read_events (struct xwl_screen *xwl_screen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (xwl_screen->wait_flush)
|
||||
return;
|
||||
|
||||
ret = wl_display_read_events(xwl_screen->display);
|
||||
if (ret == -1)
|
||||
xwl_give_up("failed to read Wayland events: %s\n", strerror(errno));
|
||||
|
||||
xwl_screen->prepare_read = 0;
|
||||
|
||||
ret = wl_display_dispatch_pending(xwl_screen->display);
|
||||
if (ret == -1)
|
||||
xwl_give_up("failed to dispatch Wayland events: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
static int
|
||||
xwl_display_pollout (struct xwl_screen *xwl_screen, int timeout)
|
||||
{
|
||||
struct pollfd poll_fd;
|
||||
|
||||
poll_fd.fd = wl_display_get_fd(xwl_screen->display);
|
||||
poll_fd.events = POLLOUT;
|
||||
|
||||
return xserver_poll(&poll_fd, 1, timeout);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_dispatch_events (struct xwl_screen *xwl_screen)
|
||||
{
|
||||
int ret = 0;
|
||||
int ready;
|
||||
|
||||
if (xwl_screen->wait_flush)
|
||||
goto pollout;
|
||||
|
||||
while (xwl_screen->prepare_read == 0 &&
|
||||
wl_display_prepare_read(xwl_screen->display) == -1) {
|
||||
ret = wl_display_dispatch_pending(xwl_screen->display);
|
||||
if (ret == -1)
|
||||
xwl_give_up("failed to dispatch Wayland events: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
xwl_screen->prepare_read = 1;
|
||||
|
||||
pollout:
|
||||
ready = xwl_display_pollout(xwl_screen, 5);
|
||||
if (ready == -1 && errno != EINTR)
|
||||
xwl_give_up("error polling on XWayland fd: %s\n", strerror(errno));
|
||||
|
||||
if (ready > 0)
|
||||
ret = wl_display_flush(xwl_screen->display);
|
||||
|
||||
if (ret == -1 && errno != EAGAIN)
|
||||
xwl_give_up("failed to write to XWayland fd: %s\n", strerror(errno));
|
||||
|
||||
xwl_screen->wait_flush = (ready == 0 || ready == -1 || ret == -1);
|
||||
}
|
||||
|
||||
static void
|
||||
socket_handler(int fd, int ready, void *data)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = data;
|
||||
|
||||
xwl_read_events (xwl_screen);
|
||||
}
|
||||
|
||||
static void
|
||||
wakeup_handler(void *data, int err)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
block_handler(void *data, void *timeout)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = data;
|
||||
|
||||
xwl_screen_post_damage(xwl_screen);
|
||||
xwl_dispatch_events (xwl_screen);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_sync_events (struct xwl_screen *xwl_screen)
|
||||
{
|
||||
xwl_dispatch_events (xwl_screen);
|
||||
xwl_read_events (xwl_screen);
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
||||
{
|
||||
static const char allow_commits[] = "_XWAYLAND_ALLOW_COMMITS";
|
||||
struct xwl_screen *xwl_screen;
|
||||
Pixel red_mask, blue_mask, green_mask;
|
||||
int ret, bpc, green_bpc, i;
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
Bool use_eglstreams = FALSE;
|
||||
#endif
|
||||
|
||||
xwl_screen = calloc(1, sizeof *xwl_screen);
|
||||
if (xwl_screen == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!dixRegisterPrivateKey(&xwl_screen_private_key, PRIVATE_SCREEN, 0))
|
||||
return FALSE;
|
||||
if (!xwl_pixmap_init())
|
||||
return FALSE;
|
||||
if (!xwl_window_init())
|
||||
return FALSE;
|
||||
/* There are no easy to use new / delete client hooks, we could use a
|
||||
* ClientStateCallback, but it is easier to let the dix code manage the
|
||||
* memory for us. This will zero fill the initial xwl_client data.
|
||||
*/
|
||||
if (!dixRegisterPrivateKey(&xwl_client_private_key, PRIVATE_CLIENT,
|
||||
sizeof(struct xwl_client)))
|
||||
return FALSE;
|
||||
|
||||
dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen);
|
||||
xwl_screen->screen = pScreen;
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
xwl_screen->glamor = 1;
|
||||
#endif
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-rootless") == 0) {
|
||||
xwl_screen->rootless = 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "-shm") == 0) {
|
||||
xwl_screen->glamor = 0;
|
||||
}
|
||||
else if (strcmp(argv[i], "-eglstream") == 0) {
|
||||
#ifdef XWL_HAS_EGLSTREAM
|
||||
use_eglstreams = TRUE;
|
||||
#else
|
||||
ErrorF("xwayland glamor: this build does not have EGLStream support\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (xwl_screen->glamor)
|
||||
xwl_glamor_init_backends(xwl_screen, use_eglstreams);
|
||||
#endif
|
||||
|
||||
/* In rootless mode, we don't have any screen storage, and the only
|
||||
* rendering should be to redirected mode. */
|
||||
if (xwl_screen->rootless)
|
||||
xwl_screen->root_clip_mode = ROOT_CLIP_INPUT_ONLY;
|
||||
else
|
||||
xwl_screen->root_clip_mode = ROOT_CLIP_FULL;
|
||||
|
||||
xorg_list_init(&xwl_screen->output_list);
|
||||
xorg_list_init(&xwl_screen->seat_list);
|
||||
xorg_list_init(&xwl_screen->damage_window_list);
|
||||
xorg_list_init(&xwl_screen->window_list);
|
||||
xwl_screen->depth = 24;
|
||||
|
||||
xwl_screen->display = wl_display_connect(NULL);
|
||||
if (xwl_screen->display == NULL) {
|
||||
ErrorF("could not connect to wayland server\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!xwl_screen_init_output(xwl_screen))
|
||||
return FALSE;
|
||||
|
||||
xwl_screen->expecting_event = 0;
|
||||
xwl_screen->registry = wl_display_get_registry(xwl_screen->display);
|
||||
wl_registry_add_listener(xwl_screen->registry,
|
||||
®istry_listener, xwl_screen);
|
||||
ret = wl_display_roundtrip(xwl_screen->display);
|
||||
if (ret == -1) {
|
||||
ErrorF("could not connect to wayland server\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (xwl_screen->expecting_event > 0)
|
||||
wl_display_roundtrip(xwl_screen->display);
|
||||
|
||||
bpc = xwl_screen->depth / 3;
|
||||
green_bpc = xwl_screen->depth - 2 * bpc;
|
||||
blue_mask = (1 << bpc) - 1;
|
||||
green_mask = ((1 << green_bpc) - 1) << bpc;
|
||||
red_mask = blue_mask << (green_bpc + bpc);
|
||||
|
||||
miSetVisualTypesAndMasks(xwl_screen->depth,
|
||||
((1 << TrueColor) | (1 << DirectColor)),
|
||||
green_bpc, TrueColor,
|
||||
red_mask, green_mask, blue_mask);
|
||||
|
||||
miSetPixmapDepths();
|
||||
|
||||
ret = fbScreenInit(pScreen, NULL,
|
||||
xwl_screen->width, xwl_screen->height,
|
||||
96, 96, 0,
|
||||
BitsPerPixel(xwl_screen->depth));
|
||||
if (!ret)
|
||||
return FALSE;
|
||||
|
||||
fbPictureInit(pScreen, 0, 0);
|
||||
|
||||
#ifdef HAVE_XSHMFENCE
|
||||
if (!miSyncShmScreenInit(pScreen))
|
||||
return FALSE;
|
||||
#endif
|
||||
|
||||
xwl_screen->wayland_fd = wl_display_get_fd(xwl_screen->display);
|
||||
SetNotifyFd(xwl_screen->wayland_fd, socket_handler, X_NOTIFY_READ, xwl_screen);
|
||||
RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, xwl_screen);
|
||||
|
||||
pScreen->blackPixel = 0;
|
||||
pScreen->whitePixel = 1;
|
||||
|
||||
ret = fbCreateDefColormap(pScreen);
|
||||
|
||||
if (!xwl_screen_init_cursor(xwl_screen))
|
||||
return FALSE;
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (xwl_screen->glamor) {
|
||||
xwl_glamor_select_backend(xwl_screen, use_eglstreams);
|
||||
|
||||
if (xwl_screen->egl_backend == NULL || !xwl_glamor_init(xwl_screen)) {
|
||||
ErrorF("Failed to initialize glamor, falling back to sw\n");
|
||||
xwl_screen->glamor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (xwl_screen->glamor && xwl_screen->rootless)
|
||||
xwl_screen->present = xwl_present_init(pScreen);
|
||||
#endif
|
||||
|
||||
if (!xwl_screen->glamor) {
|
||||
xwl_screen->CreateScreenResources = pScreen->CreateScreenResources;
|
||||
pScreen->CreateScreenResources = xwl_shm_create_screen_resources;
|
||||
pScreen->CreatePixmap = xwl_shm_create_pixmap;
|
||||
pScreen->DestroyPixmap = xwl_shm_destroy_pixmap;
|
||||
}
|
||||
|
||||
xwl_screen->RealizeWindow = pScreen->RealizeWindow;
|
||||
pScreen->RealizeWindow = xwl_realize_window;
|
||||
|
||||
xwl_screen->UnrealizeWindow = pScreen->UnrealizeWindow;
|
||||
pScreen->UnrealizeWindow = xwl_unrealize_window;
|
||||
|
||||
xwl_screen->DestroyWindow = pScreen->DestroyWindow;
|
||||
pScreen->DestroyWindow = xwl_destroy_window;
|
||||
|
||||
xwl_screen->CloseScreen = pScreen->CloseScreen;
|
||||
pScreen->CloseScreen = xwl_close_screen;
|
||||
|
||||
xwl_screen->ResizeWindow = pScreen->ResizeWindow;
|
||||
pScreen->ResizeWindow = xwl_resize_window;
|
||||
|
||||
if (xwl_screen->rootless) {
|
||||
xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap;
|
||||
pScreen->SetWindowPixmap = xwl_window_set_window_pixmap;
|
||||
}
|
||||
|
||||
pScreen->CursorWarpedTo = xwl_cursor_warped_to;
|
||||
pScreen->CursorConfinedTo = xwl_cursor_confined_to;
|
||||
|
||||
xwl_screen->allow_commits_prop = MakeAtom(allow_commits,
|
||||
strlen(allow_commits),
|
||||
TRUE);
|
||||
if (xwl_screen->allow_commits_prop == BAD_RESOURCE)
|
||||
return FALSE;
|
||||
|
||||
AddCallback(&PropertyStateCallback, xwl_property_callback, pScreen);
|
||||
|
||||
wl_display_roundtrip(xwl_screen->display);
|
||||
while (xwl_screen->expecting_event)
|
||||
wl_display_roundtrip(xwl_screen->display);
|
||||
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* Copyright © 2011-2014 Intel Corporation
|
||||
*
|
||||
* 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 XWAYLAND_SCREEN_H
|
||||
#define XWAYLAND_SCREEN_H
|
||||
|
||||
#include <xwayland-config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <X11/X.h>
|
||||
#include <dix.h>
|
||||
|
||||
#include "xwayland-types.h"
|
||||
#include "xwayland-output.h"
|
||||
#include "xwayland-glamor.h"
|
||||
|
||||
struct xwl_format {
|
||||
uint32_t format;
|
||||
int num_modifiers;
|
||||
uint64_t *modifiers;
|
||||
};
|
||||
|
||||
struct xwl_screen {
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
ScreenPtr screen;
|
||||
int expecting_event;
|
||||
enum RootClipMode root_clip_mode;
|
||||
|
||||
int rootless;
|
||||
int glamor;
|
||||
int present;
|
||||
|
||||
CreateScreenResourcesProcPtr CreateScreenResources;
|
||||
CloseScreenProcPtr CloseScreen;
|
||||
RealizeWindowProcPtr RealizeWindow;
|
||||
UnrealizeWindowProcPtr UnrealizeWindow;
|
||||
DestroyWindowProcPtr DestroyWindow;
|
||||
XYToWindowProcPtr XYToWindow;
|
||||
SetWindowPixmapProcPtr SetWindowPixmap;
|
||||
ResizeWindowProcPtr ResizeWindow;
|
||||
|
||||
struct xorg_list output_list;
|
||||
struct xorg_list seat_list;
|
||||
struct xorg_list damage_window_list;
|
||||
struct xorg_list window_list;
|
||||
|
||||
int wayland_fd;
|
||||
struct wl_display *display;
|
||||
struct wl_registry *registry;
|
||||
struct wl_registry *input_registry;
|
||||
struct wl_compositor *compositor;
|
||||
struct zwp_tablet_manager_v2 *tablet_manager;
|
||||
struct wl_shm *shm;
|
||||
struct wl_shell *shell;
|
||||
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
|
||||
struct zwp_pointer_constraints_v1 *pointer_constraints;
|
||||
struct zwp_xwayland_keyboard_grab_manager_v1 *wp_grab;
|
||||
struct zxdg_output_manager_v1 *xdg_output_manager;
|
||||
struct wp_viewporter *viewporter;
|
||||
uint32_t serial;
|
||||
|
||||
#define XWL_FORMAT_ARGB8888 (1 << 0)
|
||||
#define XWL_FORMAT_XRGB8888 (1 << 1)
|
||||
#define XWL_FORMAT_RGB565 (1 << 2)
|
||||
|
||||
int prepare_read;
|
||||
int wait_flush;
|
||||
|
||||
uint32_t num_formats;
|
||||
struct xwl_format *formats;
|
||||
void *egl_display, *egl_context;
|
||||
|
||||
struct xwl_egl_backend gbm_backend;
|
||||
struct xwl_egl_backend eglstream_backend;
|
||||
/* pointer to the current backend for creating pixmaps on wayland */
|
||||
struct xwl_egl_backend *egl_backend;
|
||||
|
||||
struct glamor_context *glamor_ctx;
|
||||
|
||||
Atom allow_commits_prop;
|
||||
};
|
||||
|
||||
/* Apps which use randr/vidmode to change the mode when going fullscreen,
|
||||
* usually change the mode of only a single monitor, so this should be plenty.
|
||||
*/
|
||||
#define XWL_CLIENT_MAX_EMULATED_MODES 16
|
||||
|
||||
struct xwl_client {
|
||||
struct xwl_emulated_mode emulated_modes[XWL_CLIENT_MAX_EMULATED_MODES];
|
||||
};
|
||||
|
||||
struct xwl_client *xwl_client_get(ClientPtr client);
|
||||
struct xwl_screen *xwl_screen_get(ScreenPtr screen);
|
||||
Bool xwl_screen_has_viewport_support(struct xwl_screen *xwl_screen);
|
||||
Bool xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen);
|
||||
void xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen);
|
||||
struct xwl_output *xwl_screen_get_first_output(struct xwl_screen *xwl_screen);
|
||||
Bool xwl_close_screen(ScreenPtr screen);
|
||||
Bool xwl_screen_init(ScreenPtr pScreen, int argc, char **argv);
|
||||
void xwl_sync_events (struct xwl_screen *xwl_screen);
|
||||
void xwl_surface_damage(struct xwl_screen *xwl_screen,
|
||||
struct wl_surface *surface,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height);
|
||||
|
||||
#endif /* XWAYLAND_SCREEN_H */
|
|
@ -42,6 +42,7 @@
|
|||
|
||||
#include "xwayland.h"
|
||||
#include "xwayland-pixmap.h"
|
||||
#include "xwayland-screen.h"
|
||||
#include "xwayland-shm.h"
|
||||
|
||||
struct xwl_pixmap {
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
#include "randrstr.h"
|
||||
#include "vidmodestr.h"
|
||||
|
||||
#include "xwayland-screen.h"
|
||||
|
||||
static DevPrivateKeyRec xwlVidModePrivateKeyRec;
|
||||
#define xwlVidModePrivateKey (&xwlVidModePrivateKeyRec)
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "xwayland-window.h"
|
||||
#include "xwayland-pixmap.h"
|
||||
#include "xwayland-screen.h"
|
||||
#include "xwayland-window-buffers.h"
|
||||
|
||||
#define BUFFER_TIMEOUT 1 * 1000 /* ms */
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "xwayland-types.h"
|
||||
#include "xwayland-input.h"
|
||||
#include "xwayland-present.h"
|
||||
#include "xwayland-screen.h"
|
||||
#include "xwayland-window.h"
|
||||
#include "xwayland-window-buffers.h"
|
||||
#include "xwayland-shm.h"
|
||||
|
|
|
@ -37,15 +37,7 @@
|
|||
#include <propertyst.h>
|
||||
|
||||
#include "xwayland.h"
|
||||
#include "xwayland-cursor.h"
|
||||
#include "xwayland-glamor.h"
|
||||
#include "xwayland-input.h"
|
||||
#include "xwayland-output.h"
|
||||
#include "xwayland-pixmap.h"
|
||||
#include "xwayland-present.h"
|
||||
#include "xwayland-shm.h"
|
||||
#include "xwayland-window-buffers.h"
|
||||
#include "xwayland-window.h"
|
||||
#include "xwayland-screen.h"
|
||||
|
||||
#ifdef XF86VIDMODE
|
||||
#include <X11/extensions/xf86vmproto.h>
|
||||
|
@ -86,22 +78,6 @@ ddxInputThreadInit(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
_X_NORETURN
|
||||
static void _X_ATTRIBUTE_PRINTF(1, 2)
|
||||
xwl_give_up(const char *f, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
va_start(args, f);
|
||||
VErrorFSigSafe(f, args);
|
||||
va_end(args);
|
||||
|
||||
CloseWellKnownConnections();
|
||||
OsCleanup(TRUE);
|
||||
fflush(stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
ddxUseMsg(void)
|
||||
{
|
||||
|
@ -174,388 +150,6 @@ ddxProcessArgument(int argc, char *argv[], int i)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static DevPrivateKeyRec xwl_client_private_key;
|
||||
static DevPrivateKeyRec xwl_screen_private_key;
|
||||
|
||||
struct xwl_client *
|
||||
xwl_client_get(ClientPtr client)
|
||||
{
|
||||
return dixLookupPrivate(&client->devPrivates, &xwl_client_private_key);
|
||||
}
|
||||
|
||||
struct xwl_screen *
|
||||
xwl_screen_get(ScreenPtr screen)
|
||||
{
|
||||
return dixLookupPrivate(&screen->devPrivates, &xwl_screen_private_key);
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_screen_has_viewport_support(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
return wl_compositor_get_version(xwl_screen->compositor) >=
|
||||
WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION &&
|
||||
xwl_screen->viewporter != NULL;
|
||||
}
|
||||
|
||||
Bool
|
||||
xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
/* Resolution change emulation is only supported in rootless mode and
|
||||
* it requires viewport support.
|
||||
*/
|
||||
return xwl_screen->rootless && xwl_screen_has_viewport_support(xwl_screen);
|
||||
}
|
||||
|
||||
/* Return the output @ 0x0, falling back to the first output in the list */
|
||||
struct xwl_output *
|
||||
xwl_screen_get_first_output(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
struct xwl_output *xwl_output;
|
||||
|
||||
xorg_list_for_each_entry(xwl_output, &xwl_screen->output_list, link) {
|
||||
if (xwl_output->x == 0 && xwl_output->y == 0)
|
||||
return xwl_output;
|
||||
}
|
||||
|
||||
if (xorg_list_is_empty(&xwl_screen->output_list))
|
||||
return NULL;
|
||||
|
||||
return xorg_list_first_entry(&xwl_screen->output_list, struct xwl_output, link);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_property_callback(CallbackListPtr *pcbl, void *closure,
|
||||
void *calldata)
|
||||
{
|
||||
ScreenPtr screen = closure;
|
||||
PropertyStateRec *rec = calldata;
|
||||
struct xwl_screen *xwl_screen;
|
||||
struct xwl_window *xwl_window;
|
||||
|
||||
if (rec->win->drawable.pScreen != screen)
|
||||
return;
|
||||
|
||||
xwl_window = xwl_window_get(rec->win);
|
||||
if (!xwl_window)
|
||||
return;
|
||||
|
||||
xwl_screen = xwl_screen_get(screen);
|
||||
|
||||
if (rec->prop->propertyName == xwl_screen->allow_commits_prop)
|
||||
xwl_window_update_property(xwl_window, rec);
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_close_screen(ScreenPtr screen)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
struct xwl_output *xwl_output, *next_xwl_output;
|
||||
struct xwl_seat *xwl_seat, *next_xwl_seat;
|
||||
|
||||
DeleteCallback(&PropertyStateCallback, xwl_property_callback, screen);
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_output, next_xwl_output,
|
||||
&xwl_screen->output_list, link)
|
||||
xwl_output_destroy(xwl_output);
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_seat, next_xwl_seat,
|
||||
&xwl_screen->seat_list, link)
|
||||
xwl_seat_destroy(xwl_seat);
|
||||
|
||||
xwl_screen_release_tablet_manager(xwl_screen);
|
||||
|
||||
RemoveNotifyFd(xwl_screen->wayland_fd);
|
||||
|
||||
wl_display_disconnect(xwl_screen->display);
|
||||
|
||||
screen->CloseScreen = xwl_screen->CloseScreen;
|
||||
free(xwl_screen);
|
||||
|
||||
return screen->CloseScreen(screen);
|
||||
}
|
||||
|
||||
static struct xwl_seat *
|
||||
xwl_screen_get_default_seat(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
if (xorg_list_is_empty(&xwl_screen->seat_list))
|
||||
return NULL;
|
||||
|
||||
return container_of(xwl_screen->seat_list.prev,
|
||||
struct xwl_seat,
|
||||
link);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_cursor_warped_to(DeviceIntPtr device,
|
||||
ScreenPtr screen,
|
||||
ClientPtr client,
|
||||
WindowPtr window,
|
||||
SpritePtr sprite,
|
||||
int x, int y)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
struct xwl_seat *xwl_seat = device->public.devicePrivate;
|
||||
struct xwl_window *xwl_window;
|
||||
WindowPtr focus;
|
||||
|
||||
if (!xwl_seat)
|
||||
xwl_seat = xwl_screen_get_default_seat(xwl_screen);
|
||||
|
||||
if (!window)
|
||||
window = XYToWindow(sprite, x, y);
|
||||
|
||||
xwl_window = xwl_window_from_window(window);
|
||||
if (!xwl_window && xwl_seat->focus_window) {
|
||||
focus = xwl_seat->focus_window->window;
|
||||
|
||||
/* Warps on non wl_surface backed Windows are only allowed
|
||||
* as long as the pointer stays within the focus window.
|
||||
*/
|
||||
if (x >= focus->drawable.x &&
|
||||
y >= focus->drawable.y &&
|
||||
x < focus->drawable.x + focus->drawable.width &&
|
||||
y < focus->drawable.y + focus->drawable.height) {
|
||||
if (!window) {
|
||||
DebugF("Warp relative to pointer, assuming pointer focus\n");
|
||||
xwl_window = xwl_seat->focus_window;
|
||||
} else if (window == screen->root) {
|
||||
DebugF("Warp on root window, assuming pointer focus\n");
|
||||
xwl_window = xwl_seat->focus_window;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!xwl_window)
|
||||
return;
|
||||
|
||||
xwl_seat_emulate_pointer_warp(xwl_seat, xwl_window, sprite, x, y);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_cursor_confined_to(DeviceIntPtr device,
|
||||
ScreenPtr screen,
|
||||
WindowPtr window)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
|
||||
struct xwl_seat *xwl_seat = device->public.devicePrivate;
|
||||
struct xwl_window *xwl_window;
|
||||
|
||||
if (!xwl_seat)
|
||||
xwl_seat = xwl_screen_get_default_seat(xwl_screen);
|
||||
|
||||
/* xwl_seat hasn't been setup yet, don't do anything just yet */
|
||||
if (!xwl_seat)
|
||||
return;
|
||||
|
||||
if (window == screen->root) {
|
||||
xwl_seat_unconfine_pointer(xwl_seat);
|
||||
return;
|
||||
}
|
||||
|
||||
xwl_window = xwl_window_from_window(window);
|
||||
if (!xwl_window && xwl_seat->focus_window) {
|
||||
/* Allow confining on InputOnly windows, but only if the geometry
|
||||
* is the same than the focus window.
|
||||
*/
|
||||
if (window->drawable.class == InputOnly) {
|
||||
DebugF("Confine on InputOnly window, assuming pointer focus\n");
|
||||
xwl_window = xwl_seat->focus_window;
|
||||
}
|
||||
}
|
||||
if (!xwl_window)
|
||||
return;
|
||||
|
||||
xwl_seat_confine_pointer(xwl_seat, xwl_window);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
struct xwl_window *xwl_window;
|
||||
|
||||
xorg_list_for_each_entry(xwl_window, &xwl_screen->window_list, link_window)
|
||||
xwl_window_check_resolution_change_emulation(xwl_window);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_screen_post_damage(struct xwl_screen *xwl_screen)
|
||||
{
|
||||
struct xwl_window *xwl_window, *next_xwl_window;
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_window, next_xwl_window,
|
||||
&xwl_screen->damage_window_list, link_damage) {
|
||||
/* If we're waiting on a frame callback from the server,
|
||||
* don't attach a new buffer. */
|
||||
if (xwl_window->frame_callback)
|
||||
continue;
|
||||
|
||||
if (!xwl_window->allow_commits)
|
||||
continue;
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (xwl_screen->glamor && !xwl_glamor_allow_commits(xwl_window))
|
||||
continue;
|
||||
#endif
|
||||
|
||||
xwl_window_post_damage(xwl_window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
registry_global(void *data, struct wl_registry *registry, uint32_t id,
|
||||
const char *interface, uint32_t version)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = data;
|
||||
|
||||
if (strcmp(interface, "wl_compositor") == 0) {
|
||||
uint32_t request_version = 1;
|
||||
|
||||
if (version >= WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION)
|
||||
request_version = WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION;
|
||||
|
||||
xwl_screen->compositor =
|
||||
wl_registry_bind(registry, id, &wl_compositor_interface, request_version);
|
||||
}
|
||||
else if (strcmp(interface, "wl_shm") == 0) {
|
||||
xwl_screen->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
|
||||
}
|
||||
else if (strcmp(interface, "wl_shell") == 0) {
|
||||
xwl_screen->shell =
|
||||
wl_registry_bind(registry, id, &wl_shell_interface, 1);
|
||||
}
|
||||
else if (strcmp(interface, "wl_output") == 0 && version >= 2) {
|
||||
if (xwl_output_create(xwl_screen, id))
|
||||
xwl_screen->expecting_event++;
|
||||
}
|
||||
else if (strcmp(interface, "zxdg_output_manager_v1") == 0) {
|
||||
/* We support xdg-output from version 1 to version 3 */
|
||||
version = min(version, 3);
|
||||
xwl_screen->xdg_output_manager =
|
||||
wl_registry_bind(registry, id, &zxdg_output_manager_v1_interface, version);
|
||||
xwl_screen_init_xdg_output(xwl_screen);
|
||||
}
|
||||
else if (strcmp(interface, "wp_viewporter") == 0) {
|
||||
xwl_screen->viewporter = wl_registry_bind(registry, id, &wp_viewporter_interface, 1);
|
||||
}
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
else if (xwl_screen->glamor) {
|
||||
xwl_glamor_init_wl_registry(xwl_screen, registry, id, interface,
|
||||
version);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
global_remove(void *data, struct wl_registry *registry, uint32_t name)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = data;
|
||||
struct xwl_output *xwl_output, *tmp_xwl_output;
|
||||
|
||||
xorg_list_for_each_entry_safe(xwl_output, tmp_xwl_output,
|
||||
&xwl_screen->output_list, link) {
|
||||
if (xwl_output->server_output_id == name) {
|
||||
xwl_output_remove(xwl_output);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const struct wl_registry_listener registry_listener = {
|
||||
registry_global,
|
||||
global_remove
|
||||
};
|
||||
|
||||
static void
|
||||
xwl_read_events (struct xwl_screen *xwl_screen)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (xwl_screen->wait_flush)
|
||||
return;
|
||||
|
||||
ret = wl_display_read_events(xwl_screen->display);
|
||||
if (ret == -1)
|
||||
xwl_give_up("failed to read Wayland events: %s\n", strerror(errno));
|
||||
|
||||
xwl_screen->prepare_read = 0;
|
||||
|
||||
ret = wl_display_dispatch_pending(xwl_screen->display);
|
||||
if (ret == -1)
|
||||
xwl_give_up("failed to dispatch Wayland events: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
static int
|
||||
xwl_display_pollout (struct xwl_screen *xwl_screen, int timeout)
|
||||
{
|
||||
struct pollfd poll_fd;
|
||||
|
||||
poll_fd.fd = wl_display_get_fd(xwl_screen->display);
|
||||
poll_fd.events = POLLOUT;
|
||||
|
||||
return xserver_poll(&poll_fd, 1, timeout);
|
||||
}
|
||||
|
||||
static void
|
||||
xwl_dispatch_events (struct xwl_screen *xwl_screen)
|
||||
{
|
||||
int ret = 0;
|
||||
int ready;
|
||||
|
||||
if (xwl_screen->wait_flush)
|
||||
goto pollout;
|
||||
|
||||
while (xwl_screen->prepare_read == 0 &&
|
||||
wl_display_prepare_read(xwl_screen->display) == -1) {
|
||||
ret = wl_display_dispatch_pending(xwl_screen->display);
|
||||
if (ret == -1)
|
||||
xwl_give_up("failed to dispatch Wayland events: %s\n",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
xwl_screen->prepare_read = 1;
|
||||
|
||||
pollout:
|
||||
ready = xwl_display_pollout(xwl_screen, 5);
|
||||
if (ready == -1 && errno != EINTR)
|
||||
xwl_give_up("error polling on XWayland fd: %s\n", strerror(errno));
|
||||
|
||||
if (ready > 0)
|
||||
ret = wl_display_flush(xwl_screen->display);
|
||||
|
||||
if (ret == -1 && errno != EAGAIN)
|
||||
xwl_give_up("failed to write to XWayland fd: %s\n", strerror(errno));
|
||||
|
||||
xwl_screen->wait_flush = (ready == 0 || ready == -1 || ret == -1);
|
||||
}
|
||||
|
||||
static void
|
||||
socket_handler(int fd, int ready, void *data)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = data;
|
||||
|
||||
xwl_read_events (xwl_screen);
|
||||
}
|
||||
|
||||
static void
|
||||
wakeup_handler(void *data, int err)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
block_handler(void *data, void *timeout)
|
||||
{
|
||||
struct xwl_screen *xwl_screen = data;
|
||||
|
||||
xwl_screen_post_damage(xwl_screen);
|
||||
xwl_dispatch_events (xwl_screen);
|
||||
}
|
||||
|
||||
void
|
||||
xwl_sync_events (struct xwl_screen *xwl_screen)
|
||||
{
|
||||
xwl_dispatch_events (xwl_screen);
|
||||
xwl_read_events (xwl_screen);
|
||||
}
|
||||
|
||||
static CARD32
|
||||
add_client_fd(OsTimerPtr timer, CARD32 time, void *arg)
|
||||
{
|
||||
|
@ -595,196 +189,6 @@ wm_selection_callback(CallbackListPtr *p, void *data, void *arg)
|
|||
DeleteCallback(&SelectionCallback, wm_selection_callback, xwl_screen);
|
||||
}
|
||||
|
||||
static Bool
|
||||
xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
|
||||
{
|
||||
static const char allow_commits[] = "_XWAYLAND_ALLOW_COMMITS";
|
||||
struct xwl_screen *xwl_screen;
|
||||
Pixel red_mask, blue_mask, green_mask;
|
||||
int ret, bpc, green_bpc, i;
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
Bool use_eglstreams = FALSE;
|
||||
#endif
|
||||
|
||||
xwl_screen = calloc(1, sizeof *xwl_screen);
|
||||
if (xwl_screen == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (!dixRegisterPrivateKey(&xwl_screen_private_key, PRIVATE_SCREEN, 0))
|
||||
return FALSE;
|
||||
if (!xwl_pixmap_init())
|
||||
return FALSE;
|
||||
if (!xwl_window_init())
|
||||
return FALSE;
|
||||
/* There are no easy to use new / delete client hooks, we could use a
|
||||
* ClientStateCallback, but it is easier to let the dix code manage the
|
||||
* memory for us. This will zero fill the initial xwl_client data.
|
||||
*/
|
||||
if (!dixRegisterPrivateKey(&xwl_client_private_key, PRIVATE_CLIENT,
|
||||
sizeof(struct xwl_client)))
|
||||
return FALSE;
|
||||
|
||||
dixSetPrivate(&pScreen->devPrivates, &xwl_screen_private_key, xwl_screen);
|
||||
xwl_screen->screen = pScreen;
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
xwl_screen->glamor = 1;
|
||||
#endif
|
||||
|
||||
for (i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "-rootless") == 0) {
|
||||
xwl_screen->rootless = 1;
|
||||
}
|
||||
else if (strcmp(argv[i], "-shm") == 0) {
|
||||
xwl_screen->glamor = 0;
|
||||
}
|
||||
else if (strcmp(argv[i], "-eglstream") == 0) {
|
||||
#ifdef XWL_HAS_EGLSTREAM
|
||||
use_eglstreams = TRUE;
|
||||
#else
|
||||
ErrorF("xwayland glamor: this build does not have EGLStream support\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (xwl_screen->glamor)
|
||||
xwl_glamor_init_backends(xwl_screen, use_eglstreams);
|
||||
#endif
|
||||
|
||||
/* In rootless mode, we don't have any screen storage, and the only
|
||||
* rendering should be to redirected mode. */
|
||||
if (xwl_screen->rootless)
|
||||
xwl_screen->root_clip_mode = ROOT_CLIP_INPUT_ONLY;
|
||||
else
|
||||
xwl_screen->root_clip_mode = ROOT_CLIP_FULL;
|
||||
|
||||
xorg_list_init(&xwl_screen->output_list);
|
||||
xorg_list_init(&xwl_screen->seat_list);
|
||||
xorg_list_init(&xwl_screen->damage_window_list);
|
||||
xorg_list_init(&xwl_screen->window_list);
|
||||
xwl_screen->depth = 24;
|
||||
|
||||
xwl_screen->display = wl_display_connect(NULL);
|
||||
if (xwl_screen->display == NULL) {
|
||||
ErrorF("could not connect to wayland server\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!xwl_screen_init_output(xwl_screen))
|
||||
return FALSE;
|
||||
|
||||
xwl_screen->expecting_event = 0;
|
||||
xwl_screen->registry = wl_display_get_registry(xwl_screen->display);
|
||||
wl_registry_add_listener(xwl_screen->registry,
|
||||
®istry_listener, xwl_screen);
|
||||
ret = wl_display_roundtrip(xwl_screen->display);
|
||||
if (ret == -1) {
|
||||
ErrorF("could not connect to wayland server\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (xwl_screen->expecting_event > 0)
|
||||
wl_display_roundtrip(xwl_screen->display);
|
||||
|
||||
bpc = xwl_screen->depth / 3;
|
||||
green_bpc = xwl_screen->depth - 2 * bpc;
|
||||
blue_mask = (1 << bpc) - 1;
|
||||
green_mask = ((1 << green_bpc) - 1) << bpc;
|
||||
red_mask = blue_mask << (green_bpc + bpc);
|
||||
|
||||
miSetVisualTypesAndMasks(xwl_screen->depth,
|
||||
((1 << TrueColor) | (1 << DirectColor)),
|
||||
green_bpc, TrueColor,
|
||||
red_mask, green_mask, blue_mask);
|
||||
|
||||
miSetPixmapDepths();
|
||||
|
||||
ret = fbScreenInit(pScreen, NULL,
|
||||
xwl_screen->width, xwl_screen->height,
|
||||
96, 96, 0,
|
||||
BitsPerPixel(xwl_screen->depth));
|
||||
if (!ret)
|
||||
return FALSE;
|
||||
|
||||
fbPictureInit(pScreen, 0, 0);
|
||||
|
||||
#ifdef HAVE_XSHMFENCE
|
||||
if (!miSyncShmScreenInit(pScreen))
|
||||
return FALSE;
|
||||
#endif
|
||||
|
||||
xwl_screen->wayland_fd = wl_display_get_fd(xwl_screen->display);
|
||||
SetNotifyFd(xwl_screen->wayland_fd, socket_handler, X_NOTIFY_READ, xwl_screen);
|
||||
RegisterBlockAndWakeupHandlers(block_handler, wakeup_handler, xwl_screen);
|
||||
|
||||
pScreen->blackPixel = 0;
|
||||
pScreen->whitePixel = 1;
|
||||
|
||||
ret = fbCreateDefColormap(pScreen);
|
||||
|
||||
if (!xwl_screen_init_cursor(xwl_screen))
|
||||
return FALSE;
|
||||
|
||||
#ifdef XWL_HAS_GLAMOR
|
||||
if (xwl_screen->glamor) {
|
||||
xwl_glamor_select_backend(xwl_screen, use_eglstreams);
|
||||
|
||||
if (xwl_screen->egl_backend == NULL || !xwl_glamor_init(xwl_screen)) {
|
||||
ErrorF("Failed to initialize glamor, falling back to sw\n");
|
||||
xwl_screen->glamor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (xwl_screen->glamor && xwl_screen->rootless)
|
||||
xwl_screen->present = xwl_present_init(pScreen);
|
||||
#endif
|
||||
|
||||
if (!xwl_screen->glamor) {
|
||||
xwl_screen->CreateScreenResources = pScreen->CreateScreenResources;
|
||||
pScreen->CreateScreenResources = xwl_shm_create_screen_resources;
|
||||
pScreen->CreatePixmap = xwl_shm_create_pixmap;
|
||||
pScreen->DestroyPixmap = xwl_shm_destroy_pixmap;
|
||||
}
|
||||
|
||||
xwl_screen->RealizeWindow = pScreen->RealizeWindow;
|
||||
pScreen->RealizeWindow = xwl_realize_window;
|
||||
|
||||
xwl_screen->UnrealizeWindow = pScreen->UnrealizeWindow;
|
||||
pScreen->UnrealizeWindow = xwl_unrealize_window;
|
||||
|
||||
xwl_screen->DestroyWindow = pScreen->DestroyWindow;
|
||||
pScreen->DestroyWindow = xwl_destroy_window;
|
||||
|
||||
xwl_screen->CloseScreen = pScreen->CloseScreen;
|
||||
pScreen->CloseScreen = xwl_close_screen;
|
||||
|
||||
xwl_screen->ResizeWindow = pScreen->ResizeWindow;
|
||||
pScreen->ResizeWindow = xwl_resize_window;
|
||||
|
||||
if (xwl_screen->rootless) {
|
||||
xwl_screen->SetWindowPixmap = pScreen->SetWindowPixmap;
|
||||
pScreen->SetWindowPixmap = xwl_window_set_window_pixmap;
|
||||
}
|
||||
|
||||
pScreen->CursorWarpedTo = xwl_cursor_warped_to;
|
||||
pScreen->CursorConfinedTo = xwl_cursor_confined_to;
|
||||
|
||||
xwl_screen->allow_commits_prop = MakeAtom(allow_commits,
|
||||
strlen(allow_commits),
|
||||
TRUE);
|
||||
if (xwl_screen->allow_commits_prop == BAD_RESOURCE)
|
||||
return FALSE;
|
||||
|
||||
AddCallback(&PropertyStateCallback, xwl_property_callback, pScreen);
|
||||
|
||||
wl_display_roundtrip(xwl_screen->display);
|
||||
while (xwl_screen->expecting_event)
|
||||
wl_display_roundtrip(xwl_screen->display);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
_X_NORETURN
|
||||
static void _X_ATTRIBUTE_PRINTF(1, 0)
|
||||
xwl_log_handler(const char *format, va_list args)
|
||||
|
|
|
@ -45,105 +45,12 @@
|
|||
#include "pointer-constraints-unstable-v1-client-protocol.h"
|
||||
#include "tablet-unstable-v2-client-protocol.h"
|
||||
#include "xwayland-keyboard-grab-unstable-v1-client-protocol.h"
|
||||
#include "xdg-output-unstable-v1-client-protocol.h"
|
||||
#include "linux-dmabuf-unstable-v1-client-protocol.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
|
||||
#include "xwayland-types.h"
|
||||
#include "xwayland-output.h"
|
||||
#include "xwayland-glamor.h"
|
||||
|
||||
struct xwl_format {
|
||||
uint32_t format;
|
||||
int num_modifiers;
|
||||
uint64_t *modifiers;
|
||||
};
|
||||
|
||||
struct xwl_screen {
|
||||
int width;
|
||||
int height;
|
||||
int depth;
|
||||
ScreenPtr screen;
|
||||
int expecting_event;
|
||||
enum RootClipMode root_clip_mode;
|
||||
|
||||
int rootless;
|
||||
int glamor;
|
||||
int present;
|
||||
|
||||
CreateScreenResourcesProcPtr CreateScreenResources;
|
||||
CloseScreenProcPtr CloseScreen;
|
||||
RealizeWindowProcPtr RealizeWindow;
|
||||
UnrealizeWindowProcPtr UnrealizeWindow;
|
||||
DestroyWindowProcPtr DestroyWindow;
|
||||
XYToWindowProcPtr XYToWindow;
|
||||
SetWindowPixmapProcPtr SetWindowPixmap;
|
||||
ResizeWindowProcPtr ResizeWindow;
|
||||
|
||||
struct xorg_list output_list;
|
||||
struct xorg_list seat_list;
|
||||
struct xorg_list damage_window_list;
|
||||
struct xorg_list window_list;
|
||||
|
||||
int wayland_fd;
|
||||
struct wl_display *display;
|
||||
struct wl_registry *registry;
|
||||
struct wl_registry *input_registry;
|
||||
struct wl_compositor *compositor;
|
||||
struct zwp_tablet_manager_v2 *tablet_manager;
|
||||
struct wl_shm *shm;
|
||||
struct wl_shell *shell;
|
||||
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
|
||||
struct zwp_pointer_constraints_v1 *pointer_constraints;
|
||||
struct zwp_xwayland_keyboard_grab_manager_v1 *wp_grab;
|
||||
struct zxdg_output_manager_v1 *xdg_output_manager;
|
||||
struct wp_viewporter *viewporter;
|
||||
uint32_t serial;
|
||||
|
||||
#define XWL_FORMAT_ARGB8888 (1 << 0)
|
||||
#define XWL_FORMAT_XRGB8888 (1 << 1)
|
||||
#define XWL_FORMAT_RGB565 (1 << 2)
|
||||
|
||||
int prepare_read;
|
||||
int wait_flush;
|
||||
|
||||
uint32_t num_formats;
|
||||
struct xwl_format *formats;
|
||||
void *egl_display, *egl_context;
|
||||
|
||||
struct xwl_egl_backend gbm_backend;
|
||||
struct xwl_egl_backend eglstream_backend;
|
||||
/* pointer to the current backend for creating pixmaps on wayland */
|
||||
struct xwl_egl_backend *egl_backend;
|
||||
|
||||
struct glamor_context *glamor_ctx;
|
||||
|
||||
Atom allow_commits_prop;
|
||||
};
|
||||
|
||||
#define MODIFIER_META 0x01
|
||||
|
||||
/* Apps which use randr/vidmode to change the mode when going fullscreen,
|
||||
* usually change the mode of only a single monitor, so this should be plenty.
|
||||
*/
|
||||
#define XWL_CLIENT_MAX_EMULATED_MODES 16
|
||||
|
||||
struct xwl_client {
|
||||
struct xwl_emulated_mode emulated_modes[XWL_CLIENT_MAX_EMULATED_MODES];
|
||||
};
|
||||
|
||||
struct xwl_client *xwl_client_get(ClientPtr client);
|
||||
|
||||
void xwl_sync_events (struct xwl_screen *xwl_screen);
|
||||
void xwl_surface_damage(struct xwl_screen *xwl_screen,
|
||||
struct wl_surface *surface,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height);
|
||||
|
||||
struct xwl_screen *xwl_screen_get(ScreenPtr screen);
|
||||
Bool xwl_screen_has_resolution_change_emulation(struct xwl_screen *xwl_screen);
|
||||
struct xwl_output *xwl_screen_get_first_output(struct xwl_screen *xwl_screen);
|
||||
void xwl_screen_check_resolution_change_emulation(struct xwl_screen *xwl_screen);
|
||||
|
||||
RRModePtr xwayland_cvt(int HDisplay, int VDisplay,
|
||||
float VRefresh, Bool Reduced, Bool Interlaced);
|
||||
|
||||
|
|
Loading…
Reference in New Issue