Compare commits

...

21 Commits

Author SHA1 Message Date
Rui Matos
3ac563307e debug output 2014-06-04 10:52:56 +02:00
Rui Matos
24956fadcc MetaSyncRing: disable after a number of reboot attempts
If we have had to reboot this number of times, something is definitely
wrong and we're likely to just make things worse by continuing to try.

Let's err on the side of caution, disable ourselves and fallback to
the XSync() path in the compositor.

https://bugzilla.gnome.org/show_bug.cgi?id=728464
2014-06-02 16:27:28 +02:00
Rui Matos
fc5de438b5 compositor: Add support for GL_EXT_x11_sync_object
If GL advertises this extension we'll use it to synchronize X with GL
rendering instead of relying on the XSync() behavior with open source
drivers.

https://bugzilla.gnome.org/show_bug.cgi?id=728464
2014-06-02 16:27:28 +02:00
Rui Matos
94cee3ef09 display: Add public getters for sync extension presence and event base
https://bugzilla.gnome.org/show_bug.cgi?id=728464
2014-06-02 16:27:28 +02:00
Rui Matos
1e6b042778 compositor: Sync X drawing only once per frame
We only need to call XSync() once per frame to synchronize X with GL
drawing.

https://bugzilla.gnome.org/show_bug.cgi?id=728464
2014-06-02 16:27:28 +02:00
Jonas Ådahl
048f035d30 wayland: Scale smooth scroll events to pointer motion coordinate space
Smooth scroll event vectors from clutter have the same dimensions as the
ones from from Xi2, i.e. where 1.0 is 1 discrete scroll step. To scale
these to the coordinate space used by wl_pointer.axis
vertical/horizontal scroll events, multiply the vector by 10.

https://bugzilla.gnome.org/show_bug.cgi?id=729601
2014-05-31 14:22:10 +02:00
Jasper St. Pierre
b32c837df9 window: Fix placement not actually placing windows
Since we often call meta_window_move_resize_now immediately after
mapping a window, we need to make sure that the placed coordinates
are saved in the unconstrained_rect. Ideally, placement positions
wouldn't be part of the constraints system, but instead are just
done inside meta_window_move_resize_internal as part of a special
path.

We're still working out the kinks of one large-scale refactor, so
it's best not to do another one while the first is going on. This
would be a great future cleanup, though: untangling constraints
and placement, alongside the force_placement state machine and
friends.
2014-05-29 14:09:57 -04:00
Jasper St. Pierre
dd03a76d51 place: Reindent 2014-05-29 13:58:08 -04:00
Jasper St. Pierre
806a666950 Make the native backend build-optional 2014-05-29 12:43:08 -04:00
Jasper St. Pierre
b240a5e819 keybindings: Only add VT keybindings if we're using the native backend 2014-05-29 12:43:07 -04:00
Jasper St. Pierre
fe823b3553 events: Improve check for native backend 2014-05-29 12:43:07 -04:00
Florian Müllner
d380d30ef4 Update (allow-none) annotations
The annotation has been deprecated in favor of (nullable) and/or
(optional).
2014-05-28 21:55:03 +02:00
Jasper St. Pierre
1fe5b3e7d5 window: Construct the frame before the initial move_resize
This ensures sure that the initial ConfigureRequest we make is
correct.
2014-05-28 11:47:14 -04:00
Jasper St. Pierre
a8df208a5c window-x11: Keep flags where they're used
Just a simple code cleanup
2014-05-28 11:43:11 -04:00
Jasper St. Pierre
f3f3c94831 frame: Don't reset window->rect 2014-05-28 10:50:23 -04:00
Jasper St. Pierre
6e06648f7a window: Refactor all move/resize operations to be in frame rect space
For Wayland, we want to have everything possible in terms of the frame
rect, or "window geometry" as the Wayland protocol calls it, in order
to properly eliminate some flashing when changing states to fullscreen
or similar.

For this, we need to heavily refactor how the code is structured, and
make it so that meta_window_move_resize_internal is specified in terms
of the frame rect coordinate space, and transforming all entry points
to meta_window_move_resize_internal.

This is a big commit that's hard to tear apart. I tried to split it
as best I can, but there's still just a large amount of changes that
need to happen at once.

Expect some regressions from this. Sorry for any temporary regression
that this might cause.
2014-05-27 15:44:34 -04:00
Jasper St. Pierre
afb41f715b core: Make META_CORE_GET_FRAME_RECT return the "frame rect"
We have two different coordinate spaces here. One is the rectangle
returned by meta_window_get_frame_rect, which is called the "frame
rect" or "the window geometry", which includes visible frame borders
but not invisible frame borders. The other is "frame->rect" which
corresponds to the frame's server geometry. That is, it includes
both visible and invisible frame borders.

These two were of course the same until we introduced invisible
frame borders, and an executive decision was made to make
meta_window_get_frame_rect return the rectangle bounding the
visible portions of the frame.

As time went on, the "frame rect" turned out to be more useful when
making decisions upon, since the user often doesn't think about the
invisible window geometry as part of the window.

We already calculate what amounts to the "frame rect" in the theme
code, so just change META_CORE_GET_FRAME_RECT to consume that
directly.
2014-05-27 15:44:33 -04:00
Jasper St. Pierre
19d26dde92 core: Convert GET_FRAME_WIDTH / GET_FRAME_HEIGHT to GET_FRAME_RECT
Since we're going to be calling meta_window_get_frame_rect in here
soon, I'd rather it be one method call, rather than two. We can't
put it at the toplevel, since that might cause infinite recursion
(e.g. meta_core_get calls meta_window_get_frame_rect calls
meta_ui_get_frame_borders calls meta_core_get, ...)
2014-05-27 15:44:33 -04:00
Jasper St. Pierre
4acb902423 window: Correct the anchoring of drag moving / resizing
Now that meta_window_move_resize and friends act in frame rect
coordinates, we need to convert the initial grab_anchor_window_pos
storage to be in frame rect coordinates as well.
2014-05-27 15:44:33 -04:00
Jasper St. Pierre
626516d12e window: Remove meta_window_move as well
Move to meta_window_move_frame everywhere...
2014-05-27 15:44:33 -04:00
Jasper St. Pierre
1c94df2553 window: Replace meta_window_resize_with_gravity with a frame-rect variant
More low-hanging fruit for our window geometry cleanups...
2014-05-27 15:44:33 -04:00
32 changed files with 1101 additions and 539 deletions

View File

@@ -199,9 +199,15 @@ AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
AC_SUBST([WAYLAND_SCANNER])
AC_SUBST(XWAYLAND_PATH)
MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 wayland-server >= 1.4.93 libdrm libsystemd"
MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 wayland-server >= 1.4.93"
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
PKG_CHECK_MODULES(MUTTER_NATIVE_BACKEND, [libdrm libsystemd], [have_native_backend=yes], [have_native_backend=no])
if test $have_native_backend = yes; then
AC_DEFINE([HAVE_NATIVE_BACKEND],[1],[Define if you want to enable the native (KMS) backend based on systemd])
fi
AM_CONDITIONAL([HAVE_NATIVE_BACKEND],[test $have_native_backend = yes])
PKG_CHECK_EXISTS([xi >= 1.6.99.1],
AC_DEFINE([HAVE_XI23],[1],[Define if you have support for XInput 2.3 or greater]))
@@ -318,6 +324,11 @@ fi
GTK_DOC_CHECK([1.15], [--flavour no-tmpl])
AC_CHECK_DECL([GL_EXT_x11_sync_object],
[],
[AC_MSG_ERROR([GL_EXT_x11_sync_object definition not found, please update your GL headers])],
[#include <GL/glx.h>])
#### Warnings (last since -Werror can disturb other tests)
# Stay command-line compatible with the gnome-common configure option. Here

View File

@@ -11,6 +11,7 @@ INCLUDES= \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
$(MUTTER_CFLAGS) \
$(MUTTER_NATIVE_BACKEND_CFLAGS) \
-I$(srcdir) \
-I$(srcdir)/backends \
-I$(srcdir)/core \
@@ -71,18 +72,6 @@ libmutter_la_SOURCES = \
backends/meta-monitor-manager-dummy.h \
backends/edid-parse.c \
backends/edid.h \
backends/native/meta-backend-native.c \
backends/native/meta-backend-native.h \
backends/native/meta-cursor-renderer-native.c \
backends/native/meta-cursor-renderer-native.h \
backends/native/meta-idle-monitor-native.c \
backends/native/meta-idle-monitor-native.h \
backends/native/meta-monitor-manager-kms.c \
backends/native/meta-monitor-manager-kms.h \
backends/native/meta-launcher.c \
backends/native/meta-launcher.h \
backends/native/dbus-utils.c \
backends/native/dbus-utils.h \
backends/x11/meta-backend-x11.c \
backends/x11/meta-backend-x11.h \
backends/x11/meta-cursor-renderer-x11.c \
@@ -129,6 +118,8 @@ libmutter_la_SOURCES = \
compositor/meta-surface-actor-wayland.h \
compositor/meta-stage.h \
compositor/meta-stage.c \
compositor/meta-sync-ring.c \
compositor/meta-sync-ring.h \
compositor/meta-texture-rectangle.c \
compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \
@@ -243,11 +234,27 @@ libmutter_la_SOURCES = \
wayland/window-wayland.c \
wayland/window-wayland.h
if HAVE_NATIVE_BACKEND
libmutter_la_SOURCES += \
backends/native/meta-backend-native.c \
backends/native/meta-backend-native.h \
backends/native/meta-cursor-renderer-native.c \
backends/native/meta-cursor-renderer-native.h \
backends/native/meta-idle-monitor-native.c \
backends/native/meta-idle-monitor-native.h \
backends/native/meta-monitor-manager-kms.c \
backends/native/meta-monitor-manager-kms.h \
backends/native/meta-launcher.c \
backends/native/meta-launcher.h \
backends/native/dbus-utils.c \
backends/native/dbus-utils.h
endif
nodist_libmutter_la_SOURCES = \
$(mutter_built_sources)
libmutter_la_LDFLAGS = -no-undefined
libmutter_la_LIBADD = $(MUTTER_LIBS)
libmutter_la_LIBADD = $(MUTTER_LIBS) $(MUTTER_NATIVE_BACKEND_LIBS)
# Headers installed for plugins; introspected information will
# be extracted into Mutter-<version>.gir

View File

@@ -30,7 +30,10 @@
#include <clutter/clutter.h>
#include "backends/x11/meta-backend-x11.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
#endif
static MetaBackend *_backend;
@@ -214,7 +217,7 @@ get_backend_type (void)
return META_TYPE_BACKEND_X11;
#endif
#if defined(CLUTTER_WINDOWING_EGL)
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_EGL))
return META_TYPE_BACKEND_NATIVE;
#endif

View File

@@ -28,7 +28,10 @@
#include "display-private.h"
#include "screen-private.h"
#include "meta-backend.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-cursor-renderer-native.h"
#endif
#include <string.h>
@@ -171,13 +174,15 @@ meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
static struct gbm_device *
get_gbm_device (void)
{
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *meta_backend = meta_get_backend ();
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
else
return NULL;
#endif
return NULL;
}
static void

View File

