Compare commits
6 Commits
3.11.1-way
...
wip/waylan
Author | SHA1 | Date | |
---|---|---|---|
![]() |
34398b273c | ||
![]() |
00a73c5bdc | ||
![]() |
20cd02f086 | ||
![]() |
0cb9392686 | ||
![]() |
57f0b1d46d | ||
![]() |
e2d8d886a8 |
@@ -6,5 +6,3 @@ EXTRA_DIST = HACKING MAINTAINERS rationales.txt
|
|||||||
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
|
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
|
||||||
|
|
||||||
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
|
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
|
||||||
|
|
||||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
|
||||||
|
22
NEWS
22
NEWS
@@ -1,25 +1,3 @@
|
|||||||
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
|
3.10.0.1
|
||||||
========
|
========
|
||||||
* Fix bug when a window changed size twice in a single frame - this
|
* Fix bug when a window changed size twice in a single frame - this
|
||||||
|
@@ -1,9 +1,8 @@
|
|||||||
AC_PREREQ(2.50)
|
AC_PREREQ(2.50)
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
|
||||||
|
|
||||||
m4_define([mutter_major_version], [3])
|
m4_define([mutter_major_version], [3])
|
||||||
m4_define([mutter_minor_version], [11])
|
m4_define([mutter_minor_version], [10])
|
||||||
m4_define([mutter_micro_version], [1])
|
m4_define([mutter_micro_version], [0.1])
|
||||||
|
|
||||||
m4_define([mutter_version],
|
m4_define([mutter_version],
|
||||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||||
@@ -80,7 +79,7 @@ MUTTER_PC_MODULES="
|
|||||||
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
|
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
|
||||||
$CLUTTER_PACKAGE >= 1.15.94
|
$CLUTTER_PACKAGE >= 1.15.94
|
||||||
cogl-1.0 >= 1.13.3
|
cogl-1.0 >= 1.13.3
|
||||||
upower-glib >= 0.99.0
|
upower-glib > 0.9.11
|
||||||
gnome-desktop-3.0
|
gnome-desktop-3.0
|
||||||
"
|
"
|
||||||
|
|
||||||
|
@@ -207,6 +207,7 @@ meta_key_binding_get_modifiers
|
|||||||
meta_key_binding_get_mask
|
meta_key_binding_get_mask
|
||||||
meta_key_binding_is_builtin
|
meta_key_binding_is_builtin
|
||||||
meta_keybindings_set_custom_handler
|
meta_keybindings_set_custom_handler
|
||||||
|
meta_keybindings_switch_window
|
||||||
meta_screen_ungrab_all_keys
|
meta_screen_ungrab_all_keys
|
||||||
meta_screen_grab_all_keys
|
meta_screen_grab_all_keys
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
@@ -21,7 +21,6 @@ environment.</description>
|
|||||||
-->
|
-->
|
||||||
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" />
|
<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/" />
|
||||||
<download-page rdf:resource="http://download.gnome.org/sources/mutter-wayland/" />
|
|
||||||
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
|
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
|
||||||
|
|
||||||
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
|
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
|
||||||
|
@@ -52,6 +52,7 @@ libmutter_wayland_la_SOURCES = \
|
|||||||
core/async-getprop.h \
|
core/async-getprop.h \
|
||||||
core/barrier.c \
|
core/barrier.c \
|
||||||
meta/barrier.h \
|
meta/barrier.h \
|
||||||
|
core/barrier-private.h \
|
||||||
core/bell.c \
|
core/bell.c \
|
||||||
core/bell.h \
|
core/bell.h \
|
||||||
core/boxes.c \
|
core/boxes.c \
|
||||||
@@ -395,6 +396,7 @@ $(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
|
|||||||
--generate-c-code meta-dbus-xrandr \
|
--generate-c-code meta-dbus-xrandr \
|
||||||
$(srcdir)/xrandr.xml
|
$(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
|
$(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
|
||||||
$(AM_V_GEN)gdbus-codegen \
|
$(AM_V_GEN)gdbus-codegen \
|
||||||
|
@@ -31,7 +31,6 @@
|
|||||||
|
|
||||||
#include <meta/meta-shaped-texture.h>
|
#include <meta/meta-shaped-texture.h>
|
||||||
#include <meta/util.h>
|
#include <meta/util.h>
|
||||||
#include "clutter-utils.h"
|
|
||||||
#include "meta-texture-tower.h"
|
#include "meta-texture-tower.h"
|
||||||
|
|
||||||
#include "meta-shaped-texture-private.h"
|
#include "meta-shaped-texture-private.h"
|
||||||
@@ -281,7 +280,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
|||||||
CoglTexture *paint_tex;
|
CoglTexture *paint_tex;
|
||||||
ClutterActorBox alloc;
|
ClutterActorBox alloc;
|
||||||
cairo_region_t *blended_region = NULL;
|
cairo_region_t *blended_region = NULL;
|
||||||
CoglPipelineFilter filter;
|
|
||||||
|
|
||||||
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
||||||
return;
|
return;
|
||||||
@@ -318,22 +316,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
|||||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||||
return;
|
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 ());
|
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||||
fb = cogl_get_draw_framebuffer ();
|
fb = cogl_get_draw_framebuffer ();
|
||||||
|
|
||||||
@@ -362,7 +344,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
|||||||
|
|
||||||
opaque_pipeline = get_unblended_pipeline (ctx);
|
opaque_pipeline = get_unblended_pipeline (ctx);
|
||||||
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
|
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);
|
n_rects = cairo_region_num_rectangles (region);
|
||||||
for (i = 0; i < n_rects; i++)
|
for (i = 0; i < n_rects; i++)
|
||||||
@@ -404,11 +385,9 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
|||||||
{
|
{
|
||||||
pipeline = get_masked_pipeline (ctx);
|
pipeline = get_masked_pipeline (ctx);
|
||||||
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
|
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_texture (pipeline, 0, paint_tex);
|
||||||
cogl_pipeline_set_layer_filters (pipeline, 0, filter, filter);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
CoglColor color;
|
CoglColor color;
|
||||||
|
@@ -1007,7 +1007,7 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
interval = (int)(1000000 / refresh_rate) * 6;
|
interval = (int)(1000000 / refresh_rate) * 6;
|
||||||
offset = MAX (0, priv->frame_drawn_time + interval - current_time) / 1000;
|
offset = MAX (0, current_time - priv->frame_drawn_time + interval) / 1000;
|
||||||
|
|
||||||
/* The clutter master clock source has already been added with META_PRIORITY_REDRAW,
|
/* 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
|
* so the timer will run *after* the clutter frame handling, if a frame is ready
|
||||||
|
39
src/core/barrier-private.h
Normal file
39
src/core/barrier-private.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/* -*- 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,5 +1,27 @@
|
|||||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
|
/* -*- 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
|
* SECTION:barrier
|
||||||
* @Title: MetaBarrier
|
* @Title: MetaBarrier
|
||||||
@@ -9,6 +31,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include <X11/extensions/XInput2.h>
|
#include <X11/extensions/XInput2.h>
|
||||||
#include <X11/extensions/Xfixes.h>
|
#include <X11/extensions/Xfixes.h>
|
||||||
@@ -16,6 +39,7 @@
|
|||||||
#include <meta/barrier.h>
|
#include <meta/barrier.h>
|
||||||
#include "display-private.h"
|
#include "display-private.h"
|
||||||
#include "mutter-enum-types.h"
|
#include "mutter-enum-types.h"
|
||||||
|
#include "barrier-private.h"
|
||||||
#include "core.h"
|
#include "core.h"
|
||||||
|
|
||||||
G_DEFINE_TYPE (MetaBarrier, meta_barrier, G_TYPE_OBJECT)
|
G_DEFINE_TYPE (MetaBarrier, meta_barrier, G_TYPE_OBJECT)
|
||||||
@@ -56,9 +80,23 @@ struct _MetaBarrierPrivate
|
|||||||
|
|
||||||
MetaBarrierDirection directions;
|
MetaBarrierDirection directions;
|
||||||
|
|
||||||
|
/* x11 */
|
||||||
PointerBarrier xbarrier;
|
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 meta_barrier_event_unref (MetaBarrierEvent *event);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -148,7 +186,10 @@ meta_barrier_dispose (GObject *object)
|
|||||||
gboolean
|
gboolean
|
||||||
meta_barrier_is_active (MetaBarrier *barrier)
|
meta_barrier_is_active (MetaBarrier *barrier)
|
||||||
{
|
{
|
||||||
return barrier->priv->xbarrier != 0;
|
if (meta_is_wayland_compositor ())
|
||||||
|
return barrier->priv->active;
|
||||||
|
else
|
||||||
|
return barrier->priv->xbarrier != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -165,15 +206,25 @@ void
|
|||||||
meta_barrier_release (MetaBarrier *barrier,
|
meta_barrier_release (MetaBarrier *barrier,
|
||||||
MetaBarrierEvent *event)
|
MetaBarrierEvent *event)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_XI23
|
MetaBarrierPrivate *priv;
|
||||||
MetaBarrierPrivate *priv = barrier->priv;
|
|
||||||
if (META_DISPLAY_HAS_XINPUT_23 (priv->display))
|
priv = barrier->priv;
|
||||||
|
|
||||||
|
if (meta_is_wayland_compositor ())
|
||||||
{
|
{
|
||||||
XIBarrierReleasePointer (priv->display->xdisplay,
|
priv->release_event_id = event->event_id;
|
||||||
META_VIRTUAL_CORE_POINTER_ID,
|
|
||||||
priv->xbarrier, 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 */
|
#endif /* HAVE_XI23 */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -192,19 +243,29 @@ meta_barrier_constructed (GObject *object)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dpy = priv->display->xdisplay;
|
if (meta_is_wayland_compositor ())
|
||||||
root = DefaultRootWindow (dpy);
|
{
|
||||||
|
MetaBarrierManager *manager = meta_barrier_manager_get ();
|
||||||
|
|
||||||
priv->xbarrier = XFixesCreatePointerBarrier (dpy, root,
|
manager->barriers = g_list_prepend (manager->barriers, g_object_ref (barrier));
|
||||||
priv->x1, priv->y1,
|
priv->active = TRUE;
|
||||||
priv->x2, priv->y2,
|
}
|
||||||
priv->directions, 0, NULL);
|
else
|
||||||
|
{
|
||||||
|
dpy = priv->display->xdisplay;
|
||||||
|
root = DefaultRootWindow (dpy);
|
||||||
|
|
||||||
/* Take a ref that we'll release when the XID dies inside destroy(),
|
priv->xbarrier = XFixesCreatePointerBarrier (dpy, root,
|
||||||
* so that the object stays alive and doesn't get GC'd. */
|
priv->x1, priv->y1,
|
||||||
g_object_ref (barrier);
|
priv->x2, priv->y2,
|
||||||
|
priv->directions, 0, NULL);
|
||||||
|
|
||||||
g_hash_table_insert (priv->display->xids, &priv->xbarrier, 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_OBJECT_CLASS (meta_barrier_parent_class)->constructed (object);
|
G_OBJECT_CLASS (meta_barrier_parent_class)->constructed (object);
|
||||||
}
|
}
|
||||||
@@ -312,16 +373,26 @@ meta_barrier_destroy (MetaBarrier *barrier)
|
|||||||
if (priv->display == NULL)
|
if (priv->display == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dpy = priv->display->xdisplay;
|
if (meta_is_wayland_compositor ())
|
||||||
|
{
|
||||||
|
MetaBarrierManager *manager = meta_barrier_manager_get ();
|
||||||
|
|
||||||
if (!meta_barrier_is_active (barrier))
|
manager->barriers = g_list_remove (manager->barriers, barrier);
|
||||||
return;
|
g_object_unref (barrier);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dpy = priv->display->xdisplay;
|
||||||
|
|
||||||
XFixesDestroyPointerBarrier (dpy, priv->xbarrier);
|
if (!meta_barrier_is_active (barrier))
|
||||||
g_hash_table_remove (priv->display->xids, &priv->xbarrier);
|
return;
|
||||||
priv->xbarrier = 0;
|
|
||||||
|
|
||||||
g_object_unref (barrier);
|
XFixesDestroyPointerBarrier (dpy, priv->xbarrier);
|
||||||
|
g_hash_table_remove (priv->display->xids, &priv->xbarrier);
|
||||||
|
priv->xbarrier = 0;
|
||||||
|
|
||||||
|
g_object_unref (barrier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -371,6 +442,9 @@ meta_display_process_barrier_event (MetaDisplay *display,
|
|||||||
{
|
{
|
||||||
MetaBarrier *barrier;
|
MetaBarrier *barrier;
|
||||||
|
|
||||||
|
if (meta_is_wayland_compositor ())
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
barrier = g_hash_table_lookup (display->xids, &xev->barrier);
|
barrier = g_hash_table_lookup (display->xids, &xev->barrier);
|
||||||
if (barrier != NULL)
|
if (barrier != NULL)
|
||||||
{
|
{
|
||||||
@@ -382,6 +456,405 @@ meta_display_process_barrier_event (MetaDisplay *display,
|
|||||||
}
|
}
|
||||||
#endif /* HAVE_XI23 */
|
#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 *
|
static MetaBarrierEvent *
|
||||||
meta_barrier_event_ref (MetaBarrierEvent *event)
|
meta_barrier_event_ref (MetaBarrierEvent *event)
|
||||||
{
|
{
|
||||||
@@ -399,7 +872,12 @@ meta_barrier_event_unref (MetaBarrierEvent *event)
|
|||||||
g_return_if_fail (event->ref_count > 0);
|
g_return_if_fail (event->ref_count > 0);
|
||||||
|
|
||||||
if (g_atomic_int_dec_and_test ((volatile int *)&event->ref_count))
|
if (g_atomic_int_dec_and_test ((volatile int *)&event->ref_count))
|
||||||
g_slice_free (MetaBarrierEvent, event);
|
{
|
||||||
|
if (event->barrier)
|
||||||
|
g_object_unref (event->barrier);
|
||||||
|
|
||||||
|
g_slice_free (MetaBarrierEvent, event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
G_DEFINE_BOXED_TYPE (MetaBarrierEvent,
|
G_DEFINE_BOXED_TYPE (MetaBarrierEvent,
|
||||||
|
@@ -476,6 +476,26 @@ meta_core_change_workspace (Display *xdisplay,
|
|||||||
new_workspace));
|
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
|
void
|
||||||
meta_core_show_window_menu (Display *xdisplay,
|
meta_core_show_window_menu (Display *xdisplay,
|
||||||
Window frame_xwindow,
|
Window frame_xwindow,
|
||||||
|
@@ -153,6 +153,8 @@ void meta_core_change_workspace (Display *xdisplay,
|
|||||||
Window frame_xwindow,
|
Window frame_xwindow,
|
||||||
int new_workspace);
|
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,
|
int meta_core_get_frame_workspace (Display *xdisplay,
|
||||||
Window frame_xwindow);
|
Window frame_xwindow);
|
||||||
const char* meta_core_get_workspace_name_with_index (Display *xdisplay,
|
const char* meta_core_get_workspace_name_with_index (Display *xdisplay,
|
||||||
|
@@ -51,6 +51,7 @@
|
|||||||
#include <meta/compositor.h>
|
#include <meta/compositor.h>
|
||||||
#include <meta/compositor-mutter.h>
|
#include <meta/compositor-mutter.h>
|
||||||
#include <X11/Xatom.h>
|
#include <X11/Xatom.h>
|
||||||
|
#include <X11/cursorfont.h>
|
||||||
#include "mutter-enum-types.h"
|
#include "mutter-enum-types.h"
|
||||||
#include "meta-idle-monitor-private.h"
|
#include "meta-idle-monitor-private.h"
|
||||||
|
|
||||||
@@ -1514,20 +1515,27 @@ guint32
|
|||||||
meta_display_get_current_time_roundtrip (MetaDisplay *display)
|
meta_display_get_current_time_roundtrip (MetaDisplay *display)
|
||||||
{
|
{
|
||||||
guint32 timestamp;
|
guint32 timestamp;
|
||||||
|
|
||||||
timestamp = meta_display_get_current_time (display);
|
|
||||||
if (timestamp == CurrentTime)
|
|
||||||
{
|
|
||||||
XEvent property_event;
|
|
||||||
|
|
||||||
XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
|
if (meta_is_wayland_compositor ())
|
||||||
display->atom__MUTTER_TIMESTAMP_PING,
|
{
|
||||||
XA_STRING, 8, PropModeAppend, NULL, 0);
|
timestamp = g_get_monotonic_time () / 1000;
|
||||||
XIfEvent (display->xdisplay,
|
}
|
||||||
&property_event,
|
else
|
||||||
find_timestamp_predicate,
|
{
|
||||||
(XPointer) display);
|
timestamp = meta_display_get_current_time (display);
|
||||||
timestamp = property_event.xproperty.time;
|
if (timestamp == CurrentTime)
|
||||||
|
{
|
||||||
|
XEvent property_event;
|
||||||
|
|
||||||
|
XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
|
||||||
|
display->atom__MUTTER_TIMESTAMP_PING,
|
||||||
|
XA_STRING, 8, PropModeAppend, NULL, 0);
|
||||||
|
XIfEvent (display->xdisplay,
|
||||||
|
&property_event,
|
||||||
|
find_timestamp_predicate,
|
||||||
|
(XPointer) display);
|
||||||
|
timestamp = property_event.xproperty.time;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sanity_check_timestamps (display, timestamp);
|
sanity_check_timestamps (display, timestamp);
|
||||||
@@ -1667,8 +1675,7 @@ window_raise_with_delay_callback (void *data)
|
|||||||
static void
|
static void
|
||||||
meta_display_mouse_mode_focus (MetaDisplay *display,
|
meta_display_mouse_mode_focus (MetaDisplay *display,
|
||||||
MetaWindow *window,
|
MetaWindow *window,
|
||||||
guint32 timestamp)
|
guint32 timestamp) {
|
||||||
{
|
|
||||||
if (window->type != META_WINDOW_DESKTOP)
|
if (window->type != META_WINDOW_DESKTOP)
|
||||||
{
|
{
|
||||||
meta_topic (META_DEBUG_FOCUS,
|
meta_topic (META_DEBUG_FOCUS,
|
||||||
@@ -1707,8 +1714,7 @@ meta_display_mouse_mode_focus (MetaDisplay *display,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
window_focus_on_pointer_rest_callback (gpointer data)
|
window_focus_on_pointer_rest_callback (gpointer data) {
|
||||||
{
|
|
||||||
MetaFocusData *focus_data;
|
MetaFocusData *focus_data;
|
||||||
MetaDisplay *display;
|
MetaDisplay *display;
|
||||||
MetaScreen *screen;
|
MetaScreen *screen;
|
||||||
@@ -1753,9 +1759,9 @@ window_focus_on_pointer_rest_callback (gpointer data)
|
|||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
window =
|
window =
|
||||||
meta_stack_get_default_focus_window_at_point (screen->stack,
|
meta_stack_get_default_focus_window_at_point (screen->stack,
|
||||||
screen->active_workspace,
|
screen->active_workspace,
|
||||||
None, root_x, root_y);
|
None, root_x, root_y);
|
||||||
|
|
||||||
if (window == NULL)
|
if (window == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
@@ -1763,7 +1769,7 @@ window_focus_on_pointer_rest_callback (gpointer data)
|
|||||||
timestamp = meta_display_get_current_time_roundtrip (display);
|
timestamp = meta_display_get_current_time_roundtrip (display);
|
||||||
meta_display_mouse_mode_focus (display, window, timestamp);
|
meta_display_mouse_mode_focus (display, window, timestamp);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
display->focus_timeout_id = 0;
|
display->focus_timeout_id = 0;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -2191,6 +2197,40 @@ handle_window_focus_event (MetaDisplay *display,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reload_xkb_rules (MetaScreen *screen)
|
||||||
|
{
|
||||||
|
MetaWaylandCompositor *compositor;
|
||||||
|
char **names;
|
||||||
|
int n_names;
|
||||||
|
gboolean ok;
|
||||||
|
const char *rules, *model, *layout, *variant, *options;
|
||||||
|
|
||||||
|
compositor = meta_wayland_compositor_get_default ();
|
||||||
|
|
||||||
|
ok = meta_prop_get_latin1_list (screen->display, screen->xroot,
|
||||||
|
screen->display->atom__XKB_RULES_NAMES,
|
||||||
|
&names, &n_names);
|
||||||
|
if (!ok)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (n_names != 5)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
rules = names[0];
|
||||||
|
model = names[1];
|
||||||
|
layout = names[2];
|
||||||
|
variant = names[3];
|
||||||
|
options = names[4];
|
||||||
|
|
||||||
|
meta_wayland_keyboard_set_keymap_names (&compositor->seat->keyboard,
|
||||||
|
rules, model, layout, variant, options,
|
||||||
|
META_WAYLAND_KEYBOARD_SKIP_XCLIENTS);
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_strfreev (names);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* meta_display_handle_event:
|
* meta_display_handle_event:
|
||||||
* @display: The MetaDisplay that events are coming from
|
* @display: The MetaDisplay that events are coming from
|
||||||
@@ -2413,7 +2453,6 @@ meta_display_handle_event (MetaDisplay *display,
|
|||||||
|
|
||||||
if ((window &&
|
if ((window &&
|
||||||
meta_grab_op_is_mouse (display->grab_op) &&
|
meta_grab_op_is_mouse (display->grab_op) &&
|
||||||
(device_event->mods.effective & display->window_grab_modifiers) &&
|
|
||||||
display->grab_button != device_event->detail &&
|
display->grab_button != device_event->detail &&
|
||||||
display->grab_window == window) ||
|
display->grab_window == window) ||
|
||||||
grab_op_is_keyboard (display->grab_op))
|
grab_op_is_keyboard (display->grab_op))
|
||||||
@@ -2964,6 +3003,10 @@ meta_display_handle_event (MetaDisplay *display,
|
|||||||
else if (event->xproperty.atom ==
|
else if (event->xproperty.atom ==
|
||||||
display->atom__NET_DESKTOP_NAMES)
|
display->atom__NET_DESKTOP_NAMES)
|
||||||
meta_screen_update_workspace_names (screen);
|
meta_screen_update_workspace_names (screen);
|
||||||
|
else if (meta_is_wayland_compositor () &&
|
||||||
|
event->xproperty.atom ==
|
||||||
|
display->atom__XKB_RULES_NAMES)
|
||||||
|
reload_xkb_rules (screen);
|
||||||
#if 0
|
#if 0
|
||||||
else if (event->xproperty.atom ==
|
else if (event->xproperty.atom ==
|
||||||
display->atom__NET_RESTACK_WINDOW)
|
display->atom__NET_RESTACK_WINDOW)
|
||||||
@@ -3199,7 +3242,9 @@ event_callback (XEvent *event,
|
|||||||
translation altogether by directly using the Clutter events */
|
translation altogether by directly using the Clutter events */
|
||||||
if (meta_is_wayland_compositor () &&
|
if (meta_is_wayland_compositor () &&
|
||||||
event->type == GenericEvent &&
|
event->type == GenericEvent &&
|
||||||
event->xcookie.evtype == XI_Motion)
|
(event->xcookie.evtype == XI_Motion ||
|
||||||
|
event->xcookie.evtype == XI_KeyPress ||
|
||||||
|
event->xcookie.evtype == XI_KeyRelease))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
return meta_display_handle_event (display, event);
|
return meta_display_handle_event (display, event);
|
||||||
@@ -3961,6 +4006,85 @@ meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
|
|||||||
return is_a_no_focus_window;
|
return is_a_no_focus_window;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Cursor
|
||||||
|
meta_display_create_x_cursor (MetaDisplay *display,
|
||||||
|
MetaCursor cursor)
|
||||||
|
{
|
||||||
|
Cursor xcursor;
|
||||||
|
guint glyph = XC_num_glyphs;
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
|
switch (cursor)
|
||||||
|
{
|
||||||
|
case META_CURSOR_DEFAULT:
|
||||||
|
glyph = XC_left_ptr;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_NORTH_RESIZE:
|
||||||
|
glyph = XC_top_side;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_SOUTH_RESIZE:
|
||||||
|
glyph = XC_bottom_side;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_WEST_RESIZE:
|
||||||
|
glyph = XC_left_side;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_EAST_RESIZE:
|
||||||
|
glyph = XC_right_side;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_SE_RESIZE:
|
||||||
|
glyph = XC_bottom_right_corner;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_SW_RESIZE:
|
||||||
|
glyph = XC_bottom_left_corner;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_NE_RESIZE:
|
||||||
|
glyph = XC_top_right_corner;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_NW_RESIZE:
|
||||||
|
glyph = XC_top_left_corner;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
|
||||||
|
glyph = XC_fleur;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_BUSY:
|
||||||
|
glyph = XC_watch;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_DND_IN_DRAG:
|
||||||
|
name = "dnd-none";
|
||||||
|
break;
|
||||||
|
case META_CURSOR_DND_MOVE:
|
||||||
|
name = "dnd-move";
|
||||||
|
break;
|
||||||
|
case META_CURSOR_DND_COPY:
|
||||||
|
name = "dnd-copy";
|
||||||
|
break;
|
||||||
|
case META_CURSOR_DND_UNSUPPORTED_TARGET:
|
||||||
|
name = "dnd-none";
|
||||||
|
break;
|
||||||
|
case META_CURSOR_POINTING_HAND:
|
||||||
|
glyph = XC_hand2;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_CROSSHAIR:
|
||||||
|
glyph = XC_crosshair;
|
||||||
|
break;
|
||||||
|
case META_CURSOR_IBEAM:
|
||||||
|
glyph = XC_xterm;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
g_assert_not_reached ();
|
||||||
|
glyph = 0; /* silence compiler */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name != NULL)
|
||||||
|
xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
|
||||||
|
else
|
||||||
|
xcursor = XCreateFontCursor (display->xdisplay, glyph);
|
||||||
|
|
||||||
|
return xcursor;
|
||||||
|
}
|
||||||
|
|
||||||
static Cursor
|
static Cursor
|
||||||
xcursor_for_op (MetaDisplay *display,
|
xcursor_for_op (MetaDisplay *display,
|
||||||
MetaGrabOp op)
|
MetaGrabOp op)
|
||||||
@@ -5954,7 +6078,7 @@ meta_display_get_xinput_opcode (MetaDisplay *display)
|
|||||||
gboolean
|
gboolean
|
||||||
meta_display_supports_extended_barriers (MetaDisplay *display)
|
meta_display_supports_extended_barriers (MetaDisplay *display)
|
||||||
{
|
{
|
||||||
return META_DISPLAY_HAS_XINPUT_23 (display) && !meta_is_wayland_compositor ();
|
return meta_is_wayland_compositor () || META_DISPLAY_HAS_XINPUT_23 (display);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1840,6 +1840,7 @@ invoke_handler_by_name (MetaDisplay *display,
|
|||||||
invoke_handler (display, screen, handler, window, event, NULL);
|
invoke_handler (display, screen, handler, window, event, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* now called from only one place, may be worth merging */
|
||||||
static gboolean
|
static gboolean
|
||||||
process_event (MetaKeyBinding *bindings,
|
process_event (MetaKeyBinding *bindings,
|
||||||
int n_bindings,
|
int n_bindings,
|
||||||
@@ -1847,6 +1848,7 @@ process_event (MetaKeyBinding *bindings,
|
|||||||
MetaScreen *screen,
|
MetaScreen *screen,
|
||||||
MetaWindow *window,
|
MetaWindow *window,
|
||||||
XIDeviceEvent *event,
|
XIDeviceEvent *event,
|
||||||
|
KeySym keysym,
|
||||||
gboolean on_window)
|
gboolean on_window)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@@ -1864,6 +1866,7 @@ process_event (MetaKeyBinding *bindings,
|
|||||||
MetaKeyHandler *handler = bindings[i].handler;
|
MetaKeyHandler *handler = bindings[i].handler;
|
||||||
|
|
||||||
if ((!on_window && handler->flags & META_KEY_BINDING_PER_WINDOW) ||
|
if ((!on_window && handler->flags & META_KEY_BINDING_PER_WINDOW) ||
|
||||||
|
event->evtype != XI_KeyPress ||
|
||||||
bindings[i].keycode != event->detail ||
|
bindings[i].keycode != event->detail ||
|
||||||
((event->mods.effective & 0xff & ~(display->ignored_modifier_mask)) !=
|
((event->mods.effective & 0xff & ~(display->ignored_modifier_mask)) !=
|
||||||
bindings[i].mask) ||
|
bindings[i].mask) ||
|
||||||
@@ -1930,7 +1933,7 @@ process_overlay_key (MetaDisplay *display,
|
|||||||
*/
|
*/
|
||||||
if (process_event (display->key_bindings,
|
if (process_event (display->key_bindings,
|
||||||
display->n_key_bindings,
|
display->n_key_bindings,
|
||||||
display, screen, NULL, event,
|
display, screen, NULL, event, keysym,
|
||||||
FALSE))
|
FALSE))
|
||||||
{
|
{
|
||||||
/* As normally, after we've handled a global key
|
/* As normally, after we've handled a global key
|
||||||
@@ -2062,22 +2065,22 @@ meta_display_process_key_event (MetaDisplay *display,
|
|||||||
gboolean handled;
|
gboolean handled;
|
||||||
const char *str;
|
const char *str;
|
||||||
MetaScreen *screen;
|
MetaScreen *screen;
|
||||||
|
gboolean was_current_time;
|
||||||
|
|
||||||
/* if key event was on root window, we have a shortcut */
|
/* We only ever have one screen */
|
||||||
screen = meta_display_screen_for_root (display, event->event);
|
screen = display->screens->data;
|
||||||
|
|
||||||
/* else round-trip to server */
|
|
||||||
if (screen == NULL)
|
|
||||||
screen = meta_display_screen_for_xwindow (display, event->event);
|
|
||||||
|
|
||||||
if (screen == NULL)
|
|
||||||
return FALSE; /* event window is destroyed */
|
|
||||||
|
|
||||||
/* ignore key events on popup menus and such. */
|
/* ignore key events on popup menus and such. */
|
||||||
if (meta_ui_window_is_widget (screen->ui, event->event))
|
if (meta_ui_window_is_widget (screen->ui, event->event))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
/* window may be NULL */
|
if (display->current_time == CurrentTime)
|
||||||
|
{
|
||||||
|
display->current_time = event->time;
|
||||||
|
was_current_time = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
was_current_time = FALSE;
|
||||||
|
|
||||||
keysym = XKeycodeToKeysym (display->xdisplay, event->detail, 0);
|
keysym = XKeycodeToKeysym (display->xdisplay, event->detail, 0);
|
||||||
|
|
||||||
@@ -2095,11 +2098,11 @@ meta_display_process_key_event (MetaDisplay *display,
|
|||||||
{
|
{
|
||||||
handled = process_overlay_key (display, screen, event, keysym);
|
handled = process_overlay_key (display, screen, event, keysym);
|
||||||
if (handled)
|
if (handled)
|
||||||
return TRUE;
|
goto out;
|
||||||
|
|
||||||
handled = process_iso_next_group (display, screen, event, keysym);
|
handled = process_iso_next_group (display, screen, event, keysym);
|
||||||
if (handled)
|
if (handled)
|
||||||
return TRUE;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
XIAllowEvents (display->xdisplay, event->deviceid,
|
XIAllowEvents (display->xdisplay, event->deviceid,
|
||||||
@@ -2109,7 +2112,11 @@ meta_display_process_key_event (MetaDisplay *display,
|
|||||||
if (all_keys_grabbed)
|
if (all_keys_grabbed)
|
||||||
{
|
{
|
||||||
if (display->grab_op == META_GRAB_OP_NONE)
|
if (display->grab_op == META_GRAB_OP_NONE)
|
||||||
return TRUE;
|
{
|
||||||
|
handled = TRUE;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
/* If we get here we have a global grab, because
|
/* If we get here we have a global grab, because
|
||||||
* we're in some special keyboard mode such as window move
|
* we're in some special keyboard mode such as window move
|
||||||
* mode.
|
* mode.
|
||||||
@@ -2188,14 +2195,20 @@ meta_display_process_key_event (MetaDisplay *display,
|
|||||||
meta_display_end_grab_op (display, event->time);
|
meta_display_end_grab_op (display, event->time);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
handled = TRUE;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Do the normal keybindings */
|
/* Do the normal keybindings */
|
||||||
return process_event (display->key_bindings,
|
handled = process_event (display->key_bindings,
|
||||||
display->n_key_bindings,
|
display->n_key_bindings,
|
||||||
display, screen, window, event,
|
display, screen, window, event, keysym,
|
||||||
!all_keys_grabbed && window);
|
!all_keys_grabbed && window);
|
||||||
|
|
||||||
|
out:
|
||||||
|
if (was_current_time)
|
||||||
|
display->current_time = CurrentTime;
|
||||||
|
return handled;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@@ -4168,6 +4181,28 @@ meta_keybindings_set_custom_handler (const gchar *name,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_keybindings_switch_window: (skip)
|
||||||
|
* @display: a #MetaDisplay
|
||||||
|
* @screen: a #MetaScreen
|
||||||
|
* @event_window: a #MetaWindow
|
||||||
|
* @event: a #XIDeviceEvent
|
||||||
|
* @binding: a #MetaKeyBinding
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
meta_keybindings_switch_window (MetaDisplay *display,
|
||||||
|
MetaScreen *screen,
|
||||||
|
MetaWindow *event_window,
|
||||||
|
XIDeviceEvent *event,
|
||||||
|
MetaKeyBinding *binding)
|
||||||
|
{
|
||||||
|
gint backwards = (binding->handler->flags & META_KEY_BINDING_IS_REVERSED) != 0;
|
||||||
|
|
||||||
|
do_choose_window (display, screen, event_window, event, binding,
|
||||||
|
backwards, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
init_builtin_key_bindings (MetaDisplay *display)
|
init_builtin_key_bindings (MetaDisplay *display)
|
||||||
{
|
{
|
||||||
|
@@ -401,6 +401,9 @@ meta_init (void)
|
|||||||
g_strerror (errno));
|
g_strerror (errno));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (getenv ("MUTTER_SLEEP_INIT"))
|
||||||
|
sleep (60);
|
||||||
|
|
||||||
g_unix_signal_add (SIGTERM, on_sigterm, NULL);
|
g_unix_signal_add (SIGTERM, on_sigterm, NULL);
|
||||||
|
|
||||||
if (g_getenv ("MUTTER_VERBOSE"))
|
if (g_getenv ("MUTTER_VERBOSE"))
|
||||||
|
@@ -42,7 +42,6 @@
|
|||||||
|
|
||||||
#include <gdk/gdk.h>
|
#include <gdk/gdk.h>
|
||||||
|
|
||||||
#include <X11/cursorfont.h>
|
|
||||||
#include <X11/extensions/Xfixes.h>
|
#include <X11/extensions/Xfixes.h>
|
||||||
#include <X11/Xcursor/Xcursor.h>
|
#include <X11/Xcursor/Xcursor.h>
|
||||||
|
|
||||||
@@ -129,130 +128,76 @@ meta_cursor_reference_unref (MetaCursorReference *self)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static const char *
|
||||||
translate_meta_cursor (MetaCursor cursor,
|
get_cursor_filename (MetaCursor cursor)
|
||||||
guint *glyph_out,
|
|
||||||
const char **name_out)
|
|
||||||
{
|
{
|
||||||
guint glyph = XC_num_glyphs;
|
|
||||||
const char *name = NULL;
|
|
||||||
|
|
||||||
switch (cursor)
|
switch (cursor)
|
||||||
{
|
{
|
||||||
case META_CURSOR_DEFAULT:
|
case META_CURSOR_DEFAULT:
|
||||||
glyph = XC_left_ptr;
|
return "left_ptr";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_NORTH_RESIZE:
|
case META_CURSOR_NORTH_RESIZE:
|
||||||
glyph = XC_top_side;
|
return "top_side";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_SOUTH_RESIZE:
|
case META_CURSOR_SOUTH_RESIZE:
|
||||||
glyph = XC_bottom_side;
|
return "bottom_side";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_WEST_RESIZE:
|
case META_CURSOR_WEST_RESIZE:
|
||||||
glyph = XC_left_side;
|
return "left_side";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_EAST_RESIZE:
|
case META_CURSOR_EAST_RESIZE:
|
||||||
glyph = XC_right_side;
|
return "right_side";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_SE_RESIZE:
|
case META_CURSOR_SE_RESIZE:
|
||||||
glyph = XC_bottom_right_corner;
|
return "bottom_right_corner";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_SW_RESIZE:
|
case META_CURSOR_SW_RESIZE:
|
||||||
glyph = XC_bottom_left_corner;
|
return "bottom_left_corner";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_NE_RESIZE:
|
case META_CURSOR_NE_RESIZE:
|
||||||
glyph = XC_top_right_corner;
|
return "top_right_corner";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_NW_RESIZE:
|
case META_CURSOR_NW_RESIZE:
|
||||||
glyph = XC_top_left_corner;
|
return "top_left_corner";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
|
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
|
||||||
glyph = XC_fleur;
|
return "fleur";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_BUSY:
|
case META_CURSOR_BUSY:
|
||||||
glyph = XC_watch;
|
return "watch";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_DND_IN_DRAG:
|
case META_CURSOR_DND_IN_DRAG:
|
||||||
name = "dnd-none";
|
return "dnd-in-drag";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_DND_MOVE:
|
case META_CURSOR_DND_MOVE:
|
||||||
name = "dnd-move";
|
return "dnd-copy";
|
||||||
break;
|
|
||||||
case META_CURSOR_DND_COPY:
|
|
||||||
name = "dnd-copy";
|
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_DND_UNSUPPORTED_TARGET:
|
case META_CURSOR_DND_UNSUPPORTED_TARGET:
|
||||||
name = "dnd-none";
|
return "dnd-none";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_POINTING_HAND:
|
case META_CURSOR_POINTING_HAND:
|
||||||
glyph = XC_hand2;
|
return "hand";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_CROSSHAIR:
|
case META_CURSOR_CROSSHAIR:
|
||||||
glyph = XC_crosshair;
|
return "crosshair";
|
||||||
break;
|
break;
|
||||||
case META_CURSOR_IBEAM:
|
case META_CURSOR_IBEAM:
|
||||||
glyph = XC_xterm;
|
return "xterm";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
glyph = 0; /* silence compiler */
|
return NULL;
|
||||||
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 *
|
static MetaCursorReference *
|
||||||
meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
|
meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
|
||||||
MetaCursor cursor)
|
MetaCursor cursor)
|
||||||
{
|
{
|
||||||
|
const char *theme;
|
||||||
|
const char *filename;
|
||||||
|
int size;
|
||||||
XcursorImage *image;
|
XcursorImage *image;
|
||||||
int width, height, rowstride;
|
int width, height, rowstride;
|
||||||
CoglPixelFormat cogl_format;
|
CoglPixelFormat cogl_format;
|
||||||
@@ -261,7 +206,11 @@ meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
|
|||||||
CoglContext *cogl_context;
|
CoglContext *cogl_context;
|
||||||
MetaCursorReference *self;
|
MetaCursorReference *self;
|
||||||
|
|
||||||
image = load_cursor_on_client (tracker->screen->display, cursor);
|
filename = get_cursor_filename (cursor);
|
||||||
|
theme = XcursorGetTheme (tracker->screen->display->xdisplay);
|
||||||
|
size = XcursorGetDefaultSize (tracker->screen->display->xdisplay);
|
||||||
|
|
||||||
|
image = XcursorLibraryLoadImage (filename, theme, size);
|
||||||
if (!image)
|
if (!image)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -352,8 +301,6 @@ meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
|
|||||||
|
|
||||||
self = g_slice_new0 (MetaCursorReference);
|
self = g_slice_new0 (MetaCursorReference);
|
||||||
self->ref_count = 1;
|
self->ref_count = 1;
|
||||||
self->hot_x = hot_x;
|
|
||||||
self->hot_y = hot_y;
|
|
||||||
|
|
||||||
backend = clutter_get_default_backend ();
|
backend = clutter_get_default_backend ();
|
||||||
cogl_context = clutter_backend_get_cogl_context (backend);
|
cogl_context = clutter_backend_get_cogl_context (backend);
|
||||||
|
@@ -99,9 +99,8 @@ static gboolean meta_monitor_config_assign_crtcs (MetaConfiguration *config,
|
|||||||
GPtrArray *crtcs,
|
GPtrArray *crtcs,
|
||||||
GPtrArray *outputs);
|
GPtrArray *outputs);
|
||||||
|
|
||||||
static void power_client_changed_cb (UpClient *client,
|
static void power_client_changed_cb (UpClient *client,
|
||||||
GParamSpec *pspec,
|
gpointer user_data);
|
||||||
gpointer user_data);
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_output_key (MetaOutputKey *key)
|
free_output_key (MetaOutputKey *key)
|
||||||
@@ -233,7 +232,7 @@ meta_monitor_config_init (MetaMonitorConfig *self)
|
|||||||
self->up_client = up_client_new ();
|
self->up_client = up_client_new ();
|
||||||
self->lid_is_closed = up_client_get_lid_is_closed (self->up_client);
|
self->lid_is_closed = up_client_get_lid_is_closed (self->up_client);
|
||||||
|
|
||||||
g_signal_connect_object (self->up_client, "notify::lid-is-closed",
|
g_signal_connect_object (self->up_client, "changed",
|
||||||
G_CALLBACK (power_client_changed_cb), self, 0);
|
G_CALLBACK (power_client_changed_cb), self, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1336,9 +1335,8 @@ turn_off_laptop_display (MetaMonitorConfig *self,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
power_client_changed_cb (UpClient *client,
|
power_client_changed_cb (UpClient *client,
|
||||||
GParamSpec *pspec,
|
gpointer user_data)
|
||||||
gpointer user_data)
|
|
||||||
{
|
{
|
||||||
MetaMonitorManager *manager = meta_monitor_manager_get ();
|
MetaMonitorManager *manager = meta_monitor_manager_get ();
|
||||||
MetaMonitorConfig *self = user_data;
|
MetaMonitorConfig *self = user_data;
|
||||||
|
@@ -729,9 +729,6 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
|||||||
g_variant_new_take_string (make_display_name (manager, output)));
|
g_variant_new_take_string (make_display_name (manager, output)));
|
||||||
g_variant_builder_add (&properties, "{sv}", "backlight",
|
g_variant_builder_add (&properties, "{sv}", "backlight",
|
||||||
g_variant_new_int32 (output->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_builder_add (&properties, "{sv}", "primary",
|
||||||
g_variant_new_boolean (output->is_primary));
|
g_variant_new_boolean (output->is_primary));
|
||||||
g_variant_builder_add (&properties, "{sv}", "presentation",
|
g_variant_builder_add (&properties, "{sv}", "presentation",
|
||||||
|
@@ -1724,12 +1724,14 @@ get_default_focus_window (MetaStack *stack,
|
|||||||
* or top window in same group as not_this_one.
|
* or top window in same group as not_this_one.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
MetaWindow *topmost_dock;
|
||||||
MetaWindow *transient_parent;
|
MetaWindow *transient_parent;
|
||||||
MetaWindow *topmost_in_group;
|
MetaWindow *topmost_in_group;
|
||||||
MetaWindow *topmost_overall;
|
MetaWindow *topmost_overall;
|
||||||
MetaGroup *not_this_one_group;
|
MetaGroup *not_this_one_group;
|
||||||
GList *link;
|
GList *link;
|
||||||
|
|
||||||
|
topmost_dock = NULL;
|
||||||
transient_parent = NULL;
|
transient_parent = NULL;
|
||||||
topmost_in_group = NULL;
|
topmost_in_group = NULL;
|
||||||
topmost_overall = NULL;
|
topmost_overall = NULL;
|
||||||
@@ -1755,6 +1757,10 @@ get_default_focus_window (MetaStack *stack,
|
|||||||
(workspace == NULL ||
|
(workspace == NULL ||
|
||||||
meta_window_located_on_workspace (window, workspace)))
|
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 (not_this_one != NULL)
|
||||||
{
|
{
|
||||||
if (transient_parent == NULL &&
|
if (transient_parent == NULL &&
|
||||||
@@ -1772,6 +1778,10 @@ get_default_focus_window (MetaStack *stack,
|
|||||||
topmost_in_group = window;
|
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 &&
|
if (topmost_overall == NULL &&
|
||||||
window->type != META_WINDOW_DOCK &&
|
window->type != META_WINDOW_DOCK &&
|
||||||
(!must_be_at_point ||
|
(!must_be_at_point ||
|
||||||
@@ -1793,7 +1803,7 @@ get_default_focus_window (MetaStack *stack,
|
|||||||
else if (topmost_overall)
|
else if (topmost_overall)
|
||||||
return topmost_overall;
|
return topmost_overall;
|
||||||
else
|
else
|
||||||
return NULL;
|
return topmost_dock;
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaWindow*
|
MetaWindow*
|
||||||
|
@@ -6836,7 +6836,8 @@ meta_window_property_notify (MetaWindow *window,
|
|||||||
void
|
void
|
||||||
meta_window_change_workspace_by_index (MetaWindow *window,
|
meta_window_change_workspace_by_index (MetaWindow *window,
|
||||||
gint space_index,
|
gint space_index,
|
||||||
gboolean append)
|
gboolean append,
|
||||||
|
guint32 timestamp)
|
||||||
{
|
{
|
||||||
MetaWorkspace *workspace;
|
MetaWorkspace *workspace;
|
||||||
MetaScreen *screen;
|
MetaScreen *screen;
|
||||||
@@ -6855,7 +6856,11 @@ meta_window_change_workspace_by_index (MetaWindow *window,
|
|||||||
meta_screen_get_workspace_by_index (screen, space_index);
|
meta_screen_get_workspace_by_index (screen, space_index);
|
||||||
|
|
||||||
if (!workspace && append)
|
if (!workspace && append)
|
||||||
workspace = meta_screen_append_new_workspace (screen, FALSE, CurrentTime);
|
{
|
||||||
|
if (timestamp == CurrentTime)
|
||||||
|
timestamp = meta_display_get_current_time_roundtrip (window->display);
|
||||||
|
workspace = meta_screen_append_new_workspace (screen, FALSE, timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
if (workspace)
|
if (workspace)
|
||||||
{
|
{
|
||||||
@@ -10070,50 +10075,47 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
|||||||
switch (xev->evtype)
|
switch (xev->evtype)
|
||||||
{
|
{
|
||||||
case XI_ButtonRelease:
|
case XI_ButtonRelease:
|
||||||
if (xev->detail == 1)
|
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)
|
||||||
{
|
{
|
||||||
meta_display_check_threshold_reached (window->display,
|
if (meta_grab_op_is_moving (window->display->grab_op))
|
||||||
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);
|
||||||
if (window->tile_mode != META_TILE_NONE)
|
else if (xev->root == window->screen->xroot)
|
||||||
meta_window_tile (window);
|
update_move (window,
|
||||||
else if (xev->root == window->screen->xroot)
|
xev->mods.effective & ShiftMask,
|
||||||
update_move (window,
|
xev->root_x,
|
||||||
xev->mods.effective & ShiftMask,
|
xev->root_y);
|
||||||
xev->root_x,
|
}
|
||||||
xev->root_y);
|
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
||||||
}
|
{
|
||||||
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
if (xev->root == window->screen->xroot)
|
||||||
{
|
update_resize (window,
|
||||||
if (xev->root == window->screen->xroot)
|
xev->mods.effective & ShiftMask,
|
||||||
update_resize (window,
|
xev->root_x,
|
||||||
xev->mods.effective & ShiftMask,
|
xev->root_y,
|
||||||
xev->root_x,
|
TRUE);
|
||||||
xev->root_y,
|
|
||||||
TRUE);
|
/* If a tiled window has been dragged free with a
|
||||||
|
* mouse resize without snapping back to the tiled
|
||||||
/* If a tiled window has been dragged free with a
|
* state, it will end up with an inconsistent tile
|
||||||
* mouse resize without snapping back to the tiled
|
* mode on mouse release; cleaning the mode earlier
|
||||||
* state, it will end up with an inconsistent tile
|
* would break the ability to snap back to the tiled
|
||||||
* mode on mouse release; cleaning the mode earlier
|
* state, so we wait until mouse release.
|
||||||
* would break the ability to snap back to the tiled
|
*/
|
||||||
* state, so we wait until mouse release.
|
update_tile_mode (window);
|
||||||
*/
|
|
||||||
update_tile_mode (window);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
meta_display_end_grab_op (window->display, xev->time);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
meta_display_end_grab_op (window->display, xev->time);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XI_Motion:
|
case XI_Motion:
|
||||||
|
@@ -536,6 +536,81 @@ meta_prop_get_utf8_list (MetaDisplay *display,
|
|||||||
return utf8_list_from_results (&results, str_p, n_str_p);
|
return utf8_list_from_results (&results, str_p, n_str_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* this one freakishly returns g_malloc memory */
|
||||||
|
static gboolean
|
||||||
|
latin1_list_from_results (GetPropertyResults *results,
|
||||||
|
char ***str_p,
|
||||||
|
int *n_str_p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int n_strings;
|
||||||
|
char **retval;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
*str_p = NULL;
|
||||||
|
*n_str_p = 0;
|
||||||
|
|
||||||
|
if (!validate_or_free_results (results, 8, XA_STRING, FALSE))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* I'm not sure this is right, but I'm guessing the
|
||||||
|
* property is nul-separated
|
||||||
|
*/
|
||||||
|
i = 0;
|
||||||
|
n_strings = 0;
|
||||||
|
while (i < (int) results->n_items)
|
||||||
|
{
|
||||||
|
if (results->prop[i] == '\0')
|
||||||
|
++n_strings;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results->prop[results->n_items - 1] != '\0')
|
||||||
|
++n_strings;
|
||||||
|
|
||||||
|
/* we're guaranteed that results->prop has a nul on the end
|
||||||
|
* by XGetWindowProperty
|
||||||
|
*/
|
||||||
|
|
||||||
|
retval = g_new0 (char*, n_strings + 1);
|
||||||
|
|
||||||
|
p = (char *)results->prop;
|
||||||
|
i = 0;
|
||||||
|
while (i < n_strings)
|
||||||
|
{
|
||||||
|
retval[i] = g_strdup (p);
|
||||||
|
|
||||||
|
p = p + strlen (p) + 1;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
*str_p = retval;
|
||||||
|
*n_str_p = i;
|
||||||
|
|
||||||
|
meta_XFree (results->prop);
|
||||||
|
results->prop = NULL;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
meta_prop_get_latin1_list (MetaDisplay *display,
|
||||||
|
Window xwindow,
|
||||||
|
Atom xatom,
|
||||||
|
char ***str_p,
|
||||||
|
int *n_str_p)
|
||||||
|
{
|
||||||
|
GetPropertyResults results;
|
||||||
|
|
||||||
|
*str_p = NULL;
|
||||||
|
|
||||||
|
if (!get_property (display, xwindow, xatom,
|
||||||
|
XA_STRING, &results))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return latin1_list_from_results (&results, str_p, n_str_p);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_prop_set_utf8_string_hint (MetaDisplay *display,
|
meta_prop_set_utf8_string_hint (MetaDisplay *display,
|
||||||
Window xwindow,
|
Window xwindow,
|
||||||
|
@@ -102,6 +102,11 @@ gboolean meta_prop_get_utf8_list (MetaDisplay *display,
|
|||||||
Atom xatom,
|
Atom xatom,
|
||||||
char ***str_p,
|
char ***str_p,
|
||||||
int *n_str_p);
|
int *n_str_p);
|
||||||
|
gboolean meta_prop_get_latin1_list (MetaDisplay *display,
|
||||||
|
Window xwindow,
|
||||||
|
Atom xatom,
|
||||||
|
char ***str_p,
|
||||||
|
int *n_str_p);
|
||||||
void meta_prop_set_utf8_string_hint
|
void meta_prop_set_utf8_string_hint
|
||||||
(MetaDisplay *display,
|
(MetaDisplay *display,
|
||||||
Window xwindow,
|
Window xwindow,
|
||||||
|
@@ -81,6 +81,7 @@ item(TIMESTAMP)
|
|||||||
item(VERSION)
|
item(VERSION)
|
||||||
item(ATOM_PAIR)
|
item(ATOM_PAIR)
|
||||||
item(BACKLIGHT)
|
item(BACKLIGHT)
|
||||||
|
item(_XKB_RULES_NAMES)
|
||||||
|
|
||||||
/* Oddities: These are used, and we need atoms for them,
|
/* Oddities: These are used, and we need atoms for them,
|
||||||
* but when we need all _NET_WM hints (i.e. when we're making
|
* but when we need all _NET_WM hints (i.e. when we're making
|
||||||
|
@@ -94,6 +94,7 @@ typedef enum {
|
|||||||
struct _MetaBarrierEvent {
|
struct _MetaBarrierEvent {
|
||||||
/* < private > */
|
/* < private > */
|
||||||
volatile guint ref_count;
|
volatile guint ref_count;
|
||||||
|
MetaBarrier *barrier;
|
||||||
|
|
||||||
/* < public > */
|
/* < public > */
|
||||||
int event_id;
|
int event_id;
|
||||||
|
@@ -35,6 +35,13 @@ gboolean meta_keybindings_set_custom_handler (const gchar *name,
|
|||||||
gpointer user_data,
|
gpointer user_data,
|
||||||
GDestroyNotify free_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);
|
void meta_screen_ungrab_all_keys (MetaScreen *screen, guint32 timestamp);
|
||||||
gboolean meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp);
|
gboolean meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -419,13 +419,13 @@ typedef struct
|
|||||||
*/
|
*/
|
||||||
GSList *bindings;
|
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;
|
gboolean add_shift:1;
|
||||||
|
|
||||||
/* for keybindings that apply only to a window */
|
/** for keybindings that apply only to a window */
|
||||||
gboolean per_window:1;
|
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;
|
gboolean builtin:1;
|
||||||
} MetaKeyPref;
|
} MetaKeyPref;
|
||||||
|
|
||||||
|
@@ -150,7 +150,8 @@ void meta_window_unset_demands_attention (MetaWindow *window);
|
|||||||
const char* meta_window_get_startup_id (MetaWindow *window);
|
const char* meta_window_get_startup_id (MetaWindow *window);
|
||||||
void meta_window_change_workspace_by_index (MetaWindow *window,
|
void meta_window_change_workspace_by_index (MetaWindow *window,
|
||||||
gint space_index,
|
gint space_index,
|
||||||
gboolean append);
|
gboolean append,
|
||||||
|
guint32 timestamp);
|
||||||
void meta_window_change_workspace (MetaWindow *window,
|
void meta_window_change_workspace (MetaWindow *window,
|
||||||
MetaWorkspace *workspace);
|
MetaWorkspace *workspace);
|
||||||
GObject *meta_window_get_compositor_private (MetaWindow *window);
|
GObject *meta_window_get_compositor_private (MetaWindow *window);
|
||||||
|
@@ -106,11 +106,49 @@ create_anonymous_file (off_t size,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static void
|
||||||
meta_wayland_xkb_info_new_keymap (MetaWaylandXkbInfo *xkb_info)
|
inform_clients_of_new_keymap (MetaWaylandKeyboard *keyboard,
|
||||||
|
int flags)
|
||||||
{
|
{
|
||||||
|
MetaWaylandCompositor *compositor;
|
||||||
|
struct wl_client *xclient;
|
||||||
|
struct wl_resource *keyboard_resource;
|
||||||
|
|
||||||
|
compositor = meta_wayland_compositor_get_default ();
|
||||||
|
xclient = compositor->xwayland_client;
|
||||||
|
|
||||||
|
wl_resource_for_each (keyboard_resource, &keyboard->resource_list)
|
||||||
|
{
|
||||||
|
if ((flags & META_WAYLAND_KEYBOARD_SKIP_XCLIENTS) &&
|
||||||
|
wl_resource_get_client (keyboard_resource) == xclient)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wl_keyboard_send_keymap (keyboard_resource,
|
||||||
|
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
|
||||||
|
keyboard->xkb_info.keymap_fd,
|
||||||
|
keyboard->xkb_info.keymap_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
|
||||||
|
struct xkb_keymap *keymap,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
char *keymap_str;
|
char *keymap_str;
|
||||||
|
size_t previous_size;
|
||||||
|
|
||||||
|
if (keymap == NULL)
|
||||||
|
{
|
||||||
|
g_warning ("Attempting to set null keymap (compilation probably failed)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xkb_info->keymap)
|
||||||
|
xkb_keymap_unref (xkb_info->keymap);
|
||||||
|
xkb_info->keymap = keymap;
|
||||||
|
|
||||||
xkb_info->shift_mod =
|
xkb_info->shift_mod =
|
||||||
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_SHIFT);
|
xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_SHIFT);
|
||||||
@@ -129,21 +167,28 @@ meta_wayland_xkb_info_new_keymap (MetaWaylandXkbInfo *xkb_info)
|
|||||||
keymap_str = xkb_map_get_as_string (xkb_info->keymap);
|
keymap_str = xkb_map_get_as_string (xkb_info->keymap);
|
||||||
if (keymap_str == NULL)
|
if (keymap_str == NULL)
|
||||||
{
|
{
|
||||||
g_warning ("failed to get string version of keymap\n");
|
g_warning ("failed to get string version of keymap");
|
||||||
return FALSE;
|
return;
|
||||||
}
|
}
|
||||||
|
previous_size = xkb_info->keymap_size;
|
||||||
xkb_info->keymap_size = strlen (keymap_str) + 1;
|
xkb_info->keymap_size = strlen (keymap_str) + 1;
|
||||||
|
|
||||||
|
if (xkb_info->keymap_fd >= 0)
|
||||||
|
close (xkb_info->keymap_fd);
|
||||||
|
|
||||||
xkb_info->keymap_fd = create_anonymous_file (xkb_info->keymap_size, &error);
|
xkb_info->keymap_fd = create_anonymous_file (xkb_info->keymap_size, &error);
|
||||||
if (xkb_info->keymap_fd < 0)
|
if (xkb_info->keymap_fd < 0)
|
||||||
{
|
{
|
||||||
g_warning ("creating a keymap file for %lu bytes failed: %s\n",
|
g_warning ("creating a keymap file for %lu bytes failed: %s",
|
||||||
(unsigned long) xkb_info->keymap_size,
|
(unsigned long) xkb_info->keymap_size,
|
||||||
error->message);
|
error->message);
|
||||||
g_clear_error (&error);
|
g_clear_error (&error);
|
||||||
goto err_keymap_str;
|
goto err_keymap_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (xkb_info->keymap_area)
|
||||||
|
munmap (xkb_info->keymap_area, previous_size);
|
||||||
|
|
||||||
xkb_info->keymap_area = mmap (NULL, xkb_info->keymap_size,
|
xkb_info->keymap_area = mmap (NULL, xkb_info->keymap_size,
|
||||||
PROT_READ | PROT_WRITE,
|
PROT_READ | PROT_WRITE,
|
||||||
MAP_SHARED, xkb_info->keymap_fd, 0);
|
MAP_SHARED, xkb_info->keymap_fd, 0);
|
||||||
@@ -156,41 +201,24 @@ meta_wayland_xkb_info_new_keymap (MetaWaylandXkbInfo *xkb_info)
|
|||||||
strcpy (xkb_info->keymap_area, keymap_str);
|
strcpy (xkb_info->keymap_area, keymap_str);
|
||||||
free (keymap_str);
|
free (keymap_str);
|
||||||
|
|
||||||
return TRUE;
|
if (keyboard->is_evdev)
|
||||||
|
{
|
||||||
|
ClutterDeviceManager *manager;
|
||||||
|
|
||||||
|
manager = clutter_device_manager_get_default ();
|
||||||
|
clutter_evdev_set_keyboard_map (manager, xkb_info->keymap);
|
||||||
|
}
|
||||||
|
|
||||||
|
inform_clients_of_new_keymap (keyboard, flags);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
err_dev_zero:
|
err_dev_zero:
|
||||||
close (xkb_info->keymap_fd);
|
close (xkb_info->keymap_fd);
|
||||||
xkb_info->keymap_fd = -1;
|
xkb_info->keymap_fd = -1;
|
||||||
err_keymap_str:
|
err_keymap_str:
|
||||||
free (keymap_str);
|
free (keymap_str);
|
||||||
return FALSE;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
meta_wayland_keyboard_build_global_keymap (struct xkb_context *xkb_context,
|
|
||||||
struct xkb_rule_names *xkb_names,
|
|
||||||
MetaWaylandXkbInfo *xkb_info)
|
|
||||||
{
|
|
||||||
xkb_info->keymap = xkb_map_new_from_names (xkb_context,
|
|
||||||
xkb_names,
|
|
||||||
0 /* flags */);
|
|
||||||
if (xkb_info->keymap == NULL)
|
|
||||||
{
|
|
||||||
g_warning ("failed to compile global XKB keymap\n"
|
|
||||||
" tried rules %s, model %s, layout %s, variant %s, "
|
|
||||||
"options %s\n",
|
|
||||||
xkb_names->rules,
|
|
||||||
xkb_names->model,
|
|
||||||
xkb_names->layout,
|
|
||||||
xkb_names->variant,
|
|
||||||
xkb_names->options);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!meta_wayland_xkb_info_new_keymap (xkb_info))
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -306,9 +334,8 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
|||||||
struct wl_display *display,
|
struct wl_display *display,
|
||||||
gboolean is_evdev)
|
gboolean is_evdev)
|
||||||
{
|
{
|
||||||
ClutterDeviceManager *manager;
|
|
||||||
|
|
||||||
memset (keyboard, 0, sizeof *keyboard);
|
memset (keyboard, 0, sizeof *keyboard);
|
||||||
|
keyboard->xkb_info.keymap_fd = -1;
|
||||||
|
|
||||||
wl_list_init (&keyboard->resource_list);
|
wl_list_init (&keyboard->resource_list);
|
||||||
wl_array_init (&keyboard->keys);
|
wl_array_init (&keyboard->keys);
|
||||||
@@ -320,18 +347,15 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
|||||||
keyboard->display = display;
|
keyboard->display = display;
|
||||||
|
|
||||||
keyboard->xkb_context = xkb_context_new (0 /* flags */);
|
keyboard->xkb_context = xkb_context_new (0 /* flags */);
|
||||||
|
|
||||||
meta_wayland_keyboard_build_global_keymap (keyboard->xkb_context,
|
|
||||||
&keyboard->xkb_names,
|
|
||||||
&keyboard->xkb_info);
|
|
||||||
|
|
||||||
keyboard->is_evdev = is_evdev;
|
keyboard->is_evdev = is_evdev;
|
||||||
if (is_evdev)
|
|
||||||
{
|
|
||||||
manager = clutter_device_manager_get_default ();
|
|
||||||
|
|
||||||
clutter_evdev_set_keyboard_map (manager, keyboard->xkb_info.keymap);
|
/* Compute a default until gnome-settings-daemon starts and sets
|
||||||
}
|
the appropriate values
|
||||||
|
*/
|
||||||
|
meta_wayland_keyboard_set_keymap_names (keyboard,
|
||||||
|
"evdev",
|
||||||
|
"pc105",
|
||||||
|
"us", "", "", 0);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -388,6 +412,81 @@ set_modifiers (MetaWaylandKeyboard *keyboard,
|
|||||||
new_state.group);
|
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
|
static gboolean
|
||||||
update_pressed_keys (MetaWaylandKeyboard *keyboard,
|
update_pressed_keys (MetaWaylandKeyboard *keyboard,
|
||||||
uint32_t evdev_code,
|
uint32_t evdev_code,
|
||||||
@@ -460,6 +559,10 @@ meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
|
|||||||
autorepeat ? " (autorepeat)" : "",
|
autorepeat ? " (autorepeat)" : "",
|
||||||
xkb_keycode);
|
xkb_keycode);
|
||||||
|
|
||||||
|
/* Give a chance to process keybindings */
|
||||||
|
if (process_keybinding (keyboard, (ClutterEvent*) event))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
if (autorepeat)
|
if (autorepeat)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@@ -559,12 +662,6 @@ meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard)
|
|||||||
void
|
void
|
||||||
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
|
meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard)
|
||||||
{
|
{
|
||||||
g_free ((char *) keyboard->xkb_names.rules);
|
|
||||||
g_free ((char *) keyboard->xkb_names.model);
|
|
||||||
g_free ((char *) keyboard->xkb_names.layout);
|
|
||||||
g_free ((char *) keyboard->xkb_names.variant);
|
|
||||||
g_free ((char *) keyboard->xkb_names.options);
|
|
||||||
|
|
||||||
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
|
meta_wayland_xkb_info_destroy (&keyboard->xkb_info);
|
||||||
xkb_context_unref (keyboard->xkb_context);
|
xkb_context_unref (keyboard->xkb_context);
|
||||||
|
|
||||||
@@ -652,3 +749,28 @@ meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard,
|
|||||||
|
|
||||||
meta_verbose ("Released modal keyboard grab, timestamp %d\n", timestamp);
|
meta_verbose ("Released modal keyboard grab, timestamp %d\n", timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_keyboard_set_keymap_names (MetaWaylandKeyboard *keyboard,
|
||||||
|
const char *rules,
|
||||||
|
const char *model,
|
||||||
|
const char *layout,
|
||||||
|
const char *variant,
|
||||||
|
const char *options,
|
||||||
|
int flags)
|
||||||
|
{
|
||||||
|
struct xkb_rule_names xkb_names;
|
||||||
|
|
||||||
|
xkb_names.rules = rules;
|
||||||
|
xkb_names.model = model;
|
||||||
|
xkb_names.layout = layout;
|
||||||
|
xkb_names.variant = variant;
|
||||||
|
xkb_names.options = options;
|
||||||
|
|
||||||
|
meta_wayland_keyboard_take_keymap (keyboard,
|
||||||
|
xkb_keymap_new_from_names (keyboard->xkb_context,
|
||||||
|
&xkb_names,
|
||||||
|
0 /* flags */),
|
||||||
|
flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -112,7 +112,6 @@ struct _MetaWaylandKeyboard
|
|||||||
struct xkb_context *xkb_context;
|
struct xkb_context *xkb_context;
|
||||||
gboolean is_evdev;
|
gboolean is_evdev;
|
||||||
MetaWaylandXkbInfo xkb_info;
|
MetaWaylandXkbInfo xkb_info;
|
||||||
struct xkb_rule_names xkb_names;
|
|
||||||
|
|
||||||
MetaWaylandKeyboardGrab input_method_grab;
|
MetaWaylandKeyboardGrab input_method_grab;
|
||||||
struct wl_resource *input_method_resource;
|
struct wl_resource *input_method_resource;
|
||||||
@@ -123,6 +122,18 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard,
|
|||||||
struct wl_display *display,
|
struct wl_display *display,
|
||||||
gboolean is_evdev);
|
gboolean is_evdev);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
META_WAYLAND_KEYBOARD_SKIP_XCLIENTS = 1,
|
||||||
|
} MetaWaylandKeyboardSetKeymapFlags;
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_keyboard_set_keymap_names (MetaWaylandKeyboard *keyboard,
|
||||||
|
const char *rules,
|
||||||
|
const char *model,
|
||||||
|
const char *layout,
|
||||||
|
const char *variant,
|
||||||
|
const char *options,
|
||||||
|
int flags);
|
||||||
gboolean
|
gboolean
|
||||||
meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
|
meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard,
|
||||||
const ClutterKeyEvent *event);
|
const ClutterKeyEvent *event);
|
||||||
|
@@ -49,6 +49,7 @@
|
|||||||
|
|
||||||
#include "meta-wayland-pointer.h"
|
#include "meta-wayland-pointer.h"
|
||||||
#include "meta-wayland-private.h"
|
#include "meta-wayland-private.h"
|
||||||
|
#include "barrier-private.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
@@ -165,10 +166,10 @@ static const MetaWaylandPointerGrabInterface default_pointer_grab_interface = {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
check_all_screen_monitors(MetaMonitorInfo *monitors,
|
check_all_screen_monitors (MetaMonitorInfo *monitors,
|
||||||
unsigned n_monitors,
|
unsigned n_monitors,
|
||||||
float x,
|
float x,
|
||||||
float y)
|
float y)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
@@ -193,14 +194,13 @@ static void
|
|||||||
constrain_all_screen_monitors (ClutterInputDevice *device,
|
constrain_all_screen_monitors (ClutterInputDevice *device,
|
||||||
MetaMonitorInfo *monitors,
|
MetaMonitorInfo *monitors,
|
||||||
unsigned n_monitors,
|
unsigned n_monitors,
|
||||||
|
float current_x,
|
||||||
|
float current_y,
|
||||||
float *x,
|
float *x,
|
||||||
float *y)
|
float *y)
|
||||||
{
|
{
|
||||||
ClutterPoint current;
|
|
||||||
unsigned int i;
|
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 */
|
/* if we're trying to escape, clamp to the CRTC we're coming from */
|
||||||
for (i = 0; i < n_monitors; i++)
|
for (i = 0; i < n_monitors; i++)
|
||||||
{
|
{
|
||||||
@@ -213,8 +213,8 @@ constrain_all_screen_monitors (ClutterInputDevice *device,
|
|||||||
top = monitor->rect.y;
|
top = monitor->rect.y;
|
||||||
bottom = left + monitor->rect.height;
|
bottom = left + monitor->rect.height;
|
||||||
|
|
||||||
nx = current.x;
|
nx = current_x;
|
||||||
ny = current.y;
|
ny = current_y;
|
||||||
|
|
||||||
if ((nx >= left) && (nx < right) && (ny >= top) && (ny < bottom))
|
if ((nx >= left) && (nx < right) && (ny >= top) && (ny < bottom))
|
||||||
{
|
{
|
||||||
@@ -239,21 +239,32 @@ pointer_constrain_callback (ClutterInputDevice *device,
|
|||||||
float *new_y,
|
float *new_y,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
|
MetaBarrierManager *barrier_manager;
|
||||||
MetaMonitorManager *monitor_manager;
|
MetaMonitorManager *monitor_manager;
|
||||||
MetaMonitorInfo *monitors;
|
MetaMonitorInfo *monitors;
|
||||||
unsigned int n_monitors;
|
unsigned int n_monitors;
|
||||||
gboolean ret;
|
gboolean ret;
|
||||||
|
ClutterPoint current;
|
||||||
|
|
||||||
|
clutter_input_device_get_coords (device, NULL, ¤t);
|
||||||
|
|
||||||
|
barrier_manager = meta_barrier_manager_get ();
|
||||||
monitor_manager = meta_monitor_manager_get ();
|
monitor_manager = meta_monitor_manager_get ();
|
||||||
monitors = meta_monitor_manager_get_monitor_infos (monitor_manager, &n_monitors);
|
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 */
|
/* if we're moving inside a monitor, we're fine */
|
||||||
ret = check_all_screen_monitors(monitors, n_monitors, *new_x, *new_y);
|
ret = check_all_screen_monitors(monitors, n_monitors, *new_x, *new_y);
|
||||||
if (ret == TRUE)
|
if (ret)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* if we're trying to escape, clamp to the CRTC we're coming from */
|
/* if we're trying to escape, clamp to the CRTC we're coming from */
|
||||||
constrain_all_screen_monitors(device, monitors, n_monitors, new_x, new_y);
|
constrain_all_screen_monitors(device, monitors, n_monitors,
|
||||||
|
current.x, current.y,
|
||||||
|
new_x, new_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -385,6 +396,32 @@ meta_wayland_pointer_end_grab (MetaWaylandPointer *pointer)
|
|||||||
interface->focus (pointer->grab, pointer->current, NULL);
|
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
|
static void
|
||||||
modal_focus (MetaWaylandPointerGrab *grab,
|
modal_focus (MetaWaylandPointerGrab *grab,
|
||||||
MetaWaylandSurface *surface,
|
MetaWaylandSurface *surface,
|
||||||
|
@@ -62,6 +62,7 @@ struct _MetaWaylandPointer
|
|||||||
|
|
||||||
wl_fixed_t x, y; /* TODO: remove, use ClutterInputDevice instead */
|
wl_fixed_t x, y; /* TODO: remove, use ClutterInputDevice instead */
|
||||||
MetaWaylandSurface *current;
|
MetaWaylandSurface *current;
|
||||||
|
struct wl_listener current_listener;
|
||||||
wl_fixed_t current_x, current_y;
|
wl_fixed_t current_x, current_y;
|
||||||
|
|
||||||
guint32 button_count;
|
guint32 button_count;
|
||||||
@@ -96,6 +97,10 @@ gboolean
|
|||||||
meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
meta_wayland_pointer_start_popup_grab (MetaWaylandPointer *pointer,
|
||||||
MetaWaylandSurface *popup);
|
MetaWaylandSurface *popup);
|
||||||
|
|
||||||
|
void
|
||||||
|
meta_wayland_pointer_set_current (MetaWaylandPointer *pointer,
|
||||||
|
MetaWaylandSurface *surface);
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
|
meta_wayland_pointer_get_relative_coordinates (MetaWaylandPointer *pointer,
|
||||||
MetaWaylandSurface *surface,
|
MetaWaylandSurface *surface,
|
||||||
|
@@ -697,12 +697,7 @@ event_cb (ClutterActor *stage,
|
|||||||
|
|
||||||
if (surface && surface->window &&
|
if (surface && surface->window &&
|
||||||
surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
|
||||||
{
|
meta_window_focus (surface->window, clutter_event_get_time (event));
|
||||||
MetaDisplay *display = meta_get_display ();
|
|
||||||
guint32 timestamp = meta_display_get_current_time_roundtrip (display);
|
|
||||||
|
|
||||||
meta_window_focus (surface->window, timestamp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seat->cursor_tracker)
|
if (seat->cursor_tracker)
|
||||||
|
Reference in New Issue
Block a user