mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-23 20:30:15 +00:00
broadway: Initial version of separate broadway server
This kinda works but is very rudimentary
This commit is contained in:
parent
4addb2108e
commit
fc96ef51d7
@ -78,14 +78,14 @@ libgdk_broadway_la_SOURCES = \
|
||||
gdkvisual-broadway.c \
|
||||
gdkwindow-broadway.c \
|
||||
gdkwindow-broadway.h \
|
||||
gdkprivate-broadway.h
|
||||
|
||||
libgdk_broadway_la_LIBADD = libbroadway.la
|
||||
gdkprivate-broadway.h \
|
||||
gdkbroadway-server.h \
|
||||
gdkbroadway-server-client.c
|
||||
|
||||
broadway_server_SOURCES = \
|
||||
broadway-server.c
|
||||
|
||||
broadway_server_LDADD = libbroadway.la $(GDK_DEP_LIBS)
|
||||
broadway_server_LDADD = libbroadway.la $(GDK_DEP_LIBS) -lrt
|
||||
|
||||
MAINTAINERCLEANFILES = $(broadway_built_sources)
|
||||
EXTRA_DIST += $(broadway_built_sources)
|
||||
|
@ -3,6 +3,11 @@
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
typedef struct {
|
||||
gint32 x, y;
|
||||
gint32 width, height;
|
||||
} BroadwayRect;
|
||||
|
||||
typedef enum {
|
||||
BROADWAY_EVENT_ENTER = 'e',
|
||||
BROADWAY_EVENT_LEAVE = 'l',
|
||||
@ -110,4 +115,150 @@ typedef union {
|
||||
BroadwayInputScreenResizeNotify screen_resize_notify;
|
||||
} BroadwayInputMsg;
|
||||
|
||||
typedef enum {
|
||||
BROADWAY_REQUEST_NEW_WINDOW,
|
||||
BROADWAY_REQUEST_FLUSH,
|
||||
BROADWAY_REQUEST_SYNC,
|
||||
BROADWAY_REQUEST_QUERY_MOUSE,
|
||||
BROADWAY_REQUEST_DESTROY_WINDOW,
|
||||
BROADWAY_REQUEST_SHOW_WINDOW,
|
||||
BROADWAY_REQUEST_HIDE_WINDOW,
|
||||
BROADWAY_REQUEST_SET_TRANSIENT_FOR,
|
||||
BROADWAY_REQUEST_TRANSLATE,
|
||||
BROADWAY_REQUEST_UPDATE,
|
||||
BROADWAY_REQUEST_MOVE_RESIZE,
|
||||
BROADWAY_REQUEST_GRAB_POINTER,
|
||||
BROADWAY_REQUEST_UNGRAB_POINTER
|
||||
} BroadwayRequestType;
|
||||
|
||||
typedef struct {
|
||||
guint32 size;
|
||||
guint32 serial;
|
||||
guint32 type;
|
||||
} BroadwayRequestBase, BroadwayRequestFlush, BroadwayRequestSync, BroadwayRequestQueryMouse;
|
||||
|
||||
typedef struct {
|
||||
BroadwayRequestBase base;
|
||||
guint32 id;
|
||||
} BroadwayRequestDestroyWindow, BroadwayRequestShowWindow, BroadwayRequestHideWindow;
|
||||
|
||||
typedef struct {
|
||||
BroadwayRequestBase base;
|
||||
guint32 id;
|
||||
guint32 parent;
|
||||
} BroadwayRequestSetTransientFor;
|
||||
|
||||
typedef struct {
|
||||
BroadwayRequestBase base;
|
||||
guint32 id;
|
||||
gint32 dx;
|
||||
gint32 dy;
|
||||
guint32 n_rects;
|
||||
BroadwayRect rects[1];
|
||||
} BroadwayRequestTranslate;
|
||||
|
||||
typedef struct {
|
||||
BroadwayRequestBase base;
|
||||
guint32 id;
|
||||
char name[34];
|
||||
guint32 width;
|
||||
guint32 height;
|
||||
} BroadwayRequestUpdate;
|
||||
|
||||
typedef struct {
|
||||
BroadwayRequestBase base;
|
||||
guint32 id;
|
||||
guint32 owner_events;
|
||||
guint32 event_mask;
|
||||
guint32 time_;
|
||||
} BroadwayRequestGrabPointer;
|
||||
|
||||
typedef struct {
|
||||
BroadwayRequestBase base;
|
||||
guint32 time_;
|
||||
} BroadwayRequestUngrabPointer;
|
||||
|
||||
typedef struct {
|
||||
BroadwayRequestBase base;
|
||||
gint32 x;
|
||||
gint32 y;
|
||||
guint32 width;
|
||||
guint32 height;
|
||||
guint32 is_temp;
|
||||
} BroadwayRequestNewWindow;
|
||||
|
||||
typedef struct {
|
||||
BroadwayRequestBase base;
|
||||
guint32 id;
|
||||
gint32 x;
|
||||
gint32 y;
|
||||
guint32 width;
|
||||
guint32 height;
|
||||
} BroadwayRequestMoveResize;
|
||||
|
||||
typedef union {
|
||||
BroadwayRequestBase base;
|
||||
BroadwayRequestNewWindow new_window;
|
||||
BroadwayRequestFlush flush;
|
||||
BroadwayRequestSync sync;
|
||||
BroadwayRequestQueryMouse query_mouse;
|
||||
BroadwayRequestDestroyWindow destroy_window;
|
||||
BroadwayRequestShowWindow show_window;
|
||||
BroadwayRequestHideWindow hide_window;
|
||||
BroadwayRequestSetTransientFor set_transient_for;
|
||||
BroadwayRequestUpdate update;
|
||||
BroadwayRequestMoveResize move_resize;
|
||||
BroadwayRequestGrabPointer grab_pointer;
|
||||
BroadwayRequestUngrabPointer ungrab_pointer;
|
||||
BroadwayRequestTranslate translate;
|
||||
} BroadwayRequest;
|
||||
|
||||
typedef enum {
|
||||
BROADWAY_REPLY_EVENT,
|
||||
BROADWAY_REPLY_SYNC,
|
||||
BROADWAY_REPLY_QUERY_MOUSE,
|
||||
BROADWAY_REPLY_NEW_WINDOW,
|
||||
BROADWAY_REPLY_GRAB_POINTER,
|
||||
BROADWAY_REPLY_UNGRAB_POINTER
|
||||
} BroadwayReplyType;
|
||||
|
||||
typedef struct {
|
||||
guint32 size;
|
||||
guint32 last_serial;
|
||||
guint32 in_reply_to;
|
||||
guint32 type;
|
||||
} BroadwayReplyBase, BroadwayReplySync;
|
||||
|
||||
typedef struct {
|
||||
BroadwayReplyBase base;
|
||||
guint32 id;
|
||||
} BroadwayReplyNewWindow;
|
||||
|
||||
typedef struct {
|
||||
BroadwayReplyBase base;
|
||||
guint32 status;
|
||||
} BroadwayReplyGrabPointer, BroadwayReplyUngrabPointer;
|
||||
|
||||
typedef struct {
|
||||
BroadwayReplyBase base;
|
||||
guint32 toplevel;
|
||||
gint32 root_x;
|
||||
gint32 root_y;
|
||||
guint32 mask;
|
||||
} BroadwayReplyQueryMouse;
|
||||
|
||||
typedef struct {
|
||||
BroadwayReplyBase base;
|
||||
BroadwayInputMsg msg;
|
||||
} BroadwayReplyEvent;
|
||||
|
||||
typedef union {
|
||||
BroadwayReplyBase base;
|
||||
BroadwayReplyEvent event;
|
||||
BroadwayReplyQueryMouse query_mouse;
|
||||
BroadwayReplyNewWindow new_window;
|
||||
BroadwayReplyGrabPointer grab_pointer;
|
||||
BroadwayReplyUngrabPointer ungrab_pointer;
|
||||
} BroadwayReply;
|
||||
|
||||
#endif /* __BROADWAY_PROTOCOL_H__ */
|
||||
|
@ -1,13 +1,346 @@
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include <gio/gunixsocketaddress.h>
|
||||
|
||||
#include "gdkbroadway-server.h"
|
||||
|
||||
GdkBroadwayServer *server;
|
||||
GList *clients;
|
||||
|
||||
static guint32 client_id_count = 1;
|
||||
|
||||
typedef struct {
|
||||
guint32 id;
|
||||
GSocketConnection *connection;
|
||||
GBufferedInputStream *in;
|
||||
guint32 last_seen_serial;
|
||||
GList *windows;
|
||||
} BroadwayClient;
|
||||
|
||||
static void
|
||||
client_free (BroadwayClient *client)
|
||||
{
|
||||
clients = g_list_remove (clients, client);
|
||||
g_object_unref (client->connection);
|
||||
g_object_unref (client->in);
|
||||
g_free (client);
|
||||
}
|
||||
|
||||
static void
|
||||
client_disconnected (BroadwayClient *client)
|
||||
{
|
||||
g_print ("client %d disconnected\n", client->id);
|
||||
/* TODO: destroy client windows, also maybe do this in an idle, at least in some cases like on an i/o error */
|
||||
client_free (client);
|
||||
}
|
||||
|
||||
static void
|
||||
send_reply (BroadwayClient *client,
|
||||
BroadwayRequest *request,
|
||||
BroadwayReply *reply,
|
||||
gsize size,
|
||||
guint32 type)
|
||||
{
|
||||
GOutputStream *output;
|
||||
|
||||
reply->base.size = size;
|
||||
reply->base.last_serial = client->last_seen_serial;
|
||||
reply->base.in_reply_to = request ? request->base.serial : 0;
|
||||
reply->base.type = type;
|
||||
|
||||
output = g_io_stream_get_output_stream (G_IO_STREAM (client->connection));
|
||||
if (!g_output_stream_write_all (output, reply, size, NULL, NULL, NULL))
|
||||
{
|
||||
g_printerr ("can't write to client");
|
||||
client_disconnected (client);
|
||||
/* TODO: Make sure we don't access client after this */
|
||||
}
|
||||
}
|
||||
|
||||
static cairo_region_t *
|
||||
region_from_rects (BroadwayRect *rects, int n_rects)
|
||||
{
|
||||
cairo_region_t *region;
|
||||
cairo_rectangle_int_t *cairo_rects;
|
||||
int i;
|
||||
|
||||
cairo_rects = g_new (cairo_rectangle_int_t, n_rects);
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rects[i].x = rects[i].x;
|
||||
cairo_rects[i].y = rects[i].y;
|
||||
cairo_rects[i].width = rects[i].width;
|
||||
cairo_rects[i].height = rects[i].height;
|
||||
}
|
||||
region = cairo_region_create_rectangles (cairo_rects, n_rects);
|
||||
g_free (cairo_rects);
|
||||
return region;
|
||||
}
|
||||
|
||||
static const cairo_user_data_key_t shm_cairo_key;
|
||||
|
||||
typedef struct {
|
||||
void *data;
|
||||
gsize data_size;
|
||||
} ShmSurfaceData;
|
||||
|
||||
static void
|
||||
shm_data_unmap (void *_data)
|
||||
{
|
||||
ShmSurfaceData *data = _data;
|
||||
munmap (data->data, data->data_size);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
open_surface (char *name, int width, int height)
|
||||
{
|
||||
ShmSurfaceData *data;
|
||||
cairo_surface_t *surface;
|
||||
gsize size;
|
||||
void *ptr;
|
||||
int fd;
|
||||
|
||||
/* TODO: Cache this */
|
||||
|
||||
size = width * height * sizeof (guint32);
|
||||
|
||||
fd = shm_open(name, O_RDONLY, 0600);
|
||||
if (fd == -1)
|
||||
{
|
||||
perror ("Failed to shm_open");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ptr = mmap(0, size, PROT_READ, MAP_SHARED, fd, 0);
|
||||
(void) close(fd);
|
||||
|
||||
if (ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
data = g_new0 (ShmSurfaceData, 1);
|
||||
|
||||
data->data = ptr;
|
||||
data->data_size = size;
|
||||
|
||||
surface = cairo_image_surface_create_for_data ((guchar *)data->data,
|
||||
CAIRO_FORMAT_RGB24,
|
||||
width, height,
|
||||
width * sizeof (guint32));
|
||||
g_assert (surface != NULL);
|
||||
|
||||
cairo_surface_set_user_data (surface, &shm_cairo_key,
|
||||
data, shm_data_unmap);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static void
|
||||
client_handle_request (BroadwayClient *client,
|
||||
BroadwayRequest *request)
|
||||
{
|
||||
BroadwayReplyNewWindow reply_new_window;
|
||||
BroadwayReplySync reply_sync;
|
||||
BroadwayReplyQueryMouse reply_query_mouse;
|
||||
BroadwayReplyGrabPointer reply_grab_pointer;
|
||||
BroadwayReplyUngrabPointer reply_ungrab_pointer;
|
||||
cairo_region_t *area;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
client->last_seen_serial = request->base.serial;
|
||||
|
||||
switch (request->base.type)
|
||||
{
|
||||
case BROADWAY_REQUEST_NEW_WINDOW:
|
||||
reply_new_window.id =
|
||||
_gdk_broadway_server_new_window (server,
|
||||
request->new_window.x,
|
||||
request->new_window.y,
|
||||
request->new_window.width,
|
||||
request->new_window.height,
|
||||
request->new_window.is_temp);
|
||||
|
||||
send_reply (client, request, (BroadwayReply *)&reply_new_window, sizeof (reply_new_window),
|
||||
BROADWAY_REPLY_NEW_WINDOW);
|
||||
break;
|
||||
case BROADWAY_REQUEST_FLUSH:
|
||||
_gdk_broadway_server_flush (server);
|
||||
break;
|
||||
case BROADWAY_REQUEST_SYNC:
|
||||
_gdk_broadway_server_flush (server);
|
||||
send_reply (client, request, (BroadwayReply *)&reply_sync, sizeof (reply_sync),
|
||||
BROADWAY_REPLY_SYNC);
|
||||
break;
|
||||
case BROADWAY_REQUEST_QUERY_MOUSE:
|
||||
_gdk_broadway_server_query_mouse (server,
|
||||
&reply_query_mouse.toplevel,
|
||||
&reply_query_mouse.root_x,
|
||||
&reply_query_mouse.root_y,
|
||||
&reply_query_mouse.mask);
|
||||
send_reply (client, request, (BroadwayReply *)&reply_query_mouse, sizeof (reply_query_mouse),
|
||||
BROADWAY_REPLY_QUERY_MOUSE);
|
||||
break;
|
||||
case BROADWAY_REQUEST_DESTROY_WINDOW:
|
||||
_gdk_broadway_server_destroy_window (server, request->destroy_window.id);
|
||||
break;
|
||||
case BROADWAY_REQUEST_SHOW_WINDOW:
|
||||
_gdk_broadway_server_window_show (server, request->show_window.id);
|
||||
break;
|
||||
case BROADWAY_REQUEST_HIDE_WINDOW:
|
||||
_gdk_broadway_server_window_hide (server, request->hide_window.id);
|
||||
break;
|
||||
case BROADWAY_REQUEST_SET_TRANSIENT_FOR:
|
||||
_gdk_broadway_server_window_set_transient_for (server,
|
||||
request->set_transient_for.id,
|
||||
request->set_transient_for.parent);
|
||||
break;
|
||||
case BROADWAY_REQUEST_TRANSLATE:
|
||||
area = region_from_rects (request->translate.rects,
|
||||
request->translate.n_rects);
|
||||
_gdk_broadway_server_window_translate (server,
|
||||
request->translate.id,
|
||||
area,
|
||||
request->translate.dx,
|
||||
request->translate.dy);
|
||||
cairo_region_destroy (area);
|
||||
break;
|
||||
case BROADWAY_REQUEST_UPDATE:
|
||||
surface = open_surface (request->update.name,
|
||||
request->update.width,
|
||||
request->update.height);
|
||||
if (surface != NULL)
|
||||
{
|
||||
_gdk_broadway_server_window_update (server,
|
||||
request->update.id,
|
||||
surface);
|
||||
cairo_surface_destroy (surface);
|
||||
}
|
||||
break;
|
||||
case BROADWAY_REQUEST_MOVE_RESIZE:
|
||||
if (!_gdk_broadway_server_window_move_resize (server,
|
||||
request->move_resize.id,
|
||||
request->move_resize.x,
|
||||
request->move_resize.y,
|
||||
request->move_resize.width,
|
||||
request->move_resize.height))
|
||||
{
|
||||
/* TODO: Send configure request */
|
||||
}
|
||||
break;
|
||||
case BROADWAY_REQUEST_GRAB_POINTER:
|
||||
reply_grab_pointer.status =
|
||||
_gdk_broadway_server_grab_pointer (server,
|
||||
request->grab_pointer.id,
|
||||
request->grab_pointer.owner_events,
|
||||
request->grab_pointer.event_mask,
|
||||
request->grab_pointer.time_);
|
||||
send_reply (client, request, (BroadwayReply *)&reply_grab_pointer, sizeof (reply_grab_pointer),
|
||||
BROADWAY_REPLY_GRAB_POINTER);
|
||||
break;
|
||||
case BROADWAY_REQUEST_UNGRAB_POINTER:
|
||||
reply_ungrab_pointer.status =
|
||||
_gdk_broadway_server_ungrab_pointer (server,
|
||||
request->ungrab_pointer.time_);
|
||||
send_reply (client, request, (BroadwayReply *)&reply_ungrab_pointer, sizeof (reply_ungrab_pointer),
|
||||
BROADWAY_REPLY_UNGRAB_POINTER);
|
||||
break;
|
||||
default:
|
||||
g_warning ("Unknown request of type %d\n", request->base.type);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
client_fill_cb (GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
BroadwayClient *client = user_data;
|
||||
gssize res;
|
||||
|
||||
res = g_buffered_input_stream_fill_finish (client->in, result, NULL);
|
||||
|
||||
if (res > 0)
|
||||
{
|
||||
guint32 size;
|
||||
gsize count, remaining;
|
||||
guint8 *buffer;
|
||||
BroadwayRequest request;
|
||||
|
||||
buffer = (guint8 *)g_buffered_input_stream_peek_buffer (client->in, &count);
|
||||
|
||||
remaining = count;
|
||||
while (remaining >= sizeof (guint32))
|
||||
{
|
||||
memcpy (&size, buffer, sizeof (guint32));
|
||||
|
||||
if (size <= remaining)
|
||||
{
|
||||
g_assert (size >= sizeof (BroadwayRequestBase));
|
||||
g_assert (size <= sizeof (BroadwayRequest));
|
||||
|
||||
memcpy (&request, buffer, size);
|
||||
client_handle_request (client, &request);
|
||||
|
||||
remaining -= size;
|
||||
buffer += size;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is guaranteed not to block */
|
||||
g_input_stream_skip (G_INPUT_STREAM (client->in), count - remaining, NULL, NULL);
|
||||
|
||||
g_buffered_input_stream_fill_async (client->in,
|
||||
4*1024,
|
||||
0,
|
||||
NULL,
|
||||
client_fill_cb, client);
|
||||
}
|
||||
else
|
||||
{
|
||||
client_disconnected (client);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
incoming_client (GSocketService *service,
|
||||
GSocketConnection *connection,
|
||||
GObject *source_object)
|
||||
{
|
||||
BroadwayClient *client;
|
||||
GInputStream *input;
|
||||
|
||||
client = g_new0 (BroadwayClient, 1);
|
||||
client->id = client_id_count++;
|
||||
client->connection = g_object_ref (connection);
|
||||
|
||||
input = g_io_stream_get_input_stream (G_IO_STREAM (client->connection));
|
||||
client->in = (GBufferedInputStream *)g_buffered_input_stream_new (input);
|
||||
|
||||
clients = g_list_prepend (clients, client);
|
||||
|
||||
g_buffered_input_stream_fill_async (client->in,
|
||||
4*1024,
|
||||
0,
|
||||
NULL,
|
||||
client_fill_cb, client);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GdkBroadwayServer *server;
|
||||
GError *error;
|
||||
GMainLoop *loop;
|
||||
GSocketAddress *address;
|
||||
GSocketService *listener;
|
||||
char *path;
|
||||
|
||||
error = NULL;
|
||||
server = _gdk_broadway_server_new (8080, &error);
|
||||
@ -17,16 +350,90 @@ main (int argc, char *argv[])
|
||||
return 1;
|
||||
}
|
||||
|
||||
path = g_build_filename (g_get_user_runtime_dir (), "broadway1.socket", NULL);
|
||||
g_print ("Listening on %s\n", path);
|
||||
address = g_unix_socket_address_new_with_type (path, -1,
|
||||
G_UNIX_SOCKET_ADDRESS_ABSTRACT);
|
||||
g_free (path);
|
||||
|
||||
listener = g_socket_service_new ();
|
||||
if (!g_socket_listener_add_address (G_SOCKET_LISTENER (listener),
|
||||
address,
|
||||
G_SOCKET_TYPE_STREAM,
|
||||
G_SOCKET_PROTOCOL_DEFAULT,
|
||||
G_OBJECT (server),
|
||||
NULL,
|
||||
&error))
|
||||
{
|
||||
g_printerr ("Can't listen: %s\n", error->message);
|
||||
return 1;
|
||||
}
|
||||
g_object_unref (address);
|
||||
|
||||
g_signal_connect (listener, "incoming", G_CALLBACK (incoming_client), NULL);
|
||||
|
||||
g_socket_service_start (G_SOCKET_SERVICE (listener));
|
||||
|
||||
loop = g_main_loop_new (NULL, FALSE);
|
||||
g_main_loop_run (loop);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* TODO: */
|
||||
static gsize
|
||||
get_event_size (int type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case BROADWAY_EVENT_ENTER:
|
||||
case BROADWAY_EVENT_LEAVE:
|
||||
return sizeof (BroadwayInputCrossingMsg);
|
||||
case BROADWAY_EVENT_POINTER_MOVE:
|
||||
return sizeof (BroadwayInputPointerMsg);
|
||||
case BROADWAY_EVENT_BUTTON_PRESS:
|
||||
case BROADWAY_EVENT_BUTTON_RELEASE:
|
||||
return sizeof (BroadwayInputButtonMsg);
|
||||
case BROADWAY_EVENT_SCROLL:
|
||||
return sizeof (BroadwayInputScrollMsg);
|
||||
case BROADWAY_EVENT_KEY_PRESS:
|
||||
case BROADWAY_EVENT_KEY_RELEASE:
|
||||
return sizeof (BroadwayInputKeyMsg);
|
||||
case BROADWAY_EVENT_GRAB_NOTIFY:
|
||||
case BROADWAY_EVENT_UNGRAB_NOTIFY:
|
||||
return sizeof (BroadwayInputGrabReply);
|
||||
case BROADWAY_EVENT_CONFIGURE_NOTIFY:
|
||||
return sizeof (BroadwayInputConfigureNotify);
|
||||
case BROADWAY_EVENT_DELETE_NOTIFY:
|
||||
return sizeof (BroadwayInputDeleteNotify);
|
||||
case BROADWAY_EVENT_SCREEN_SIZE_CHANGED:
|
||||
return sizeof (BroadwayInputScreenResizeNotify);
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_broadway_events_got_input (BroadwayInputMsg *message)
|
||||
{
|
||||
GList *l;
|
||||
BroadwayReplyEvent reply_event;
|
||||
gsize size;
|
||||
|
||||
size = get_event_size (message->base.type);
|
||||
|
||||
reply_event.msg = *message;
|
||||
|
||||
/* TODO:
|
||||
Don't send to all clients
|
||||
Rewrite serials, etc
|
||||
*/
|
||||
for (l = clients; l != NULL; l = l->next)
|
||||
{
|
||||
BroadwayClient *client = l->data;
|
||||
|
||||
send_reply (client, NULL, (BroadwayReply *)&reply_event,
|
||||
sizeof (BroadwayReplyBase) + size,
|
||||
BROADWAY_REPLY_EVENT);
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,10 @@
|
||||
|
||||
#include <glib.h>
|
||||
#include <gio/gio.h>
|
||||
#include "broadway-protocol.h"
|
||||
|
||||
typedef struct BroadwayOutput BroadwayOutput;
|
||||
|
||||
typedef struct {
|
||||
int x, y;
|
||||
int width, height;
|
||||
} BroadwayRect;
|
||||
|
||||
typedef enum {
|
||||
BROADWAY_WS_CONTINUATION = 0,
|
||||
BROADWAY_WS_TEXT = 1,
|
||||
|
693
gdk/broadway/gdkbroadway-server-client.c
Normal file
693
gdk/broadway/gdkbroadway-server-client.c
Normal file
@ -0,0 +1,693 @@
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "gdkbroadway-server.h"
|
||||
|
||||
#include "broadway.h"
|
||||
#include "gdkprivate-broadway.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
#include <gio/gunixsocketaddress.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
|
||||
typedef struct BroadwayInput BroadwayInput;
|
||||
|
||||
struct _GdkBroadwayServer {
|
||||
GObject parent_instance;
|
||||
|
||||
guint32 next_serial;
|
||||
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);
|
||||
|
||||
G_DEFINE_TYPE (GdkBroadwayServer, gdk_broadway_server, G_TYPE_OBJECT)
|
||||
|
||||
static void
|
||||
gdk_broadway_server_init (GdkBroadwayServer *server)
|
||||
{
|
||||
server->next_serial = 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 (int port, GError **error)
|
||||
{
|
||||
GdkBroadwayServer *server;
|
||||
char *basename;
|
||||
GSocketClient *client;
|
||||
GSocketConnection *connection;
|
||||
GSocketAddress *address;
|
||||
GPollableInputStream *pollable;
|
||||
GInputStream *in;
|
||||
GSource *source;
|
||||
char *path;
|
||||
|
||||
basename = g_strdup_printf ("broadway%d.socket", port);
|
||||
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_ABSTRACT);
|
||||
g_free (path);
|
||||
|
||||
client = g_socket_client_new ();
|
||||
|
||||
error = NULL;
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
GOutputStream *out;
|
||||
gsize written;
|
||||
|
||||
base->size = size;
|
||||
base->type = type;
|
||||
base->serial = server->next_serial++;
|
||||
|
||||
out = g_io_stream_get_output_stream (G_IO_STREAM (server->connection));
|
||||
|
||||
if (!g_output_stream_write_all (out, base, 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)
|
||||
|
||||
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 (&reply->event.msg);
|
||||
else
|
||||
g_warning ("Unhandled reply type %d\n", 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);
|
||||
return reply;
|
||||
}
|
||||
|
||||
read_some_input_blocking (server);
|
||||
parse_all_input (server);
|
||||
}
|
||||
|
||||
queue_process_input_at_idle (server);
|
||||
}
|
||||
|
||||
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_query_mouse (GdkBroadwayServer *server,
|
||||
guint32 *toplevel,
|
||||
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 (toplevel)
|
||||
*toplevel = reply->query_mouse.toplevel;
|
||||
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_window (GdkBroadwayServer *server,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height,
|
||||
gboolean is_temp)
|
||||
{
|
||||
BroadwayRequestNewWindow msg;
|
||||
guint32 serial, id;
|
||||
BroadwayReply *reply;
|
||||
|
||||
msg.x = x;
|
||||
msg.y = y;
|
||||
msg.width = width;
|
||||
msg.height = height;
|
||||
msg.is_temp = is_temp;
|
||||
|
||||
serial = gdk_broadway_server_send_message (server, msg,
|
||||
BROADWAY_REQUEST_NEW_WINDOW);
|
||||
reply = gdk_broadway_server_wait_for_reply (server, serial);
|
||||
|
||||
g_assert (reply->base.type == BROADWAY_REPLY_NEW_WINDOW);
|
||||
|
||||
id = reply->new_window.id;
|
||||
|
||||
g_free (reply);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_broadway_server_destroy_window (GdkBroadwayServer *server,
|
||||
gint id)
|
||||
{
|
||||
BroadwayRequestDestroyWindow msg;
|
||||
|
||||
msg.id = id;
|
||||
gdk_broadway_server_send_message (server, msg,
|
||||
BROADWAY_REQUEST_DESTROY_WINDOW);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gdk_broadway_server_window_show (GdkBroadwayServer *server,
|
||||
gint id)
|
||||
{
|
||||
BroadwayRequestShowWindow msg;
|
||||
|
||||
msg.id = id;
|
||||
gdk_broadway_server_send_message (server, msg,
|
||||
BROADWAY_REQUEST_SHOW_WINDOW);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gdk_broadway_server_window_hide (GdkBroadwayServer *server,
|
||||
gint id)
|
||||
{
|
||||
BroadwayRequestHideWindow msg;
|
||||
|
||||
msg.id = id;
|
||||
gdk_broadway_server_send_message (server, msg,
|
||||
BROADWAY_REQUEST_HIDE_WINDOW);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_broadway_server_window_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);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gdk_broadway_server_has_client (GdkBroadwayServer *server)
|
||||
{
|
||||
/* TODO */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gdk_broadway_server_window_translate (GdkBroadwayServer *server,
|
||||
gint id,
|
||||
cairo_region_t *area,
|
||||
gint dx,
|
||||
gint dy)
|
||||
{
|
||||
BroadwayRequestTranslate *msg;
|
||||
cairo_rectangle_int_t rect;
|
||||
int i, n_rects;
|
||||
gsize msg_size;
|
||||
|
||||
n_rects = cairo_region_num_rectangles (area);
|
||||
|
||||
msg_size = sizeof (BroadwayRequestTranslate) + (n_rects-1) * sizeof (BroadwayRect);
|
||||
msg = g_malloc (msg_size);
|
||||
|
||||
msg->id = id;
|
||||
msg->dx = dx;
|
||||
msg->dy = dy;
|
||||
msg->n_rects = n_rects;
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_region_get_rectangle (area, i, &rect);
|
||||
msg->rects[i].x = rect.x;
|
||||
msg->rects[i].y = rect.y;
|
||||
msg->rects[i].width = rect.width;
|
||||
msg->rects[i].height = rect.height;
|
||||
}
|
||||
|
||||
gdk_broadway_server_send_message_with_size (server, (BroadwayRequestBase *)msg, msg_size,
|
||||
BROADWAY_REQUEST_TRANSLATE);
|
||||
g_free (msg);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static char
|
||||
make_valid_fs_char (char c)
|
||||
{
|
||||
if (c == 0 || c == '/')
|
||||
return c + 1;
|
||||
return c;
|
||||
}
|
||||
|
||||
/* name must have at least space for 34 bytes */
|
||||
static int
|
||||
create_random_shm (char *name)
|
||||
{
|
||||
guint32 r;
|
||||
int i, o, fd;
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
o = 0;
|
||||
name[o++] = '/';
|
||||
for (i = 0; i < 32/4; i++)
|
||||
{
|
||||
r = g_random_int ();
|
||||
name[o++] = make_valid_fs_char ((r >> 0) & 0xff);
|
||||
name[o++] = make_valid_fs_char ((r >> 8) & 0xff);
|
||||
name[o++] = make_valid_fs_char ((r >> 16) & 0xff);
|
||||
name[o++] = make_valid_fs_char ((r >> 24) & 0xff);
|
||||
}
|
||||
name[o++] = 0;
|
||||
|
||||
fd = shm_open(name, O_RDWR|O_CREAT|O_EXCL, 0600);
|
||||
if (fd >= 0)
|
||||
return fd;
|
||||
|
||||
if (errno != EEXIST)
|
||||
{
|
||||
g_printerr ("Unable to allocate shared mem for window");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static const cairo_user_data_key_t gdk_broadway_shm_cairo_key;
|
||||
|
||||
typedef struct {
|
||||
char name[34];
|
||||
void *data;
|
||||
gsize data_size;
|
||||
} BroadwayShmSurfaceData;
|
||||
|
||||
static void
|
||||
shm_data_destroy (void *_data)
|
||||
{
|
||||
BroadwayShmSurfaceData *data = _data;
|
||||
|
||||
munmap (data->data, data->data_size);
|
||||
shm_unlink (data->name);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
_gdk_broadway_server_create_surface (int width,
|
||||
int height)
|
||||
{
|
||||
BroadwayShmSurfaceData *data;
|
||||
cairo_surface_t *surface;
|
||||
int res;
|
||||
int fd;
|
||||
|
||||
data = g_new (BroadwayShmSurfaceData, 1);
|
||||
data->data_size = width * height * sizeof (guint32);
|
||||
|
||||
fd = create_random_shm (data->name);
|
||||
|
||||
res = ftruncate (fd, data->data_size);
|
||||
g_assert (res != -1);
|
||||
|
||||
data->data = mmap(0, data->data_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
|
||||
(void) close(fd);
|
||||
|
||||
surface = cairo_image_surface_create_for_data ((guchar *)data->data,
|
||||
CAIRO_FORMAT_RGB24, width, height, width * sizeof (guint32));
|
||||
g_assert (surface != NULL);
|
||||
|
||||
cairo_surface_set_user_data (surface, &gdk_broadway_shm_cairo_key,
|
||||
data, shm_data_destroy);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
void
|
||||
_gdk_broadway_server_window_update (GdkBroadwayServer *server,
|
||||
gint id,
|
||||
cairo_surface_t *surface)
|
||||
{
|
||||
BroadwayRequestUpdate msg;
|
||||
BroadwayShmSurfaceData *data;
|
||||
|
||||
data = cairo_surface_get_user_data (surface, &gdk_broadway_shm_cairo_key);
|
||||
g_assert (data != NULL);
|
||||
|
||||
msg.id = id;
|
||||
memcpy (msg.name, data->name, 34);
|
||||
msg.width = cairo_image_surface_get_width (surface);
|
||||
msg.height = cairo_image_surface_get_height (surface);
|
||||
|
||||
gdk_broadway_server_send_message (server, msg,
|
||||
BROADWAY_REQUEST_UPDATE);
|
||||
}
|
||||
|
||||
gboolean
|
||||
_gdk_broadway_server_window_move_resize (GdkBroadwayServer *server,
|
||||
gint id,
|
||||
int x,
|
||||
int y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
BroadwayRequestMoveResize msg;
|
||||
|
||||
msg.id = id;
|
||||
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;
|
||||
}
|
@ -594,7 +594,7 @@ _gdk_broadway_server_read_all_input_nonblocking (GdkBroadwayServer *server)
|
||||
broadway_input_free (input);
|
||||
if (res < 0)
|
||||
{
|
||||
g_print ("input error %s\n", error->message);
|
||||
g_printerr ("input error %s\n", error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
return;
|
||||
@ -1172,7 +1172,7 @@ _gdk_broadway_server_get_last_seen_time (GdkBroadwayServer *server)
|
||||
|
||||
void
|
||||
_gdk_broadway_server_query_mouse (GdkBroadwayServer *server,
|
||||
gint32 *toplevel,
|
||||
guint32 *toplevel,
|
||||
gint32 *root_x,
|
||||
gint32 *root_y,
|
||||
guint32 *mask)
|
||||
@ -1690,6 +1690,7 @@ _gdk_broadway_server_resync_windows (GdkBroadwayServer *server)
|
||||
cairo_image_surface_get_stride (window->last_surface),
|
||||
cairo_image_surface_get_data (window->last_surface));
|
||||
}
|
||||
broadway_output_surface_flush (server->output, window->id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,6 @@ typedef struct _GdkBroadwayServerClass GdkBroadwayServerClass;
|
||||
#define GDK_IS_BROADWAY_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_BROADWAY_SERVER))
|
||||
#define GDK_BROADWAY_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_BROADWAY_SERVER, GdkBroadwayServerClass))
|
||||
|
||||
|
||||
GdkBroadwayServer *_gdk_broadway_server_new (int port,
|
||||
GError **error);
|
||||
gboolean _gdk_broadway_server_has_client (GdkBroadwayServer *server);
|
||||
@ -25,9 +24,9 @@ guint32 _gdk_broadway_server_get_last_seen_time (GdkBroadwaySer
|
||||
gboolean _gdk_broadway_server_lookahead_event (GdkBroadwayServer *server,
|
||||
const char *types);
|
||||
void _gdk_broadway_server_query_mouse (GdkBroadwayServer *server,
|
||||
gint *toplevel,
|
||||
gint *root_x,
|
||||
gint *root_y,
|
||||
guint32 *toplevel,
|
||||
gint32 *root_x,
|
||||
gint32 *root_y,
|
||||
guint32 *mask);
|
||||
GdkGrabStatus _gdk_broadway_server_grab_pointer (GdkBroadwayServer *server,
|
||||
gint id,
|
||||
@ -57,6 +56,8 @@ gboolean _gdk_broadway_server_window_translate (GdkBroadwaySer
|
||||
cairo_region_t *area,
|
||||
gint dx,
|
||||
gint dy);
|
||||
cairo_surface_t *_gdk_broadway_server_create_surface (int width,
|
||||
int height);
|
||||
void _gdk_broadway_server_window_update (GdkBroadwayServer *server,
|
||||
gint id,
|
||||
cairo_surface_t *surface);
|
||||
|
@ -159,7 +159,7 @@ _gdk_broadway_display_open (const gchar *display_name)
|
||||
if (display_name != NULL)
|
||||
port = strtol(display_name, NULL, 10);
|
||||
if (port == 0)
|
||||
port = 8080;
|
||||
port = 1;
|
||||
|
||||
broadway_display->server = _gdk_broadway_server_new (port, NULL);
|
||||
if (broadway_display->server == NULL)
|
||||
|
@ -241,9 +241,8 @@ _gdk_broadway_window_resize_surface (GdkWindow *window)
|
||||
{
|
||||
old = impl->surface;
|
||||
|
||||
impl->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
|
||||
gdk_window_get_width (impl->wrapper),
|
||||
gdk_window_get_height (impl->wrapper));
|
||||
impl->surface = _gdk_broadway_server_create_surface (gdk_window_get_width (impl->wrapper),
|
||||
gdk_window_get_height (impl->wrapper));
|
||||
|
||||
cairo_surface_destroy (old);
|
||||
}
|
||||
@ -281,7 +280,7 @@ gdk_window_broadway_ref_cairo_surface (GdkWindow *window)
|
||||
|
||||
/* Create actual backing store if missing */
|
||||
if (!impl->surface)
|
||||
impl->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h);
|
||||
impl->surface = _gdk_broadway_server_create_surface (w, h);
|
||||
|
||||
/* Create a destroyable surface referencing the real one */
|
||||
if (!impl->ref_surface)
|
||||
|
Loading…
Reference in New Issue
Block a user