@@ -210,9 +210,9 @@ make_watch (MetaIdleMonitor *monitor,
* meta_idle_monitor_add_idle_watch:
* @monitor: A #MetaIdleMonitor
* @interval_msec: The idletime interval, in milliseconds
* @callback: (allow-none): The callback to call when the user has
* @callback: (nullable): The callback to call when the user has
* accumulated @interval_msec milliseconds of idle time.
* @user_data: (allow-none): The user data to pass to the callback
* @user_data: (nullable): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id
@@ -252,9 +252,9 @@ meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
/**
* meta_idle_monitor_add_user_active_watch:
* @monitor: A #MetaIdleMonitor
* @callback: (allow-none): The callback to call when the user is
* @callback: (nullable): The callback to call when the user is
* active again.
* @user_data: (allow-none): The user data to pass to the callback
* @user_data: (nullable): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id

View File

@@ -68,7 +68,7 @@ meta_create_color_texture_4ub (guint8 red,
/**
* meta_create_texture_pipeline:
* @src_texture: (allow-none): texture to use initially for the layer
* @src_texture: (nullable): texture to use initially for the layer
*
* Creates a pipeline with a single layer. Using a common template
* makes it easier for Cogl to share a shader for different uses in

View File

@@ -15,7 +15,8 @@ struct _MetaCompositor
{
MetaDisplay *display;
guint repaint_func_id;
guint pre_paint_func_id;
guint post_paint_func_id;
gint64 server_time_query_time;
gint64 server_time_offset;
@@ -38,6 +39,9 @@ struct _MetaCompositor
gint switch_workspace_in_progress;
MetaPluginManager *plugin_mgr;
gboolean frame_has_updated_xsurfaces;
gboolean have_x11_sync_object;
};
/* Wait 2ms after vblank before starting to draw next frame */

View File

@@ -79,6 +79,7 @@
#include "frame.h"
#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
#include "meta-sync-ring.h"
#include "backends/meta-backend.h"
#include "backends/x11/meta-backend-x11.h"
@@ -136,7 +137,11 @@ meta_switch_workspace_completed (MetaCompositor *compositor)
void
meta_compositor_destroy (MetaCompositor *compositor)
{
clutter_threads_remove_repaint_func (compositor->repaint_func_id);
clutter_threads_remove_repaint_func (compositor->pre_paint_func_id);
clutter_threads_remove_repaint_func (compositor->post_paint_func_id);
if (compositor->have_x11_sync_object)
meta_sync_ring_destroy ();
}
static void
@@ -146,6 +151,8 @@ process_damage (MetaCompositor *compositor,
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_process_x11_damage (window_actor, event);
compositor->frame_has_updated_xsurfaces = TRUE;
}
static Window
@@ -569,6 +576,8 @@ meta_compositor_manage (MetaCompositor *compositor)
* contents until we show the stage.
*/
XMapWindow (xdisplay, compositor->output);
compositor->have_x11_sync_object = meta_sync_ring_init (display);
}
redirect_windows (display->screen);
@@ -595,7 +604,7 @@ meta_compositor_unmanage (MetaCompositor *compositor)
/**
* meta_shape_cow_for_window:
* @compositor: A #MetaCompositor
* @window: (allow-none): A #MetaWindow to shape the COW for
* @window: (nullable): A #MetaWindow to shape the COW for
*
* Sets an bounding shape on the COW so that the given window
* is exposed. If @window is %NULL it clears the shape again.
@@ -780,6 +789,10 @@ meta_compositor_process_event (MetaCompositor *compositor,
if (!meta_is_wayland_compositor () && event->type == MapNotify)
clutter_x11_handle_event (event);
if (compositor->have_x11_sync_object &&
event->type == (compositor->display->xsync_event_base + XSyncAlarmNotify))
meta_sync_ring_handle_event ((XSyncAlarmNotifyEvent *) event);
/* The above handling is basically just "observing" the events, so we return
* FALSE to indicate that the event should not be filtered out; if we have
* GTK+ windows in the same process, GTK+ needs the ConfigureNotify event, for example.
@@ -1125,11 +1138,12 @@ frame_callback (CoglOnscreen *onscreen,
}
}
static void
pre_paint_windows (MetaCompositor *compositor)
static gboolean
meta_pre_paint_func (gpointer data)
{
GList *l;
MetaWindowActor *top_window;
MetaCompositor *compositor = data;
if (compositor->onscreen == NULL)
{
@@ -1141,7 +1155,7 @@ pre_paint_windows (MetaCompositor *compositor)
}
if (compositor->windows == NULL)
return;
return TRUE;
top_window = g_list_last (compositor->windows)->data;
@@ -1153,13 +1167,53 @@ pre_paint_windows (MetaCompositor *compositor)
for (l = compositor->windows; l; l = l->next)
meta_window_actor_pre_paint (l->data);
if (compositor->frame_has_updated_xsurfaces)
{
/* We need to make sure that any X drawing that happens before
* the XDamageSubtract() for each window above is visible to
* subsequent GL rendering; the standardized way to do this is
* GL_EXT_X11_sync_object. Since this isn't implemented yet in
* mesa, we also have a path that relies on the implementation
* of the open source drivers.
*
* Anything else, we just hope for the best.
*
* Xorg and open source driver specifics:
*
* The X server makes sure to flush drawing to the kernel before
* sending out damage events, but since we use
* DamageReportBoundingBox there may be drawing between the last
* damage event and the XDamageSubtract() that needs to be
* flushed as well.
*
* Xorg always makes sure that drawing is flushed to the kernel
* before writing events or responses to the client, so any
* round trip request at this point is sufficient to flush the
* GLX buffers.
*/
if (compositor->have_x11_sync_object)
compositor->have_x11_sync_object = meta_sync_ring_insert_wait ();
else
XSync (compositor->display->xdisplay, False);
}
return TRUE;
}
static gboolean
meta_repaint_func (gpointer data)
meta_post_paint_func (gpointer data)
{
MetaCompositor *compositor = data;
pre_paint_windows (compositor);
if (compositor->frame_has_updated_xsurfaces)
{
if (compositor->have_x11_sync_object)
compositor->have_x11_sync_object = meta_sync_ring_after_frame ();
compositor->frame_has_updated_xsurfaces = FALSE;
}
return TRUE;
}
@@ -1198,10 +1252,16 @@ meta_compositor_new (MetaDisplay *display)
G_CALLBACK (on_shadow_factory_changed),
compositor);
compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
compositor,
NULL);
compositor->pre_paint_func_id =
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_PRE_PAINT,
meta_pre_paint_func,
compositor,
NULL);
compositor->post_paint_func_id =
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
meta_post_paint_func,
compositor,
NULL);
return compositor;
}

View File

@@ -189,7 +189,7 @@ meta_shadow_unref (MetaShadow *shadow)
* @window_y: y position of the region to paint a shadow for
* @window_width: actual width of the region to paint a shadow for
* @window_height: actual height of the region to paint a shadow for
* @clip: (allow-none): if non-%NULL specifies the visible portion
* @clip: (nullable): if non-%NULL specifies the visible portion
* of the shadow.
* @clip_strictly: if %TRUE, drawing will be clipped strictly
* to @clip, otherwise, it will be only used to optimize

View File

@@ -238,26 +238,6 @@ meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
XDamageSubtract (xdisplay, priv->damage, None, None);
meta_error_trap_pop (display);
/* We need to make sure that any X drawing that happens before the
* XDamageSubtract() above is visible to subsequent GL rendering;
* the only standardized way to do this is EXT_x11_sync_object,
* which isn't yet widely available. For now, we count on details
* of Xorg and the open source drivers, and hope for the best
* otherwise.
*
* Xorg and open source driver specifics:
*
* The X server makes sure to flush drawing to the kernel before
* sending out damage events, but since we use DamageReportBoundingBox
* there may be drawing between the last damage event and the
* XDamageSubtract() that needs to be flushed as well.
*
* Xorg always makes sure that drawing is flushed to the kernel
* before writing events or responses to the client, so any round trip
* request at this point is sufficient to flush the GLX buffers.
*/
XSync (xdisplay, False);
priv->received_damage = FALSE;
}

View File

