forked from AuroraMiddleware/gtk
broadway: Implement pointer grabs
This commit is contained in:
parent
7d2ff79ddf
commit
95b19bca33
@ -661,6 +661,48 @@ broadway_output_query_pointer (BroadwayOutput *output, int id)
|
||||
return serial;
|
||||
}
|
||||
|
||||
guint32
|
||||
broadway_output_grab_pointer (BroadwayOutput *output,
|
||||
int id,
|
||||
gboolean owner_event,
|
||||
guint32 time_)
|
||||
{
|
||||
char buf[HEADER_LEN + 3 + 1 + 6];
|
||||
guint32 serial;
|
||||
int p;
|
||||
|
||||
serial = output->serial;
|
||||
p = write_header (output, buf, 'g');
|
||||
append_uint16 (id, buf, &p);
|
||||
buf[p++] = owner_event ? '1': '0';
|
||||
append_uint32 (time_, buf, &p);
|
||||
|
||||
assert (p == sizeof (buf));
|
||||
|
||||
broadway_output_write (output, buf, sizeof (buf));
|
||||
|
||||
return serial;
|
||||
}
|
||||
|
||||
guint32
|
||||
broadway_output_ungrab_pointer (BroadwayOutput *output,
|
||||
guint32 time_)
|
||||
{
|
||||
char buf[HEADER_LEN + 6];
|
||||
guint32 serial;
|
||||
int p;
|
||||
|
||||
serial = output->serial;
|
||||
p = write_header (output, buf, 'u');
|
||||
append_uint32 (time_, buf, &p);
|
||||
|
||||
assert (p == sizeof (buf));
|
||||
|
||||
broadway_output_write (output, buf, sizeof (buf));
|
||||
|
||||
return serial;
|
||||
}
|
||||
|
||||
void
|
||||
broadway_output_new_surface(BroadwayOutput *output, int id, int x, int y, int w, int h)
|
||||
{
|
||||
|
@ -57,3 +57,9 @@ void broadway_output_copy_rectangles (BroadwayOutput *output,
|
||||
int dy);
|
||||
guint32 broadway_output_query_pointer (BroadwayOutput *output,
|
||||
int id);
|
||||
guint32 broadway_output_grab_pointer (BroadwayOutput *output,
|
||||
int id,
|
||||
gboolean owner_event,
|
||||
guint32 time_);
|
||||
guint32 broadway_output_ungrab_pointer (BroadwayOutput *output,
|
||||
guint32 time_);
|
||||
|
@ -76,9 +76,15 @@ function createXHR()
|
||||
return null;
|
||||
}
|
||||
|
||||
var grab = new Object();
|
||||
grab.window = null;
|
||||
grab.owner_events = false;
|
||||
grab.time = 0;
|
||||
grab.implicit = false;
|
||||
var last_serial = 0;
|
||||
var last_x = 0;
|
||||
var last_y = 0;
|
||||
var real_window_with_mouse = 0;
|
||||
var window_with_mouse = 0;
|
||||
var surfaces = {};
|
||||
var outstanding_commands = new Array();
|
||||
@ -99,6 +105,14 @@ function initContext(canvas, x, y, id)
|
||||
return context;
|
||||
}
|
||||
|
||||
var GDK_GRAB_SUCCESS = 0;
|
||||
var GDK_GRAB_ALREADY_GRABBED = 1;
|
||||
var GDK_GRAB_INVALID_TIME = 2;
|
||||
|
||||
var GDK_CROSSING_NORMAL = 0;
|
||||
var GDK_CROSSING_GRAB = 1;
|
||||
var GDK_CROSSING_UNGRAB = 2;
|
||||
|
||||
function handleCommands(cmd_obj)
|
||||
{
|
||||
var cmd = cmd_obj.data;
|
||||
@ -265,6 +279,40 @@ function handleCommands(cmd_obj)
|
||||
send_input ("q", [pos.root_x, pos.root_y, pos.win_x, pos.win_x, window_with_mouse]);
|
||||
break;
|
||||
|
||||
case 'g': // Grab
|
||||
var id = base64_16(cmd, i);
|
||||
i = i + 3;
|
||||
var owner_events = cmd[i++] == '1';
|
||||
var time = base64_32(cmd, i);
|
||||
i = i + 6;
|
||||
|
||||
if (grab.window != null) {
|
||||
/* Previous grab, compare times */
|
||||
if (time != 0 && grab.time != 0 &&
|
||||
time > grab.time) {
|
||||
send_input ("g", [GDK_GRAB_INVALID_TIME]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
doGrab(id, owner_events, time, false);
|
||||
|
||||
send_input ("g", [GDK_GRAB_SUCCESS]);
|
||||
|
||||
break;
|
||||
|
||||
case 'u': // Ungrab
|
||||
var time = base64_32(cmd, i);
|
||||
i = i + 6;
|
||||
send_input ("u", []);
|
||||
|
||||
if (grab.window != null) {
|
||||
if (grab.time == 0 || time == 0 ||
|
||||
grab.time < time)
|
||||
grab.window = null;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
alert("Unknown op " + command);
|
||||
}
|
||||
@ -349,41 +397,99 @@ function getPositionsFromEvent(ev, relativeId) {
|
||||
return res;
|
||||
}
|
||||
|
||||
function getEffectiveEventTarget (id) {
|
||||
if (grab.window != null) {
|
||||
if (!grab.owner_events)
|
||||
return grab.window;
|
||||
if (id == 0)
|
||||
return grab.window;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
function on_mouse_move (ev) {
|
||||
var id = get_surface_id(ev);
|
||||
id = getEffectiveEventTarget (id);
|
||||
var pos = getPositionsFromEvent(ev, id);
|
||||
send_input ("m", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp]);
|
||||
}
|
||||
|
||||
function on_mouse_over (ev) {
|
||||
var id = get_surface_id(ev);
|
||||
real_window_with_mouse = id;
|
||||
id = getEffectiveEventTarget (id);
|
||||
var pos = getPositionsFromEvent(ev, id);
|
||||
window_with_mouse = id;
|
||||
if (window_with_mouse != 0) {
|
||||
send_input ("e", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp]);
|
||||
send_input ("e", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp, GDK_CROSSING_NORMAL]);
|
||||
}
|
||||
}
|
||||
|
||||
function on_mouse_out (ev) {
|
||||
var id = get_surface_id(ev);
|
||||
var origId = id;
|
||||
id = getEffectiveEventTarget (id);
|
||||
var pos = getPositionsFromEvent(ev, id);
|
||||
|
||||
if (id != 0) {
|
||||
send_input ("l", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp]);
|
||||
send_input ("l", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp, GDK_CROSSING_NORMAL]);
|
||||
}
|
||||
real_window_with_mouse = 0;
|
||||
window_with_mouse = 0;
|
||||
}
|
||||
|
||||
function doGrab(id, owner_events, time, implicit) {
|
||||
var pos;
|
||||
|
||||
if (window_with_mouse != id) {
|
||||
if (window_with_mouse != 0) {
|
||||
pos = getPositionsFromAbsCoord(last_x, last_y, window_with_mouse);
|
||||
send_input ("l", [window_with_mouse, pos.root_x, pos.root_y, pos.win_x, pos.win_y, time, GDK_CROSSING_GRAB]);
|
||||
}
|
||||
pos = getPositionsFromAbsCoord(last_x, last_y, id);
|
||||
send_input ("e", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, time, GDK_CROSSING_GRAB]);
|
||||
window_with_mouse = id;
|
||||
}
|
||||
|
||||
grab.window = id;
|
||||
grab.owner_events = owner_events;
|
||||
grab.time = time;
|
||||
grab.implicit = implicit;
|
||||
}
|
||||
|
||||
function doUngrab() {
|
||||
var pos;
|
||||
if (real_window_with_mouse != window_with_mouse) {
|
||||
if (window_with_mouse != 0) {
|
||||
pos = getPositionsFromAbsCoord(last_x, last_y, window_with_mouse);
|
||||
send_input ("l", [window_with_mouse, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp, GDK_CROSSING_UNGRAB]);
|
||||
}
|
||||
if (real_window_with_mouse != 0) {
|
||||
pos = getPositionsFromAbsCoord(last_x, last_y, id);
|
||||
send_input ("e", [real_window_with_mouse, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp, GDK_CROSSING_UNGRAB]);
|
||||
}
|
||||
window_with_mouse = real_window_with_mouse;
|
||||
}
|
||||
grab.window = null;
|
||||
}
|
||||
|
||||
function on_mouse_down (ev) {
|
||||
var id = get_surface_id(ev);
|
||||
id = getEffectiveEventTarget (id);
|
||||
var pos = getPositionsFromEvent(ev, id);
|
||||
if (grab.window != null)
|
||||
doGrab (id, false, ev.timeStamp, true);
|
||||
send_input ("b", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp, ev.button]);
|
||||
}
|
||||
|
||||
function on_mouse_up (ev) {
|
||||
var id = get_surface_id(ev);
|
||||
id = getEffectiveEventTarget (id);
|
||||
var pos = getPositionsFromEvent(ev, id);
|
||||
send_input ("B", [id, pos.root_x, pos.root_y, pos.win_x, pos.win_y, ev.timeStamp, ev.button]);
|
||||
|
||||
if (grab.window != null && grab.implicit)
|
||||
doUngrab();
|
||||
}
|
||||
|
||||
var last_key_down = 0;
|
||||
|
@ -182,7 +182,7 @@ gdk_broadway_device_query_state (GdkDevice *device,
|
||||
|
||||
serial = broadway_output_query_pointer (broadway_display->output, impl->id);
|
||||
|
||||
reply = _gdk_broadway_display_block_for_input (display, 'q', serial);
|
||||
reply = _gdk_broadway_display_block_for_input (display, 'q', serial, TRUE);
|
||||
|
||||
if (reply != NULL)
|
||||
{
|
||||
@ -266,13 +266,93 @@ gdk_broadway_device_grab (GdkDevice *device,
|
||||
GdkCursor *cursor,
|
||||
guint32 time_)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkBroadwayDisplay *broadway_display;
|
||||
GdkWindowImplBroadway *impl;
|
||||
guint32 serial;
|
||||
char *reply;
|
||||
|
||||
display = gdk_device_get_display (device);
|
||||
broadway_display = GDK_BROADWAY_DISPLAY (display);
|
||||
|
||||
if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
|
||||
{
|
||||
/* Device is a keyboard */
|
||||
return GDK_GRAB_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Device is a pointer */
|
||||
|
||||
if (broadway_display->output)
|
||||
{
|
||||
impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
|
||||
|
||||
serial = broadway_output_grab_pointer (broadway_display->output,
|
||||
impl->id, owner_events, time_);
|
||||
reply = _gdk_broadway_display_block_for_input (display, 'g', serial, FALSE);
|
||||
if (reply != NULL)
|
||||
{
|
||||
char *p;
|
||||
char cmd;
|
||||
guint32 reply_serial;
|
||||
int res;
|
||||
|
||||
p = reply;
|
||||
|
||||
cmd = *p++;
|
||||
reply_serial = (guint32)strtol(p, &p, 10);
|
||||
p++; /* Skip , */
|
||||
|
||||
res = strtol(p, &p, 10);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return GDK_GRAB_NOT_VIEWABLE;
|
||||
}
|
||||
}
|
||||
|
||||
#define TIME_IS_LATER(time1, time2) \
|
||||
( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) || \
|
||||
(( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 )) \
|
||||
)
|
||||
|
||||
static void
|
||||
gdk_broadway_device_ungrab (GdkDevice *device,
|
||||
guint32 time_)
|
||||
{
|
||||
GdkDisplay *display;
|
||||
GdkBroadwayDisplay *broadway_display;
|
||||
GdkDeviceGrabInfo *grab;
|
||||
guint32 serial;
|
||||
|
||||
display = gdk_device_get_display (device);
|
||||
broadway_display = GDK_BROADWAY_DISPLAY (display);
|
||||
|
||||
if (gdk_device_get_source (device) == GDK_SOURCE_KEYBOARD)
|
||||
{
|
||||
/* Device is a keyboard */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Device is a pointer */
|
||||
|
||||
if (broadway_display->output)
|
||||
{
|
||||
serial = broadway_output_ungrab_pointer (broadway_display->output, time_);
|
||||
|
||||
gdk_display_flush (display);
|
||||
|
||||
grab = _gdk_display_get_last_device_grab (display, device);
|
||||
if (grab &&
|
||||
(time_ == GDK_CURRENT_TIME ||
|
||||
grab->time == GDK_CURRENT_TIME ||
|
||||
!TIME_IS_LATER (grab->time, time_)))
|
||||
grab->serial_end = serial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GdkWindow *
|
||||
|
@ -261,7 +261,8 @@ process_input_idle_cb (GdkBroadwayDisplay *display)
|
||||
|
||||
/* Note: This may be called while handling a message (i.e. sorta recursively) */
|
||||
char *
|
||||
_gdk_broadway_display_block_for_input (GdkDisplay *display, char op, guint32 serial)
|
||||
_gdk_broadway_display_block_for_input (GdkDisplay *display, char op,
|
||||
guint32 serial, gboolean remove_message)
|
||||
{
|
||||
GdkBroadwayDisplay *broadway_display;
|
||||
char *message;
|
||||
@ -295,6 +296,7 @@ _gdk_broadway_display_block_for_input (GdkDisplay *display, char op, guint32 ser
|
||||
msg_serial = (guint32)strtol(message+1, NULL, 10);
|
||||
if (msg_serial == serial)
|
||||
{
|
||||
if (remove_message)
|
||||
broadway_display->input_messages =
|
||||
g_list_delete_link (broadway_display->input_messages, l);
|
||||
return message;
|
||||
|
@ -124,7 +124,7 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
|
||||
GdkScreen *screen;
|
||||
GdkWindow *root, *window;
|
||||
char *p;
|
||||
int button, dir,key;
|
||||
int button, dir, key, detail;
|
||||
guint32 serial;
|
||||
guint64 time;
|
||||
GdkEvent *event = NULL;
|
||||
@ -142,6 +142,8 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
|
||||
switch (cmd) {
|
||||
case 'e': /* Enter */
|
||||
p = parse_pointer_data (p, &data);
|
||||
p++; /* Skip , */
|
||||
detail = strtol(p, &p, 10);
|
||||
|
||||
display_broadway->last_x = data.root_x;
|
||||
display_broadway->last_y = data.root_y;
|
||||
@ -160,7 +162,7 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
|
||||
event->crossing.y = data.win_y;
|
||||
event->crossing.x_root = data.root_x;
|
||||
event->crossing.y_root = data.root_y;
|
||||
event->crossing.mode = GDK_CROSSING_NORMAL;
|
||||
event->crossing.mode = detail;
|
||||
event->crossing.detail = GDK_NOTIFY_ANCESTOR;
|
||||
gdk_event_set_device (event, display->core_pointer);
|
||||
|
||||
@ -178,6 +180,8 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
|
||||
break;
|
||||
case 'l': /* Leave */
|
||||
p = parse_pointer_data (p, &data);
|
||||
p++; /* Skip , */
|
||||
detail = strtol(p, &p, 10);
|
||||
|
||||
display_broadway->last_x = data.root_x;
|
||||
display_broadway->last_y = data.root_y;
|
||||
@ -196,7 +200,7 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
|
||||
event->crossing.x_root = data.root_x;
|
||||
event->crossing.y_root = data.root_y;
|
||||
event->crossing.mode = GDK_CROSSING_NORMAL;
|
||||
event->crossing.detail = GDK_NOTIFY_ANCESTOR;
|
||||
event->crossing.detail = detail;
|
||||
gdk_event_set_device (event, display->core_pointer);
|
||||
|
||||
node = _gdk_event_queue_append (display, event);
|
||||
@ -310,6 +314,10 @@ _gdk_broadway_events_got_input (GdkDisplay *display,
|
||||
}
|
||||
|
||||
break;
|
||||
case 'g':
|
||||
case 'u':
|
||||
_gdk_display_device_grab_update (display, display->core_pointer, NULL, serial);
|
||||
break;
|
||||
case 'q':
|
||||
g_printerr ("Got unexpected query pointer reply w serial %d\n", serial);
|
||||
break;
|
||||
|
@ -189,7 +189,8 @@ gchar *_gdk_broadway_display_utf8_to_string_target (GdkDisplay *display,
|
||||
GdkKeymap* _gdk_broadway_display_get_keymap (GdkDisplay *display);
|
||||
char * _gdk_broadway_display_block_for_input (GdkDisplay *display,
|
||||
char op,
|
||||
guint32 serial);
|
||||
guint32 serial,
|
||||
gboolean remove);
|
||||
|
||||
/* Window methods - testing */
|
||||
void _gdk_broadway_window_sync_rendering (GdkWindow *window);
|
||||
|
Loading…
Reference in New Issue
Block a user