forked from AuroraMiddleware/gtk
03d6d272f7
surface->x/y (and various x,y arguments) should be in the parent coordinates, so treat it as such. We also keep track of the root coords as these are needed for popup positioning. Also, drop the isTemp property server side and the weird initial placement at (100, 100) in the daemon. We now fully control window placement from the client instead. If this is not we want we should do a serious design for that but until then lets do the simplest thing.
785 lines
19 KiB
C
785 lines
19 KiB
C
#include "config.h"
|
|
|
|
#ifdef HAVE_LINUX_MEMFD_H
|
|
#include <linux/memfd.h>
|
|
#endif
|
|
|
|
#ifdef HAVE_SYS_MMAN_H
|
|
#include <sys/mman.h>
|
|
#endif
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "gdkbroadway-server.h"
|
|
|
|
#include "gdkprivate-broadway.h"
|
|
#include <gdk/gdktextureprivate.h>
|
|
|
|
#include <glib.h>
|
|
#include <glib/gprintf.h>
|
|
#include <gio/gunixsocketaddress.h>
|
|
#include <gio/gunixfdmessage.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#elif defined (G_OS_WIN32)
|
|
#include <io.h>
|
|
#define ftruncate _chsize_s
|
|
#endif
|
|
#include <sys/types.h>
|
|
#ifdef G_OS_WIN32
|
|
#include <windows.h>
|
|
#endif
|
|
#include "gdkintl.h"
|
|
|
|
typedef struct BroadwayInput BroadwayInput;
|
|
|
|
struct _GdkBroadwayServer {
|
|
GObject parent_instance;
|
|
GdkDisplay *display;
|
|
|
|
guint32 next_serial;
|
|
guint32 next_texture_id;
|
|
GSocketConnection *connection;
|
|
|
|
guint32 recv_buffer_size;
|
|
guint8 recv_buffer[1024];
|
|
|
|
guint process_input_idle;
|
|
GList *incomming;
|
|
};
|
|
|
|
struct _GdkBroadwayServerClass
|
|
{
|
|
GObjectClass parent_class;
|
|
};
|
|
|
|
static gboolean input_available_cb (gpointer stream, gpointer user_data);
|
|
|
|
static GType gdk_broadway_server_get_type (void);
|
|
|
|
G_DEFINE_TYPE (GdkBroadwayServer, gdk_broadway_server, G_TYPE_OBJECT)
|
|
|
|
static void
|
|
gdk_broadway_server_init (GdkBroadwayServer *server)
|
|
{
|
|
server->next_serial = 1;
|
|
server->next_texture_id = 1;
|
|
}
|
|
|
|
static void
|
|
gdk_broadway_server_finalize (GObject *object)
|
|
{
|
|
G_OBJECT_CLASS (gdk_broadway_server_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gdk_broadway_server_class_init (GdkBroadwayServerClass * class)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
|
|
|
object_class->finalize = gdk_broadway_server_finalize;
|
|
}
|
|
|
|
gboolean
|
|
_gdk_broadway_server_lookahead_event (GdkBroadwayServer *server,
|
|
const char *types)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
gulong
|
|
_gdk_broadway_server_get_next_serial (GdkBroadwayServer *server)
|
|
{
|
|
return (gulong)server->next_serial;
|
|
}
|
|
|
|
GdkBroadwayServer *
|
|
_gdk_broadway_server_new (GdkDisplay *display,
|
|
const char *display_name,
|
|
GError **error)
|
|
{
|
|
GdkBroadwayServer *server;
|
|
GSocketClient *client;
|
|
GSocketConnection *connection;
|
|
GSocketAddress *address;
|
|
GPollableInputStream *pollable;
|
|
GInputStream *in;
|
|
GSource *source;
|
|
char *local_socket_type = NULL;
|
|
int port;
|
|
|
|
if (display_name == NULL)
|
|
display_name = ":0";
|
|
|
|
if (display_name[0] == ':' && g_ascii_isdigit(display_name[1]))
|
|
{
|
|
char *path, *basename;
|
|
|
|
port = strtol (display_name + strlen (":"), NULL, 10);
|
|
basename = g_strdup_printf ("broadway%d.socket", port + 1);
|
|
path = g_build_filename (g_get_user_runtime_dir (), basename, NULL);
|
|
g_free (basename);
|
|
|
|
address = g_unix_socket_address_new_with_type (path, -1,
|
|
G_UNIX_SOCKET_ADDRESS_PATH);
|
|
g_free (path);
|
|
}
|
|
else
|
|
{
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
|
_("Broadway display type not supported: %s"), display_name);
|
|
return NULL;
|
|
}
|
|
|
|
g_free (local_socket_type);
|
|
|
|
client = g_socket_client_new ();
|
|
|
|
connection = g_socket_client_connect (client, G_SOCKET_CONNECTABLE (address), NULL, error);
|
|
|
|
g_object_unref (address);
|
|
g_object_unref (client);
|
|
|
|
if (connection == NULL)
|
|
return NULL;
|
|
|
|
server = g_object_new (GDK_TYPE_BROADWAY_SERVER, NULL);
|
|
server->connection = connection;
|
|
server->display = display;
|
|
|
|
in = g_io_stream_get_input_stream (G_IO_STREAM (server->connection));
|
|
pollable = G_POLLABLE_INPUT_STREAM (in);
|
|
|
|
source = g_pollable_input_stream_create_source (pollable, NULL);
|
|
g_source_attach (source, NULL);
|
|
g_source_set_callback (source, (GSourceFunc)input_available_cb, server, NULL);
|
|
|
|
return server;
|
|
}
|
|
|
|
guint32
|
|
_gdk_broadway_server_get_last_seen_time (GdkBroadwayServer *server)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static guint32
|
|
gdk_broadway_server_send_message_with_size (GdkBroadwayServer *server, BroadwayRequestBase *base,
|
|
gsize size, guint32 type, int fd)
|
|
{
|
|
GOutputStream *out;
|
|
gsize written;
|
|
guchar *buf;
|
|
|
|
base->size = size;
|
|
base->type = type;
|
|
base->serial = server->next_serial++;
|
|
|
|
buf = (guchar *)base;
|
|
|
|
if (fd != -1)
|
|
{
|
|
GUnixFDList *fd_list = g_unix_fd_list_new_from_array (&fd, 1);
|
|
GSocketControlMessage *control_message = g_unix_fd_message_new_with_fd_list (fd_list);
|
|
GSocket *socket = g_socket_connection_get_socket (server->connection);
|
|
GOutputVector vector;
|
|
gssize bytes_written;
|
|
|
|
vector.buffer = buf;
|
|
vector.size = size;
|
|
|
|
bytes_written = g_socket_send_message (socket,
|
|
NULL, /* address */
|
|
&vector,
|
|
1,
|
|
&control_message, 1,
|
|
G_SOCKET_MSG_NONE,
|
|
NULL,
|
|
NULL);
|
|
|
|
if (bytes_written <= 0)
|
|
{
|
|
g_printerr ("Unable to write to server\n");
|
|
exit (1);
|
|
}
|
|
|
|
buf += bytes_written;
|
|
size -= bytes_written;
|
|
|
|
g_object_unref (control_message);
|
|
g_object_unref (fd_list);
|
|
}
|
|
|
|
if (size > 0)
|
|
{
|
|
out = g_io_stream_get_output_stream (G_IO_STREAM (server->connection));
|
|
if (!g_output_stream_write_all (out, buf, size, &written, NULL, NULL))
|
|
{
|
|
g_printerr ("Unable to write to server\n");
|
|
exit (1);
|
|
}
|
|
|
|
g_assert (written == size);
|
|
}
|
|
|
|
|
|
return base->serial;
|
|
}
|
|
|
|
#define gdk_broadway_server_send_message(_server, _msg, _type) \
|
|
gdk_broadway_server_send_message_with_size(_server, (BroadwayRequestBase *)&_msg, sizeof (_msg), _type, -1)
|
|
|
|
#define gdk_broadway_server_send_fd_message(_server, _msg, _type, _fd) \
|
|
gdk_broadway_server_send_message_with_size(_server, (BroadwayRequestBase *)&_msg, sizeof (_msg), _type, _fd)
|
|
|
|
static void
|
|
parse_all_input (GdkBroadwayServer *server)
|
|
{
|
|
guint8 *p, *end;
|
|
guint32 size;
|
|
BroadwayReply *reply;
|
|
|
|
p = server->recv_buffer;
|
|
end = p + server->recv_buffer_size;
|
|
|
|
while (p + sizeof (guint32) <= end)
|
|
{
|
|
memcpy (&size, p, sizeof (guint32));
|
|
if (p + size > end)
|
|
break;
|
|
|
|
reply = g_memdup (p, size);
|
|
p += size;
|
|
|
|
server->incomming = g_list_append (server->incomming, reply);
|
|
}
|
|
|
|
if (p < end)
|
|
memmove (server->recv_buffer, p, end - p);
|
|
server->recv_buffer_size = end - p;
|
|
}
|
|
|
|
static void
|
|
read_some_input_blocking (GdkBroadwayServer *server)
|
|
{
|
|
GInputStream *in;
|
|
gssize res;
|
|
|
|
in = g_io_stream_get_input_stream (G_IO_STREAM (server->connection));
|
|
|
|
g_assert (server->recv_buffer_size < sizeof (server->recv_buffer));
|
|
res = g_input_stream_read (in, &server->recv_buffer[server->recv_buffer_size],
|
|
sizeof (server->recv_buffer) - server->recv_buffer_size,
|
|
NULL, NULL);
|
|
|
|
if (res <= 0)
|
|
{
|
|
g_printerr ("Unable to read from broadway server\n");
|
|
exit (1);
|
|
}
|
|
|
|
server->recv_buffer_size += res;
|
|
}
|
|
|
|
static void
|
|
read_some_input_nonblocking (GdkBroadwayServer *server)
|
|
{
|
|
GInputStream *in;
|
|
GPollableInputStream *pollable;
|
|
gssize res;
|
|
GError *error;
|
|
|
|
in = g_io_stream_get_input_stream (G_IO_STREAM (server->connection));
|
|
pollable = G_POLLABLE_INPUT_STREAM (in);
|
|
|
|
g_assert (server->recv_buffer_size < sizeof (server->recv_buffer));
|
|
error = NULL;
|
|
res = g_pollable_input_stream_read_nonblocking (pollable, &server->recv_buffer[server->recv_buffer_size],
|
|
sizeof (server->recv_buffer) - server->recv_buffer_size,
|
|
NULL, &error);
|
|
|
|
if (res < 0 && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
|
|
{
|
|
g_error_free (error);
|
|
res = 0;
|
|
}
|
|
else if (res <= 0)
|
|
{
|
|
g_printerr ("Unable to read from broadway server: %s\n", error ? error->message : "eof");
|
|
exit (1);
|
|
}
|
|
|
|
server->recv_buffer_size += res;
|
|
}
|
|
|
|
static BroadwayReply *
|
|
find_response_by_serial (GdkBroadwayServer *server, guint32 serial)
|
|
{
|
|
GList *l;
|
|
|
|
for (l = server->incomming; l != NULL; l = l->next)
|
|
{
|
|
BroadwayReply *reply = l->data;
|
|
|
|
if (reply->base.in_reply_to == serial)
|
|
return reply;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
process_input_messages (GdkBroadwayServer *server)
|
|
{
|
|
BroadwayReply *reply;
|
|
|
|
if (server->process_input_idle != 0)
|
|
{
|
|
g_source_remove (server->process_input_idle);
|
|
server->process_input_idle = 0;
|
|
}
|
|
|
|
while (server->incomming)
|
|
{
|
|
reply = server->incomming->data;
|
|
server->incomming =
|
|
g_list_delete_link (server->incomming,
|
|
server->incomming);
|
|
|
|
if (reply->base.type == BROADWAY_REPLY_EVENT)
|
|
_gdk_broadway_events_got_input (server->display, &reply->event.msg);
|
|
else
|
|
g_warning ("Unhandled reply type %d", reply->base.type);
|
|
g_free (reply);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
process_input_idle_cb (GdkBroadwayServer *server)
|
|
{
|
|
server->process_input_idle = 0;
|
|
process_input_messages (server);
|
|
return G_SOURCE_REMOVE;
|
|
}
|
|
|
|
static void
|
|
queue_process_input_at_idle (GdkBroadwayServer *server)
|
|
{
|
|
if (server->process_input_idle == 0)
|
|
server->process_input_idle =
|
|
g_idle_add_full (G_PRIORITY_DEFAULT, (GSourceFunc)process_input_idle_cb, server, NULL);
|
|
}
|
|
|
|
static gboolean
|
|
input_available_cb (gpointer stream, gpointer user_data)
|
|
{
|
|
GdkBroadwayServer *server = user_data;
|
|
|
|
read_some_input_nonblocking (server);
|
|
parse_all_input (server);
|
|
|
|
process_input_messages (server);
|
|
|
|
return G_SOURCE_CONTINUE;
|
|
}
|
|
|
|
static BroadwayReply *
|
|
gdk_broadway_server_wait_for_reply (GdkBroadwayServer *server,
|
|
guint32 serial)
|
|
{
|
|
BroadwayReply *reply;
|
|
|
|
while (TRUE)
|
|
{
|
|
reply = find_response_by_serial (server, serial);
|
|
if (reply)
|
|
{
|
|
server->incomming = g_list_remove (server->incomming, reply);
|
|
break;
|
|
}
|
|
|
|
read_some_input_blocking (server);
|
|
parse_all_input (server);
|
|
}
|
|
|
|
queue_process_input_at_idle (server);
|
|
return reply;
|
|
}
|
|
|
|
void
|
|
_gdk_broadway_server_flush (GdkBroadwayServer *server)
|
|
{
|
|
BroadwayRequestFlush msg;
|
|
|
|
gdk_broadway_server_send_message (server, msg, BROADWAY_REQUEST_FLUSH);
|
|
}
|
|
|
|
void
|
|
_gdk_broadway_server_sync (GdkBroadwayServer *server)
|
|
{
|
|
BroadwayRequestSync msg;
|
|
guint32 serial;
|
|
BroadwayReply *reply;
|
|
|
|
serial = gdk_broadway_server_send_message (server, msg,
|
|
BROADWAY_REQUEST_SYNC);
|
|
reply = gdk_broadway_server_wait_for_reply (server, serial);
|
|
|
|
g_assert (reply->base.type == BROADWAY_REPLY_SYNC);
|
|
|
|
g_free (reply);
|
|
|
|
return;
|
|
}
|
|
|
|
void
|
|
_gdk_broadway_server_roundtrip (GdkBroadwayServer *server,
|
|
gint32 id,
|
|
guint32 tag)
|
|
{
|
|
BroadwayRequestRoundtrip msg;
|
|
|
|
msg.id = id;
|
|
msg.tag = tag;
|
|
gdk_broadway_server_send_message (server, msg,
|
|
BROADWAY_REQUEST_ROUNDTRIP);
|
|
}
|
|
|
|
void
|
|
_gdk_broadway_server_query_mouse (GdkBroadwayServer *server,
|
|
guint32 *surface,
|
|
gint32 *root_x,
|
|
gint32 *root_y,
|
|
guint32 *mask)
|
|
{
|
|
BroadwayRequestQueryMouse msg;
|
|
guint32 serial;
|
|
BroadwayReply *reply;
|
|
|
|
serial = gdk_broadway_server_send_message (server, msg,
|
|
BROADWAY_REQUEST_QUERY_MOUSE);
|
|
reply = gdk_broadway_server_wait_for_reply (server, serial);
|
|
|
|
g_assert (reply->base.type == BROADWAY_REPLY_QUERY_MOUSE);
|
|
|
|
if (surface)
|
|
*surface = reply->query_mouse.surface;
|
|
if (root_x)
|
|
*root_x = reply->query_mouse.root_x;
|
|
if (root_y)
|
|
*root_y = reply->query_mouse.root_y;
|
|
if (mask)
|
|
*mask = reply->query_mouse.mask;
|
|
|
|
g_free (reply);
|
|
}
|
|
|
|
guint32
|
|
_gdk_broadway_server_new_surface (GdkBroadwayServer *server,
|
|
int x,
|
|
int y,
|
|
int width,
|
|
int height)
|
|
{
|
|
BroadwayRequestNewSurface msg;
|
|
guint32 serial, id;
|
|
BroadwayReply *reply;
|
|
|
|
msg.x = x;
|
|
msg.y = y;
|
|
msg.width = width;
|
|
msg.height = height;
|
|
serial = gdk_broadway_server_send_message (server, msg,
|
|
BROADWAY_REQUEST_NEW_SURFACE);
|
|
reply = gdk_broadway_server_wait_for_reply (server, serial);
|
|
|
|
g_assert (reply->base.type == BROADWAY_REPLY_NEW_SURFACE);
|
|
|
|
id = reply->new_surface.id;
|
|
|
|
g_free (reply);
|
|
|
|
return id;
|
|
}
|
|
|
|
void
|
|
_gdk_broadway_server_destroy_surface (GdkBroadwayServer *server,
|
|
gint id)
|
|
{
|
|
BroadwayRequestDestroySurface msg;
|
|
|
|
msg.id = id;
|
|
gdk_broadway_server_send_message (server, msg,
|
|
BROADWAY_REQUEST_DESTROY_SURFACE);
|
|
}
|
|
|
|
gboolean
|
|
_gdk_broadway_server_surface_show (GdkBroadwayServer *server,
|
|
gint id)
|
|
{
|
|
BroadwayRequestShowSurface msg;
|
|
|
|
msg.id = id;
|
|
gdk_broadway_server_send_message (server, msg,
|
|
BROADWAY_REQUEST_SHOW_SURFACE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
gboolean
|
|
_gdk_broadway_server_surface_hide (GdkBroadwayServer *server,
|
|
gint id)
|
|
{
|
|
BroadwayRequestHideSurface msg;
|
|
|
|
msg.id = id;
|
|
gdk_broadway_server_send_message (server, msg,
|
|
BROADWAY_REQUEST_HIDE_SURFACE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
_gdk_broadway_server_surface_focus (GdkBroadwayServer *server,
|
|
gint id)
|
|
{
|
|
BroadwayRequestFocusSurface msg;
|
|
|
|
msg.id = id;
|
|
gdk_broadway_server_send_message (server, msg,
|
|
BROADWAY_REQUEST_FOCUS_SURFACE);
|
|
}
|
|
|
|
void
|
|
_gdk_broadway_server_surface_set_transient_for (GdkBroadwayServer *server,
|
|
gint id, gint parent)
|
|
{
|
|
BroadwayRequestSetTransientFor msg;
|
|
|
|
msg.id = id;
|
|
msg.parent = parent;
|
|
gdk_broadway_server_send_message (server, msg,
|
|
BROADWAY_REQUEST_SET_TRANSIENT_FOR);
|
|
}
|
|
|
|
static int
|
|
open_shared_memory (void)
|
|
{
|
|
static gboolean force_shm_open = FALSE;
|
|
int ret = -1;
|
|
|
|
#if !defined (__NR_memfd_create)
|
|
force_shm_open = TRUE;
|
|
#endif
|
|
|
|
do
|
|
{
|
|
#if defined (__NR_memfd_create)
|
|
if (!force_shm_open)
|
|
{
|
|
ret = syscall (__NR_memfd_create, "gdk-broadway", MFD_CLOEXEC);
|
|
|
|
/* fall back to shm_open until debian stops shipping 3.16 kernel
|
|
* See bug 766341
|
|
*/
|
|
if (ret < 0 && errno == ENOSYS)
|
|
force_shm_open = TRUE;
|
|
}
|
|
#endif
|
|
|
|
if (force_shm_open)
|
|
{
|
|
char name[NAME_MAX - 1] = "";
|
|
|
|
sprintf (name, "/gdk-broadway-%x", g_random_int ());
|
|
|
|
ret = shm_open (name, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0600);
|
|
|
|
if (ret >= 0)
|
|
shm_unlink (name);
|
|
else if (errno == EEXIST)
|
|
continue;
|
|
}
|
|
}
|
|
while (ret < 0 && errno == EINTR);
|
|
|
|
if (ret < 0)
|
|
g_critical (G_STRLOC ": creating shared memory file (using %s) failed: %m",
|
|
force_shm_open? "shm_open" : "memfd_create");
|
|
|
|
return ret;
|
|
}
|
|
|
|
typedef struct {
|
|
int fd;
|
|
gsize size;
|
|
} PngData;
|
|
|
|
static cairo_status_t
|
|
write_png_cb (void *closure,
|
|
const guchar *data,
|
|
unsigned int length)
|
|
{
|
|
PngData *png_data = closure;
|
|
int fd = png_data->fd;
|
|
|
|
while (length)
|
|
{
|
|
gssize ret = write (fd, data, length);
|
|
|
|
if (ret <= 0)
|
|
return CAIRO_STATUS_WRITE_ERROR;
|
|
|
|
png_data->size += ret;
|
|
length -= ret;
|
|
data += ret;
|
|
}
|
|
|
|
return CAIRO_STATUS_SUCCESS;
|
|
}
|
|
|
|
guint32
|
|
gdk_broadway_server_upload_texture (GdkBroadwayServer *server,
|
|
GdkTexture *texture)
|
|
{
|
|
guint32 id;
|
|
cairo_surface_t *surface = gdk_texture_download_surface (texture);
|
|
BroadwayRequestUploadTexture msg;
|
|
PngData data;
|
|
|
|
id = server->next_texture_id++;
|
|
|
|
data.fd = open_shared_memory ();
|
|
data.size = 0;
|
|
cairo_surface_write_to_png_stream (surface, write_png_cb, &data);
|
|
|
|
msg.id = id;
|
|
msg.offset = 0;
|
|
msg.size = data.size;
|
|
|
|
/* This passes ownership of fd */
|
|
gdk_broadway_server_send_fd_message (server, msg,
|
|
BROADWAY_REQUEST_UPLOAD_TEXTURE, data.fd);
|
|
|
|
return id;
|
|
}
|
|
|
|
|
|
void
|
|
gdk_broadway_server_release_texture (GdkBroadwayServer *server,
|
|
guint32 id)
|
|
{
|
|
BroadwayRequestReleaseTexture msg;
|
|
|
|
msg.id = id;
|
|
|
|
gdk_broadway_server_send_message (server, msg,
|
|
BROADWAY_REQUEST_RELEASE_TEXTURE);
|
|
}
|
|
|
|
void
|
|
gdk_broadway_server_surface_set_nodes (GdkBroadwayServer *server,
|
|
guint32 id,
|
|
GArray *nodes)
|
|
{
|
|
gsize size = sizeof(BroadwayRequestSetNodes) + sizeof(guint32) * (nodes->len - 1);
|
|
BroadwayRequestSetNodes *msg = g_alloca (size);
|
|
int i;
|
|
|
|
for (i = 0; i < nodes->len; i++)
|
|
msg->data[i] = g_array_index (nodes, guint32, i);
|
|
|
|
msg->id = id;
|
|
gdk_broadway_server_send_message_with_size (server, (BroadwayRequestBase *) msg, size, BROADWAY_REQUEST_SET_NODES, -1);
|
|
}
|
|
|
|
gboolean
|
|
_gdk_broadway_server_surface_move_resize (GdkBroadwayServer *server,
|
|
gint id,
|
|
gboolean with_move,
|
|
int x,
|
|
int y,
|
|
int width,
|
|
int height)
|
|
{
|
|
BroadwayRequestMoveResize msg;
|
|
|
|
msg.id = id;
|
|
msg.with_move = with_move;
|
|
msg.x = x;
|
|
msg.y = y;
|
|
msg.width = width;
|
|
msg.height = height;
|
|
|
|
gdk_broadway_server_send_message (server, msg,
|
|
BROADWAY_REQUEST_MOVE_RESIZE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
GdkGrabStatus
|
|
_gdk_broadway_server_grab_pointer (GdkBroadwayServer *server,
|
|
gint id,
|
|
gboolean owner_events,
|
|
guint32 event_mask,
|
|
guint32 time_)
|
|
{
|
|
BroadwayRequestGrabPointer msg;
|
|
guint32 serial, status;
|
|
BroadwayReply *reply;
|
|
|
|
msg.id = id;
|
|
msg.owner_events = owner_events;
|
|
msg.event_mask = event_mask;
|
|
msg.time_ = time_;
|
|
|
|
serial = gdk_broadway_server_send_message (server, msg,
|
|
BROADWAY_REQUEST_GRAB_POINTER);
|
|
reply = gdk_broadway_server_wait_for_reply (server, serial);
|
|
|
|
g_assert (reply->base.type == BROADWAY_REPLY_GRAB_POINTER);
|
|
|
|
status = reply->grab_pointer.status;
|
|
|
|
g_free (reply);
|
|
|
|
return status;
|
|
}
|
|
|
|
guint32
|
|
_gdk_broadway_server_ungrab_pointer (GdkBroadwayServer *server,
|
|
guint32 time_)
|
|
{
|
|
BroadwayRequestUngrabPointer msg;
|
|
guint32 serial, status;
|
|
BroadwayReply *reply;
|
|
|
|
msg.time_ = time_;
|
|
|
|
serial = gdk_broadway_server_send_message (server, msg,
|
|
BROADWAY_REQUEST_UNGRAB_POINTER);
|
|
reply = gdk_broadway_server_wait_for_reply (server, serial);
|
|
|
|
g_assert (reply->base.type == BROADWAY_REPLY_UNGRAB_POINTER);
|
|
|
|
status = reply->ungrab_pointer.status;
|
|
|
|
g_free (reply);
|
|
|
|
return status;
|
|
}
|
|
|
|
void
|
|
_gdk_broadway_server_set_show_keyboard (GdkBroadwayServer *server,
|
|
gboolean show)
|
|
{
|
|
BroadwayRequestSetShowKeyboard msg;
|
|
|
|
msg.show_keyboard = show;
|
|
gdk_broadway_server_send_message (server, msg,
|
|
BROADWAY_REQUEST_SET_SHOW_KEYBOARD);
|
|
}
|