@@ -0,0 +1,574 @@
/*
* This is based on an original C++ implementation for compiz that
* carries the following copyright notice:
*
*
* Copyright © 2011 NVIDIA Corporation
*
* Permission to use, copy, modify, distribute, and sell this software
* and its documentation for any purpose is hereby granted without
* fee, provided that the above copyright notice appear in all copies
* and that both that copyright notice and this permission notice
* appear in supporting documentation, and that the name of NVIDIA
* Corporation not be used in advertising or publicity pertaining to
* distribution of the software without specific, written prior
* permission. NVIDIA Corporation makes no representations about the
* suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* NVIDIA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
* SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS, IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
* SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
* AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* SOFTWARE.
*
* Authors: James Jones <jajones@nvidia.com>
*/
#include <string.h>
#include <GL/gl.h>
#include <GL/glx.h>
#include <cogl/cogl.h>
#include <meta/display.h>
#include <meta/util.h>
#include "meta-sync-ring.h"
/* Theory of operation:
*
* We use a ring of NUM_SYNCS fence objects. On each frame we advance
* to the next fence in the ring. For each fence we do:
*
* 1. fence is XSyncTriggerFence()'d and glWaitSync()'d
* 2. NUM_SYNCS / 2 frames later, fence should be triggered
* 3. fence is XSyncResetFence()'d
* 4. NUM_SYNCS / 2 frames later, fence should be reset
* 5. go back to 1 and re-use fence
*
* glClientWaitSync() and XAlarms are used in steps 2 and 4,
* respectively, to double-check the expectections.
*/
#define NUM_SYNCS 10
#define MAX_SYNC_WAIT_TIME (1 * 1000 * 1000 * 1000) /* one sec */
#define MAX_REBOOT_ATTEMPTS 2
typedef enum
{
META_SYNC_STATE_READY,
META_SYNC_STATE_WAITING,
META_SYNC_STATE_DONE,
META_SYNC_STATE_RESET_PENDING,
} MetaSyncState;
typedef struct
{
Display *xdisplay;
XSyncFence xfence;
GLsync glsync;
XSyncCounter xcounter;
XSyncAlarm xalarm;
XSyncValue next_counter_value;
MetaSyncState state;
} MetaSync;
typedef struct
{
MetaDisplay *display;
GHashTable *alarm_to_sync;
MetaSync *syncs_array[NUM_SYNCS];
guint current_sync_idx;
MetaSync *current_sync;
guint warmup_syncs;
guint reboots;
} MetaSyncRing;
static MetaSyncRing meta_sync_ring = { 0 };
static XSyncValue SYNC_VALUE_ZERO;
static XSyncValue SYNC_VALUE_ONE;
static void (*meta_gl_get_integerv) (GLenum pname,
GLint *params);
static const char* (*meta_gl_get_stringi) (GLenum name,
GLuint index);
static void (*meta_gl_delete_sync) (GLsync sync);
static GLenum (*meta_gl_client_wait_sync) (GLsync sync,
GLbitfield flags,
GLuint64 timeout);
static void (*meta_gl_wait_sync) (GLsync sync,
GLbitfield flags,
GLuint64 timeout);
static GLsync (*meta_gl_import_sync) (GLenum external_sync_type,
GLintptr external_sync,
GLbitfield flags);
static GLenum (*meta_gl_get_error) (void);
static GLboolean (*meta_gl_is_sync) (GLsync sync);
static MetaSyncRing *
meta_sync_ring_get (void)
{
if (meta_sync_ring.reboots > MAX_REBOOT_ATTEMPTS)
return NULL;
return &meta_sync_ring;
}
static gboolean
load_gl_symbol (const char *name,
void **func)
{
*func = cogl_get_proc_address (name);
if (!*func)
{
meta_verbose ("MetaSyncRing: failed to resolve required GL symbol \"%s\"\n", name);
return FALSE;
}
return TRUE;
}
static gboolean
check_gl_extensions (void)
{
int num_extensions, i;
gboolean sync = FALSE;
gboolean x11_sync_object = FALSE;
meta_gl_get_integerv (GL_NUM_EXTENSIONS, &num_extensions);
for (i = 0; i < num_extensions; ++i)
{
const char *ext = meta_gl_get_stringi (GL_EXTENSIONS, i);
if (g_strcmp0 ("GL_ARB_sync", ext) == 0)
sync = TRUE;
else if (g_strcmp0 ("GL_EXT_x11_sync_object", ext) == 0)
x11_sync_object = TRUE;
}
return sync && x11_sync_object;
}
static gboolean
load_required_symbols (void)
{
static gboolean success = FALSE;
if (success)
return TRUE;
/* We don't link against libGL directly because cogl may want to
* use something else. This assumes that cogl has been initialized
* and dynamically loaded libGL at this point.
*/
if (!load_gl_symbol ("glGetIntegerv", (void **) &meta_gl_get_integerv))
goto out;
if (!load_gl_symbol ("glGetStringi", (void **) &meta_gl_get_stringi))
goto out;
if (!check_gl_extensions ())
{
meta_verbose ("MetaSyncRing: couldn't find required GL extensions\n");
goto out;
}
if (!load_gl_symbol ("glDeleteSync", (void **) &meta_gl_delete_sync))
goto out;
if (!load_gl_symbol ("glClientWaitSync", (void **) &meta_gl_client_wait_sync))
goto out;
if (!load_gl_symbol ("glWaitSync", (void **) &meta_gl_wait_sync))
goto out;
if (!load_gl_symbol ("glImportSyncEXT", (void **) &meta_gl_import_sync))
goto out;
if (!load_gl_symbol ("glGetError", (void **) &meta_gl_get_error))
goto out;
if (!load_gl_symbol ("glIsSync", (void **) &meta_gl_is_sync))
goto out;
success = TRUE;
out:
return success;
}
static void
print_gl_error (void)
{
GLenum e;
switch (e = meta_gl_get_error ())
{
case GL_NO_ERROR:
meta_warning ("GL_NO_ERROR\n");
break;
case GL_INVALID_ENUM:
meta_warning ("GL_INVALID_ENUM\n");
break;
case GL_INVALID_VALUE:
meta_warning ("GL_INVALID_VALUE\n");
break;
case GL_INVALID_OPERATION:
meta_warning ("GL_INVALID_OPERATION\n");
break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
meta_warning ("GL_INVALID_FRAMEBUFFER_OPERATION\n");
break;
case GL_OUT_OF_MEMORY:
meta_warning ("GL_OUT_OF_MEMORY\n");
break;
case GL_STACK_OVERFLOW:
meta_warning ("GL_STACK_OVERFLOW\n");
break;
case GL_STACK_UNDERFLOW:
meta_warning ("GL_STACK_UNDERFLOW\n");
break;
default:
meta_warning ("GL error 0x%x\n", e);
break;
}
}
static void
meta_sync_insert (MetaSync *self)
{
g_return_if_fail (self->state == META_SYNC_STATE_READY);
XSyncTriggerFence (self->xdisplay, self->xfence);
XFlush (self->xdisplay);
meta_gl_wait_sync (self->glsync, 0, GL_TIMEOUT_IGNORED);
self->state = META_SYNC_STATE_WAITING;
}
static GLenum
meta_sync_check_update_finished (MetaSync *self,
GLuint64 timeout)
{
GLenum status = GL_WAIT_FAILED;
switch (self->state)
{
case META_SYNC_STATE_DONE:
status = GL_ALREADY_SIGNALED;
break;
case META_SYNC_STATE_WAITING:
status = meta_gl_client_wait_sync (self->glsync, 0, timeout);
if (status == GL_ALREADY_SIGNALED || status == GL_CONDITION_SATISFIED)
self->state = META_SYNC_STATE_DONE;
break;
default:
break;
}
g_warn_if_fail (status != GL_WAIT_FAILED);
return status;
}
static void
meta_sync_reset (MetaSync *self)
{
XSyncAlarmAttributes attrs;
int overflow;
g_return_if_fail (self->state == META_SYNC_STATE_DONE);
XSyncResetFence (self->xdisplay, self->xfence);
attrs.trigger.wait_value = self->next_counter_value;
XSyncChangeAlarm (self->xdisplay, self->xalarm, XSyncCAValue, &attrs);
XSyncSetCounter (self->xdisplay, self->xcounter, self->next_counter_value);
XSyncValueAdd (&self->next_counter_value,
self->next_counter_value,
SYNC_VALUE_ONE,
&overflow);
self->state = META_SYNC_STATE_RESET_PENDING;
}
static void
meta_sync_handle_event (MetaSync *self,
XSyncAlarmNotifyEvent *event)
{
g_return_if_fail (event->alarm == self->xalarm);
g_return_if_fail (self->state == META_SYNC_STATE_RESET_PENDING);
self->state = META_SYNC_STATE_READY;
}
static MetaSync *
meta_sync_new (Display *xdisplay)
{
MetaSync *self;
XSyncAlarmAttributes attrs;
self = g_malloc0 (sizeof (MetaSync));
self->xdisplay = xdisplay;
self->xfence = XSyncCreateFence (xdisplay, DefaultRootWindow (xdisplay), FALSE);
meta_warning ("created X fence 0x%x\n", self->xfence);
self->glsync = meta_gl_import_sync (GL_SYNC_X11_FENCE_EXT, self->xfence, 0);
print_gl_error ();
self->xcounter = XSyncCreateCounter (xdisplay, SYNC_VALUE_ZERO);
attrs.trigger.counter = self->xcounter;
attrs.trigger.value_type = XSyncAbsolute;
attrs.trigger.wait_value = SYNC_VALUE_ONE;
attrs.trigger.test_type = XSyncPositiveTransition;
attrs.events = TRUE;
self->xalarm = XSyncCreateAlarm (xdisplay,
XSyncCACounter |
XSyncCAValueType |
XSyncCAValue |
XSyncCATestType |
XSyncCAEvents,
&attrs);
XSyncIntToValue (&self->next_counter_value, 1);
self->state = META_SYNC_STATE_READY;
return self;
}
static Bool
alarm_event_predicate (Display *dpy,
XEvent *event,
XPointer data)
{
int xsync_event_base;
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return False;
xsync_event_base = meta_display_get_sync_event_base (ring->display);
if (event->type == xsync_event_base + XSyncAlarmNotify)
{
if (((MetaSync *) data)->xalarm == ((XSyncAlarmNotifyEvent *) event)->alarm)
return True;
}
return False;
}
static void
meta_sync_free (MetaSync *self)
{
/* When our assumptions don't hold, something has gone wrong but we
* don't know what, so we reboot the ring. While doing that, we
* trigger fences before deleting them to try to get ourselves out
* of a potentially stuck GPU state.
*/
switch (self->state)
{
case META_SYNC_STATE_WAITING:
case META_SYNC_STATE_DONE:
/* nothing to do */
break;
case META_SYNC_STATE_RESET_PENDING:
{
XEvent event;
XIfEvent (self->xdisplay, &event, alarm_event_predicate, (XPointer) self);
meta_sync_handle_event (self, (XSyncAlarmNotifyEvent *) &event);
}
/* fall through */
case META_SYNC_STATE_READY:
XSyncTriggerFence (self->xdisplay, self->xfence);
XFlush (self->xdisplay);
break;
default:
break;
}
meta_gl_delete_sync (self->glsync);
XSyncDestroyFence (self->xdisplay, self->xfence);
XSyncDestroyCounter (self->xdisplay, self->xcounter);
XSyncDestroyAlarm (self->xdisplay, self->xalarm);
g_free (self);
}
gboolean
meta_sync_ring_init (MetaDisplay *display)
{
guint i;
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return FALSE;
g_return_val_if_fail (display != NULL, FALSE);
g_return_val_if_fail (ring->display == NULL, FALSE);
if (!load_required_symbols ())
return FALSE;
if (!meta_display_has_sync (display))
return FALSE;
print_gl_error ();
XSyncIntToValue (&SYNC_VALUE_ZERO, 0);
XSyncIntToValue (&SYNC_VALUE_ONE, 1);
ring->display = display;
ring->alarm_to_sync = g_hash_table_new (NULL, NULL);
for (i = 0; i < NUM_SYNCS; ++i)
{
MetaSync *sync = meta_sync_new (meta_display_get_xdisplay (display));
ring->syncs_array[i] = sync;
g_hash_table_replace (ring->alarm_to_sync, (gpointer) sync->xalarm, sync);
}
ring->current_sync_idx = 0;
ring->current_sync = ring->syncs_array[0];
ring->warmup_syncs = 0;
return TRUE;
}
void
meta_sync_ring_destroy (void)
{
guint i;
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return;
g_return_if_fail (ring->display != NULL);
ring->current_sync_idx = 0;
ring->current_sync = NULL;
ring->warmup_syncs = 0;
for (i = 0; i < NUM_SYNCS; ++i)
meta_sync_free (ring->syncs_array[i]);
g_hash_table_destroy (ring->alarm_to_sync);
ring->display = NULL;
}
static gboolean
meta_sync_ring_reboot (MetaDisplay *display)
{
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return FALSE;
meta_sync_ring_destroy ();
ring->reboots += 1;
if (!meta_sync_ring_get ())
{
meta_warning ("MetaSyncRing: Too many reboots -- disabling\n");
return FALSE;
}
return meta_sync_ring_init (display);
}
gboolean
meta_sync_ring_after_frame (void)
{
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return FALSE;
g_return_if_fail (ring->display != NULL);
if (ring->warmup_syncs >= NUM_SYNCS / 2)
{
guint reset_sync_idx = (ring->current_sync_idx + NUM_SYNCS - (NUM_SYNCS / 2)) % NUM_SYNCS;
MetaSync *sync_to_reset = ring->syncs_array[reset_sync_idx];
GLenum status = meta_sync_check_update_finished (sync_to_reset, 0);
if (status == GL_TIMEOUT_EXPIRED)
{
meta_warning ("MetaSyncRing: We should never wait for a sync -- add more syncs?\n");
status = meta_sync_check_update_finished (sync_to_reset, MAX_SYNC_WAIT_TIME);
}
if (status != GL_ALREADY_SIGNALED && status != GL_CONDITION_SATISFIED)
{
meta_warning ("MetaSyncRing: Timed out waiting for sync object.\n");
return meta_sync_ring_reboot (ring->display);
}
meta_sync_reset (sync_to_reset);
}
else
{
ring->warmup_syncs += 1;
}
ring->current_sync_idx += 1;
ring->current_sync_idx %= NUM_SYNCS;
ring->current_sync = ring->syncs_array[ring->current_sync_idx];
return TRUE;
}
gboolean
meta_sync_ring_insert_wait (void)
{
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return FALSE;
g_return_if_fail (ring->display != NULL);
if (ring->current_sync->state != META_SYNC_STATE_READY)
{
meta_warning ("MetaSyncRing: Sync object is not ready -- were events handled properly?\n");
if (!meta_sync_ring_reboot (ring->display))
return FALSE;
}
meta_sync_insert (ring->current_sync);
return TRUE;
}
void
meta_sync_ring_handle_event (XSyncAlarmNotifyEvent *event)
{
MetaSync *sync;
MetaSyncRing *ring = meta_sync_ring_get ();
if (!ring)
return;
g_return_if_fail (ring->display != NULL);
sync = g_hash_table_lookup (ring->alarm_to_sync, (gpointer) event->alarm);
if (sync)
meta_sync_handle_event (sync, event);
}

