Compare commits
40 Commits
wip/waylan
...
wip/waylan
Author | SHA1 | Date | |
---|---|---|---|
![]() |
531a7b2812 | ||
![]() |
580669cdea | ||
![]() |
e50a578ad3 | ||
![]() |
06b3d36e97 | ||
![]() |
715fa91599 | ||
![]() |
997188e914 | ||
![]() |
c6dd56f9ce | ||
![]() |
466af03ed3 | ||
![]() |
9c2d806556 | ||
![]() |
13a7c8da85 | ||
![]() |
d69d566087 | ||
![]() |
b722274886 | ||
![]() |
164cdabb21 | ||
![]() |
0b025f0e9c | ||
![]() |
87354bdac6 | ||
![]() |
02e163882a | ||
![]() |
9db02a7379 | ||
![]() |
78fcfec5c1 | ||
![]() |
1bd3a162f8 | ||
![]() |
918cfdcbda | ||
![]() |
cd76313297 | ||
![]() |
dc8231c2cf | ||
![]() |
4d01eb3a23 | ||
![]() |
35f47b211d | ||
![]() |
77046edf21 | ||
![]() |
488df061c7 | ||
![]() |
21d511e50f | ||
![]() |
15e83f0c2f | ||
![]() |
a23830fd13 | ||
![]() |
c8bf8c17be | ||
![]() |
d82e24981b | ||
![]() |
01b8ffac5d | ||
![]() |
1fa56bd7e0 | ||
![]() |
c3f28b9cdb | ||
![]() |
dc4e1d4cd1 | ||
![]() |
d69553e8f5 | ||
![]() |
0ead0d945a | ||
![]() |
c24d9bf142 | ||
![]() |
a6bf340ff8 | ||
![]() |
35ef7c95b2 |
@@ -6,3 +6,5 @@ EXTRA_DIST = HACKING MAINTAINERS rationales.txt
|
||||
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
|
22
NEWS
22
NEWS
@@ -1,3 +1,25 @@
|
||||
3.11.1
|
||||
======
|
||||
* Fix tile previews getting stuck on right click during drags [Lionel; #704759]
|
||||
* Use new UPower API [Bastien]
|
||||
* Set hot spot when cursor set from wl_buffer [Jonas; #709593]
|
||||
* Expose min-backlight-step [Asad; #710380]
|
||||
* Misc. bug fixes and cleanups [Jasper, Olav, Magdalen; #709776]
|
||||
|
||||
Contributors:
|
||||
Magdalen Berns, Lionel Landwerlin, Asad Mehmood, Bastien Nocera,
|
||||
Jasper St. Pierre, Olav Vitters, Jonas Ådahl
|
||||
|
||||
3.10.1
|
||||
======
|
||||
* Don't apply fullscreen workarounds to CSD windows [Giovanni; #708718]
|
||||
* Fix hangs during DND operations [Adel; #709340]
|
||||
* Misc bug fixes [Dan, Giovanni, Jasper; #708813, #708420]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Adel Gadllah, Dan Horák, Hans Petter Jansson,
|
||||
Jasper St. Pierre
|
||||
|
||||
3.10.0.1
|
||||
========
|
||||
* Fix bug when a window changed size twice in a single frame - this
|
||||
|
@@ -1,8 +1,9 @@
|
||||
AC_PREREQ(2.50)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [10])
|
||||
m4_define([mutter_micro_version], [0.1])
|
||||
m4_define([mutter_minor_version], [11])
|
||||
m4_define([mutter_micro_version], [1])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@@ -79,7 +80,7 @@ MUTTER_PC_MODULES="
|
||||
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
|
||||
$CLUTTER_PACKAGE >= 1.15.94
|
||||
cogl-1.0 >= 1.13.3
|
||||
upower-glib > 0.9.11
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
"
|
||||
|
||||
|
@@ -207,7 +207,6 @@ meta_key_binding_get_modifiers
|
||||
meta_key_binding_get_mask
|
||||
meta_key_binding_is_builtin
|
||||
meta_keybindings_set_custom_handler
|
||||
meta_keybindings_switch_window
|
||||
meta_screen_ungrab_all_keys
|
||||
meta_screen_grab_all_keys
|
||||
</SECTION>
|
||||
|
@@ -21,6 +21,7 @@ environment.</description>
|
||||
-->
|
||||
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" />
|
||||
<download-page rdf:resource="http://download.gnome.org/sources/mutter/" />
|
||||
<download-page rdf:resource="http://download.gnome.org/sources/mutter-wayland/" />
|
||||
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
|
||||
|
||||
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
|
||||
|
@@ -52,7 +52,6 @@ libmutter_wayland_la_SOURCES = \
|
||||
core/async-getprop.h \
|
||||
core/barrier.c \
|
||||
meta/barrier.h \
|
||||
core/barrier-private.h \
|
||||
core/bell.c \
|
||||
core/bell.h \
|
||||
core/boxes.c \
|
||||
@@ -396,7 +395,6 @@ $(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
|
||||
--generate-c-code meta-dbus-xrandr \
|
||||
$(srcdir)/xrandr.xml
|
||||
|
||||
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
|
||||
|
||||
$(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
|
||||
$(AM_V_GEN)gdbus-codegen \
|
||||
|
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include <meta/util.h>
|
||||
#include "clutter-utils.h"
|
||||
#include "meta-texture-tower.h"
|
||||
|
||||
#include "meta-shaped-texture-private.h"
|
||||
@@ -280,6 +281,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
CoglTexture *paint_tex;
|
||||
ClutterActorBox alloc;
|
||||
cairo_region_t *blended_region = NULL;
|
||||
CoglPipelineFilter filter;
|
||||
|
||||
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
||||
return;
|
||||
@@ -316,6 +318,22 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
/* Use nearest-pixel interpolation if the texture is unscaled. This
|
||||
* improves performance, especially with software rendering.
|
||||
*/
|
||||
|
||||
filter = COGL_PIPELINE_FILTER_LINEAR;
|
||||
|
||||
if (!clutter_actor_is_in_clone_paint (actor))
|
||||
{
|
||||
int x_origin, y_origin;
|
||||
|
||||
if (meta_actor_is_untransformed (actor,
|
||||
&x_origin,
|
||||
&y_origin))
|
||||
filter = COGL_PIPELINE_FILTER_NEAREST;
|
||||
}
|
||||
|
||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
fb = cogl_get_draw_framebuffer ();
|
||||
|
||||
@@ -344,6 +362,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
|
||||
opaque_pipeline = get_unblended_pipeline (ctx);
|
||||
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
|
||||
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
|
||||
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
for (i = 0; i < n_rects; i++)
|
||||
@@ -385,9 +404,11 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
{
|
||||
pipeline = get_masked_pipeline (ctx);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
|
||||
cogl_pipeline_set_layer_filters (pipeline, 1, filter, filter);
|
||||
}
|
||||
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, paint_tex);
|
||||
cogl_pipeline_set_layer_filters (pipeline, 0, filter, filter);
|
||||
|
||||
{
|
||||
CoglColor color;
|
||||
|
@@ -1007,7 +1007,7 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
|
||||
}
|
||||
|
||||
interval = (int)(1000000 / refresh_rate) * 6;
|
||||
offset = MAX (0, current_time - priv->frame_drawn_time + interval) / 1000;
|
||||
offset = MAX (0, priv->frame_drawn_time + interval - current_time) / 1000;
|
||||
|
||||
/* The clutter master clock source has already been added with META_PRIORITY_REDRAW,
|
||||
* so the timer will run *after* the clutter frame handling, if a frame is ready
|
||||
|
@@ -1,39 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
|
||||
|
||||
/*
|
||||
* Copyright 2012, 2013 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Authors: Jaster St. Pierre <jstpierr@redhat.com>
|
||||
* Giovanni Campagna <gcampagn@redhat.com>
|
||||
*/
|
||||
|
||||
#ifndef BARRIER_PRIVATE_H
|
||||
#define BARRIER_PRIVATE_H
|
||||
|
||||
typedef struct _MetaBarrierManager MetaBarrierManager;
|
||||
|
||||
MetaBarrierManager *meta_barrier_manager_get (void);
|
||||
|
||||
void meta_barrier_manager_constrain_cursor (MetaBarrierManager *manager,
|
||||
guint32 time,
|
||||
float current_x,
|
||||
float current_y,
|
||||
float *new_x,
|
||||
float *new_y);
|
||||
|
||||
#endif
|
@@ -1,27 +1,5 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
|
||||
|
||||
/*
|
||||
* Copyright 2012, 2013 Red Hat Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Authors: Jaster St. Pierre <jstpierr@redhat.com>
|
||||
* Giovanni Campagna <gcampagn@redhat.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:barrier
|
||||
* @Title: MetaBarrier
|
||||
@@ -31,7 +9,6 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
@@ -39,7 +16,6 @@
|
||||
#include <meta/barrier.h>
|
||||
#include "display-private.h"
|
||||
#include "mutter-enum-types.h"
|
||||
#include "barrier-private.h"
|
||||
#include "core.h"
|
||||
|
||||
G_DEFINE_TYPE (MetaBarrier, meta_barrier, G_TYPE_OBJECT)
|
||||
@@ -80,23 +56,9 @@ struct _MetaBarrierPrivate
|
||||
|
||||
MetaBarrierDirection directions;
|
||||
|
||||
/* x11 */
|
||||
PointerBarrier xbarrier;
|
||||
|
||||
/* wayland */
|
||||
gboolean active;
|
||||
gboolean seen, hit;
|
||||
|
||||
int barrier_event_id;
|
||||
int release_event_id;
|
||||
guint32 last_timestamp;
|
||||
};
|
||||
|
||||
struct _MetaBarrierManager
|
||||
{
|
||||
GList *barriers;
|
||||
} *global_barrier_manager;
|
||||
|
||||
static void meta_barrier_event_unref (MetaBarrierEvent *event);
|
||||
|
||||
static void
|
||||
@@ -186,10 +148,7 @@ meta_barrier_dispose (GObject *object)
|
||||
gboolean
|
||||
meta_barrier_is_active (MetaBarrier *barrier)
|
||||
{
|
||||
if (meta_is_wayland_compositor ())
|
||||
return barrier->priv->active;
|
||||
else
|
||||
return barrier->priv->xbarrier != 0;
|
||||
return barrier->priv->xbarrier != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -206,25 +165,15 @@ void
|
||||
meta_barrier_release (MetaBarrier *barrier,
|
||||
MetaBarrierEvent *event)
|
||||
{
|
||||
MetaBarrierPrivate *priv;
|
||||
|
||||
priv = barrier->priv;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
priv->release_event_id = event->event_id;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef HAVE_XI23
|
||||
if (META_DISPLAY_HAS_XINPUT_23 (priv->display))
|
||||
{
|
||||
XIBarrierReleasePointer (priv->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
priv->xbarrier, event->event_id);
|
||||
}
|
||||
#endif /* HAVE_XI23 */
|
||||
MetaBarrierPrivate *priv = barrier->priv;
|
||||
if (META_DISPLAY_HAS_XINPUT_23 (priv->display))
|
||||
{
|
||||
XIBarrierReleasePointer (priv->display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
priv->xbarrier, event->event_id);
|
||||
}
|
||||
#endif /* HAVE_XI23 */
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -243,29 +192,19 @@ meta_barrier_constructed (GObject *object)
|
||||
return;
|
||||
}
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaBarrierManager *manager = meta_barrier_manager_get ();
|
||||
dpy = priv->display->xdisplay;
|
||||
root = DefaultRootWindow (dpy);
|
||||
|
||||
manager->barriers = g_list_prepend (manager->barriers, g_object_ref (barrier));
|
||||
priv->active = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dpy = priv->display->xdisplay;
|
||||
root = DefaultRootWindow (dpy);
|
||||
priv->xbarrier = XFixesCreatePointerBarrier (dpy, root,
|
||||
priv->x1, priv->y1,
|
||||
priv->x2, priv->y2,
|
||||
priv->directions, 0, NULL);
|
||||
|
||||
priv->xbarrier = XFixesCreatePointerBarrier (dpy, root,
|
||||
priv->x1, priv->y1,
|
||||
priv->x2, priv->y2,
|
||||
priv->directions, 0, NULL);
|
||||
/* Take a ref that we'll release when the XID dies inside destroy(),
|
||||
* so that the object stays alive and doesn't get GC'd. */
|
||||
g_object_ref (barrier);
|
||||
|
||||
/* Take a ref that we'll release when the XID dies inside destroy(),
|
||||
* so that the object stays alive and doesn't get GC'd. */
|
||||
g_object_ref (barrier);
|
||||
|
||||
g_hash_table_insert (priv->display->xids, &priv->xbarrier, barrier);
|
||||
}
|
||||
g_hash_table_insert (priv->display->xids, &priv->xbarrier, barrier);
|
||||
|
||||
G_OBJECT_CLASS (meta_barrier_parent_class)->constructed (object);
|
||||
}
|
||||
@@ -373,26 +312,16 @@ meta_barrier_destroy (MetaBarrier *barrier)
|
||||
if (priv->display == NULL)
|
||||
return;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
{
|
||||
MetaBarrierManager *manager = meta_barrier_manager_get ();
|
||||
dpy = priv->display->xdisplay;
|
||||
|
||||
manager->barriers = g_list_remove (manager->barriers, barrier);
|
||||
g_object_unref (barrier);
|
||||
}
|
||||
else
|
||||
{
|
||||
dpy = priv->display->xdisplay;
|
||||
if (!meta_barrier_is_active (barrier))
|
||||
return;
|
||||
|
||||
if (!meta_barrier_is_active (barrier))
|
||||
return;
|
||||
XFixesDestroyPointerBarrier (dpy, priv->xbarrier);
|
||||
g_hash_table_remove (priv->display->xids, &priv->xbarrier);
|
||||
priv->xbarrier = 0;
|
||||
|
||||
XFixesDestroyPointerBarrier (dpy, priv->xbarrier);
|
||||
g_hash_table_remove (priv->display->xids, &priv->xbarrier);
|
||||
priv->xbarrier = 0;
|
||||
|
||||
g_object_unref (barrier);
|
||||
}
|
||||
g_object_unref (barrier);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -437,14 +366,25 @@ meta_barrier_fire_event (MetaBarrier *barrier,
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_display_process_barrier_event (MetaDisplay *display,
|
||||
XIBarrierEvent *xev)
|
||||
meta_display_process_barrier_event (MetaDisplay *display,
|
||||
XIEvent *event)
|
||||
{
|
||||
MetaBarrier *barrier;
|
||||
XIBarrierEvent *xev;
|
||||
|
||||
if (meta_is_wayland_compositor ())
|
||||
if (event == NULL)
|
||||
return FALSE;
|
||||
|
||||
switch (event->evtype)
|
||||
{
|
||||
case XI_BarrierHit:
|
||||
case XI_BarrierLeave:
|
||||
break;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
xev = (XIBarrierEvent *) event;
|
||||
barrier = g_hash_table_lookup (display->xids, &xev->barrier);
|
||||
if (barrier != NULL)
|
||||
{
|
||||
@@ -456,405 +396,6 @@ meta_display_process_barrier_event (MetaDisplay *display,
|
||||
}
|
||||
#endif /* HAVE_XI23 */
|
||||
|
||||
/*
|
||||
* The following code was copied and adapted from the X server (Xi/xibarriers.c)
|
||||
*
|
||||
* Copyright 2012 Red Hat, Inc.
|
||||
* Copyright © 2002 Keith Packard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
barrier_is_horizontal(MetaBarrier *barrier)
|
||||
{
|
||||
return barrier->priv->y1 == barrier->priv->y2;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
barrier_is_vertical(MetaBarrier *barrier)
|
||||
{
|
||||
return barrier->priv->x1 == barrier->priv->x2;
|
||||
}
|
||||
|
||||
/*
|
||||
* @return The set of barrier movement directions the movement vector
|
||||
* x1/y1 → x2/y2 represents.
|
||||
*/
|
||||
static int
|
||||
barrier_get_direction(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
int direction = 0;
|
||||
|
||||
/* which way are we trying to go */
|
||||
if (x2 > x1)
|
||||
direction |= META_BARRIER_DIRECTION_POSITIVE_X;
|
||||
if (x2 < x1)
|
||||
direction |= META_BARRIER_DIRECTION_NEGATIVE_X;
|
||||
if (y2 > y1)
|
||||
direction |= META_BARRIER_DIRECTION_POSITIVE_Y;
|
||||
if (y2 < y1)
|
||||
direction |= META_BARRIER_DIRECTION_NEGATIVE_Y;
|
||||
|
||||
return direction;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test if the barrier may block movement in the direction defined by
|
||||
* x1/y1 → x2/y2. This function only tests whether the directions could be
|
||||
* blocked, it does not test if the barrier actually blocks the movement.
|
||||
*
|
||||
* @return TRUE if the barrier blocks the direction of movement or FALSE
|
||||
* otherwise.
|
||||
*/
|
||||
static gboolean
|
||||
barrier_is_blocking_direction(MetaBarrier *barrier,
|
||||
MetaBarrierDirection direction)
|
||||
{
|
||||
/* Barriers define which way is ok, not which way is blocking */
|
||||
return (barrier->priv->directions & direction) != direction;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
inside_segment(int v, int v1, int v2)
|
||||
{
|
||||
if (v1 < 0 && v2 < 0) /* line */
|
||||
return TRUE;
|
||||
else if (v1 < 0) /* ray */
|
||||
return v <= v2;
|
||||
else if (v2 < 0) /* ray */
|
||||
return v >= v1;
|
||||
else /* line segment */
|
||||
return v >= v1 && v <= v2;
|
||||
}
|
||||
|
||||
#define T(v, a, b) (((float)v) - (a)) / ((b) - (a))
|
||||
#define F(t, a, b) ((t) * ((a) - (b)) + (a))
|
||||
|
||||
/*
|
||||
* Test if the movement vector x1/y1 → x2/y2 is intersecting with the
|
||||
* barrier. A movement vector with the startpoint or endpoint adjacent to
|
||||
* the barrier itself counts as intersecting.
|
||||
*
|
||||
* @param x1 X start coordinate of movement vector
|
||||
* @param y1 Y start coordinate of movement vector
|
||||
* @param x2 X end coordinate of movement vector
|
||||
* @param y2 Y end coordinate of movement vector
|
||||
* @param[out] distance The distance between the start point and the
|
||||
* intersection with the barrier (if applicable).
|
||||
* @return TRUE if the barrier intersects with the given vector
|
||||
*/
|
||||
static gboolean
|
||||
barrier_is_blocking(MetaBarrier *barrier,
|
||||
int x1, int y1, int x2, int y2, double *distance)
|
||||
{
|
||||
if (barrier_is_vertical (barrier))
|
||||
{
|
||||
float t, y;
|
||||
t = T (barrier->priv->x1, x1, x2);
|
||||
if (t < 0 || t > 1)
|
||||
return FALSE;
|
||||
|
||||
/* Edge case: moving away from barrier. */
|
||||
if (x2 > x1 && t == 0)
|
||||
return FALSE;
|
||||
|
||||
y = F (t, y1, y2);
|
||||
if (!inside_segment (y, barrier->priv->y1, barrier->priv->y2))
|
||||
return FALSE;
|
||||
|
||||
*distance = sqrt ((y - y1) * (y - y1) + (barrier->priv->x1 - x1) * (barrier->priv->x1 - x1));
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
float t, x;
|
||||
t = T (barrier->priv->y1, y1, y2);
|
||||
if (t < 0 || t > 1)
|
||||
return FALSE;
|
||||
|
||||
/* Edge case: moving away from barrier. */
|
||||
if (y2 > y1 && t == 0)
|
||||
return FALSE;
|
||||
|
||||
x = F(t, x1, x2);
|
||||
if (!inside_segment (x, barrier->priv->x1, barrier->priv->x2))
|
||||
return FALSE;
|
||||
|
||||
*distance = sqrt ((x - x1) * (x - x1) + (barrier->priv->y1 - y1) * (barrier->priv->y1 - y1));
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
#define HIT_EDGE_EXTENTS 2
|
||||
static gboolean
|
||||
barrier_inside_hit_box(MetaBarrier *barrier, int x, int y)
|
||||
{
|
||||
int x1, x2, y1, y2;
|
||||
int dir;
|
||||
|
||||
x1 = barrier->priv->x1;
|
||||
x2 = barrier->priv->x2;
|
||||
y1 = barrier->priv->y1;
|
||||
y2 = barrier->priv->y2;
|
||||
dir = ~(barrier->priv->directions);
|
||||
|
||||
if (barrier_is_vertical (barrier))
|
||||
{
|
||||
if (dir & META_BARRIER_DIRECTION_POSITIVE_X)
|
||||
x1 -= HIT_EDGE_EXTENTS;
|
||||
if (dir & META_BARRIER_DIRECTION_NEGATIVE_X)
|
||||
x2 += HIT_EDGE_EXTENTS;
|
||||
}
|
||||
if (barrier_is_horizontal (barrier))
|
||||
{
|
||||
if (dir & META_BARRIER_DIRECTION_POSITIVE_Y)
|
||||
y1 -= HIT_EDGE_EXTENTS;
|
||||
if (dir & META_BARRIER_DIRECTION_NEGATIVE_Y)
|
||||
y2 += HIT_EDGE_EXTENTS;
|
||||
}
|
||||
|
||||
return x >= x1 && x <= x2 && y >= y1 && y <= y2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the nearest barrier client that is blocking movement from x1/y1 to x2/y2.
|
||||
*
|
||||
* @param dir Only barriers blocking movement in direction dir are checked
|
||||
* @param x1 X start coordinate of movement vector
|
||||
* @param y1 Y start coordinate of movement vector
|
||||
* @param x2 X end coordinate of movement vector
|
||||
* @param y2 Y end coordinate of movement vector
|
||||
* @return The barrier nearest to the movement origin that blocks this movement.
|
||||
*/
|
||||
static MetaBarrier *
|
||||
barrier_find_nearest(MetaBarrierManager *manager,
|
||||
int dir,
|
||||
int x1,
|
||||
int y1,
|
||||
int x2,
|
||||
int y2)
|
||||
{
|
||||
GList *iter;
|
||||
MetaBarrier *nearest = NULL;
|
||||
double min_distance = INT_MAX; /* can't get higher than that in X anyway */
|
||||
|
||||
for (iter = manager->barriers; iter; iter = iter->next)
|
||||
{
|
||||
MetaBarrier *b = iter->data;
|
||||
double distance;
|
||||
|
||||
if (b->priv->seen || !b->priv->active)
|
||||
continue;
|
||||
|
||||
if (!barrier_is_blocking_direction (b, dir))
|
||||
continue;
|
||||
|
||||
if (barrier_is_blocking (b, x1, y1, x2, y2, &distance))
|
||||
{
|
||||
if (min_distance > distance)
|
||||
{
|
||||
min_distance = distance;
|
||||
nearest = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nearest;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clamp to the given barrier given the movement direction specified in dir.
|
||||
*
|
||||
* @param barrier The barrier to clamp to
|
||||
* @param dir The movement direction
|
||||
* @param[out] x The clamped x coordinate.
|
||||
* @param[out] y The clamped x coordinate.
|
||||
*/
|
||||
static void
|
||||
barrier_clamp_to_barrier(MetaBarrier *barrier,
|
||||
int dir,
|
||||
float *x,
|
||||
float *y)
|
||||
{
|
||||
if (barrier_is_vertical (barrier))
|
||||
{
|
||||
if ((dir & META_BARRIER_DIRECTION_NEGATIVE_X) & ~barrier->priv->directions)
|
||||
*x = barrier->priv->x1;
|
||||
if ((dir & META_BARRIER_DIRECTION_POSITIVE_X) & ~barrier->priv->directions)
|
||||
*x = barrier->priv->x1 - 1;
|
||||
}
|
||||
if (barrier_is_horizontal (barrier))
|
||||
{
|
||||
if ((dir & META_BARRIER_DIRECTION_NEGATIVE_Y) & ~barrier->priv->directions)
|
||||
*y = barrier->priv->y1;
|
||||
if ((dir & META_BARRIER_DIRECTION_POSITIVE_Y) & ~barrier->priv->directions)
|
||||
*y = barrier->priv->y1 - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
emit_hit_event (gpointer data)
|
||||
{
|
||||
MetaBarrierEvent *event = data;
|
||||
|
||||
g_signal_emit (event->barrier, obj_signals[HIT], 0, event);
|
||||
|
||||
meta_barrier_event_unref (event);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
emit_left_event (gpointer data)
|
||||
{
|
||||
MetaBarrierEvent *event = data;
|
||||
|
||||
g_signal_emit (event->barrier, obj_signals[LEFT], 0, event);
|
||||
|
||||
meta_barrier_event_unref (event);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_barrier_manager_constrain_cursor (MetaBarrierManager *manager,
|
||||
guint32 time,
|
||||
float current_x,
|
||||
float current_y,
|
||||
float *new_x,
|
||||
float *new_y)
|
||||
{
|
||||
float x = *new_x;
|
||||
float y = *new_y;
|
||||
int dir;
|
||||
MetaBarrier *nearest = NULL;
|
||||
GList *iter;
|
||||
float dx = x - current_x;
|
||||
float dy = y - current_y;
|
||||
|
||||
/* How this works:
|
||||
* Given the origin and the movement vector, get the nearest barrier
|
||||
* to the origin that is blocking the movement.
|
||||
* Clamp to that barrier.
|
||||
* Then, check from the clamped intersection to the original
|
||||
* destination, again finding the nearest barrier and clamping.
|
||||
*/
|
||||
dir = barrier_get_direction (current_x, current_y, x, y);
|
||||
|
||||
while (dir != 0)
|
||||
{
|
||||
MetaBarrierEvent *event;
|
||||
gboolean new_sequence;
|
||||
|
||||
nearest = barrier_find_nearest (manager, dir, current_x, current_y, x, y);
|
||||
if (!nearest)
|
||||
break;
|
||||
|
||||
new_sequence = !nearest->priv->hit;
|
||||
|
||||
nearest->priv->seen = TRUE;
|
||||
nearest->priv->hit = TRUE;
|
||||
|
||||
if (nearest->priv->barrier_event_id == nearest->priv->release_event_id)
|
||||
continue;
|
||||
|
||||
barrier_clamp_to_barrier (nearest, dir, &x, &y);
|
||||
|
||||
if (barrier_is_vertical (nearest))
|
||||
{
|
||||
dir &= ~(META_BARRIER_DIRECTION_NEGATIVE_X | META_BARRIER_DIRECTION_POSITIVE_X);
|
||||
current_x = x;
|
||||
}
|
||||
else if (barrier_is_horizontal (nearest))
|
||||
{
|
||||
dir &= ~(META_BARRIER_DIRECTION_NEGATIVE_Y | META_BARRIER_DIRECTION_POSITIVE_Y);
|
||||
current_y = y;
|
||||
}
|
||||
|
||||
event = g_slice_new0 (MetaBarrierEvent);
|
||||
|
||||
event->ref_count = 1;
|
||||
event->barrier = g_object_ref (nearest);
|
||||
event->event_id = nearest->priv->barrier_event_id;
|
||||
event->time = time;
|
||||
event->dt = new_sequence ? 0 : time - nearest->priv->last_timestamp;
|
||||
event->x = current_x;
|
||||
event->y = current_y;
|
||||
event->dx = dx;
|
||||
event->dy = dy;
|
||||
event->released = FALSE;
|
||||
event->grabbed = FALSE;
|
||||
|
||||
g_idle_add (emit_hit_event, event);
|
||||
}
|
||||
|
||||
for (iter = manager->barriers; iter; iter = iter->next)
|
||||
{
|
||||
MetaBarrierEvent *event;
|
||||
MetaBarrier *barrier = iter->data;
|
||||
|
||||
if (!barrier->priv->active)
|
||||
continue;
|
||||
|
||||
barrier->priv->seen = FALSE;
|
||||
if (!barrier->priv->hit)
|
||||
continue;
|
||||
|
||||
if (barrier_inside_hit_box (barrier, x, y))
|
||||
continue;
|
||||
|
||||
barrier->priv->hit = FALSE;
|
||||
|
||||
event = g_slice_new0 (MetaBarrierEvent);
|
||||
|
||||
event->ref_count = 1;
|
||||
event->barrier = g_object_ref (barrier);
|
||||
event->event_id = barrier->priv->barrier_event_id;
|
||||
event->time = time;
|
||||
event->dt = time - barrier->priv->last_timestamp;
|
||||
event->x = current_x;
|
||||
event->y = current_y;
|
||||
event->dx = dx;
|
||||
event->dy = dy;
|
||||
event->released = barrier->priv->barrier_event_id == barrier->priv->release_event_id;
|
||||
event->grabbed = FALSE;
|
||||
|
||||
g_idle_add (emit_left_event, event);
|
||||
|
||||
/* If we've left the hit box, this is the
|
||||
* start of a new event ID. */
|
||||
barrier->priv->barrier_event_id++;
|
||||
}
|
||||
|
||||
*new_x = x;
|
||||
*new_y = y;
|
||||
}
|
||||
|
||||
MetaBarrierManager *
|
||||
meta_barrier_manager_get (void)
|
||||
{
|
||||
if (!global_barrier_manager)
|
||||
global_barrier_manager = g_new0 (MetaBarrierManager, 1);
|
||||
|
||||
return global_barrier_manager;
|
||||
}
|
||||
|
||||
static MetaBarrierEvent *
|
||||
meta_barrier_event_ref (MetaBarrierEvent *event)
|
||||
{
|
||||
@@ -872,12 +413,7 @@ meta_barrier_event_unref (MetaBarrierEvent *event)
|
||||
g_return_if_fail (event->ref_count > 0);
|
||||
|
||||
if (g_atomic_int_dec_and_test ((volatile int *)&event->ref_count))
|
||||
{
|
||||
if (event->barrier)
|
||||
g_object_unref (event->barrier);
|
||||
|
||||
g_slice_free (MetaBarrierEvent, event);
|
||||
}
|
||||
g_slice_free (MetaBarrierEvent, event);
|
||||
}
|
||||
|
||||
G_DEFINE_BOXED_TYPE (MetaBarrierEvent,
|
||||
|
@@ -476,26 +476,6 @@ meta_core_change_workspace (Display *xdisplay,
|
||||
new_workspace));
|
||||
}
|
||||
|
||||
int
|
||||
meta_core_get_num_workspaces (Screen *xscreen)
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
screen = meta_screen_for_x_screen (xscreen);
|
||||
|
||||
return meta_screen_get_n_workspaces (screen);
|
||||
}
|
||||
|
||||
int
|
||||
meta_core_get_active_workspace (Screen *xscreen)
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
screen = meta_screen_for_x_screen (xscreen);
|
||||
|
||||
return meta_workspace_index (screen->active_workspace);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_show_window_menu (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
|
@@ -153,8 +153,6 @@ void meta_core_change_workspace (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
int new_workspace);
|
||||
|
||||
int meta_core_get_num_workspaces (Screen *xscreen);
|
||||
int meta_core_get_active_workspace (Screen *xscreen);
|
||||
int meta_core_get_frame_workspace (Display *xdisplay,
|
||||
Window frame_xwindow);
|
||||
const char* meta_core_get_workspace_name_with_index (Display *xdisplay,
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#include "keybindings-private.h"
|
||||
#include <meta/prefs.h>
|
||||
#include <meta/barrier.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#ifdef HAVE_STARTUP_NOTIFICATION
|
||||
#include <libsn/sn.h>
|
||||
@@ -189,7 +190,7 @@ struct _MetaDisplay
|
||||
MetaWindow* autoraise_window;
|
||||
|
||||
/* Alt+click button grabs */
|
||||
unsigned int window_grab_modifiers;
|
||||
ClutterModifierType window_grab_modifiers;
|
||||
|
||||
/* current window operation */
|
||||
MetaGrabOp grab_op;
|
||||
@@ -473,21 +474,23 @@ void meta_display_queue_autoraise_callback (MetaDisplay *display,
|
||||
void meta_display_remove_autoraise_callback (MetaDisplay *display);
|
||||
|
||||
void meta_display_overlay_key_activate (MetaDisplay *display);
|
||||
void meta_display_accelerator_activate (MetaDisplay *display,
|
||||
guint action,
|
||||
guint deviceid,
|
||||
guint timestamp);
|
||||
void meta_display_accelerator_activate (MetaDisplay *display,
|
||||
guint action,
|
||||
ClutterKeyEvent *event);
|
||||
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
|
||||
|
||||
/* In above-tab-keycode.c */
|
||||
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
|
||||
|
||||
gboolean meta_display_handle_event (MetaDisplay *display,
|
||||
XEvent *event);
|
||||
gboolean meta_display_handle_xevent (MetaDisplay *display,
|
||||
XEvent *event);
|
||||
|
||||
gboolean meta_display_handle_event (MetaDisplay *display,
|
||||
const ClutterEvent *event);
|
||||
|
||||
#ifdef HAVE_XI23
|
||||
gboolean meta_display_process_barrier_event (MetaDisplay *display,
|
||||
XIBarrierEvent *event);
|
||||
gboolean meta_display_process_barrier_event (MetaDisplay *display,
|
||||
XIEvent *event);
|
||||
#endif /* HAVE_XI23 */
|
||||
|
||||
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
|
||||
|
2260
src/core/display.c
2260
src/core/display.c
File diff suppressed because it is too large
Load Diff
@@ -66,9 +66,9 @@ gboolean meta_window_grab_all_keys (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
void meta_window_ungrab_all_keys (MetaWindow *window,
|
||||
guint32 timestamp);
|
||||
gboolean meta_display_process_key_event (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
XIDeviceEvent *event);
|
||||
gboolean meta_display_process_key_event (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
ClutterKeyEvent *event);
|
||||
void meta_display_process_mapping_event (MetaDisplay *display,
|
||||
XEvent *event);
|
||||
|
||||
@@ -81,7 +81,3 @@ gboolean meta_prefs_remove_keybinding (const char *name);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -401,9 +401,6 @@ meta_init (void)
|
||||
g_strerror (errno));
|
||||
#endif
|
||||
|
||||
if (getenv ("MUTTER_SLEEP_INIT"))
|
||||
sleep (60);
|
||||
|
||||
g_unix_signal_add (SIGTERM, on_sigterm, NULL);
|
||||
|
||||
if (g_getenv ("MUTTER_VERBOSE"))
|
||||
|
@@ -42,6 +42,7 @@
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
|
||||
@@ -128,76 +129,130 @@ meta_cursor_reference_unref (MetaCursorReference *self)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
get_cursor_filename (MetaCursor cursor)
|
||||
static void
|
||||
translate_meta_cursor (MetaCursor cursor,
|
||||
guint *glyph_out,
|
||||
const char **name_out)
|
||||
{
|
||||
guint glyph = XC_num_glyphs;
|
||||
const char *name = NULL;
|
||||
|
||||
switch (cursor)
|
||||
{
|
||||
case META_CURSOR_DEFAULT:
|
||||
return "left_ptr";
|
||||
glyph = XC_left_ptr;
|
||||
break;
|
||||
case META_CURSOR_NORTH_RESIZE:
|
||||
return "top_side";
|
||||
glyph = XC_top_side;
|
||||
break;
|
||||
case META_CURSOR_SOUTH_RESIZE:
|
||||
return "bottom_side";
|
||||
glyph = XC_bottom_side;
|
||||
break;
|
||||
case META_CURSOR_WEST_RESIZE:
|
||||
return "left_side";
|
||||
glyph = XC_left_side;
|
||||
break;
|
||||
case META_CURSOR_EAST_RESIZE:
|
||||
return "right_side";
|
||||
glyph = XC_right_side;
|
||||
break;
|
||||
case META_CURSOR_SE_RESIZE:
|
||||
return "bottom_right_corner";
|
||||
glyph = XC_bottom_right_corner;
|
||||
break;
|
||||
case META_CURSOR_SW_RESIZE:
|
||||
return "bottom_left_corner";
|
||||
glyph = XC_bottom_left_corner;
|
||||
break;
|
||||
case META_CURSOR_NE_RESIZE:
|
||||
return "top_right_corner";
|
||||
glyph = XC_top_right_corner;
|
||||
break;
|
||||
case META_CURSOR_NW_RESIZE:
|
||||
return "top_left_corner";
|
||||
glyph = XC_top_left_corner;
|
||||
break;
|
||||
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
|
||||
return "fleur";
|
||||
glyph = XC_fleur;
|
||||
break;
|
||||
case META_CURSOR_BUSY:
|
||||
return "watch";
|
||||
glyph = XC_watch;
|
||||
break;
|
||||
case META_CURSOR_DND_IN_DRAG:
|
||||
return "dnd-in-drag";
|
||||
name = "dnd-none";
|
||||
break;
|
||||
case META_CURSOR_DND_MOVE:
|
||||
return "dnd-copy";
|
||||
name = "dnd-move";
|
||||
break;
|
||||
case META_CURSOR_DND_COPY:
|
||||
name = "dnd-copy";
|
||||
break;
|
||||
case META_CURSOR_DND_UNSUPPORTED_TARGET:
|
||||
return "dnd-none";
|
||||
name = "dnd-none";
|
||||
break;
|
||||
case META_CURSOR_POINTING_HAND:
|
||||
return "hand";
|
||||
glyph = XC_hand2;
|
||||
break;
|
||||
case META_CURSOR_CROSSHAIR:
|
||||
return "crosshair";
|
||||
glyph = XC_crosshair;
|
||||
break;
|
||||
case META_CURSOR_IBEAM:
|
||||
return "xterm";
|
||||
glyph = XC_xterm;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
return NULL;
|
||||
glyph = 0; /* silence compiler */
|
||||
break;
|
||||
}
|
||||
|
||||
*glyph_out = glyph;
|
||||
*name_out = name;
|
||||
}
|
||||
|
||||
static Cursor
|
||||
load_cursor_on_server (MetaDisplay *display,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
Cursor xcursor;
|
||||
guint glyph;
|
||||
const char *name;
|
||||
|
||||
translate_meta_cursor (cursor, &glyph, &name);
|
||||
|
||||
if (name != NULL)
|
||||
xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
|
||||
else
|
||||
xcursor = XCreateFontCursor (display->xdisplay, glyph);
|
||||
|
||||
return xcursor;
|
||||
}
|
||||
|
||||
Cursor
|
||||
meta_display_create_x_cursor (MetaDisplay *display,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
return load_cursor_on_server (display, cursor);
|
||||
}
|
||||
|
||||
static XcursorImage *
|
||||
load_cursor_on_client (MetaDisplay *display,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
XcursorImage *image;
|
||||
guint glyph;
|
||||
const char *name;
|
||||
const char *theme = XcursorGetTheme (display->xdisplay);
|
||||
int size = XcursorGetDefaultSize (display->xdisplay);
|
||||
|
||||
translate_meta_cursor (cursor, &glyph, &name);
|
||||
|
||||
if (name != NULL)
|
||||
image = XcursorLibraryLoadImage (name, theme, size);
|
||||
else
|
||||
image = XcursorShapeLoadImage (glyph, theme, size);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
static MetaCursorReference *
|
||||
meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
const char *theme;
|
||||
const char *filename;
|
||||
int size;
|
||||
XcursorImage *image;
|
||||
int width, height, rowstride;
|
||||
CoglPixelFormat cogl_format;
|
||||
@@ -206,11 +261,7 @@ meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
|
||||
CoglContext *cogl_context;
|
||||
MetaCursorReference *self;
|
||||
|
||||
filename = get_cursor_filename (cursor);
|
||||
theme = XcursorGetTheme (tracker->screen->display->xdisplay);
|
||||
size = XcursorGetDefaultSize (tracker->screen->display->xdisplay);
|
||||
|
||||
image = XcursorLibraryLoadImage (filename, theme, size);
|
||||
image = load_cursor_on_client (tracker->screen->display, cursor);
|
||||
if (!image)
|
||||
return NULL;
|
||||
|
||||
@@ -301,6 +352,8 @@ meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
|
||||
|
||||
self = g_slice_new0 (MetaCursorReference);
|
||||
self->ref_count = 1;
|
||||
self->hot_x = hot_x;
|
||||
self->hot_y = hot_y;
|
||||
|
||||
backend = clutter_get_default_backend ();
|
||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
||||
|
@@ -99,8 +99,9 @@ static gboolean meta_monitor_config_assign_crtcs (MetaConfiguration *config,
|
||||
GPtrArray *crtcs,
|
||||
GPtrArray *outputs);
|
||||
|
||||
static void power_client_changed_cb (UpClient *client,
|
||||
gpointer user_data);
|
||||
static void power_client_changed_cb (UpClient *client,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data);
|
||||
|
||||
static void
|
||||
free_output_key (MetaOutputKey *key)
|
||||
@@ -232,7 +233,7 @@ meta_monitor_config_init (MetaMonitorConfig *self)
|
||||
self->up_client = up_client_new ();
|
||||
self->lid_is_closed = up_client_get_lid_is_closed (self->up_client);
|
||||
|
||||
g_signal_connect_object (self->up_client, "changed",
|
||||
g_signal_connect_object (self->up_client, "notify::lid-is-closed",
|
||||
G_CALLBACK (power_client_changed_cb), self, 0);
|
||||
}
|
||||
|
||||
@@ -1335,8 +1336,9 @@ turn_off_laptop_display (MetaMonitorConfig *self,
|
||||
}
|
||||
|
||||
static void
|
||||
power_client_changed_cb (UpClient *client,
|
||||
gpointer user_data)
|
||||
power_client_changed_cb (UpClient *client,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaMonitorManager *manager = meta_monitor_manager_get ();
|
||||
MetaMonitorConfig *self = user_data;
|
||||
|
@@ -729,6 +729,9 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
g_variant_new_take_string (make_display_name (manager, output)));
|
||||
g_variant_builder_add (&properties, "{sv}", "backlight",
|
||||
g_variant_new_int32 (output->backlight));
|
||||
g_variant_builder_add (&properties, "{sv}", "min-backlight-step",
|
||||
g_variant_new_int32 ((output->backlight_max - output->backlight_min) ?
|
||||
100 / (output->backlight_max - output->backlight_min) : -1));
|
||||
g_variant_builder_add (&properties, "{sv}", "primary",
|
||||
g_variant_new_boolean (output->is_primary));
|
||||
g_variant_builder_add (&properties, "{sv}", "presentation",
|
||||
|
@@ -1724,14 +1724,12 @@ get_default_focus_window (MetaStack *stack,
|
||||
* or top window in same group as not_this_one.
|
||||
*/
|
||||
|
||||
MetaWindow *topmost_dock;
|
||||
MetaWindow *transient_parent;
|
||||
MetaWindow *topmost_in_group;
|
||||
MetaWindow *topmost_overall;
|
||||
MetaGroup *not_this_one_group;
|
||||
GList *link;
|
||||
|
||||
topmost_dock = NULL;
|
||||
transient_parent = NULL;
|
||||
topmost_in_group = NULL;
|
||||
topmost_overall = NULL;
|
||||
@@ -1757,10 +1755,6 @@ get_default_focus_window (MetaStack *stack,
|
||||
(workspace == NULL ||
|
||||
meta_window_located_on_workspace (window, workspace)))
|
||||
{
|
||||
if (topmost_dock == NULL &&
|
||||
window->type == META_WINDOW_DOCK)
|
||||
topmost_dock = window;
|
||||
|
||||
if (not_this_one != NULL)
|
||||
{
|
||||
if (transient_parent == NULL &&
|
||||
@@ -1778,10 +1772,6 @@ get_default_focus_window (MetaStack *stack,
|
||||
topmost_in_group = window;
|
||||
}
|
||||
|
||||
/* Note that DESKTOP windows can be topmost_overall so
|
||||
* we prefer focusing desktop or other windows over
|
||||
* focusing dock, even though docks are stacked higher.
|
||||
*/
|
||||
if (topmost_overall == NULL &&
|
||||
window->type != META_WINDOW_DOCK &&
|
||||
(!must_be_at_point ||
|
||||
@@ -1803,7 +1793,7 @@ get_default_focus_window (MetaStack *stack,
|
||||
else if (topmost_overall)
|
||||
return topmost_overall;
|
||||
else
|
||||
return topmost_dock;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MetaWindow*
|
||||
|
@@ -44,6 +44,7 @@
|
||||
#include <X11/Xutil.h>
|
||||
#include <cairo.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include "meta-wayland-types.h"
|
||||
|
||||
typedef struct _MetaWindowQueue MetaWindowQueue;
|
||||
@@ -642,8 +643,8 @@ void meta_window_update_sync_request_counter (MetaWindow *window,
|
||||
gint64 new_counter_value);
|
||||
#endif /* HAVE_XSYNC */
|
||||
|
||||
void meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
||||
XIDeviceEvent *xev);
|
||||
void meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
||||
const ClutterEvent *event);
|
||||
|
||||
GList* meta_window_get_workspaces (MetaWindow *window);
|
||||
|
||||
@@ -733,4 +734,9 @@ void meta_window_set_gtk_dbus_properties (MetaWindow *window,
|
||||
void meta_window_set_transient_for (MetaWindow *window,
|
||||
MetaWindow *parent);
|
||||
|
||||
void meta_window_handle_enter (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
guint root_x,
|
||||
guint root_y);
|
||||
|
||||
#endif
|
||||
|
@@ -63,6 +63,7 @@
|
||||
#include <X11/extensions/Xcomposite.h>
|
||||
|
||||
#include "meta-wayland-private.h"
|
||||
#include "meta/compositor-mutter.h"
|
||||
|
||||
/* Windows that unmaximize to a size bigger than that fraction of the workarea
|
||||
* will be scaled down to that size (while maintaining aspect ratio).
|
||||
@@ -2001,6 +2002,8 @@ meta_window_unmanage (MetaWindow *window,
|
||||
meta_window_ungrab_keys (window);
|
||||
meta_display_ungrab_window_buttons (window->display, window->xwindow);
|
||||
meta_display_ungrab_focus_window_button (window->display, window);
|
||||
if (window->display->autoraise_window == window)
|
||||
meta_display_remove_autoraise_callback (window->display);
|
||||
|
||||
if (window->client_type == META_WINDOW_CLIENT_TYPE_X11)
|
||||
{
|
||||
@@ -6836,8 +6839,7 @@ meta_window_property_notify (MetaWindow *window,
|
||||
void
|
||||
meta_window_change_workspace_by_index (MetaWindow *window,
|
||||
gint space_index,
|
||||
gboolean append,
|
||||
guint32 timestamp)
|
||||
gboolean append)
|
||||
{
|
||||
MetaWorkspace *workspace;
|
||||
MetaScreen *screen;
|
||||
@@ -6856,11 +6858,7 @@ meta_window_change_workspace_by_index (MetaWindow *window,
|
||||
meta_screen_get_workspace_by_index (screen, space_index);
|
||||
|
||||
if (!workspace && append)
|
||||
{
|
||||
if (timestamp == CurrentTime)
|
||||
timestamp = meta_display_get_current_time_roundtrip (window->display);
|
||||
workspace = meta_screen_append_new_workspace (screen, FALSE, timestamp);
|
||||
}
|
||||
workspace = meta_screen_append_new_workspace (screen, FALSE, CurrentTime);
|
||||
|
||||
if (workspace)
|
||||
{
|
||||
@@ -9906,96 +9904,20 @@ update_resize (MetaWindow *window,
|
||||
g_get_current_time (&window->display->grab_last_moveresize_time);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Window window;
|
||||
int count;
|
||||
guint32 last_time;
|
||||
} EventScannerData;
|
||||
|
||||
static Bool
|
||||
find_last_time_predicate (Display *display,
|
||||
XEvent *ev,
|
||||
XPointer arg)
|
||||
{
|
||||
EventScannerData *esd = (void*) arg;
|
||||
XIEvent *xev;
|
||||
|
||||
if (ev->type != GenericEvent)
|
||||
return False;
|
||||
|
||||
/* We are peeking into events not yet handled by GDK,
|
||||
* Allocate cookie events here so we can handle XI2.
|
||||
*
|
||||
* GDK will handle later these events, and eventually
|
||||
* free the cookie data itself.
|
||||
*/
|
||||
XGetEventData (display, &ev->xcookie);
|
||||
xev = (XIEvent *) ev->xcookie.data;
|
||||
|
||||
if (xev->evtype != XI_Motion)
|
||||
return False;
|
||||
|
||||
if (esd->window != ((XIDeviceEvent *) xev)->event)
|
||||
return False;
|
||||
|
||||
esd->count += 1;
|
||||
esd->last_time = xev->time;
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
check_use_this_motion_notify (MetaWindow *window,
|
||||
XIDeviceEvent *xev)
|
||||
check_use_this_motion_notify (MetaWindow *window,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
EventScannerData esd;
|
||||
XEvent useless;
|
||||
|
||||
/* This code is copied from Owen's GDK code. */
|
||||
|
||||
if (window->display->grab_motion_notify_time != 0)
|
||||
{
|
||||
/* == is really the right test, but I'm all for paranoia */
|
||||
if (window->display->grab_motion_notify_time <=
|
||||
xev->time)
|
||||
{
|
||||
meta_topic (META_DEBUG_RESIZING,
|
||||
"Arrived at event with time %u (waiting for %u), using it\n",
|
||||
(unsigned int)xev->time,
|
||||
window->display->grab_motion_notify_time);
|
||||
window->display->grab_motion_notify_time = 0;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return FALSE; /* haven't reached the saved timestamp yet */
|
||||
}
|
||||
|
||||
esd.window = xev->event;
|
||||
esd.count = 0;
|
||||
esd.last_time = 0;
|
||||
|
||||
/* "useless" isn't filled in because the predicate never returns True */
|
||||
XCheckIfEvent (window->display->xdisplay,
|
||||
&useless,
|
||||
find_last_time_predicate,
|
||||
(XPointer) &esd);
|
||||
|
||||
if (esd.count > 0)
|
||||
meta_topic (META_DEBUG_RESIZING,
|
||||
"Will skip %d motion events and use the event with time %u\n",
|
||||
esd.count, (unsigned int) esd.last_time);
|
||||
|
||||
if (esd.last_time == 0)
|
||||
return TRUE;
|
||||
else
|
||||
{
|
||||
/* Save this timestamp, and ignore all motion notify
|
||||
* until we get to the one with this stamp.
|
||||
*/
|
||||
window->display->grab_motion_notify_time = esd.last_time;
|
||||
return FALSE;
|
||||
}
|
||||
/* XXX: Previously this code would walk through the X event queue
|
||||
and filter out motion events that are followed by a later motion
|
||||
event. There currently isn't any API to do the equivalent
|
||||
procedure with the Clutter event queue so this function does
|
||||
nothing. Clutter does its own motion event squashing so it may be
|
||||
the case that this function isn't necessary. If it turns out that
|
||||
we do need additional motion event squashing we could add some
|
||||
extra API to the Clutter event queue and implement this function
|
||||
properly. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -10069,81 +9991,89 @@ meta_window_update_sync_request_counter (MetaWindow *window,
|
||||
#endif /* HAVE_XSYNC */
|
||||
|
||||
void
|
||||
meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
||||
XIDeviceEvent *xev)
|
||||
meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
switch (xev->evtype)
|
||||
{
|
||||
case XI_ButtonRelease:
|
||||
meta_display_check_threshold_reached (window->display,
|
||||
xev->root_x,
|
||||
xev->root_y);
|
||||
/* If the user was snap moving then ignore the button release
|
||||
* because they may have let go of shift before releasing the
|
||||
* mouse button and they almost certainly do not want a
|
||||
* non-snapped movement to occur from the button release.
|
||||
*/
|
||||
if (!window->display->grab_last_user_action_was_snap)
|
||||
{
|
||||
if (meta_grab_op_is_moving (window->display->grab_op))
|
||||
{
|
||||
if (window->tile_mode != META_TILE_NONE)
|
||||
meta_window_tile (window);
|
||||
else if (xev->root == window->screen->xroot)
|
||||
update_move (window,
|
||||
xev->mods.effective & ShiftMask,
|
||||
xev->root_x,
|
||||
xev->root_y);
|
||||
}
|
||||
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
||||
{
|
||||
if (xev->root == window->screen->xroot)
|
||||
update_resize (window,
|
||||
xev->mods.effective & ShiftMask,
|
||||
xev->root_x,
|
||||
xev->root_y,
|
||||
TRUE);
|
||||
gboolean is_window_root = (event->any.stage != NULL &&
|
||||
window &&
|
||||
window->screen &&
|
||||
CLUTTER_ACTOR (event->any.stage) ==
|
||||
meta_get_stage_for_screen (window->screen));
|
||||
|
||||
/* If a tiled window has been dragged free with a
|
||||
* mouse resize without snapping back to the tiled
|
||||
* state, it will end up with an inconsistent tile
|
||||
* mode on mouse release; cleaning the mode earlier
|
||||
* would break the ability to snap back to the tiled
|
||||
* state, so we wait until mouse release.
|
||||
*/
|
||||
update_tile_mode (window);
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
if (event->button.button == 1)
|
||||
{
|
||||
meta_display_check_threshold_reached (window->display,
|
||||
event->button.x,
|
||||
event->button.y);
|
||||
/* If the user was snap moving then ignore the button
|
||||
* release because they may have let go of shift before
|
||||
* releasing the mouse button and they almost certainly do
|
||||
* not want a non-snapped movement to occur from the button
|
||||
* release.
|
||||
*/
|
||||
if (!window->display->grab_last_user_action_was_snap)
|
||||
{
|
||||
if (meta_grab_op_is_moving (window->display->grab_op))
|
||||
{
|
||||
if (window->tile_mode != META_TILE_NONE)
|
||||
meta_window_tile (window);
|
||||
else if (is_window_root)
|
||||
update_move (window,
|
||||
event->button.modifier_state & CLUTTER_SHIFT_MASK,
|
||||
event->button.x,
|
||||
event->button.y);
|
||||
}
|
||||
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
||||
{
|
||||
if (is_window_root)
|
||||
update_resize (window,
|
||||
event->button.modifier_state & CLUTTER_SHIFT_MASK,
|
||||
event->button.x,
|
||||
event->button.y,
|
||||
TRUE);
|
||||
|
||||
/* If a tiled window has been dragged free with a
|
||||
* mouse resize without snapping back to the tiled
|
||||
* state, it will end up with an inconsistent tile
|
||||
* mode on mouse release; cleaning the mode earlier
|
||||
* would break the ability to snap back to the tiled
|
||||
* state, so we wait until mouse release.
|
||||
*/
|
||||
update_tile_mode (window);
|
||||
}
|
||||
|
||||
meta_display_end_grab_op (window->display, event->any.time);
|
||||
}
|
||||
}
|
||||
|
||||
meta_display_end_grab_op (window->display, xev->time);
|
||||
break;
|
||||
|
||||
case XI_Motion:
|
||||
case CLUTTER_MOTION:
|
||||
meta_display_check_threshold_reached (window->display,
|
||||
xev->root_x,
|
||||
xev->root_y);
|
||||
event->motion.x,
|
||||
event->motion.y);
|
||||
if (meta_grab_op_is_moving (window->display->grab_op))
|
||||
{
|
||||
if (xev->root == window->screen->xroot)
|
||||
if (is_window_root)
|
||||
{
|
||||
if (check_use_this_motion_notify (window,
|
||||
xev))
|
||||
if (check_use_this_motion_notify (window, event))
|
||||
update_move (window,
|
||||
xev->mods.effective & ShiftMask,
|
||||
xev->root_x,
|
||||
xev->root_y);
|
||||
event->button.modifier_state & CLUTTER_SHIFT_MASK,
|
||||
event->motion.x,
|
||||
event->motion.y);
|
||||
}
|
||||
}
|
||||
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
||||
{
|
||||
if (xev->root == window->screen->xroot)
|
||||
if (is_window_root)
|
||||
{
|
||||
if (check_use_this_motion_notify (window,
|
||||
xev))
|
||||
if (check_use_this_motion_notify (window, event))
|
||||
update_resize (window,
|
||||
xev->mods.effective & ShiftMask,
|
||||
xev->root_x,
|
||||
xev->root_y,
|
||||
event->button.modifier_state & CLUTTER_SHIFT_MASK,
|
||||
event->motion.x,
|
||||
event->motion.y,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
@@ -11739,3 +11669,185 @@ meta_window_set_transient_for (MetaWindow *window,
|
||||
if (meta_window_appears_focused (window) && window->transient_for != None)
|
||||
meta_window_propagate_focus_appearance (window, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_ignored_crossing_serials (MetaDisplay *display)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = 0;
|
||||
while (i < N_IGNORED_CROSSING_SERIALS)
|
||||
{
|
||||
display->ignored_crossing_serials[i] = 0;
|
||||
++i;
|
||||
}
|
||||
|
||||
display->ungrab_should_not_cause_focus_window = None;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaWindow *window;
|
||||
int pointer_x;
|
||||
int pointer_y;
|
||||
} MetaFocusData;
|
||||
|
||||
static void
|
||||
mouse_mode_focus (MetaWindow *window,
|
||||
guint32 timestamp)
|
||||
{
|
||||
MetaDisplay *display = window->display;
|
||||
|
||||
if (window->type != META_WINDOW_DESKTOP)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focusing %s at time %u.\n", window->desc, timestamp);
|
||||
|
||||
meta_window_focus (window, timestamp);
|
||||
|
||||
if (meta_prefs_get_auto_raise ())
|
||||
meta_display_queue_autoraise_callback (display, window);
|
||||
else
|
||||
meta_topic (META_DEBUG_FOCUS, "Auto raise is disabled\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In mouse focus mode, we defocus when the mouse *enters*
|
||||
* the DESKTOP window, instead of defocusing on LeaveNotify.
|
||||
* This is because having the mouse enter override-redirect
|
||||
* child windows unfortunately causes LeaveNotify events that
|
||||
* we can't distinguish from the mouse actually leaving the
|
||||
* toplevel window as we expect. But, since we filter out
|
||||
* EnterNotify events on override-redirect windows, this
|
||||
* alternative mechanism works great.
|
||||
*/
|
||||
if (meta_prefs_get_focus_mode() == G_DESKTOP_FOCUS_MODE_MOUSE &&
|
||||
display->focus_window != NULL)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Unsetting focus from %s due to mouse entering "
|
||||
"the DESKTOP window\n",
|
||||
display->focus_window->desc);
|
||||
meta_display_focus_the_no_focus_window (display,
|
||||
window->screen,
|
||||
timestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
window_focus_on_pointer_rest_callback (gpointer data)
|
||||
{
|
||||
MetaFocusData *focus_data = data;
|
||||
MetaWindow *window = focus_data->window;
|
||||
MetaDisplay *display = window->display;
|
||||
MetaScreen *screen = window->screen;
|
||||
Window root, child;
|
||||
double root_x, root_y, x, y;
|
||||
guint32 timestamp;
|
||||
XIButtonState buttons;
|
||||
XIModifierState mods;
|
||||
XIGroupState group;
|
||||
|
||||
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
|
||||
goto out;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XIQueryPointer (display->xdisplay,
|
||||
META_VIRTUAL_CORE_POINTER_ID,
|
||||
screen->xroot,
|
||||
&root, &child,
|
||||
&root_x, &root_y, &x, &y,
|
||||
&buttons, &mods, &group);
|
||||
meta_error_trap_pop (display);
|
||||
free (buttons.mask);
|
||||
|
||||
if (root_x != focus_data->pointer_x ||
|
||||
root_y != focus_data->pointer_y)
|
||||
{
|
||||
focus_data->pointer_x = root_x;
|
||||
focus_data->pointer_y = root_y;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Explicitly check for the overlay window, as get_focus_window_at_point()
|
||||
* may return windows that extend underneath the chrome (like
|
||||
* override-redirect or DESKTOP windows)
|
||||
*/
|
||||
if (child == meta_get_overlay_window (screen))
|
||||
goto out;
|
||||
|
||||
window =
|
||||
meta_stack_get_default_focus_window_at_point (screen->stack,
|
||||
screen->active_workspace,
|
||||
None, root_x, root_y);
|
||||
|
||||
if (window == NULL)
|
||||
goto out;
|
||||
|
||||
timestamp = meta_display_get_current_time_roundtrip (display);
|
||||
mouse_mode_focus (window, timestamp);
|
||||
|
||||
out:
|
||||
display->focus_timeout_id = 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* The interval, in milliseconds, we use in focus-follows-mouse
|
||||
* mode to check whether the pointer has stopped moving after a
|
||||
* crossing event.
|
||||
*/
|
||||
#define FOCUS_TIMEOUT_DELAY 25
|
||||
|
||||
static void
|
||||
queue_focus_callback (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
int pointer_x,
|
||||
int pointer_y)
|
||||
{
|
||||
MetaFocusData *focus_data;
|
||||
|
||||
focus_data = g_new (MetaFocusData, 1);
|
||||
focus_data->window = window;
|
||||
focus_data->pointer_x = pointer_x;
|
||||
focus_data->pointer_y = pointer_y;
|
||||
|
||||
if (display->focus_timeout_id != 0)
|
||||
g_source_remove (display->focus_timeout_id);
|
||||
|
||||
display->focus_timeout_id =
|
||||
g_timeout_add_full (G_PRIORITY_DEFAULT,
|
||||
FOCUS_TIMEOUT_DELAY,
|
||||
window_focus_on_pointer_rest_callback,
|
||||
focus_data,
|
||||
g_free);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_handle_enter (MetaWindow *window,
|
||||
guint32 timestamp,
|
||||
guint root_x,
|
||||
guint root_y)
|
||||
{
|
||||
MetaDisplay *display = window->display;
|
||||
|
||||
switch (meta_prefs_get_focus_mode ())
|
||||
{
|
||||
case G_DESKTOP_FOCUS_MODE_SLOPPY:
|
||||
case G_DESKTOP_FOCUS_MODE_MOUSE:
|
||||
display->mouse_mode = TRUE;
|
||||
if (window->type != META_WINDOW_DOCK)
|
||||
{
|
||||
if (meta_prefs_get_focus_change_on_pointer_rest())
|
||||
queue_focus_callback (display, window, root_x, root_y);
|
||||
else
|
||||
mouse_mode_focus (window, timestamp);
|
||||
|
||||
/* stop ignoring stuff */
|
||||
reset_ignored_crossing_serials (display);
|
||||
}
|
||||
break;
|
||||
case G_DESKTOP_FOCUS_MODE_CLICK:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@@ -94,7 +94,6 @@ typedef enum {
|
||||
struct _MetaBarrierEvent {
|
||||
/* < private > */
|
||||
volatile guint ref_count;
|
||||
MetaBarrier *barrier;
|
||||
|
||||
/* < public > */
|
||||
int event_id;
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/extensions/XInput.h>
|
||||
#include <X11/extensions/XInput2.h>
|
||||
#include <clutter/clutter.h>
|
||||
#include <glib.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
|
@@ -35,13 +35,6 @@ gboolean meta_keybindings_set_custom_handler (const gchar *name,
|
||||
gpointer user_data,
|
||||
GDestroyNotify free_data);
|
||||
|
||||
void meta_keybindings_switch_window (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *event_window,
|
||||
XIDeviceEvent *event,
|
||||
MetaKeyBinding *binding);
|
||||
|
||||
|
||||
void meta_screen_ungrab_all_keys (MetaScreen *screen, guint32 timestamp);
|
||||
gboolean meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp);
|
||||
#endif
|
||||
|
@@ -391,17 +391,17 @@ struct _MetaKeyCombo
|
||||
* @display: a #MetaDisplay
|
||||
* @screen: a #MetaScreen
|
||||
* @window: a #MetaWindow
|
||||
* @event: (type gpointer): a #XIDeviceEvent
|
||||
* @event: a #ClutterKeyEvent
|
||||
* @binding: a #MetaKeyBinding
|
||||
* @user_data: data passed to the function
|
||||
*
|
||||
*/
|
||||
typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
XIDeviceEvent *event,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer user_data);
|
||||
typedef void (* MetaKeyHandlerFunc) (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
ClutterKeyEvent *event,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer user_data);
|
||||
|
||||
typedef struct _MetaKeyHandler MetaKeyHandler;
|
||||
|
||||
@@ -419,13 +419,13 @@ typedef struct
|
||||
*/
|
||||
GSList *bindings;
|
||||
|
||||
/** for keybindings that can have shift or not like Alt+Tab */
|
||||
/* for keybindings that can have shift or not like Alt+Tab */
|
||||
gboolean add_shift:1;
|
||||
|
||||
/** for keybindings that apply only to a window */
|
||||
/* for keybindings that apply only to a window */
|
||||
gboolean per_window:1;
|
||||
|
||||
/** for keybindings not added with meta_display_add_keybinding() */
|
||||
/* for keybindings not added with meta_display_add_keybinding() */
|
||||
gboolean builtin:1;
|
||||
} MetaKeyPref;
|
||||
|
||||
|
@@ -150,8 +150,7 @@ void meta_window_unset_demands_attention (MetaWindow *window);
|
||||
const char* meta_window_get_startup_id (MetaWindow *window);
|
||||
void meta_window_change_workspace_by_index (MetaWindow *window,
|
||||
gint space_index,
|
||||
gboolean append,
|
||||
guint32 timestamp);
|
||||
gboolean append);
|
||||
void meta_window_change_workspace (MetaWindow *window,
|
||||
MetaWorkspace *workspace);
|
||||
GObject *meta_window_get_compositor_private (MetaWindow *window);
|
||||
|
@@ -412,81 +412,6 @@ set_modifiers (MetaWaylandKeyboard *keyboard,
|
||||
new_state.group);
|
||||
}
|
||||
|
||||
#define N_BUTTONS 5
|
||||
|
||||
static gboolean
|
||||
process_keybinding (MetaWaylandKeyboard *keyboard,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandSurface *surface;
|
||||
XGenericEventCookie generic_event;
|
||||
XIDeviceEvent device_event;
|
||||
unsigned char button_mask[(N_BUTTONS + 7) / 8] = { 0 };
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
ClutterModifierType button_state;
|
||||
int i;
|
||||
|
||||
if (!display) /* not initialized yet */
|
||||
return FALSE;
|
||||
|
||||
generic_event.type = GenericEvent;
|
||||
generic_event.serial = 0;
|
||||
generic_event.send_event = False;
|
||||
generic_event.display = display->xdisplay;
|
||||
generic_event.extension = display->xinput_opcode;
|
||||
if (clutter_event_type (event) == CLUTTER_KEY_PRESS)
|
||||
generic_event.evtype = XI_KeyPress;
|
||||
else
|
||||
generic_event.evtype = XI_KeyRelease;
|
||||
/* Mutter assumes the data for the event is already retrieved by GDK
|
||||
* so we don't need the cookie */
|
||||
generic_event.cookie = 0;
|
||||
generic_event.data = &device_event;
|
||||
|
||||
memcpy (&device_event, &generic_event, sizeof (XGenericEvent));
|
||||
|
||||
device_event.time = clutter_event_get_time (event);
|
||||
device_event.deviceid = clutter_event_get_device_id (event);
|
||||
device_event.sourceid = 0; /* not used, not sure what this should be */
|
||||
device_event.detail = clutter_event_get_key_code (event);
|
||||
device_event.root = DefaultRootWindow (display->xdisplay);
|
||||
device_event.flags = 0;
|
||||
|
||||
surface = keyboard->focus;
|
||||
if (surface)
|
||||
device_event.event = surface->window ? surface->window->xwindow : device_event.root;
|
||||
else
|
||||
device_event.event = device_event.root;
|
||||
|
||||
/* Mutter doesn't really know about the sub-windows. This assumes it
|
||||
doesn't care either */
|
||||
device_event.child = device_event.event;
|
||||
device_event.root_x = 0;
|
||||
device_event.root_y = 0;
|
||||
|
||||
clutter_event_get_state_full (event,
|
||||
&button_state,
|
||||
(ClutterModifierType*)&device_event.mods.base,
|
||||
(ClutterModifierType*)&device_event.mods.latched,
|
||||
(ClutterModifierType*)&device_event.mods.locked,
|
||||
(ClutterModifierType*)&device_event.mods.effective);
|
||||
device_event.mods.effective &= ~button_state;
|
||||
memset (&device_event.group, 0, sizeof (device_event.group));
|
||||
device_event.group.effective = (device_event.mods.effective >> 13) & 0x3;
|
||||
|
||||
for (i = 0; i < N_BUTTONS; i++)
|
||||
if ((button_state & (CLUTTER_BUTTON1_MASK << i)))
|
||||
XISetMask (button_mask, i + 1);
|
||||
device_event.buttons.mask_len = N_BUTTONS + 1;
|
||||
device_event.buttons.mask = button_mask;
|
||||
|
||||
device_event.valuators.mask_len = 0;
|
||||
device_event.valuators.mask = NULL;
|
||||
device_event.valuators.values = NULL;
|
||||
|
||||
return meta_display_process_key_event (display, surface ? surface->window : NULL, &device_event);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_pressed_keys (MetaWaylandKeyboard *keyboard,
|
||||
uint32_t evdev_code,
|
||||
@@ -559,10 +484,6 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
|
||||
autorepeat ? " (autorepeat)" : "",
|
||||
xkb_keycode);
|
||||
|
||||
/* Give a chance to process keybindings */
|
||||
if (process_keybinding (keyboard, (ClutterEvent*) event))
|
||||
return TRUE;
|
||||
|
||||
if (autorepeat)
|
||||
return FALSE;
|
||||
|
||||
|
@@ -49,7 +49,6 @@
|
||||
|
||||
#include "meta-wayland-pointer.h"
|
||||
#include "meta-wayland-private.h"
|
||||
#include "barrier-private.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
@@ -166,10 +165,10 @@ static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = {
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
check_all_screen_monitors (MetaMonitorInfo *monitors,
|
||||
unsigned n_monitors,
|
||||
float x,
|
||||
float y)
|
||||
check_all_screen_monitors(MetaMonitorInfo *monitors,
|
||||
unsigned n_monitors,
|
||||
float x,
|
||||
float y)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@@ -194,13 +193,14 @@ static void
|
||||
constrain_all_screen_monitors (ClutterInputDevice *device,
|
||||
MetaMonitorInfo *monitors,
|
||||
unsigned n_monitors,
|
||||
float current_x,
|
||||
float current_y,
|
||||
float *x,
|
||||
float *y)
|
||||
{
|
||||
ClutterPoint current;
|
||||
unsigned int i;
|
||||
|
||||
clutter_input_device_get_coords (device, NULL, ¤t);
|
||||
|
||||
/* if we're trying to escape, clamp to the CRTC we're coming from */
|
||||
for (i = 0; i < n_monitors; i++)
|
||||
{
|
||||
@@ -213,8 +213,8 @@ constrain_all_screen_monitors (ClutterInputDevice *device,
|
||||
top = monitor->rect.y;
|
||||
bottom = left + monitor->rect.height;
|
||||
|
||||
nx = current_x;
|
||||
ny = current_y;
|
||||
nx = current.x;
|
||||
ny = current.y;
|
||||
|
||||
if ((nx >= left) && (nx < right) && (ny >= top) && (ny < bottom))
|
||||
{
|
||||
@@ -239,32 +239,21 @@ pointer_constrain_callback (ClutterInputDevice *device,
|
||||
float *new_y,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaBarrierManager *barrier_manager;
|
||||
MetaMonitorManager *monitor_manager;
|
||||
MetaMonitorInfo *monitors;
|
||||
unsigned int n_monitors;
|
||||
gboolean ret;
|
||||
ClutterPoint current;
|
||||
|
||||
clutter_input_device_get_coords (device, NULL, ¤t);
|
||||
|
||||
barrier_manager = meta_barrier_manager_get ();
|
||||
monitor_manager = meta_monitor_manager_get ();
|
||||
monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
|
||||
|
||||
meta_barrier_manager_constrain_cursor (barrier_manager, time,
|
||||
current.x, current.y,
|
||||
new_x, new_y);
|
||||
|
||||
/* if we're moving inside a monitor, we're fine */
|
||||
ret = check_all_screen_monitors(monitors, n_monitors, *new_x, *new_y);
|
||||
if (ret)
|
||||
if (ret == TRUE)
|
||||
return;
|
||||
|
||||
/* if we're trying to escape, clamp to the CRTC we're coming from */
|
||||
constrain_all_screen_monitors(device, monitors, n_monitors,
|
||||
current.x, current.y,
|
||||
new_x, new_y);
|
||||
constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -363,6 +352,11 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer,
|
||||
}
|
||||
|
||||
meta_wayland_pointer_get_relative_coordinates (pointer, surface, &sx, &sy);
|
||||
meta_window_handle_enter (surface->window,
|
||||
/* XXX -- can we reliably get a timestamp for setting focus? */
|
||||
clutter_get_current_event_time (),
|
||||
wl_fixed_to_int (pointer->x),
|
||||
wl_fixed_to_int (pointer->y));
|
||||
wl_pointer_send_enter (resource, serial, surface->resource, sx, sy);
|
||||
wl_resource_add_destroy_listener (resource, &pointer->focus_listener);
|
||||
pointer->focus_serial = serial;
|
||||
@@ -396,32 +390,6 @@ meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer)
|
||||
interface->focus (pointer->grab, pointer->current, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
current_surface_destroy (struct wl_listener *listener, void *data)
|
||||
{
|
||||
MetaWaylandPointer *pointer =
|
||||
wl_container_of (listener, pointer, current_listener);
|
||||
|
||||
pointer->current = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
meta_wayland_pointer_set_current (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface)
|
||||
{
|
||||
if (pointer->current)
|
||||
wl_list_remove (&pointer->current_listener.link);
|
||||
|
||||
pointer->current = surface;
|
||||
|
||||
if (!surface)
|
||||
return;
|
||||
|
||||
wl_resource_add_destroy_listener (surface->resource,
|
||||
&pointer->current_listener);
|
||||
pointer->current_listener.notify = current_surface_destroy;
|
||||
}
|
||||
|
||||
static void
|
||||
modal_focus (MetaWaylandPointerGrab *grab,
|
||||
MetaWaylandSurface *surface,
|
||||
|
@@ -62,8 +62,6 @@ struct _MetaWaylandPointer
|
||||
|
||||
wl_fixed_t x, y; /* TODO: remove, use ClutterInputDevice instead */
|
||||
MetaWaylandSurface *current;
|
||||
struct wl_listener current_listener;
|
||||
wl_fixed_t current_x, current_y;
|
||||
|
||||
guint32 button_count;
|
||||
};
|
||||
@@ -97,10 +95,6 @@ gboolean
|
||||
meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *popup);
|
||||
|
||||
void
|
||||
meta_wayland_pointer_set_current (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface);
|
||||
|
||||
void
|
||||
meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
|
||||
MetaWaylandSurface *surface,
|
||||
|
@@ -83,14 +83,6 @@ struct _MetaWaylandCompositor
|
||||
int drm_fd;
|
||||
|
||||
MetaWaylandSeat *seat;
|
||||
|
||||
/* This surface is only used to keep drag of the implicit grab when
|
||||
synthesizing XEvents for Mutter */
|
||||
MetaWaylandSurface *implicit_grab_surface;
|
||||
/* Button that was pressed to initiate an implicit grab. The
|
||||
implicit grab will only be released when this button is
|
||||
released */
|
||||
guint32 implicit_grab_button;
|
||||
};
|
||||
|
||||
void meta_wayland_init (void);
|
||||
@@ -104,6 +96,8 @@ void meta_wayland_compositor_repick (MetaWaylandComp
|
||||
|
||||
void meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
gboolean meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event);
|
||||
|
||||
MetaLauncher *meta_wayland_compositor_get_launcher (MetaWaylandCompositor *compositor);
|
||||
gboolean meta_wayland_compositor_is_native (MetaWaylandCompositor *compositor);
|
||||
|
@@ -280,31 +280,9 @@ handle_button_event (MetaWaylandSeat *seat,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandPointer *pointer = &seat->pointer;
|
||||
gboolean state = event->type == CLUTTER_BUTTON_PRESS;
|
||||
uint32_t button;
|
||||
MetaWaylandSurface *surface;
|
||||
|
||||
notify_motion (seat, event);
|
||||
|
||||
if (state && pointer->button_count == 1)
|
||||
{
|
||||
button = clutter_event_get_button (event);
|
||||
pointer->grab_button = button;
|
||||
pointer->grab_time = clutter_event_get_time (event);
|
||||
pointer->grab_x = pointer->x;
|
||||
pointer->grab_y = pointer->y;
|
||||
|
||||
/* FIXME: synth a XI2 event and handle in display.c */
|
||||
surface = pointer->current;
|
||||
if (button == CLUTTER_BUTTON_PRIMARY &&
|
||||
surface &&
|
||||
surface->window &&
|
||||
surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
||||
{
|
||||
meta_window_raise (surface->window);
|
||||
}
|
||||
}
|
||||
|
||||
pointer->grab->interface->button (pointer->grab, event);
|
||||
|
||||
if (pointer->button_count == 1)
|
||||
@@ -381,6 +359,19 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
|
||||
{
|
||||
seat->pointer.button_count = count_buttons (event);
|
||||
|
||||
if (seat->cursor_tracker)
|
||||
{
|
||||
meta_cursor_tracker_update_position (seat->cursor_tracker,
|
||||
wl_fixed_to_int (seat->pointer.x),
|
||||
wl_fixed_to_int (seat->pointer.y));
|
||||
|
||||
if (seat->pointer.current == NULL)
|
||||
meta_cursor_tracker_revert_root (seat->cursor_tracker);
|
||||
|
||||
meta_cursor_tracker_queue_redraw (seat->cursor_tracker,
|
||||
CLUTTER_ACTOR (event->any.stage));
|
||||
}
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_MOTION:
|
||||
@@ -408,20 +399,6 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
update_pointer_position_for_actor (MetaWaylandPointer *pointer,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
float ax, ay;
|
||||
|
||||
clutter_actor_transform_stage_point (actor,
|
||||
wl_fixed_to_double (pointer->x),
|
||||
wl_fixed_to_double (pointer->y),
|
||||
&ax, &ay);
|
||||
pointer->current_x = wl_fixed_from_double (ax);
|
||||
pointer->current_y = wl_fixed_from_double (ay);
|
||||
}
|
||||
|
||||
/* The actor argument can be NULL in which case a Clutter pick will be
|
||||
performed to determine the right actor. An actor should only be
|
||||
passed if the repick is being performed due to an event in which
|
||||
@@ -458,16 +435,12 @@ meta_wayland_seat_repick (MetaWaylandSeat *seat,
|
||||
MetaWindow *window =
|
||||
meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor));
|
||||
|
||||
update_pointer_position_for_actor (pointer, actor);
|
||||
|
||||
surface = window->surface;
|
||||
}
|
||||
else if (META_IS_SHAPED_TEXTURE (actor))
|
||||
{
|
||||
MetaShapedTexture *shaped_texture = META_SHAPED_TEXTURE (actor);
|
||||
|
||||
update_pointer_position_for_actor (pointer, actor);
|
||||
|
||||
surface = meta_shaped_texture_get_wayland_surface (shaped_texture);
|
||||
}
|
||||
|
||||
|
@@ -409,9 +409,6 @@ meta_wayland_surface_free (MetaWaylandSurface *surface)
|
||||
g_assert (surface != compositor->seat->pointer.focus);
|
||||
}
|
||||
|
||||
if (compositor->implicit_grab_surface == surface)
|
||||
compositor->implicit_grab_surface = compositor->seat->pointer.current;
|
||||
|
||||
if (surface->resource)
|
||||
wl_resource_set_user_data (surface->resource, NULL);
|
||||
g_slice_free (MetaWaylandSurface, surface);
|
||||
|
@@ -533,119 +533,6 @@ stage_destroy_cb (void)
|
||||
meta_quit (META_EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
#define N_BUTTONS 5
|
||||
|
||||
static void
|
||||
synthesize_motion_event (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
/* We want to synthesize X events for mouse motion events so that we
|
||||
don't have to rely on the X server's window position being
|
||||
synched with the surface position. See the comment in
|
||||
event_callback() in display.c */
|
||||
MetaWaylandSeat *seat = compositor->seat;
|
||||
MetaWaylandPointer *pointer = &seat->pointer;
|
||||
MetaWaylandSurface *surface;
|
||||
XGenericEventCookie generic_event;
|
||||
XIDeviceEvent device_event;
|
||||
unsigned char button_mask[(N_BUTTONS + 7) / 8] = { 0 };
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
ClutterModifierType button_state;
|
||||
int i;
|
||||
|
||||
generic_event.type = GenericEvent;
|
||||
generic_event.serial = 0;
|
||||
generic_event.send_event = False;
|
||||
generic_event.display = display->xdisplay;
|
||||
generic_event.extension = display->xinput_opcode;
|
||||
generic_event.evtype = XI_Motion;
|
||||
/* Mutter assumes the data for the event is already retrieved by GDK
|
||||
* so we don't need the cookie */
|
||||
generic_event.cookie = 0;
|
||||
generic_event.data = &device_event;
|
||||
|
||||
memcpy (&device_event, &generic_event, sizeof (XGenericEvent));
|
||||
|
||||
device_event.time = clutter_event_get_time (event);
|
||||
device_event.deviceid = clutter_event_get_device_id (event);
|
||||
device_event.sourceid = 0; /* not used, not sure what this should be */
|
||||
device_event.detail = 0;
|
||||
device_event.root = DefaultRootWindow (display->xdisplay);
|
||||
device_event.flags = 0 /* not used for motion events */;
|
||||
|
||||
if (compositor->implicit_grab_surface)
|
||||
surface = compositor->implicit_grab_surface;
|
||||
else
|
||||
surface = pointer->current;
|
||||
|
||||
if (surface == pointer->current)
|
||||
{
|
||||
device_event.event_x = wl_fixed_to_int (pointer->current_x);
|
||||
device_event.event_y = wl_fixed_to_int (pointer->current_y);
|
||||
}
|
||||
else if (surface && surface->window)
|
||||
{
|
||||
ClutterActor *window_actor =
|
||||
CLUTTER_ACTOR (meta_window_get_compositor_private (surface->window));
|
||||
|
||||
if (window_actor)
|
||||
{
|
||||
float ax, ay;
|
||||
|
||||
clutter_actor_transform_stage_point (window_actor,
|
||||
wl_fixed_to_double (pointer->x),
|
||||
wl_fixed_to_double (pointer->y),
|
||||
&ax, &ay);
|
||||
|
||||
device_event.event_x = ax;
|
||||
device_event.event_y = ay;
|
||||
}
|
||||
else
|
||||
{
|
||||
device_event.event_x = wl_fixed_to_double (pointer->x);
|
||||
device_event.event_y = wl_fixed_to_double (pointer->y);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
device_event.event_x = wl_fixed_to_double (pointer->x);
|
||||
device_event.event_y = wl_fixed_to_double (pointer->y);
|
||||
}
|
||||
|
||||
if (surface && surface->window != NULL)
|
||||
device_event.event = surface->window->xwindow;
|
||||
else
|
||||
device_event.event = device_event.root;
|
||||
|
||||
/* Mutter doesn't really know about the sub-windows. This assumes it
|
||||
doesn't care either */
|
||||
device_event.child = device_event.event;
|
||||
device_event.root_x = wl_fixed_to_double (pointer->x);
|
||||
device_event.root_y = wl_fixed_to_double (pointer->y);
|
||||
|
||||
clutter_event_get_state_full (event,
|
||||
&button_state,
|
||||
(ClutterModifierType*)&device_event.mods.base,
|
||||
(ClutterModifierType*)&device_event.mods.latched,
|
||||
(ClutterModifierType*)&device_event.mods.locked,
|
||||
(ClutterModifierType*)&device_event.mods.effective);
|
||||
device_event.mods.effective &= ~button_state;
|
||||
memset (&device_event.group, 0, sizeof (device_event.group));
|
||||
device_event.group.effective = (device_event.mods.effective >> 13) & 0x3;
|
||||
|
||||
for (i = 0; i < N_BUTTONS; i++)
|
||||
if ((button_state & (CLUTTER_BUTTON1_MASK << i)))
|
||||
XISetMask (button_mask, i + 1);
|
||||
device_event.buttons.mask_len = N_BUTTONS + 1;
|
||||
device_event.buttons.mask = button_mask;
|
||||
|
||||
device_event.valuators.mask_len = 0;
|
||||
device_event.valuators.mask = NULL;
|
||||
device_event.valuators.values = NULL;
|
||||
|
||||
meta_display_handle_event (display, (XEvent *) &generic_event);
|
||||
}
|
||||
|
||||
static void
|
||||
reset_idletimes (const ClutterEvent *event)
|
||||
{
|
||||
@@ -671,127 +558,13 @@ reset_idletimes (const ClutterEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
event_cb (ClutterActor *stage,
|
||||
const ClutterEvent *event,
|
||||
MetaWaylandCompositor *compositor)
|
||||
gboolean
|
||||
meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor,
|
||||
const ClutterEvent *event)
|
||||
{
|
||||
MetaWaylandSeat *seat = compositor->seat;
|
||||
MetaWaylandPointer *pointer = &seat->pointer;
|
||||
MetaWaylandSurface *surface;
|
||||
MetaDisplay *display;
|
||||
|
||||
reset_idletimes (event);
|
||||
|
||||
if (meta_wayland_seat_handle_event (compositor->seat, event))
|
||||
return TRUE;
|
||||
|
||||
/* HACK: for now, the surfaces from Wayland clients aren't
|
||||
integrated into Mutter's event handling and Mutter won't give them
|
||||
focus on mouse clicks. As a hack to work around this we can just
|
||||
give them input focus on mouse clicks so we can at least test the
|
||||
keyboard support */
|
||||
if (event->type == CLUTTER_BUTTON_PRESS)
|
||||
{
|
||||
surface = pointer->current;
|
||||
|
||||
if (surface && surface->window &&
|
||||
surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
||||
meta_window_focus (surface->window, clutter_event_get_time (event));
|
||||
}
|
||||
|
||||
if (seat->cursor_tracker)
|
||||
{
|
||||
meta_cursor_tracker_update_position (seat->cursor_tracker,
|
||||
wl_fixed_to_int (pointer->x),
|
||||
wl_fixed_to_int (pointer->y));
|
||||
|
||||
if (pointer->current == NULL)
|
||||
meta_cursor_tracker_revert_root (seat->cursor_tracker);
|
||||
|
||||
meta_cursor_tracker_queue_redraw (seat->cursor_tracker, stage);
|
||||
}
|
||||
|
||||
display = meta_get_display ();
|
||||
if (!display)
|
||||
return FALSE;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
if (compositor->implicit_grab_surface == NULL)
|
||||
{
|
||||
compositor->implicit_grab_button = event->button.button;
|
||||
compositor->implicit_grab_surface = pointer->current;
|
||||
}
|
||||
return FALSE;
|
||||
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
if (event->type == CLUTTER_BUTTON_RELEASE &&
|
||||
compositor->implicit_grab_surface &&
|
||||
event->button.button == compositor->implicit_grab_button)
|
||||
compositor->implicit_grab_surface = NULL;
|
||||
return FALSE;
|
||||
|
||||
case CLUTTER_MOTION:
|
||||
synthesize_motion_event (compositor, event);
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
event_emission_hook_cb (GSignalInvocationHint *ihint,
|
||||
guint n_param_values,
|
||||
const GValue *param_values,
|
||||
gpointer data)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = data;
|
||||
ClutterActor *actor;
|
||||
ClutterEvent *event;
|
||||
|
||||
g_return_val_if_fail (n_param_values == 2, FALSE);
|
||||
|
||||
actor = g_value_get_object (param_values + 0);
|
||||
event = g_value_get_boxed (param_values + 1);
|
||||
|
||||
if (actor == NULL)
|
||||
return TRUE /* stay connected */;
|
||||
|
||||
/* If this event belongs to the corresponding grab for this event
|
||||
* type then the captured-event signal won't be emitted so we have
|
||||
* to manually forward it on */
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
/* Pointer events */
|
||||
case CLUTTER_MOTION:
|
||||
case CLUTTER_ENTER:
|
||||
case CLUTTER_LEAVE:
|
||||
case CLUTTER_BUTTON_PRESS:
|
||||
case CLUTTER_BUTTON_RELEASE:
|
||||
case CLUTTER_SCROLL:
|
||||
if (actor == clutter_get_pointer_grab ())
|
||||
event_cb (clutter_actor_get_stage (actor),
|
||||
event,
|
||||
compositor);
|
||||
break;
|
||||
|
||||
/* Keyboard events */
|
||||
case CLUTTER_KEY_PRESS:
|
||||
case CLUTTER_KEY_RELEASE:
|
||||
if (actor == clutter_get_keyboard_grab ())
|
||||
event_cb (clutter_actor_get_stage (actor),
|
||||
event,
|
||||
compositor);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE /* stay connected */;
|
||||
return meta_wayland_seat_handle_event (compositor->seat, event);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -834,7 +607,6 @@ void
|
||||
meta_wayland_init (void)
|
||||
{
|
||||
MetaWaylandCompositor *compositor = &_meta_wayland_compositor;
|
||||
guint event_signal;
|
||||
MetaMonitorManager *monitors;
|
||||
ClutterBackend *backend;
|
||||
CoglContext *cogl_context;
|
||||
@@ -923,21 +695,6 @@ meta_wayland_init (void)
|
||||
compositor->seat = meta_wayland_seat_new (compositor->wayland_display,
|
||||
compositor->drm_fd >= 0);
|
||||
|
||||
g_signal_connect (compositor->stage,
|
||||
"captured-event",
|
||||
G_CALLBACK (event_cb),
|
||||
compositor);
|
||||
/* If something sets a grab on an actor then the captured event
|
||||
* signal won't get emitted but we still want to see these events so
|
||||
* we can update the cursor position. To make sure we see all events
|
||||
* we also install an emission hook on the event signal */
|
||||
event_signal = g_signal_lookup ("event", CLUTTER_TYPE_STAGE);
|
||||
g_signal_add_emission_hook (event_signal,
|
||||
0 /* detail */,
|
||||
event_emission_hook_cb,
|
||||
compositor, /* hook_data */
|
||||
NULL /* data_destroy */);
|
||||
|
||||
meta_wayland_init_shell (compositor);
|
||||
|
||||
clutter_actor_show (compositor->stage);
|
||||
|
Reference in New Issue
Block a user