View File

@@ -0,0 +1,17 @@
#ifndef _META_SYNC_RING_H_
#define _META_SYNC_RING_H_
#include <glib.h>
#include <X11/Xlib.h>
#include <X11/extensions/sync.h>
#include <meta/display.h>
gboolean meta_sync_ring_init (MetaDisplay *dpy);
void meta_sync_ring_destroy (void);
gboolean meta_sync_ring_after_frame (void);
gboolean meta_sync_ring_insert_wait (void);
void meta_sync_ring_handle_event (XSyncAlarmNotifyEvent *event);
#endif /* _META_SYNC_RING_H_ */

View File

@@ -29,6 +29,9 @@
#include <meta/errors.h>
#include "util-private.h"
#include "x11/window-x11.h"
#include "x11/window-x11-private.h"
/* Looks up the MetaWindow representing the frame of the given X window.
* Used as a helper function by a bunch of the functions below.
*
@@ -69,6 +72,8 @@ meta_core_get (Display *xdisplay,
MetaDisplay *display = meta_display_for_x_display (xdisplay);
MetaWindow *window = meta_display_lookup_x_window (display, xwindow);
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = window_x11->priv;
va_start (args, xwindow);
@@ -103,10 +108,10 @@ meta_core_get (Display *xdisplay,
if (!*((gboolean*)answer)) goto out; /* see above */
break;
case META_CORE_GET_CLIENT_WIDTH:
*((gint*)answer) = window->rect.width;
*((gint*)answer) = priv->client_rect.width;
break;
case META_CORE_GET_CLIENT_HEIGHT:
*((gint*)answer) = window->rect.height;
*((gint*)answer) = priv->client_rect.height;
break;
case META_CORE_GET_FRAME_FLAGS:
*((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
@@ -120,11 +125,8 @@ meta_core_get (Display *xdisplay,
case META_CORE_GET_ICON:
*((GdkPixbuf**)answer) = window->icon;
break;
case META_CORE_GET_FRAME_WIDTH:
*((gint*)answer) = window->frame->rect.width;
break;
case META_CORE_GET_FRAME_HEIGHT:
*((gint*)answer) = window->frame->rect.height;
case META_CORE_GET_FRAME_RECT:
meta_window_get_frame_rect (window, ((MetaRectangle*)answer));
break;
case META_CORE_GET_THEME_VARIANT:
*((char**)answer) = window->gtk_theme_variant;

View File

@@ -37,8 +37,7 @@ typedef enum
META_CORE_GET_FRAME_TYPE,
META_CORE_GET_MINI_ICON,
META_CORE_GET_ICON,
META_CORE_GET_FRAME_WIDTH,
META_CORE_GET_FRAME_HEIGHT,
META_CORE_GET_FRAME_RECT,
META_CORE_GET_THEME_VARIANT,
} MetaCoreGetType;

View File

@@ -1826,8 +1826,8 @@ meta_display_begin_grab_op (MetaDisplay *display,
"Grab op %u on window %s successful\n",
display->grab_op, window ? window->desc : "(null)");
meta_window_get_client_root_coords (display->grab_window,
&display->grab_initial_window_pos);
meta_window_get_frame_rect (display->grab_window,
&display->grab_initial_window_pos);
display->grab_anchor_window_pos = display->grab_initial_window_pos;
if (meta_is_wayland_compositor ())
@@ -2526,7 +2526,7 @@ mru_cmp (gconstpointer a,
* @display: a #MetaDisplay
* @type: type of tab list
* @screen: a #MetaScreen
* @workspace: (allow-none): origin workspace
* @workspace: (nullable): origin workspace
*
* Determine the list of windows that should be displayed for Alt-TAB
* functionality. The windows are returned in most recently used order.
@@ -2595,7 +2595,7 @@ meta_display_get_tab_list (MetaDisplay *display,
* @display: a #MetaDisplay
* @type: type of tab list
* @workspace: origin workspace
* @window: (allow-none): starting window
* @window: (nullable): starting window
* @backward: If %TRUE, look for the previous window.
*
* Determine the next window that should be displayed for Alt-TAB
@@ -3120,6 +3120,12 @@ meta_display_has_shape (MetaDisplay *display)
return META_DISPLAY_HAS_SHAPE (display);
}
gboolean
meta_display_has_sync (MetaDisplay *display)
{
return META_DISPLAY_HAS_XSYNC (display);
}
/**
* meta_display_get_focus_window:
* @display: a #MetaDisplay
@@ -3148,6 +3154,12 @@ meta_display_get_shape_event_base (MetaDisplay *display)
return display->shape_event_base;
}
int
meta_display_get_sync_event_base (MetaDisplay *display)
{
return display->xsync_event_base;
}
/**
* meta_display_clear_mouse_mode:
* @display: a #MetaDisplay

View File

@@ -1134,13 +1134,8 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
initialize_grab_edge_resistance_data (display);
}
/* Note that old_[xy] and new_[xy] are with respect to inner positions of
* the window.
*/
void
meta_window_edge_resistance_for_move (MetaWindow *window,
int old_x,
int old_y,
int *new_x,
int *new_y,
GSourceFunc timeout_func,
@@ -1153,8 +1148,8 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
meta_window_get_frame_rect (window, &old_outer);
proposed_outer = old_outer;
proposed_outer.x += (*new_x - old_x);
proposed_outer.y += (*new_y - old_y);
proposed_outer.x = *new_x;
proposed_outer.y = *new_y;
new_outer = proposed_outer;
window->display->grab_last_user_action_was_snap = snap;
@@ -1205,26 +1200,20 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
else
smaller_y_change = bottom_change;
*new_x = old_x + smaller_x_change +
*new_x = old_outer.x + smaller_x_change +
(BOX_LEFT (*reference) - BOX_LEFT (old_outer));
*new_y = old_y + smaller_y_change +
*new_y = old_outer.y + smaller_y_change +
(BOX_TOP (*reference) - BOX_TOP (old_outer));
meta_topic (META_DEBUG_EDGE_RESISTANCE,
"outer x & y move-to coordinate changed from %d,%d to %d,%d\n",
proposed_outer.x, proposed_outer.y,
old_outer.x + (*new_x - old_x),
old_outer.y + (*new_y - old_y));
*new_x, *new_y);
}
}
/* Note that old_(width|height) and new_(width|height) are with respect to
* sizes of the inner window.
*/
void
meta_window_edge_resistance_for_resize (MetaWindow *window,
int old_width,
int old_height,
int *new_width,
int *new_height,
int gravity,
@@ -1237,8 +1226,8 @@ meta_window_edge_resistance_for_resize (MetaWindow *window,
gboolean is_resize;
meta_window_get_frame_rect (window, &old_outer);
proposed_outer_width = old_outer.width + (*new_width - old_width);
proposed_outer_height = old_outer.height + (*new_height - old_height);
proposed_outer_width = *new_width;
proposed_outer_height = *new_height;
meta_rectangle_resize_with_gravity (&old_outer,
&new_outer,
gravity,
@@ -1256,8 +1245,8 @@ meta_window_edge_resistance_for_resize (MetaWindow *window,
is_keyboard_op,
is_resize))
{
*new_width = old_width + (new_outer.width - old_outer.width);
*new_height = old_height + (new_outer.height - old_outer.height);
*new_width = new_outer.width;
*new_height = new_outer.height;
meta_topic (META_DEBUG_EDGE_RESISTANCE,
"outer width & height got changed from %d,%d to %d,%d\n",

View File

@@ -25,16 +25,12 @@
#include "window-private.h"
void meta_window_edge_resistance_for_move (MetaWindow *window,
int old_x,
int old_y,
int *new_x,
int *new_y,
GSourceFunc timeout_func,
gboolean snap,
gboolean is_keyboard_op);
void meta_window_edge_resistance_for_resize (MetaWindow *window,
int old_width,
int old_height,
int *new_width,
int *new_height,
int gravity,

View File

@@ -33,9 +33,13 @@
#include "bell.h"
#include "workspace-private.h"
#include "backends/meta-backend.h"
#include "backends/native/meta-idle-monitor-native.h"
#include "backends/x11/meta-backend-x11.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
#include "backends/native/meta-idle-monitor-native.h"
#endif
#include "x11/window-x11.h"
#include "x11/xprops.h"
#include "wayland/meta-xwayland.h"
@@ -1827,35 +1831,37 @@ meta_display_handle_xevent (MetaDisplay *display,
static void
handle_idletime_for_event (const ClutterEvent *event)
{
ClutterInputDevice *device, *source_device;
MetaIdleMonitor *core_monitor, *device_monitor;
int device_id;
#ifdef HAVE_NATIVE_BACKEND
/* This is handled by XSync under X11. */
#if defined(CLUTTER_WINDOWING_X11)
if (clutter_check_windowing_backend (CLUTTER_WINDOWING_X11))
return;
#endif
MetaBackend *backend = meta_get_backend ();
device = clutter_event_get_device (event);
if (device == NULL)
return;
device_id = clutter_input_device_get_device_id (device);
core_monitor = meta_idle_monitor_get_core ();
device_monitor = meta_idle_monitor_get_for_device (device_id);
meta_idle_monitor_native_reset_idletime (core_monitor);
meta_idle_monitor_native_reset_idletime (device_monitor);
source_device = clutter_event_get_source_device (event);
if (source_device != device)
if (META_IS_BACKEND_NATIVE (backend))
{
ClutterInputDevice *device, *source_device;
MetaIdleMonitor *core_monitor, *device_monitor;
int device_id;
device = clutter_event_get_device (event);
if (device == NULL)
return;
device_id = clutter_input_device_get_device_id (device);
core_monitor = meta_idle_monitor_get_core ();
device_monitor = meta_idle_monitor_get_for_device (device_id);
meta_idle_monitor_native_reset_idletime (core_monitor);
meta_idle_monitor_native_reset_idletime (device_monitor);
source_device = clutter_event_get_source_device (event);
if (source_device != device)
{
device_id = clutter_input_device_get_device_id (device);
device_monitor = meta_idle_monitor_get_for_device (device_id);
meta_idle_monitor_native_reset_idletime (device_monitor);
}
}
#endif /* HAVE_NATIVE_BACKEND */
}
static gboolean

View File

@@ -121,9 +121,6 @@ meta_window_ensure_frame (MetaWindow *window)
"Incrementing unmaps_pending on %s for reparent\n", window->desc);
window->unmaps_pending += 1;
}
/* window was reparented to this position */
window->rect.x = 0;
window->rect.y = 0;
stack_window.x11.xwindow = window->xwindow;
meta_stack_tracker_record_remove (window->screen->stack_tracker,
@@ -132,8 +129,8 @@ meta_window_ensure_frame (MetaWindow *window)
XReparentWindow (window->display->xdisplay,
window->xwindow,
frame->xwindow,
window->rect.x,
window->rect.y);
frame->child_x,
frame->child_y);
/* FIXME handle this error */
meta_error_trap_pop (window->display);
@@ -202,7 +199,7 @@ meta_window_destroy_frame (MetaWindow *window)
XReparentWindow (window->display->xdisplay,
window->xwindow,
window->screen->xroot,
/* Using anything other than meta_window_get_position()
/* Using anything other than client root window coordinates
* coordinates here means we'll need to ensure a configure
* notify event is sent; see bug 399552.
*/

View File

@@ -57,7 +57,10 @@
#include "wayland/meta-wayland.h"
#include "backends/x11/meta-backend-x11.h"
#ifdef HAVE_NATIVE_BACKEND
#include "backends/native/meta-backend-native.h"
#endif
#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
@@ -1906,12 +1909,12 @@ process_mouse_move_resize_grab (MetaDisplay *display,
else if (window->tile_mode != META_TILE_NONE)
meta_window_tile (window);
else
meta_window_move_resize (display->grab_window,
TRUE,
display->grab_initial_window_pos.x,
display->grab_initial_window_pos.y,
display->grab_initial_window_pos.width,
display->grab_initial_window_pos.height);
meta_window_move_resize_frame (display->grab_window,
TRUE,
display->grab_initial_window_pos.x,
display->grab_initial_window_pos.y,
display->grab_initial_window_pos.width,
display->grab_initial_window_pos.height);
/* End grab */
return FALSE;
@@ -1927,6 +1930,7 @@ process_keyboard_move_grab (MetaDisplay *display,
ClutterKeyEvent *event)
{
gboolean handled;
MetaRectangle frame_rect;
int x, y;
int incr;
gboolean smart_snap;
@@ -1941,7 +1945,9 @@ process_keyboard_move_grab (MetaDisplay *display,
if (is_modifier (event->keyval))
return TRUE;
meta_window_get_position (window, &x, &y);
meta_window_get_frame_rect (window, &frame_rect);
x = frame_rect.x;
y = frame_rect.y;
smart_snap = (event->modifier_state & CLUTTER_SHIFT_MASK) != 0;
@@ -1965,12 +1971,12 @@ process_keyboard_move_grab (MetaDisplay *display,
if (window->shaken_loose)
meta_window_maximize (window, META_MAXIMIZE_BOTH);
else
meta_window_move_resize (display->grab_window,
TRUE,
display->grab_initial_window_pos.x,
display->grab_initial_window_pos.y,
display->grab_initial_window_pos.width,
display->grab_initial_window_pos.height);
meta_window_move_resize_frame (display->grab_window,
TRUE,
display->grab_initial_window_pos.x,
display->grab_initial_window_pos.y,
display->grab_initial_window_pos.width,
display->grab_initial_window_pos.height);
}
/* When moving by increments, we still snap to edges if the move
@@ -2016,23 +2022,18 @@ process_keyboard_move_grab (MetaDisplay *display,
if (handled)
{
MetaRectangle old_rect;
meta_topic (META_DEBUG_KEYBINDINGS,
"Computed new window location %d,%d due to keypress\n",
x, y);
meta_window_get_client_root_coords (window, &old_rect);
meta_window_edge_resistance_for_move (window,
old_rect.x,
old_rect.y,
&x,
&y,
NULL,
smart_snap,
TRUE);
meta_window_move (window, TRUE, x, y);
meta_window_move_frame (window, TRUE, x, y);
meta_window_update_keyboard_move (window);
}
@@ -2166,6 +2167,7 @@ process_keyboard_resize_grab (MetaDisplay *display,
MetaWindow *window,
ClutterKeyEvent *event)
{
MetaRectangle frame_rect;
gboolean handled;
int height_inc;
int width_inc;
@@ -2186,12 +2188,12 @@ process_keyboard_resize_grab (MetaDisplay *display,
if (event->keyval == CLUTTER_KEY_Escape)
{
/* End resize and restore to original state. */
meta_window_move_resize (display->grab_window,
TRUE,
display->grab_initial_window_pos.x,
display->grab_initial_window_pos.y,
display->grab_initial_window_pos.width,
display->grab_initial_window_pos.height);
meta_window_move_resize_frame (display->grab_window,
TRUE,
display->grab_initial_window_pos.x,
display->grab_initial_window_pos.y,
display->grab_initial_window_pos.width,
display->grab_initial_window_pos.height);
return FALSE;
}
@@ -2202,6 +2204,10 @@ process_keyboard_resize_grab (MetaDisplay *display,
width = window->rect.width;
height = window->rect.height;
meta_window_get_frame_rect (window, &frame_rect);
width = frame_rect.width;
height = frame_rect.height;
gravity = meta_resize_gravity_from_grab_op (display->grab_op);
smart_snap = (event->modifier_state & CLUTTER_SHIFT_MASK) != 0;
@@ -2359,18 +2365,13 @@ process_keyboard_resize_grab (MetaDisplay *display,
if (handled)
{
MetaRectangle old_rect;
meta_topic (META_DEBUG_KEYBINDINGS,
"Computed new window size due to keypress: "
"%dx%d, gravity %s\n",
width, height, meta_gravity_to_string (gravity));
old_rect = window->rect; /* Don't actually care about x,y */
/* Do any edge resistance/snapping */
meta_window_edge_resistance_for_resize (window,
old_rect.width,
old_rect.height,
&width,
&height,
gravity,
@@ -2378,15 +2379,11 @@ process_keyboard_resize_grab (MetaDisplay *display,
smart_snap,
TRUE);
/* We don't need to update unless the specified width and height
* are actually different from what we had before.
*/
if (window->rect.width != width || window->rect.height != height)
meta_window_resize_with_gravity (window,
TRUE,
width,
height,
gravity);
meta_window_resize_frame_with_gravity (window,
TRUE,
width,
height,
gravity);
meta_window_update_keyboard_resize (window, FALSE);
}
@@ -3172,6 +3169,7 @@ handle_set_spew_mark (MetaDisplay *display,
meta_verbose ("-- MARK MARK MARK MARK --\n");
}
#ifdef HAVE_NATIVE_BACKEND
static void
handle_switch_vt (MetaDisplay *display,
MetaScreen *screen,
@@ -3189,11 +3187,12 @@ handle_switch_vt (MetaDisplay *display,
g_error_free (error);
}
}
#endif /* HAVE_NATIVE_BACKEND */
/**
* meta_keybindings_set_custom_handler:
* @name: The name of the keybinding to set
* @handler: (allow-none): The new handler function
* @handler: (nullable): The new handler function
* @user_data: User data to pass to the callback
* @free_data: Will be called when this handler is overridden.
*
@@ -3481,7 +3480,9 @@ init_builtin_key_bindings (MetaDisplay *display)
META_KEYBINDING_ACTION_SET_SPEW_MARK,
handle_set_spew_mark, 0);
if (meta_is_wayland_compositor ())
#ifdef HAVE_NATIVE_BACKEND
MetaBackend *backend = meta_get_backend ();
if (META_IS_BACKEND_NATIVE (backend))
{
add_builtin_keybinding (display,
"switch-to-session-1",
@@ -3532,6 +3533,7 @@ init_builtin_key_bindings (MetaDisplay *display)
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 7);
}
#endif /* HAVE_NATIVE_BACKEND */
#undef REVERSES_AND_REVERSED

View File

@@ -181,7 +181,9 @@ static gboolean opt_replace_wm;
static gboolean opt_disable_sm;
static gboolean opt_sync;
static gboolean opt_wayland;
#ifdef HAVE_NATIVE_BACKEND
static gboolean opt_display_server;
#endif
static GOptionEntry meta_options[] = {
{
@@ -225,11 +227,13 @@ static GOptionEntry meta_options[] = {
N_("Run as a wayland compositor"),
NULL
},
#ifdef HAVE_NATIVE_BACKEND
{
"display-server", 0, 0, G_OPTION_ARG_NONE,
&opt_display_server,
N_("Run as a full display server, rather than nested")
},
#endif
{NULL}
};
@@ -332,8 +336,10 @@ meta_init (void)
if (g_getenv ("MUTTER_DEBUG"))
meta_set_debugging (TRUE);
#if defined(CLUTTER_WINDOWING_EGL) && defined(HAVE_NATIVE_BACKEND)
if (opt_display_server)
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
#endif
meta_set_is_wayland_compositor (opt_wayland);

View File

@@ -515,85 +515,84 @@ find_first_fit (MetaWindow *window,
meta_window_get_frame_rect (window, &rect);
#ifdef WITH_VERBOSE_MODE
{
char monitor_location_string[RECT_LENGTH];
meta_rectangle_to_string (&window->screen->monitor_infos[monitor].rect,
monitor_location_string);
meta_topic (META_DEBUG_XINERAMA,
"Natural monitor is %s\n",
monitor_location_string);
}
{
char monitor_location_string[RECT_LENGTH];
meta_rectangle_to_string (&window->screen->monitor_infos[monitor].rect,
monitor_location_string);
meta_topic (META_DEBUG_XINERAMA,
"Natural monitor is %s\n",
monitor_location_string);
}
#endif
meta_window_get_work_area_for_monitor (window, monitor, &work_area);
meta_window_get_work_area_for_monitor (window, monitor, &work_area);
center_tile_rect_in_area (&rect, &work_area);
center_tile_rect_in_area (&rect, &work_area);
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, windows))
{
*new_x = rect.x;
*new_y = rect.y;
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, windows))
{
*new_x = rect.x;
*new_y = rect.y;
retval = TRUE;
retval = TRUE;
goto out;
}
goto out;
}
/* try below each window */
tmp = below_sorted;
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
MetaRectangle frame_rect;
/* try below each window */
tmp = below_sorted;
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
MetaRectangle frame_rect;
meta_window_get_frame_rect (w, &frame_rect);
meta_window_get_frame_rect (w, &frame_rect);
rect.x = frame_rect.x;
rect.y = frame_rect.y + frame_rect.height;
rect.x = frame_rect.x;
rect.y = frame_rect.y + frame_rect.height;
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, below_sorted))
{
*new_x = rect.x;
*new_y = rect.y;
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, below_sorted))
{
*new_x = rect.x;
*new_y = rect.y;
retval = TRUE;
retval = TRUE;
goto out;
}
goto out;
}
tmp = tmp->next;
}
tmp = tmp->next;
}
/* try to the right of each window */
tmp = right_sorted;
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
MetaRectangle frame_rect;
/* try to the right of each window */
tmp = right_sorted;
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
MetaRectangle frame_rect;
meta_window_get_frame_rect (w, &frame_rect);
meta_window_get_frame_rect (w, &frame_rect);
rect.x = frame_rect.x + frame_rect.width;
rect.y = frame_rect.y;
rect.x = frame_rect.x + frame_rect.width;
rect.y = frame_rect.y;
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, right_sorted))
{
*new_x = rect.x;
*new_y = rect.y;
if (meta_rectangle_contains_rect (&work_area, &rect) &&
!rectangle_overlaps_some_window (&rect, right_sorted))
{
*new_x = rect.x;
*new_y = rect.y;
retval = TRUE;
retval = TRUE;
goto out;
}
goto out;
}
tmp = tmp->next;
}
tmp = tmp->next;
}
out:
g_list_free (below_sorted);
g_list_free (right_sorted);
return retval;

View File

@@ -180,7 +180,7 @@ typedef struct
/**
* MetaStringPreference:
* @handler: (allow-none): A handler. Many of the string preferences
* @handler: (nullable): A handler. Many of the string preferences
* aren't stored as strings and need parsing; others of them have
* default values which can't be solved in the general case. If you
* include a function pointer here, it will be called instead of writing
@@ -192,7 +192,7 @@ typedef struct
* in particular the @result (out) parameter as returned by
* g_settings_get_mapped() will be ignored in all cases.
* This may be %NULL. If it is, see "target", below.
* @target: (allow-none): Where to write the incoming string.
* @target: (nullable): Where to write the incoming string.
* This must be %NULL if the handler is non-%NULL.
* If the incoming string is %NULL, no change will be made.
*/

View File

@@ -357,7 +357,8 @@ struct _MetaWindow
/* if non-NULL, the bounds of the window frame */
cairo_region_t *frame_bounds;
/* if non-NULL, the bounding shape region of the window */
/* if non-NULL, the bounding shape region of the window. Relative to
* the server-side client window. */
cairo_region_t *shape_region;
/* if non-NULL, the opaque region _NET_WM_OPAQUE_REGION */
@@ -403,32 +404,23 @@ struct _MetaWindow
gboolean has_custom_frame_extents;
GtkBorder custom_frame_extents;
/* The size we set the window to last (i.e. what we believe
* to be its actual size on the server). The x, y are
* the actual server-side x,y so are relative to the frame
* (meaning that they just hold the frame width and height)
* or the root window (meaning they specify the location
* of the top left of the inner window) as appropriate.
*/
/* The rectangles here are in "frame rect" coordinates. See the
* comment at the top of meta_window_move_resize_internal() for more
* information. */
/* The current window geometry of the window. */
MetaRectangle rect;
/* The geometry to restore when we unmaximize. The position is in
* root window coords, even if there's a frame, which contrasts with
* window->rect above. Note that this gives the position and size
* of the client window (i.e. ignoring the frame).
*/
/* The geometry to restore when we unmaximize. */
MetaRectangle saved_rect;
/* This is the geometry the window will have if no constraints have
* applied. We use this whenever we are moving implicitly (for example,
* if we move to avoid a panel, we can snap back to this position if
* the panel moves again). Note that this gives the position and size
* of the client window (i.e. ignoring the frame).
*
* Position always in root coords, unlike window->rect.
* the panel moves again).
*/
MetaRectangle unconstrained_rect;
/* Cached net_wm_icon_geometry */
MetaRectangle icon_geometry;
@@ -539,23 +531,12 @@ void meta_window_update_fullscreen_monitors (MetaWindow *window,
unsigned long left,
unsigned long right);
void meta_window_resize_frame_with_gravity (MetaWindow *window,
gboolean user_op,
int w,
int h,
int gravity);
/* args to move are window pos, not frame pos */
void meta_window_move (MetaWindow *window,
gboolean user_op,
int root_x_nw,
int root_y_nw);
void meta_window_move_resize (MetaWindow *window,
gboolean user_op,
int root_x_nw,
int root_y_nw,
int w,
int h);
void meta_window_resize_with_gravity (MetaWindow *window,
gboolean user_op,
int w,
int h,
int gravity);
void meta_window_change_workspace (MetaWindow *window,
MetaWorkspace *workspace);
@@ -564,17 +545,6 @@ gboolean meta_window_should_be_showing (MetaWindow *window);
void meta_window_update_struts (MetaWindow *window);
/* this gets root coords */
void meta_window_get_position (MetaWindow *window,
int *x,
int *y);
/* Gets root coords for x, y, width & height of client window; uses
* meta_window_get_position for x & y.
*/
void meta_window_get_client_root_coords (MetaWindow *window,
MetaRectangle *rect);
/* gets position we need to set to stay in current position,
* assuming position will be gravity-compensated. i.e.
* this is the position a client would send in a configure
@@ -721,7 +691,7 @@ void meta_window_update_resize (MetaWindow *window,
void meta_window_move_resize_internal (MetaWindow *window,
MetaMoveResizeFlags flags,
int gravity,
MetaRectangle client_rect);
MetaRectangle frame_rect);
void meta_window_grab_op_began (MetaWindow *window, MetaGrabOp op);
void meta_window_grab_op_ended (MetaWindow *window, MetaGrabOp op);

View File

@@ -1044,9 +1044,6 @@ _meta_window_shared_new (MetaDisplay *display,
if (window->attached)
meta_window_recalc_features (window);
if (window->decorated)
meta_window_ensure_frame (window);
if (window->type == META_WINDOW_DESKTOP ||
window->type == META_WINDOW_DOCK)
{
@@ -1393,9 +1390,6 @@ meta_window_unmanage (MetaWindow *window,
META_WINDOW_GET_CLASS (window)->unmanage (window);
if (window->frame)
meta_window_destroy_frame (window);
meta_prefs_remove_listener (prefs_changed_callback, window);
meta_screen_queue_check_fullscreen (window->screen);
@@ -2654,15 +2648,11 @@ meta_window_save_rect (MetaWindow *window)
{
window->saved_rect.x = window->rect.x;
window->saved_rect.width = window->rect.width;
if (window->frame)
window->saved_rect.x += window->frame->rect.x;
}
if (!window->maximized_vertically)
{
window->saved_rect.y = window->rect.y;
window->saved_rect.height = window->rect.height;
if (window->frame)
window->saved_rect.y += window->frame->rect.y;
}
}
}
@@ -3016,12 +3006,12 @@ unmaximize_window_before_freeing (MetaWindow *window)
* Moreover, it will need to know the unmaximized geometry,
* therefore move_resize the window to saved_rect here
* before closing it. */
meta_window_move_resize (window,
FALSE,
window->saved_rect.x,
window->saved_rect.y,
window->saved_rect.width,
window->saved_rect.height);
meta_window_move_resize_frame (window,
FALSE,
window->saved_rect.x,
window->saved_rect.y,
window->saved_rect.width,
window->saved_rect.height);
}
}
@@ -3078,7 +3068,7 @@ meta_window_unmaximize_internal (MetaWindow *window,
/* Unmaximize to the saved_rect position in the direction(s)
* being unmaximized.
*/
meta_window_get_client_root_coords (window, &target_rect);
target_rect = old_rect;
/* Avoid unmaximizing to "almost maximized" size when the previous size
* is greater then 80% of the work area use MAX_UNMAXIMIZED_WINDOW_AREA of the work area as upper limit
@@ -3115,7 +3105,9 @@ meta_window_unmaximize_internal (MetaWindow *window,
/* Window's size hints may have changed while maximized, making
* saved_rect invalid. #329152
*/
meta_window_frame_rect_to_client_rect (window, &target_rect, &target_rect);
ensure_size_hints_satisfied (&target_rect, &window->size_hints);
meta_window_client_rect_to_frame_rect (window, &target_rect, &target_rect);
meta_window_move_resize_internal (window,
META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION,
@@ -3176,7 +3168,6 @@ meta_window_unmaximize_with_gravity (MetaWindow *window,
{
MetaRectangle desired_rect;
meta_window_get_position (window, &desired_rect.x, &desired_rect.y);
desired_rect.width = new_width;
desired_rect.height = new_height;
@@ -3293,12 +3284,12 @@ meta_window_unmake_fullscreen (MetaWindow *window)
meta_window_recalc_features (window);
set_net_wm_state (window);
meta_window_move_resize (window,
FALSE,
target_rect.x,
target_rect.y,
target_rect.width,
target_rect.height);
meta_window_move_resize_frame (window,
FALSE,
target_rect.x,
target_rect.y,
target_rect.width,
target_rect.height);
meta_window_update_layer (window);
@@ -3532,7 +3523,7 @@ maybe_move_attached_dialog (MetaWindow *window,
{
if (meta_window_is_attached_dialog (window))
/* It ignores x,y for such a dialog */
meta_window_move (window, FALSE, 0, 0);
meta_window_move_frame (window, FALSE, 0, 0);
return FALSE;
}
@@ -3645,13 +3636,27 @@ void
meta_window_move_resize_internal (MetaWindow *window,
MetaMoveResizeFlags flags,
int gravity,
MetaRectangle client_rect)
MetaRectangle frame_rect)
{
/* The rectangle here that's passed in is always the root position
* of the client window. For undecorated or client-decorated windows,
* this is the root position of the X11 window. For server-decorated
* windows, this is the root position of the client area of the window.
/* The rectangle here that's passed in *always* in "frame rect"
* coordinates. That means the position of the frame's visible bounds,
* with x and y being absolute (root window) coordinates.
*
* For an X11 framed window, the client window's server rectangle is
* inset from this rectangle by the frame's visible borders, and the
* frame window's server rectangle is outset by the invisible borders.
*
* For an X11 unframed window, the rectangle here directly matches
* the server's rectangle, since the visible and invisible borders
* are both 0.
*
* For an X11 CSD window, the client window's server rectangle is
* outset from this rectagle by the client-specified frame extents.
*
* For a Wayland window, this rectangle can simply be sent directly
* to the client.
*/
gboolean did_placement;
MetaRectangle unconstrained_rect;
MetaRectangle constrained_rect;
@@ -3674,18 +3679,15 @@ meta_window_move_resize_internal (MetaWindow *window,
* resizing the old rectangle with the given gravity. */
if ((flags & (META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION)) == META_IS_RESIZE_ACTION)
{
MetaRectangle old_rect;
meta_window_get_client_root_coords (window, &old_rect);
meta_rectangle_resize_with_gravity (&old_rect,
meta_rectangle_resize_with_gravity (&window->rect,
&unconstrained_rect,
gravity,
client_rect.width,
client_rect.height);
frame_rect.width,
frame_rect.height);
}
else
{
unconstrained_rect = client_rect;
unconstrained_rect = frame_rect;
}
/* If this is only a move, then ignore the passed in size and
@@ -3706,15 +3708,21 @@ meta_window_move_resize_internal (MetaWindow *window,
MetaRectangle old_rect;
meta_window_get_frame_rect (window, &old_rect);
meta_window_client_rect_to_frame_rect (window, &constrained_rect, &constrained_rect);
meta_window_constrain (window,
flags,
gravity,
&old_rect,
&constrained_rect);
}
meta_window_frame_rect_to_client_rect (window, &constrained_rect, &constrained_rect);
/* If we did placement, then we need to save the position that the window
* was placed at to make sure that meta_window_move_resize_now places the
* window correctly.
*/
if (did_placement)
{
window->unconstrained_rect.x = constrained_rect.x;
window->unconstrained_rect.y = constrained_rect.y;
}
/* Do the protocol-specific move/resize logic */
@@ -3736,12 +3744,6 @@ meta_window_move_resize_internal (MetaWindow *window,
meta_window_update_monitor (window);
/* Invariants leaving this function are:
* a) window->rect and frame->rect reflect the actual
* server-side size/pos of window->xwindow and frame->xwindow
* b) all constraints are obeyed by window->rect and frame->rect
*/
if ((result & META_MOVE_RESIZE_RESULT_FRAME_SHAPE_CHANGED) && window->frame_bounds)
{
cairo_region_destroy (window->frame_bounds);
@@ -3754,33 +3756,6 @@ meta_window_move_resize_internal (MetaWindow *window,
window->screen->active_workspace);
}
/**
* meta_window_move:
* @window: a #MetaWindow
* @user_op: bool to indicate whether or not this is a user operation
* @root_x_nw: desired x pos
* @root_y_nw: desired y pos
*
* Moves the window to the desired location on window's assigned workspace.
* NOTE: does NOT place according to the origin of the enclosing
* frame/window-decoration, but according to the origin of the window,
* itself.
*/
void
meta_window_move (MetaWindow *window,
gboolean user_op,
int root_x_nw,
int root_y_nw)
{
MetaMoveResizeFlags flags;
MetaRectangle rect = { root_x_nw, root_y_nw, 0, 0 };
g_return_if_fail (!window->override_redirect);
flags = (user_op ? META_IS_USER_ACTION : 0) | META_IS_MOVE_ACTION;
meta_window_move_resize_internal (window, flags, NorthWestGravity, rect);
}
/**
* meta_window_move_frame:
* @window: a #MetaWindow
@@ -3799,10 +3774,13 @@ meta_window_move_frame (MetaWindow *window,
int root_x_nw,
int root_y_nw)
{
MetaMoveResizeFlags flags;
MetaRectangle rect = { root_x_nw, root_y_nw, 0, 0 };
meta_window_frame_rect_to_client_rect (window, &rect, &rect);
meta_window_move (window, user_op, rect.x, rect.y);
g_return_if_fail (!window->override_redirect);
flags = (user_op ? META_IS_USER_ACTION : 0) | META_IS_MOVE_ACTION;
meta_window_move_resize_internal (window, flags, NorthWestGravity, rect);
}
static void
@@ -3846,10 +3824,14 @@ meta_window_move_resize_frame (MetaWindow *window,
int w,
int h)
{
MetaMoveResizeFlags flags;
MetaRectangle rect = { root_x_nw, root_y_nw, w, h };
meta_window_frame_rect_to_client_rect (window, &rect, &rect);
meta_window_move_resize (window, user_op, rect.x, rect.y, rect.width, rect.height);
g_return_if_fail (!window->override_redirect);
flags = (user_op ? META_IS_USER_ACTION : 0) | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION;
meta_window_move_resize_internal (window, flags, NorthWestGravity, rect);
}
/**
@@ -3886,35 +3868,11 @@ meta_window_move_to_monitor (MetaWindow *window,
}
void
meta_window_move_resize (MetaWindow *window,
gboolean user_op,
int root_x_nw,
int root_y_nw,
int w,
int h)
{
MetaMoveResizeFlags flags;
MetaRectangle rect;
g_return_if_fail (!window->override_redirect);
flags = (user_op ? META_IS_USER_ACTION : 0) |
META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION;
rect.x = root_x_nw;
rect.y = root_y_nw;
rect.width = w;
rect.height = h;
meta_window_move_resize_internal (window, flags, NorthWestGravity, rect);
}
void
meta_window_resize_with_gravity (MetaWindow *window,
gboolean user_op,
int w,
int h,
int gravity)
meta_window_resize_frame_with_gravity (MetaWindow *window,
gboolean user_op,
int w,
int h,
int gravity)
{
MetaMoveResizeFlags flags;
MetaRectangle rect;
@@ -3929,11 +3887,11 @@ meta_window_resize_with_gravity (MetaWindow *window,
static void
meta_window_move_resize_now (MetaWindow *window)
{
meta_window_move_resize (window, FALSE,
window->unconstrained_rect.x,
window->unconstrained_rect.y,
window->unconstrained_rect.width,
window->unconstrained_rect.height);
meta_window_move_resize_frame (window, FALSE,
window->unconstrained_rect.x,
window->unconstrained_rect.y,
window->unconstrained_rect.width,
window->unconstrained_rect.height);
}
static gboolean
@@ -3976,36 +3934,6 @@ idle_move_resize (gpointer data)
return FALSE;
}
void
meta_window_get_position (MetaWindow *window,
int *x,
int *y)
{
if (window->frame)
{
if (x)
*x = window->frame->rect.x + window->frame->child_x;
if (y)
*y = window->frame->rect.y + window->frame->child_y;
}
else
{
if (x)
*x = window->rect.x;
if (y)
*y = window->rect.y;
}
}
void
meta_window_get_client_root_coords (MetaWindow *window,
MetaRectangle *rect)
{
meta_window_get_position (window, &rect->x, &rect->y);
rect->width = window->rect.width;
rect->height = window->rect.height;
}
void
meta_window_get_gravity_position (MetaWindow *window,
int gravity,
@@ -4124,7 +4052,10 @@ meta_window_get_input_rect (const MetaWindow *window,
if (window->frame)
*rect = window->frame->rect;
else
*rect = window->rect;
{
*rect = window->rect;
meta_window_frame_rect_to_client_rect ((MetaWindow *) window, rect, rect);
}
}
/**
@@ -4234,30 +4165,7 @@ void
meta_window_get_frame_rect (const MetaWindow *window,
MetaRectangle *rect)
{
if (window->frame)
{
MetaFrameBorders borders;
*rect = window->frame->rect;
meta_frame_calc_borders (window->frame, &borders);
rect->x += borders.invisible.left;
rect->y += borders.invisible.top;
rect->width -= borders.invisible.left + borders.invisible.right;
rect->height -= borders.invisible.top + borders.invisible.bottom;
}
else
{
*rect = window->rect;
if (window->has_custom_frame_extents)
{
const GtkBorder *extents = &window->custom_frame_extents;
rect->x += extents->left;
rect->y += extents->top;
rect->width -= extents->left + extents->right;
rect->height -= extents->top + extents->bottom;
}
}
*rect = window->rect;
}
/**
@@ -4292,22 +4200,18 @@ void
meta_window_get_client_area_rect (const MetaWindow *window,
cairo_rectangle_int_t *rect)
{
if (window->frame)
{
rect->x = window->frame->child_x;
rect->y = window->frame->child_y;
}
else
{
rect->x = 0;
rect->y = 0;
}
MetaFrameBorders borders;
rect->width = window->rect.width;
meta_frame_calc_borders (window->frame, &borders);
rect->x = borders.total.left;
rect->y = borders.total.top;
rect->width = window->rect.width - borders.visible.left - borders.visible.right;
if (window->shaded)
rect->height = 0;
else
rect->height = window->rect.height;
rect->height = window->rect.height - borders.visible.top - borders.visible.bottom;
}
void
@@ -4895,7 +4799,7 @@ meta_window_get_icon_geometry (MetaWindow *window,
/**
* meta_window_set_icon_geometry:
* @window: a #MetaWindow
* @rect: (allow-none): rectangle with the desired geometry or %NULL.
* @rect: (nullable): rectangle with the desired geometry or %NULL.
*
* Sets or unsets the location of the icon corresponding to the window. If
* set, the location should correspond to a dock, task bar or other user
@@ -5694,7 +5598,7 @@ update_move (MetaWindow *window,
meta_screen_update_tile_preview (window->screen,
window->tile_mode != META_TILE_NONE);
meta_window_get_client_root_coords (window, &old);
meta_window_get_frame_rect (window, &old);
/* Don't allow movement in the maximized directions or while tiled */
if (window->maximized_horizontally || META_WINDOW_TILED_SIDE_BY_SIDE (window))
@@ -5704,15 +5608,13 @@ update_move (MetaWindow *window,
/* Do any edge resistance/snapping */
meta_window_edge_resistance_for_move (window,
old.x,
old.y,
&new_x,
&new_y,
update_move_timeout,
snap,
FALSE);
meta_window_move (window, TRUE, new_x, new_y);
meta_window_move_frame (window, TRUE, new_x, new_y);
}
/* When resizing a maximized window by using alt-middle-drag (resizing
@@ -5998,7 +5900,7 @@ update_resize (MetaWindow *window,
window->display->grab_resize_timeout_id = 0;
}
old = window->rect; /* Don't actually care about x,y */
meta_window_get_frame_rect (window, &old);
/* One sided resizing ought to actually be one-sided, despite the fact that
* aspect ratio windows don't interact nicely with the above stuff. So,
@@ -6026,8 +5928,6 @@ update_resize (MetaWindow *window,
/* Do any edge resistance/snapping */
meta_window_edge_resistance_for_resize (window,
old.width,
old.height,
&new_w,
&new_h,
gravity,
@@ -6037,13 +5937,7 @@ update_resize (MetaWindow *window,
if (new_unmaximize == window->display->grab_resize_unmaximize)
{
/* We don't need to update unless the specified width and height
* are actually different from what we had before.
*/
if (old.width != new_w || old.height != new_h)
{
meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity);
}
meta_window_resize_frame_with_gravity (window, TRUE, new_w, new_h, gravity);
}
else
{
@@ -6582,8 +6476,8 @@ warp_grab_pointer (MetaWindow *window,
display->grab_anchor_root_y = *y;
display->grab_latest_motion_x = *x;
display->grab_latest_motion_y = *y;
meta_window_get_client_root_coords (window,
&display->grab_anchor_window_pos);
meta_window_get_frame_rect (window,
&display->grab_anchor_window_pos);
{
MetaBackend *backend = meta_get_backend ();
@@ -7396,7 +7290,7 @@ meta_window_get_frame_type (MetaWindow *window)
*
* Gets a region representing the outer bounds of the window's frame.
*
* Return value: (transfer none) (allow-none): a #cairo_region_t
* Return value: (transfer none) (nullable): a #cairo_region_t
* holding the outer bounds of the window, or %NULL if the window
* doesn't have a frame.
*/
@@ -7441,7 +7335,7 @@ meta_window_is_attached_dialog (MetaWindow *window)
* - there is no 3rd window stacked between both tiled windows that's
* partially visible in the common edge.
*
* Return value: (transfer none) (allow-none): the matching tiled window or
* Return value: (transfer none) (nullable): the matching tiled window or
* %NULL if it doesn't exist.
*/
MetaWindow *

View File

@@ -75,6 +75,7 @@ Display *meta_display_get_xdisplay (MetaDisplay *display);
MetaCompositor *meta_display_get_compositor (MetaDisplay *display);
gboolean meta_display_has_shape (MetaDisplay *display);
gboolean meta_display_has_sync (MetaDisplay *display);
MetaWindow *meta_display_get_focus_window (MetaDisplay *display);
@@ -83,6 +84,7 @@ gboolean meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
int meta_display_get_damage_event_base (MetaDisplay *display);
int meta_display_get_shape_event_base (MetaDisplay *display);
int meta_display_get_sync_event_base (MetaDisplay *display);
gboolean meta_display_xserver_time_is_before (MetaDisplay *display,
guint32 time1,

View File

@@ -147,7 +147,6 @@ const char * meta_window_get_gtk_window_object_path (MetaWindow *window);
const char * meta_window_get_gtk_app_menu_object_path (MetaWindow *window);
const char * meta_window_get_gtk_menubar_object_path (MetaWindow *window);
void meta_window_move(MetaWindow *window, gboolean user_op, int root_x_nw, int root_y_nw);
void meta_window_move_frame(MetaWindow *window, gboolean user_op, int root_x_nw, int root_y_nw);
void meta_window_move_resize_frame (MetaWindow *window, gboolean user_op, int root_x_nw, int root_y_nw, int w, int h);
void meta_window_move_to_monitor (MetaWindow *window, int monitor);

View File

@@ -1601,21 +1601,20 @@ static void
clip_region_to_visible_frame_border (cairo_region_t *region,
MetaUIFrame *frame)
{
MetaRectangle frame_rect;
cairo_rectangle_int_t area;
cairo_region_t *frame_border;
MetaFrameFlags flags;
MetaFrameType type;
MetaFrameBorders borders;
Display *display;
int frame_width, frame_height;
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
meta_core_get (display, frame->xwindow,
META_CORE_GET_FRAME_FLAGS, &flags,
META_CORE_GET_FRAME_TYPE, &type,
META_CORE_GET_FRAME_WIDTH, &frame_width,
META_CORE_GET_FRAME_HEIGHT, &frame_height,
META_CORE_GET_FRAME_RECT, &frame_rect,
META_CORE_GET_END);
meta_theme_get_frame_borders (meta_theme_get_current (),
@@ -1625,8 +1624,8 @@ clip_region_to_visible_frame_border (cairo_region_t *region,
/* Visible frame rect */
area.x = borders.invisible.left;
area.y = borders.invisible.top;
area.width = frame_width - borders.invisible.left - borders.invisible.right;
area.height = frame_height - borders.invisible.top - borders.invisible.bottom;
area.width = frame_rect.width;
area.height = frame_rect.height;
frame_border = cairo_region_create_rectangle (&area);

View File

@@ -383,9 +383,13 @@ handle_scroll_event (MetaWaylandPointer *pointer,
case CLUTTER_SCROLL_SMOOTH:
{
double dx, dy;
/* Clutter smooth scroll events are in discrete steps (1 step = 1.0 long
* vector along one axis). To convert to smooth scroll events that are
* in pointer motion event space, multiply the vector with the 10. */
const double factor = 10.0;
clutter_event_get_scroll_delta (event, &dx, &dy);
x_value = wl_fixed_from_double (dx);
y_value = wl_fixed_from_double (dy);
x_value = wl_fixed_from_double (dx) * factor;
y_value = wl_fixed_from_double (dy) * factor;
}
break;

View File

@@ -1018,9 +1018,9 @@ xdg_shell_get_xdg_popup (struct wl_client *client,
}
window = meta_window_wayland_new (meta_get_display (), surface);
meta_window_move (window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
meta_window_move_frame (window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
window->showing_for_first_time = FALSE;
window->placed = TRUE;
meta_window_set_transient_for (window, parent_surf->window);
@@ -1212,9 +1212,9 @@ wl_shell_surface_set_transient (struct wl_client *client,
wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
meta_window_set_transient_for (surface->window, parent_surf->window);
meta_window_move (surface->window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
meta_window_move_frame (surface->window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
surface->window->placed = TRUE;
}
@@ -1247,9 +1247,9 @@ wl_shell_surface_set_popup (struct wl_client *client,
wl_shell_surface_set_state (surface, SURFACE_STATE_TOPLEVEL);
meta_window_set_transient_for (surface->window, parent_surf->window);
meta_window_move (surface->window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
meta_window_move_frame (surface->window, FALSE,
parent_surf->window->rect.x + x,
parent_surf->window->rect.y + y);
surface->window->placed = TRUE;
meta_wayland_pointer_start_popup_grab (&seat->pointer, surface);

View File

@@ -55,6 +55,10 @@ struct _MetaWindowX11Private
int border_width;
MetaResizePopup *grab_resize_popup;
/* These are in server coordinates. If we have a frame, it's
* relative to the frame. */
MetaRectangle client_rect;
};
G_END_DECLS

View File

@@ -210,8 +210,8 @@ send_configure_notify (MetaWindow *window)
event.xconfigure.display = window->display->xdisplay;
event.xconfigure.event = window->xwindow;
event.xconfigure.window = window->xwindow;
event.xconfigure.x = window->rect.x - priv->border_width;
event.xconfigure.y = window->rect.y - priv->border_width;
event.xconfigure.x = priv->client_rect.x - priv->border_width;
event.xconfigure.y = priv->client_rect.y - priv->border_width;
if (window->frame)
{
if (window->withdrawn)
@@ -233,8 +233,8 @@ send_configure_notify (MetaWindow *window)
event.xconfigure.y += window->frame->rect.y;
}
}
event.xconfigure.width = window->rect.width;
event.xconfigure.height = window->rect.height;
event.xconfigure.width = priv->client_rect.width;
event.xconfigure.height = priv->client_rect.height;
event.xconfigure.border_width = priv->border_width; /* requested not actual */
event.xconfigure.above = None; /* FIXME */
event.xconfigure.override_redirect = False;
@@ -492,6 +492,7 @@ meta_window_apply_session_info (MetaWindow *window,
flags = META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION;
adjust_for_gravity (window, FALSE, gravity, &rect);
meta_window_client_rect_to_frame_rect (window, &rect, &rect);
meta_window_move_resize_internal (window, flags, gravity, rect);
}
}
@@ -500,7 +501,6 @@ static void
meta_window_x11_manage (MetaWindow *window)
{
MetaDisplay *display = window->display;
MetaMoveResizeFlags flags;
meta_display_register_x_window (display, &window->xwindow, window);
meta_window_x11_update_shape_region (window);
@@ -518,6 +518,9 @@ meta_window_x11_manage (MetaWindow *window)
meta_window_x11_update_net_wm_type (window);
if (window->decorated)
meta_window_ensure_frame (window);
/* Now try applying saved stuff from the session */
{
const MetaWindowSessionInfo *info;
@@ -535,10 +538,10 @@ meta_window_x11_manage (MetaWindow *window)
* passing TRUE for is_configure_request, ICCCM says
* initial map is handled same as configure request
*/
flags = META_IS_CONFIGURE_REQUEST | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION;
if (!window->override_redirect)
{
MetaRectangle rect;
MetaMoveResizeFlags flags;
int gravity = window->size_hints.win_gravity;
rect.x = window->size_hints.x;
@@ -546,7 +549,10 @@ meta_window_x11_manage (MetaWindow *window)
rect.width = window->size_hints.width;
rect.height = window->size_hints.height;
flags = META_IS_CONFIGURE_REQUEST | META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION;
adjust_for_gravity (window, TRUE, gravity, &rect);
meta_window_client_rect_to_frame_rect (window, &rect, &rect);
meta_window_move_resize_internal (window, flags, gravity, rect);
}
}
@@ -644,6 +650,9 @@ meta_window_x11_unmanage (MetaWindow *window)
meta_display_ungrab_focus_window_button (window->display, window);
meta_error_trap_pop (window->display);
if (window->frame)
meta_window_destroy_frame (window);
}
static void
@@ -785,6 +794,22 @@ meta_window_x11_focus (MetaWindow *window,
}
}
static void
meta_window_get_client_root_coords (MetaWindow *window,
MetaRectangle *rect)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
*rect = priv->client_rect;
if (window->frame)
{
rect->x += window->frame->rect.x;
rect->y += window->frame->rect.y;
}
}
static void
meta_window_refresh_resize_popup (MetaWindow *window)
{
@@ -1003,9 +1028,7 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
MetaFrameBorders borders;
int root_x_nw, root_y_nw;
int w, h;
int client_move_x, client_move_y;
MetaRectangle client_rect;
int size_dx, size_dy;
XWindowChanges values;
unsigned int mask;
@@ -1021,32 +1044,22 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
is_configure_request = (flags & META_IS_CONFIGURE_REQUEST) != 0;
/* meta_window_constrain() might have maximized the window after placement,
* changing the borders.
*/
meta_frame_calc_borders (window->frame, &borders);
root_x_nw = constrained_rect.x;
root_y_nw = constrained_rect.y;
w = constrained_rect.width;
h = constrained_rect.height;
size_dx = constrained_rect.x - window->rect.width;
size_dy = constrained_rect.y - window->rect.height;
size_dx = w - window->rect.width;
size_dy = h - window->rect.height;
if (size_dx != 0 || size_dy != 0)
need_resize_client = TRUE;
window->rect.width = w;
window->rect.height = h;
window->rect = constrained_rect;
if (window->frame)
{
int new_w, new_h;
int new_x, new_y;
new_w = window->rect.width + borders.total.left + borders.total.right;
/* Compute new frame size */
new_w = window->rect.width + borders.invisible.left + borders.invisible.right;
new_h = borders.total.top + borders.total.bottom;
new_h = borders.invisible.top + borders.invisible.bottom;
if (!window->shaded)
new_h += window->rect.height;
@@ -1058,19 +1071,9 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
window->frame->rect.height = new_h;
}
meta_topic (META_DEBUG_GEOMETRY,
"Calculated frame size %dx%d\n",
window->frame->rect.width,
window->frame->rect.height);
}
if (window->frame)
{
int new_x, new_y;
/* Compute new frame coords */
new_x = root_x_nw - borders.total.left;
new_y = root_y_nw - borders.total.top;
new_x = window->rect.x - borders.invisible.left;
new_y = window->rect.y - borders.invisible.top;
if (new_x != window->frame->rect.x ||
new_y != window->frame->rect.y)
@@ -1079,22 +1082,35 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
window->frame->rect.x = new_x;
window->frame->rect.y = new_y;
}
client_move_x = borders.total.left;
client_move_y = borders.total.top;
}
else
/* Calculate the new client rect */
meta_window_frame_rect_to_client_rect (window, &constrained_rect, &client_rect);
/* The above client_rect is in root window coordinates. The
* values we need to pass to XConfigureWindow are in parent
* coordinates, so if the window is in a frame, we need to
* correct the x/y positions here. */
if (window->frame)
{
client_move_x = root_x_nw;
client_move_y = root_y_nw;
client_rect.x = borders.total.left;
client_rect.y = borders.total.top;
}
if (client_move_x != window->rect.x ||
client_move_y != window->rect.y)
if (client_rect.x != priv->client_rect.x ||
client_rect.y != priv->client_rect.y)
{
need_move_client = TRUE;
window->rect.x = client_move_x;
window->rect.y = client_move_y;
priv->client_rect.x = client_rect.x;
priv->client_rect.y = client_rect.y;
}
if (client_rect.width != priv->client_rect.width ||
client_rect.height != priv->client_rect.height)
{
need_resize_client = TRUE;
priv->client_rect.width = client_rect.width;
priv->client_rect.height = client_rect.height;
}
/* If frame extents have changed, fill in other frame fields and
@@ -1186,10 +1202,10 @@ meta_window_x11_move_resize_internal (MetaWindow *window,
need_move_frame, need_resize_frame);
values.border_width = 0;
values.x = client_move_x;
values.y = client_move_y;
values.width = window->rect.width;
values.height = window->rect.height;
values.x = client_rect.x;
values.y = client_rect.y;
values.width = client_rect.width;
values.height = client_rect.height;
mask = 0;
if (is_configure_request && priv->border_width != 0)
@@ -1768,6 +1784,8 @@ void
meta_window_x11_update_input_region (MetaWindow *window)
{
cairo_region_t *region = NULL;
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
/* Decorated windows don't have an input region, because
we don't shape the frame to match the client windows
@@ -1804,8 +1822,8 @@ meta_window_x11_update_input_region (MetaWindow *window)
(n_rects == 1 &&
(rects[0].x != 0 ||
rects[0].y != 0 ||
rects[0].width != window->rect.width ||
rects[0].height != window->rect.height)))
rects[0].width != priv->client_rect.width ||
rects[0].height != priv->client_rect.height)))
region = region_create_from_x_rectangles (rects, n_rects);
XFree (rects);
@@ -1818,8 +1836,8 @@ meta_window_x11_update_input_region (MetaWindow *window)
client_area.x = 0;
client_area.y = 0;
client_area.width = window->rect.width;
client_area.height = window->rect.height;
client_area.width = priv->client_rect.width;
client_area.height = priv->client_rect.height;
/* The shape we get back from the client may have coordinates
* outside of the frame. The X SHAPE Extension requires that
@@ -1850,6 +1868,8 @@ meta_window_set_shape_region (MetaWindow *window,
void
meta_window_x11_update_shape_region (MetaWindow *window)
{
MetaWindowX11 *window_x11 = META_WINDOW_X11 (window);
MetaWindowX11Private *priv = meta_window_x11_get_instance_private (window_x11);
cairo_region_t *region = NULL;
if (META_DISPLAY_HAS_SHAPE (window->display))
@@ -1893,8 +1913,8 @@ meta_window_x11_update_shape_region (MetaWindow *window)
client_area.x = 0;
client_area.y = 0;
client_area.width = window->rect.width;
client_area.height = window->rect.height;
client_area.width = priv->client_rect.width;
client_area.height = priv->client_rect.height;
/* The shape we get back from the client may have coordinates
* outside of the frame. The X SHAPE Extension requires that
@@ -2080,6 +2100,7 @@ meta_window_move_resize_request (MetaWindow *window,
rect.height = height;
adjust_for_gravity (window, TRUE, gravity, &rect);
meta_window_client_rect_to_frame_rect (window, &rect, &rect);
meta_window_move_resize_internal (window, flags, gravity, rect);
}
}