Compare commits

...

52 Commits

Author SHA1 Message Date
Rui Matos
78522c9986 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,
so let's err on the side of caution and disable ourselves.
2014-05-14 14:48:10 +02:00
Rui Matos
e6f100b6d4 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-05-13 01:16:30 +02:00
Rui Matos
a294989fce display: Add public getters for sync extension presence and event base 2014-05-13 00:50:31 +02:00
Rui Matos
1ed41b7ed3 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-05-12 17:50:09 +02:00
Alberto Milone
3d1d155561 xrandr: ignore the error if setting the primary output fails
Some drivers which support RandR 1.4 may not support setting
or getting the primary output, therefore mutter should trap
and ignore any relevant errors.

The modesetting driver exposes this problem when used in
combination with the nvidia binary driver using RandR 1.4
offloading.

Also use a local display variable instead of calling
meta_get_display () every time.
2014-04-22 11:05:30 +02:00
Florian Müllner
7943cf50d4 window-actor: Guard against %NULL frame mask
Creating a new cogl texture may fail, in which case the intent to
free it will crash. While something is clearly wrong (insanely
large window, oom, ...), crashing the WM is harsh and we should
try to avoid it if at all possible, so carry on.

https://bugzilla.gnome.org/show_bug.cgi?id=722266
2014-04-10 15:03:19 +02:00
Florian Müllner
489ad9e978 Bump version to 3.10.4
Update NEWS.
2014-02-19 19:40:16 +01:00
Ryan Lortie
a3f3c60a6c idle-monitor: avoid XSyncBadAlarm X error
If we fail to find the IDLETIME counter, then the alarm variable will be
uninitialised.  Most code paths are careful to check this before
submitting XSync calls, but there is one check missing.

https://bugzilla.gnome.org/show_bug.cgi?id=724364
2014-02-15 13:14:29 +01:00
Giovanni Campagna
b39ef6a961 window: don't set _NET_WM_FULLSCREEN_MONITORS to bogus values
Prior to the DisplayConfig merge, we would set _NET_WM_FULLSCREEN_MONITORS
to (unsigned)-1 when unset. After that, we would have invalid
reads inside meta_screen_monitor_index_to_xinerama_index() (called
with -1).
The way I read the specification, the proper way to indicate
that the window is back to fullscreen on all monitors is to
remove the property, so do that.

Also, add an assertion that meta_screne_monitor_index_to_xinerama_index()
is doing the right thing.

https://bugzilla.gnome.org/show_bug.cgi?id=724258
2014-02-13 13:19:32 +01:00
Khaled Hosny
14dbe8ac8a Update Arabic translation 2014-02-06 15:37:28 +02:00
Shankar Prasad
d158e19133 updated kn.po 2014-02-05 16:27:18 +05:30
Robert Ancell
c2dadecab8 xrandr: Use specified output property name for backlight control
Backlight controls are set using the "BACKLIGHT" XRANDR output property.
This should be "Backlight" according to the XRANDR spec [1].

Some drivers (Intel) export both properties and some only the specified property (nvidia).
Users of drivers that only export the specified property cannot change their backlight using XRANDR.

[1] http://cgit.freedesktop.org/xorg/proto/randrproto/tree/randrproto.txt section 9.1

https://bugzilla.gnome.org/show_bug.cgi?id=723606
2014-02-05 09:48:01 +01:00
Adel Gadllah
099059c930 monitorManager: Fix logic bug in make_logical_config
The code that prevents the creation of multiple MonitorInfos for clones
wasn't working due to using the wrong index when getting the already
created info so fix that to use the correct one.

https://bugzilla.gnome.org/show_bug.cgi?id=710610
2014-02-02 15:16:04 +01:00
Adel Gadllah
24f5b37d6b window_actor: Remove the frame_messages timeout in destroy
Otherwise it might fire off later and cause a crash.

https://bugzilla.gnome.org/show_bug.cgi?id=723468
2014-02-02 15:16:02 +01:00
Adel Gadllah
2958b15a61 window-actor: Fix unobscured_region handling when computing paint volume
We currently ignore the unobscured region when we have mapped clones in
meta_window_actor_process_damage and meta_window_actor_damage_all but
use it unconditionally when computing the paint volume.

This is wrong. We should ignore it there as well or we will end up with
empty clones if the cloned window is completly obscured
(like the tray icons in gnome-shell).

https://bugzilla.gnome.org/show_bug.cgi?id=721596
2014-01-31 15:27:20 +01:00
Jasper St. Pierre
fd263d8457 window-actor: Fix optimization in get_paint_volume
We need to clip the paint volume to the unobscured region, not the
other way around...

https://bugzilla.gnome.org/show_bug.cgi?id=720630
2014-01-31 15:27:04 +01:00
Florian Müllner
47758f0f5f window: Add "skip-taskbar" property
We currently only have a method to query the skip-taskbar hint.
Add a corresponding property to allow listening for change
notifications.

https://bugzilla.gnome.org/show_bug.cgi?id=723307
2014-01-31 10:09:36 +01:00
Jasper St. Pierre
477eb1afed constraints: CSD windows need to have their titlebar kept onscreen too
GTK+ CSD windows are considered undecorated by the code, so we should
not force ourselves to only run on decorated windows.

https://bugzilla.gnome.org/show_bug.cgi?id=719772
2014-01-29 12:26:41 -05:00
Florian Müllner
3b8b05518c Bump version to 3.10.3
Update NEWS.
2014-01-15 15:21:39 +01:00
Daniel Drake
0bd30696b1 window: don't grab server during calc_showing
This grab was added in commit caf43a123f
https://bugzilla.gnome.org/show_bug.cgi?id=381127
to minimize window flickering when switching workspaces.

While this grab is held, some signals are emitted to the shell,
which can lead to deadlocks (reproduced under Mali binary OpenGLESv2
drivers).

Now that we are a compositing window manager, we do not have to
worry about flickers, this grab should no longer be necessary.

https://bugzilla.gnome.org/show_bug.cgi?id=721709
2014-01-07 14:26:35 -06:00
Daniel Drake
fb4e9d2232 Reduce server grabs during window creation
Remove some obvious server grabs from the window creation codepath,
also ones that are taken at startup.

During startup, there is no need to grab: we install the event handlers
before querying for the already-existing windows, so there is no danger
that we will 'lose' some window. We might try to create a window twice
(if it comes back in the original query and then we get an event for it)
but the code is already protected against such conditions.

When windows are created later, we also do not need grabs, we just need
appropriate error checking as the window may be destroyed at any time
(or it may have already been destroyed).

The stack tracker is unaffected here - as it listens to CreateNotify and
DestroyNotify events and responds directly, the internal stack
representation will always be consistent even if the window goes away while
we are processing MapRequest or similar.

https://bugzilla.gnome.org/show_bug.cgi?id=721345
2014-01-06 16:16:31 -06:00
Daniel Drake
e072295395 meta_window_new: clean up error handling
The return code of XGetWindowAttributes() indicates whether an error
was encountered or not. There is no need to specifically check the error
trap.

The trap around XAddToSaveSet() was superfluous. We have a global error
trap to ignore any errors here, and there is no need to XSync() as GDK
will later ignore the error asynchronously if one is raised.

Also move common error exit path to an error label.

https://bugzilla.gnome.org/show_bug.cgi?id=721345
2014-01-06 16:16:23 -06:00
Daniel Drake
1066c19e67 screen: use stack tracker for initial window query
In meta_screen_manage_all_windows() we can use our own stack
tracker to get the list of windows - no need to query X again.

A copy is needed because the stack gets modified as part of the loop.
Specifically, meta_stack_tracker_get_stack() at this time returns the
predicted stack, and meta_window_new() performs a few operations
(e.g. framing) which cause immediate changes to the predicted stack.

https://bugzilla.gnome.org/show_bug.cgi?id=721345
2014-01-06 16:16:15 -06:00
Daniel Drake
d654c93ed2 frame: remove unnecessary server grab
meta_window_ensure_frame() creates its own grab and has a comment
claiming that it must be called under a grab too.

But the reasoning given in the comment does not seem relevant here.
We only frame non-override-redirect windows, so we are creating
the frame in response to MapRequest. There is no way that the child
could receive a MapNotify at this point, since that only happens
much later, once we go through the CALC_SHOWING queue and call
XMapWindow() from meta_window_show().

Remove the unnecessary grab.

https://bugzilla.gnome.org/show_bug.cgi?id=721345
2014-01-06 16:16:07 -06:00
Daniel Drake
7d1611f666 Discourage server grabs
Server grabs are not as evil as you might expect, but there is agreement
in that their usage should be limited.

Server grabs can cause things to go rather wrong when mutter emits
a signal while it has grabbed the server. If the receiver of that signal
waits for a synchronous action performed by another client, then you
have a deadlock. This happens with Mali binary GLESv2 drivers :(

https://bugzilla.gnome.org/show_bug.cgi?id=721345
2014-01-06 16:15:58 -06:00
Daniel Drake
2579e48f21 Remove meta_window_new_with_attrs
The compositor code used to handle X windows that didn't have a
corresponding MetaWindow (see commit d538690b), which is why the
attribute query is separated.

As that doesn't happen any more, we can clean up. No functional changes.

Suggested by Owen Taylor.

https://bugzilla.gnome.org/show_bug.cgi?id=721345
2014-01-06 16:15:50 -06:00
Owen W. Taylor
7278f9bd6b display: Don't leave focus on a window we are unmanaging when sending WM_TAKE_FOCUS
When we move focus elsewhere when unmanaging a window, we *need* to move
the focus, so if the target is globally active, move the focus to the
no-focus-window in anticipation that the focus will normally get moved
to the right window when the target window responds to WM_TAKE_FOCUS.

If the window doesn't respond to WM_TAKE_FOCUS, then focus will be left
on the no-focus-window, but there's no way to distinguish whether the
app will respond or not.

https://bugzilla.gnome.org/show_bug.cgi?id=711618
2013-12-24 11:30:04 -05:00
Owen W. Taylor
da55e27c3b Be willing to unfocus the grab window when we are unmanaging it
When we are unmanaging the grab window, we /need/ to unfocus it,
so we shouldn't bail out early from meta_window_focus().

https://bugzilla.gnome.org/show_bug.cgi?id=711618
2013-12-24 11:29:53 -05:00
Owen W. Taylor
f3196e356b Fix problems with focus tracking
When a client spontaneously focuses their window, perhaps in response
to WM_TAKE_FOCUS we'll get a FocusOut/FocusIn pair with same serial.
Updating display->focus_serial in response to FocusOut then was causing
us to ignore FocusIn and think that the focus was not on any window.

We need to distinguish this spontaneous case from the case where we
set the focus ourselves - when we set the focus ourselves, we're careful
to combine the SetFocus with a property change so that we know definitively
what focus events we have already accounted for.

https://bugzilla.gnome.org/show_bug.cgi?id=720558
2013-12-18 09:41:49 -05:00
Jasper St. Pierre
491b17af19 display: Fix checks for KeyPress/ButtonPress
https://bugzilla.gnome.org/show_bug.cgi?id=720545
2013-12-16 15:13:25 -05:00
Owen W. Taylor
01e0eaf1fc MetaWindowGroup: fix paint volume
In the past, MetaWindowGroup was allocated the size of the screen and
painted the size of the screen because it contained the screen background,
but now we also have the "top window group" which contains only popup
windows, so the allocation doesn't properly reflect the paint bounds
of the window group. Compute the paint bounds accurately from the
children.

https://bugzilla.gnome.org/show_bug.cgi?id=719669
2013-12-09 15:29:33 -05:00
甘露(Gan Lu)
f679ce7017 Update Chinese simplified translation 2013-12-07 15:03:56 +08:00
Jasper St. Pierre
844f4e9348 display: Don't focus the no-focus-window when sending WM_TAKE_FOCUS to a globally active window
Clients like on-screen keyboards try not to take focus when the user clicks
on their window by setting the Input hint to false. However, due to GTK+ and
GDK bugs, the public API for setting the Input hint to false don't remove
WM_TAKE_FOCUS from WM_PROTOCOLS, unintentionally putting them into Globally
Active mode.

These clients also expect that since they don't want to take focus, they want
the focus to remain on the existing window. In this case, for clients like
on-screen keyboards, it's so they can send synthesized keyboard events to the
focused window.

https://bugzilla.gnome.org/show_bug.cgi?id=710296
2013-12-04 11:09:57 -05:00
Marc-André Lureau
5cfc1461a1 xrandr: use "hotplug_mode_update" property
Use the "hotplug_mode_update" connector property indicating that the
screen settings should be updated: get a new preferred mode on hotplug
events to handle dynamic guest resizing (where you resize the host
window and the guest resizes with it).

https://bugzilla.gnome.org/show_bug.cgi?id=711216
2013-11-14 14:57:23 +01:00
Florian Müllner
323e1aba59 Bump version to 3.10.2
Update NEWS.
2013-11-14 12:28:08 +00:00
Lionel Landwerlin
992b97d565 window: don't ignore resize button release event for move/resize actions
https://bugzilla.gnome.org/show_bug.cgi?id=710251
2013-11-04 13:53:21 +00:00
Reinout van Schouwen
da5b9f3255 Updated Dutch translation 2013-10-25 00:24:34 +02:00
Efstathios Iosifidis
6c1eff0dc2 Updated Greek translation 2013-10-24 11:05:09 +03:00
Florian Müllner
1ff986e227 Bump version to 3.10.1.1
Update NEWS.
2013-10-15 23:42:40 +02:00
Giovanni Campagna
b86a289ee3 monitor-config: prevent assert that at least one output is connected
Apparently some connector technologies don't distinguish between
on and off, and there might be valid use cases for running without
any connected monitor.
In that case, just avoid any configuration at all.

https://bugzilla.gnome.org/show_bug.cgi?id=709009
2013-10-15 23:22:05 +02:00
Florian Müllner
badebfae6b Bump version to 3.10.1
Update NEWS.
2013-10-14 22:33:45 +02:00
Carles Ferrando
6693420005 [l10n] Updated Catalan (Valencian) translation 2013-10-13 23:59:35 +02:00
Lionel Landwerlin
0e3aab8691 display: don't interrupt grab move/resize without modifiers
The part of code dealing with move/resize grab in display.c is only
responsible of this behavior when triggered with a modifier. So it
shouldn't stop the move/resize behavior triggered from a mouse event
without modifier on the title bar or sides of the window.

https://bugzilla.gnome.org/show_bug.cgi?id=704759
2013-10-13 01:58:56 +01:00
Lionel Landwerlin
55840c626c window: don't process unrelated release events
When processing button events related to moving/resizing the window,
only the first button should be considered.

https://bugzilla.gnome.org/show_bug.cgi?id=704759
2013-10-13 01:55:58 +01:00
Reinout van Schouwen
f0e5656717 Updated Dutch translation (work in progress) 2013-10-12 00:32:54 +02:00
Hans Petter Jansson
8af0e10aa4 shaped-texture: Use nearest-pixel interpolation if the texture is unscaled
Use nearest-pixel interpolation if the texture is unscaled. This
improves performance, especially with software rendering.

Bug: https://bugzilla.gnome.org/show_bug.cgi?id=708389
2013-10-10 02:38:52 +02:00
Jasper St. Pierre
71f574bc52 prefs: Fix introspection issues 2013-10-09 17:32:05 -04:00
Jasper St. Pierre
2518d6138f stack: Never try to focus a DOCK window 2013-10-09 17:32:05 -04:00
Adel Gadllah
36be084655 meta-window-actor: Fix offset calculation in queue_send_frame_messages_timeout
The current time offset calculation is wrong. It is supposed to calculate
the offset between the current time and the
"time where it message should be sent" (last_time + interval).

Fix the math to actually do that.

https://bugzilla.gnome.org/show_bug.cgi?id=709340
2013-10-07 20:24:16 +02:00
Khaled Hosny
d863182810 Update Arabic translation 2013-10-07 17:10:14 +02:00
Giovanni Campagna
85c2bc29e6 MetaIdleMonitor: protect the monitor instance while calling destroy notify
The destroy notify for a DBus watch holds a reference to the IdleMonitor,
but the IdleMonitorWatch object doesn't (it knows all watches will
be destroyed before the monitor is, so it doesn't need one). This
means that the DBus watch reference can be the only one keeping
the IdleMonitor alive (expecially true for device idle monitors,
which are only used by g-s-d/cursor), and that means that calling
the destroy notify freezes the monitor (and the next X calls
access garbage).

https://bugzilla.gnome.org/show_bug.cgi?id=708420
2013-09-26 18:55:44 +02:00
Giovanni Campagna
4eeeb1557a constraints: don't apply fullscreen workarounds for CSD windows
If you maximize a CSD window on a monitor without struts, it ends
up taking the whole monitor size, but it doesn't mean that the
application wants to fullscreen.

https://bugzilla.gnome.org/show_bug.cgi?id=708718
2013-09-26 10:35:05 +02:00
32 changed files with 3267 additions and 6764 deletions

65
NEWS
View File

@@ -1,3 +1,68 @@
3.10.4
======
* Fix CSD titlebars being placed off-screen [Jasper; #719772]
* Expose MetaWindow:skip-taskbar property [Florian; #723307]
* Fix legacy tray icons showing up blank [Adel; #721596]
* Fix configuration of cloned monitors [Adel; #710610]
* Use correct output property for backlight control [Robert; #723606]
* Misc. bug fixes [Jasper, Adel, Giovanni, Ryan; #720630, #723468, #724258,
#724364]
Contributors:
Robert Ancell, Giovanni Campagna, Adel Gadllah, Ryan Lortie, Florian Müllner,
Jasper St. Pierre
Translations:
Shankar Prasad [kn], Khaled Hosny [ar]
3.10.3
======
* xrandr: Use "hotplug_mode_update" property [Marc-André; #711216]
* Don't focus the no-focus-window for globally active windows [Jasper; #710296]
* Fix window group paint volume [Owen; #719669]
* Fix checks for KeyPress/ButtonPress [Jasper; #720545]
* Fix problems with focus tracking [Owen; #720558]
* Don't leave focus on windows that are being unmanaged [Owen; #711618]
* Reduce server grabs [Daniel; #721345, #721709]
Contributors:
Daniel Drake, Marc-André Lureau, Jasper St. Pierre, Owen W. Taylor
Translations:
甘露(Gan Lu) [zh_CN]
3.10.2
======
* Fix resize operations using mouse-button-modifier [Lionel; #710251]
Contributors:
Lionel Landwerlin
Translations:
Efstathios Iosifidis [el], Reinout van Schouwen [nl]
3.10.1.1
========
* Don't assert that at least one output is connected [Giovanni; #709009]
Contributors:
Giovanni Campagna
3.10.1
======
* Don't apply fullscreen workarounds to CSD windows [Giovanni; #708718]
* Fix hangs during DND operations [Adel; #709340]
* Use nearest-pixel interpolation when possible [Hans; #708389]
* Fix tile previews getting stuck on right click during drags [Lionel; #704759]
* Misc bug fixes [Giovanni, Jasper; #708420]
Contributors:
Giovanni Campagna, Adel Gadllah, Lionel Landwerlin, Hans Petter Jansson,
Jasper St. Pierre
Translations:
Khaled Hosny [ar], Reinout van Schouwen [nl], Carles Ferrando [ca@valencia]
3.10.0.1
========
* Fix bug when a window changed size twice in a single frame - this

View File

@@ -2,7 +2,7 @@ AC_PREREQ(2.50)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [10])
m4_define([mutter_micro_version], [0.1])
m4_define([mutter_micro_version], [4])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@@ -363,6 +363,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

650
po/ar.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

664
po/el.po

File diff suppressed because it is too large Load Diff

2012
po/kn.po

File diff suppressed because it is too large Load Diff

1192
po/nl.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -64,6 +64,8 @@ libmutter_la_SOURCES = \
compositor/meta-shadow-factory.c \
compositor/meta-shadow-factory-private.h \
compositor/meta-shaped-texture.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 \

View File

@@ -19,7 +19,8 @@ struct _MetaCompositor
Atom atom_x_root_pixmap;
Atom atom_net_wm_window_opacity;
guint repaint_func_id;
guint pre_paint_func_id;
guint post_paint_func_id;
ClutterActor *shadow_src;
@@ -32,6 +33,9 @@ struct _MetaCompositor
guint show_redraw : 1;
guint debug : 1;
guint no_mipmaps : 1;
gboolean frame_has_updated_xsurfaces;
gboolean have_x11_sync_object;
};
struct _MetaCompScreen

View File

@@ -86,6 +86,7 @@
#include "display-private.h" /* for meta_display_lookup_x_window() */
#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
#include "meta-sync-ring.h"
/* #define DEBUG_TRACE g_print */
#define DEBUG_TRACE(X)
@@ -142,7 +143,11 @@ meta_switch_workspace_completed (MetaScreen *screen)
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
@@ -173,6 +178,8 @@ process_damage (MetaCompositor *compositor,
return;
meta_window_actor_process_damage (window_actor, event);
compositor->frame_has_updated_xsurfaces = TRUE;
}
static void
@@ -719,6 +726,8 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
*/
XMapWindow (xdisplay, info->output);
compositor->have_x11_sync_object = meta_sync_ring_init (display);
redirect_windows (compositor, screen);
}
@@ -1019,6 +1028,10 @@ meta_compositor_process_event (MetaCompositor *compositor,
if (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.
@@ -1468,7 +1481,7 @@ pre_paint_windows (MetaCompScreen *info)
}
static gboolean
meta_repaint_func (gpointer data)
meta_pre_paint_func (gpointer data)
{
MetaCompositor *compositor = data;
GSList *screens = meta_display_get_screens (compositor->display);
@@ -1484,6 +1497,52 @@ meta_repaint_func (gpointer data)
pre_paint_windows (info);
}
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_post_paint_func (gpointer data)
{
MetaCompositor *compositor = data;
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;
}
@@ -1545,10 +1604,16 @@ meta_compositor_new (MetaDisplay *display)
compositor->atom_x_root_pixmap = atoms[0];
compositor->atom_net_wm_window_opacity = atoms[1];
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

@@ -30,6 +30,7 @@
#include <config.h>
#include <meta/meta-shaped-texture.h>
#include "clutter-utils.h"
#include "meta-texture-tower.h"
#include <clutter/clutter.h>
@@ -209,6 +210,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
CoglTexture *paint_tex;
ClutterActorBox alloc;
cairo_region_t *blended_region = NULL;
CoglPipelineFilter filter;
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
return;
@@ -245,6 +247,22 @@ meta_shaped_texture_paint (ClutterActor *actor)
if (tex_width == 0 || tex_height == 0) /* no contents yet */
return;
/* Use nearest-pixel interpolation if the texture is unscaled. This
* improves performance, especially with software rendering.
*/
filter = COGL_PIPELINE_FILTER_LINEAR;
if (!clutter_actor_is_in_clone_paint (actor))
{
int x_origin, y_origin;
if (meta_actor_is_untransformed (actor,
&x_origin,
&y_origin))
filter = COGL_PIPELINE_FILTER_NEAREST;
}
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
fb = cogl_get_draw_framebuffer ();
@@ -273,6 +291,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
opaque_pipeline = get_unblended_pipeline (ctx);
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
n_rects = cairo_region_num_rectangles (region);
for (i = 0; i < n_rects; i++)
@@ -314,9 +333,11 @@ meta_shaped_texture_paint (ClutterActor *actor)
{
pipeline = get_masked_pipeline (ctx);
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
cogl_pipeline_set_layer_filters (pipeline, 1, filter, filter);
}
cogl_pipeline_set_layer_texture (pipeline, 0, paint_tex);
cogl_pipeline_set_layer_filters (pipeline, 0, filter, filter);
{
CoglColor color;

View File

@@ -0,0 +1,526 @@
/*
* 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 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;
success = TRUE;
out:
return success;
}
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);
self->glsync = meta_gl_import_sync (GL_SYNC_X11_FENCE_EXT, self->xfence, 0);
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;
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

@@ -734,8 +734,12 @@ meta_window_actor_get_paint_volume (ClutterActor *actor,
gdk_rectangle_union (&bounds, &shadow_bounds, &bounds);
}
if (priv->unobscured_region)
cairo_region_intersect_rectangle (priv->unobscured_region, &bounds);
if (priv->unobscured_region && !clutter_actor_has_mapped_clones (actor))
{
cairo_rectangle_int_t unobscured_bounds;
cairo_region_get_extents (priv->unobscured_region, &unobscured_bounds);
gdk_rectangle_intersect (&bounds, &unobscured_bounds, &bounds);
}
origin.x = bounds.x;
origin.y = bounds.y;
@@ -973,7 +977,7 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
}
interval = (int)(1000000 / refresh_rate) * 6;
offset = MAX (0, current_time - priv->frame_drawn_time + interval) / 1000;
offset = MAX (0, priv->frame_drawn_time + interval - current_time) / 1000;
/* The clutter master clock source has already been added with META_PRIORITY_REDRAW,
* so the timer will run *after* the clutter frame handling, if a frame is ready
@@ -1395,6 +1399,12 @@ meta_window_actor_destroy (MetaWindowActor *self)
window_type = meta_window_get_window_type (window);
meta_window_set_compositor_private (window, NULL);
if (priv->send_frame_messages_timer != 0)
{
g_source_remove (priv->send_frame_messages_timer);
priv->send_frame_messages_timer = 0;
}
/*
* We remove the window from internal lookup hashes and thus any other
* unmap events etc fail
@@ -2219,7 +2229,8 @@ build_and_scan_frame_mask (MetaWindowActor *self,
meta_shaped_texture_set_mask_texture (META_SHAPED_TEXTURE (priv->actor),
mask_texture);
cogl_object_unref (mask_texture);
if (mask_texture)
cogl_object_unref (mask_texture);
g_free (mask_data);
}
@@ -2365,26 +2376,6 @@ meta_window_actor_handle_updates (MetaWindowActor *self)
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

@@ -277,11 +277,30 @@ meta_window_group_paint (ClutterActor *actor)
}
}
/* Adapted from clutter_actor_update_default_paint_volume() */
static gboolean
meta_window_group_get_paint_volume (ClutterActor *actor,
meta_window_group_get_paint_volume (ClutterActor *self,
ClutterPaintVolume *volume)
{
return clutter_paint_volume_set_from_allocation (volume, actor);
ClutterActorIter iter;
ClutterActor *child;
clutter_actor_iter_init (&iter, self);
while (clutter_actor_iter_next (&iter, &child))
{
const ClutterPaintVolume *child_volume;
if (!CLUTTER_ACTOR_IS_MAPPED (child))
continue;
child_volume = clutter_actor_get_transformed_paint_volume (child, self);
if (child_volume == NULL)
return FALSE;
clutter_paint_volume_union (volume, child_volume);
}
return TRUE;
}
static void

View File

@@ -447,12 +447,14 @@ setup_constraint_info (ConstraintInfo *info,
/* Workaround braindead legacy apps that don't know how to
* fullscreen themselves properly - don't get fooled by
* windows which hide their titlebar when maximized; that's
* not the same as fullscreen, even if there are no struts
* making the workarea smaller than the monitor.
* windows which hide their titlebar when maximized or which are
* client decorated; that's not the same as fullscreen, even
* if there are no struts making the workarea smaller than
* the monitor.
*/
if (meta_prefs_get_force_fullscreen() &&
!window->hide_titlebar_when_maximized &&
window->decorated &&
meta_rectangle_equal (new, &monitor_info->rect) &&
window->has_fullscreen_func &&
!window->fullscreen)
@@ -1388,7 +1390,6 @@ constrain_titlebar_visible (MetaWindow *window,
window->type == META_WINDOW_DOCK ||
window->fullscreen ||
!window->require_titlebar_visible ||
!window->decorated ||
unconstrained_user_action)
return TRUE;

View File

@@ -138,6 +138,14 @@ struct _MetaDisplay
*/
guint allow_terminal_deactivation : 1;
/* If true, server->focus_serial refers to us changing the focus; in
* this case, we can ignore focus events that have exactly focus_serial,
* since we take care to make another request immediately afterwards.
* But if focus is being changed by another client, we have to accept
* multiple events with the same serial.
*/
guint focused_by_us : 1;
guint static_gravity_works : 1;
/*< private-ish >*/

View File

@@ -925,8 +925,6 @@ meta_display_open (void)
enable_compositor (the_display);
meta_display_grab (the_display);
/* Now manage all existing windows */
tmp = the_display->screens;
while (tmp != NULL)
@@ -978,8 +976,6 @@ meta_display_open (void)
meta_idle_monitor_init_dbus ();
meta_display_ungrab (the_display);
/* Done opening new display */
the_display->display_opening = FALSE;
@@ -1224,7 +1220,18 @@ meta_display_screen_for_x_screen (MetaDisplay *display,
return NULL;
}
/* Grab/ungrab routines taken from fvwm */
/* Grab/ungrab routines taken from fvwm.
* Calling this function will cause X to ignore all other clients until
* you ungrab. This may not be quite as bad as it sounds, yet there is
* agreement that avoiding server grabs except when they are clearly needed
* is a good thing.
*
* If you do use such grabs, please clearly explain the necessity for their
* usage in a comment. Try to keep their scope extremely limited. In
* particular, try to avoid emitting any signals or notifications while
* a grab is active (if the signal receiver tries to block on an X request
* from another client at this point, you will have a deadlock).
*/
void
meta_display_grab (MetaDisplay *display)
{
@@ -1890,9 +1897,11 @@ static void
update_focus_window (MetaDisplay *display,
MetaWindow *window,
Window xwindow,
gulong serial)
gulong serial,
gboolean focused_by_us)
{
display->focus_serial = serial;
display->focused_by_us = focused_by_us;
if (display->focus_xwindow == xwindow)
return;
@@ -2003,7 +2012,8 @@ request_xserver_input_focus_change (MetaDisplay *display,
update_focus_window (display,
meta_window,
xwindow,
serial);
serial,
TRUE);
meta_error_trap_pop (display);
@@ -2117,12 +2127,20 @@ handle_window_focus_event (MetaDisplay *display,
else
g_return_if_reached ();
if (display->server_focus_serial > display->focus_serial)
/* If display->focused_by_us, then the focus_serial will be used only
* for a focus change we made and have already accounted for.
* (See request_xserver_input_focus_change().) Otherwise, we can get
* multiple focus events with the same serial.
*/
if (display->server_focus_serial > display->focus_serial ||
(!display->focused_by_us &&
display->server_focus_serial == display->focus_serial))
{
update_focus_window (display,
focus_window,
focus_window ? focus_window->xwindow : None,
display->server_focus_serial);
display->server_focus_serial,
FALSE);
}
}
@@ -2179,7 +2197,8 @@ event_callback (XEvent *event,
display->current_time = event_get_time (display, event);
display->monitor_cache_invalidated = TRUE;
if (event->xany.serial > display->focus_serial &&
if (display->focused_by_us &&
event->xany.serial > display->focus_serial &&
display->focus_window &&
display->focus_window->xwindow != display->server_focus_window)
{
@@ -2188,7 +2207,8 @@ event_callback (XEvent *event,
update_focus_window (display,
meta_display_lookup_x_window (display, display->server_focus_window),
display->server_focus_window,
display->server_focus_serial);
display->server_focus_serial,
FALSE);
}
screen = meta_display_screen_for_root (display, event->xany.window);
@@ -2304,7 +2324,7 @@ event_callback (XEvent *event,
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
if (window && !window->override_redirect &&
((input_event->type == XI_KeyPress) || (input_event->type == XI_ButtonPress)))
((input_event->evtype == XI_KeyPress) || (input_event->evtype == XI_ButtonPress)))
{
if (CurrentTime == display->current_time)
{
@@ -2349,6 +2369,7 @@ event_callback (XEvent *event,
if ((window &&
meta_grab_op_is_mouse (display->grab_op) &&
(device_event->mods.effective & display->window_grab_modifiers) &&
display->grab_button != device_event->detail &&
display->grab_window == window) ||
grab_op_is_keyboard (display->grab_op))
@@ -2773,14 +2794,14 @@ event_callback (XEvent *event,
&& meta_display_screen_for_root (display, event->xmap.event))
{
window = meta_window_new (display, event->xmap.window,
FALSE);
FALSE, META_COMP_EFFECT_CREATE);
}
break;
case MapRequest:
if (window == NULL)
{
window = meta_window_new (display, event->xmaprequest.window,
FALSE);
FALSE, META_COMP_EFFECT_CREATE);
}
/* if frame was receiver it's some malicious send event or something */
else if (!frame_was_receiver && window)
@@ -5807,25 +5828,6 @@ meta_display_request_take_focus (MetaDisplay *display,
meta_topic (META_DEBUG_FOCUS, "WM_TAKE_FOCUS(%s, %u)\n",
window->desc, timestamp);
if (window != display->focus_window)
{
/* The "Globally Active Input" window case, where the window
* doesn't want us to call XSetInputFocus on it, but does
* want us to send a WM_TAKE_FOCUS.
*
* We can't just set display->focus_window to @window, since we
* we don't know when (or even if) the window will actually take
* focus, so we could end up being wrong for arbitrarily long.
* But we also can't leave it set to the current window, or else
* bug #597352 would come back. So we focus the no_focus_window
* now (and set display->focus_window to that), send the
* WM_TAKE_FOCUS, and then just forget about @window
* until/unless we get a FocusIn.
*/
meta_display_focus_the_no_focus_window (display,
window->screen,
timestamp);
}
meta_window_send_icccm_message (window,
display->atom_WM_TAKE_FOCUS,
timestamp);
@@ -5968,6 +5970,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
@@ -6014,6 +6022,12 @@ meta_display_get_leader_window (MetaDisplay *display)
return display->leader_window;
}
int
meta_display_get_sync_event_base (MetaDisplay *display)
{
return display->xsync_event_base;
}
/**
* meta_display_clear_mouse_mode:
* @display: a #MetaDisplay

View File

@@ -51,9 +51,6 @@ meta_window_ensure_frame (MetaWindow *window)
if (window->frame)
return;
/* See comment below for why this is required. */
meta_display_grab (window->display);
frame = g_new (MetaFrame, 1);
frame->window = window;
@@ -116,14 +113,6 @@ meta_window_ensure_frame (MetaWindow *window)
meta_display_register_x_window (window->display, &frame->xwindow, window);
/* Reparent the client window; it may be destroyed,
* thus the error trap. We'll get a destroy notify later
* and free everything. Comment in FVWM source code says
* we need a server grab or the child can get its MapNotify
* before we've finished reparenting and getting the decoration
* window onscreen, so ensure_frame must be called with
* a grab.
*/
meta_error_trap_push (window->display);
if (window->mapped)
{
@@ -165,8 +154,6 @@ meta_window_ensure_frame (MetaWindow *window)
/* Move keybindings to frame instead of window */
meta_window_grab_keys (window);
meta_display_ungrab (window->display);
}
void

View File

@@ -287,6 +287,7 @@ idle_monitor_watch_free (MetaIdleMonitorWatch *watch)
return;
monitor = watch->monitor;
g_object_ref (monitor);
if (watch->idle_source_id)
{
@@ -304,6 +305,7 @@ idle_monitor_watch_free (MetaIdleMonitorWatch *watch)
g_hash_table_remove (monitor->alarms, (gpointer) watch->xalarm);
}
g_object_unref (monitor);
g_slice_free (MetaIdleMonitorWatch, watch);
}
@@ -499,7 +501,7 @@ make_watch (MetaIdleMonitor *monitor,
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
}
else
else if (monitor->user_active_alarm != None)
{
watch->xalarm = monitor->user_active_alarm;

View File

@@ -816,6 +816,22 @@ meta_monitor_config_match_current (MetaMonitorConfig *self,
return ok;
}
gboolean
meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
{
MetaOutput *outputs;
unsigned n_outputs;
unsigned int i;
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
for (i = 0; i < n_outputs; i++)
if (outputs[i].hotplug_mode_update)
return TRUE;
return FALSE;
}
static MetaConfiguration *
meta_monitor_config_get_stored (MetaMonitorConfig *self,
MetaOutput *outputs,
@@ -824,6 +840,9 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self,
MetaConfiguration key;
MetaConfiguration *stored;
if (n_outputs == 0)
return NULL;
make_config_key (&key, outputs, n_outputs, -1);
stored = g_hash_table_lookup (self->configs, &key);
@@ -1231,6 +1250,12 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height);
if (n_outputs == 0)
{
meta_verbose ("No output connected, not applying configuration\n");
return;
}
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
if (default_config != NULL)

View File

@@ -116,6 +116,9 @@ struct _MetaOutput
*/
gboolean is_primary;
gboolean is_presentation;
/* get a new preferred mode on hotplug events, to handle dynamic guest resizing */
gboolean hotplug_mode_update;
};
struct _MetaCRTC
@@ -383,6 +386,7 @@ void meta_output_info_free (MetaOutputInfo *info);
void meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
int n_old_outputs);
gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager);
/* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */

View File

@@ -187,7 +187,7 @@ output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id,
display->atom_BACKLIGHT,
display->atom_Backlight,
0, G_MAXLONG, False, False, XA_INTEGER,
&actual_type, &actual_format,
&nitems, &bytes_after, &buffer);
@@ -212,7 +212,7 @@ output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
meta_error_trap_push (display);
info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id,
display->atom_BACKLIGHT);
display->atom_Backlight);
meta_error_trap_pop (display);
if (info == NULL)
@@ -311,6 +311,29 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
return NULL;
}
static gboolean
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
XID output_id)
{
MetaDisplay *display = meta_get_display ();
XRRPropertyInfo *info;
gboolean result = FALSE;
meta_error_trap_push (display);
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
display->atom_hotplug_mode_update);
meta_error_trap_pop (display);
if (info)
{
result = TRUE;
XFree (info);
}
return result;
}
static void
meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
{
@@ -430,8 +453,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
XRRFreeCrtcInfo (crtc);
}
meta_error_trap_push (meta_get_display ());
primary_output = XRRGetOutputPrimary (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay));
meta_error_trap_pop (meta_get_display ());
n_actual_outputs = 0;
for (i = 0; i < (unsigned)resources->noutput; i++)
@@ -484,6 +509,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
meta_output->width_mm = output->mm_width;
meta_output->height_mm = output->mm_height;
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
meta_output->hotplug_mode_update =
output_get_hotplug_mode_update (manager_xrandr, meta_output->output_id);
meta_output->n_modes = output->nmode;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
@@ -668,10 +695,11 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
unsigned int n_outputs)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
MetaDisplay *display = meta_get_display ();
unsigned i;
int width, height, width_mm, height_mm;
meta_display_grab (meta_get_display ());
meta_display_grab (display);
/* First compute the new size of the screen (framebuffer) */
width = 0; height = 0;
@@ -765,10 +793,10 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
*/
width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5;
height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5;
meta_error_trap_push (meta_get_display ());
meta_error_trap_push (display);
XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
width, height, width_mm, height_mm);
meta_error_trap_pop (meta_get_display ());
meta_error_trap_pop (display);
for (i = 0; i < n_crtcs; i++)
{
@@ -825,7 +853,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
goto next;
}
meta_error_trap_push (meta_get_display ());
meta_error_trap_push (display);
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
manager_xrandr->resources,
(XID)crtc->crtc_id,
@@ -834,7 +862,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
(XID)mode->mode_id,
wl_transform_to_xrandr (crtc_info->transform),
outputs, n_outputs);
meta_error_trap_pop (meta_get_display ());
meta_error_trap_pop (display);
if (ok != Success)
{
@@ -875,9 +903,11 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
if (output_info->is_primary)
{
meta_error_trap_push (display);
XRRSetOutputPrimary (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay),
(XID)output_info->output->output_id);
meta_error_trap_pop (display);
}
output_set_presentation_xrandr (manager_xrandr,
@@ -903,7 +933,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
output->is_primary = FALSE;
}
meta_display_ungrab (meta_get_display ());
meta_display_ungrab (display);
}
static void
@@ -920,7 +950,7 @@ meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
meta_error_trap_push (display);
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id,
display->atom_BACKLIGHT,
display->atom_Backlight,
XA_INTEGER, 32, PropModeReplace,
(unsigned char *) &hw_value, 1);
meta_error_trap_pop (display);
@@ -971,6 +1001,16 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
XRRFreeGamma (gamma);
}
static void
meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager)
{
/* This will be a no-op if the change was from our side, as
we already called it in the DBus method handler */
meta_monitor_config_update_current (manager->config, manager);
meta_monitor_manager_rebuild_derived (manager);
}
static gboolean
meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
XEvent *event)
@@ -980,6 +1020,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
MetaCRTC *old_crtcs;
MetaMonitorMode *old_modes;
int n_old_outputs;
gboolean new_config;
if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
return FALSE;
@@ -995,31 +1036,36 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
manager->serial++;
meta_monitor_manager_xrandr_read_current (manager);
/* Check if the current intended configuration has the same outputs
as the new real one, or if the event is a result of an XRandR call.
If so, we can go straight to rebuild the logical config and tell
the outside world.
Otherwise, this event was caused by hotplug, so give a chance to
MetaMonitorConfig.
new_config = manager_xrandr->resources->timestamp >=
manager_xrandr->resources->configTimestamp;
if (meta_monitor_manager_has_hotplug_mode_update (manager))
Note that we need to check both the timestamps and the list of
outputs, because the X server might emit spurious events with
new configTimestamps (bug 702804), and the driver may have
changed the EDID for some other reason (old broken qxl and vbox
drivers...).
*/
if (manager_xrandr->resources->timestamp >= manager_xrandr->resources->configTimestamp ||
meta_monitor_config_match_current (manager->config, manager))
{
/* This will be a no-op if the change was from our side, as
we already called it in the DBus method handler */
meta_monitor_config_update_current (manager->config, manager);
meta_monitor_manager_rebuild_derived (manager);
/* Check if the current intended configuration is a result of an
XRandR call. Otherwise, hotplug_mode_update tells us to get
a new preferred mode on hotplug events to handle dynamic
guest resizing. */
if (new_config)
meta_monitor_manager_xrandr_rebuild_derived (manager);
else
meta_monitor_config_make_default (manager->config, manager);
}
else
{
if (!meta_monitor_config_apply_stored (manager->config, manager))
/* Check if the current intended configuration has the same outputs
as the new real one, or if the event is a result of an XRandR call.
If so, we can go straight to rebuild the logical config and tell
the outside world.
Otherwise, this event was caused by hotplug, so give a chance to
MetaMonitorConfig.
Note that we need to check both the timestamps and the list of
outputs, because the X server might emit spurious events with new
configTimestamps (bug 702804), and the driver may have changed
the EDID for some other reason (old qxl and vbox drivers). */
if (new_config || meta_monitor_config_match_current (manager->config, manager))
meta_monitor_manager_xrandr_rebuild_derived (manager);
else if (!meta_monitor_config_apply_stored (manager->config, manager))
meta_monitor_config_make_default (manager->config, manager);
}

View File

@@ -406,7 +406,7 @@ make_logical_config (MetaMonitorManager *manager)
for (j = 0; j < monitor_infos->len; j++)
{
MetaMonitorInfo *info = &g_array_index (monitor_infos, MetaMonitorInfo, i);
MetaMonitorInfo *info = &g_array_index (monitor_infos, MetaMonitorInfo, j);
if (meta_rectangle_equal (&crtc->rect,
&info->rect))
{

View File

@@ -392,6 +392,8 @@ int
meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
int index)
{
g_return_val_if_fail (index >= 0 && index < screen->n_monitor_infos, -1);
meta_screen_ensure_xinerama_indices (screen);
return screen->monitor_infos[index].xinerama_index;
@@ -877,83 +879,31 @@ meta_screen_free (MetaScreen *screen,
meta_display_ungrab (display);
}
typedef struct
{
Window xwindow;
XWindowAttributes attrs;
} WindowInfo;
static GList *
list_windows (MetaScreen *screen)
{
Window ignored1, ignored2;
Window *children;
guint n_children, i;
GList *result;
XQueryTree (screen->display->xdisplay,
screen->xroot,
&ignored1, &ignored2, &children, &n_children);
result = NULL;
for (i = 0; i < n_children; ++i)
{
WindowInfo *info = g_new0 (WindowInfo, 1);
meta_error_trap_push_with_return (screen->display);
XGetWindowAttributes (screen->display->xdisplay,
children[i], &info->attrs);
if (meta_error_trap_pop_with_return (screen->display))
{
meta_verbose ("Failed to get attributes for window 0x%lx\n",
children[i]);
g_free (info);
}
else
{
info->xwindow = children[i];
}
result = g_list_prepend (result, info);
}
if (children)
XFree (children);
return g_list_reverse (result);
}
void
meta_screen_manage_all_windows (MetaScreen *screen)
{
GList *windows;
GList *list;
meta_display_grab (screen->display);
Window *_children;
Window *children;
int n_children, i;
if (screen->guard_window == None)
screen->guard_window = create_guard_window (screen->display->xdisplay,
screen);
windows = list_windows (screen);
meta_stack_freeze (screen->stack);
for (list = windows; list != NULL; list = list->next)
meta_stack_tracker_get_stack (screen->stack_tracker, &_children, &n_children);
/* Copy the stack as it will be modified as part of the loop */
children = g_memdup (_children, sizeof (Window) * n_children);
for (i = 0; i < n_children; ++i)
{
WindowInfo *info = list->data;
meta_window_new_with_attrs (screen->display, info->xwindow, TRUE,
META_COMP_EFFECT_NONE,
&info->attrs);
meta_window_new (screen->display, children[i], TRUE,
META_COMP_EFFECT_NONE);
}
g_free (children);
meta_stack_thaw (screen->stack);
g_list_foreach (windows, (GFunc)g_free, NULL);
g_list_free (windows);
meta_display_ungrab (screen->display);
}
/**

View File

@@ -1484,14 +1484,12 @@ get_default_focus_window (MetaStack *stack,
* or top window in same group as not_this_one.
*/
MetaWindow *topmost_dock;
MetaWindow *transient_parent;
MetaWindow *topmost_in_group;
MetaWindow *topmost_overall;
MetaGroup *not_this_one_group;
GList *link;
topmost_dock = NULL;
transient_parent = NULL;
topmost_in_group = NULL;
topmost_overall = NULL;
@@ -1517,10 +1515,6 @@ get_default_focus_window (MetaStack *stack,
(workspace == NULL ||
meta_window_located_on_workspace (window, workspace)))
{
if (topmost_dock == NULL &&
window->type == META_WINDOW_DOCK)
topmost_dock = window;
if (not_this_one != NULL)
{
if (transient_parent == NULL &&
@@ -1538,10 +1532,6 @@ get_default_focus_window (MetaStack *stack,
topmost_in_group = window;
}
/* Note that DESKTOP windows can be topmost_overall so
* we prefer focusing desktop or other windows over
* focusing dock, even though docks are stacked higher.
*/
if (topmost_overall == NULL &&
window->type != META_WINDOW_DOCK &&
(!must_be_at_point ||
@@ -1563,7 +1553,7 @@ get_default_focus_window (MetaStack *stack,
else if (topmost_overall)
return topmost_overall;
else
return topmost_dock;
return NULL;
}
MetaWindow*

View File

@@ -484,12 +484,8 @@ struct _MetaWindowClass
MetaWindow* meta_window_new (MetaDisplay *display,
Window xwindow,
gboolean must_be_viewable);
MetaWindow* meta_window_new_with_attrs (MetaDisplay *display,
Window xwindow,
gboolean must_be_viewable,
MetaCompEffect effect,
XWindowAttributes *attrs);
gboolean must_be_viewable,
MetaCompEffect effect);
void meta_window_unmanage (MetaWindow *window,
guint32 timestamp);
void meta_window_calc_showing (MetaWindow *window);

View File

@@ -175,6 +175,7 @@ enum {
PROP_USER_TIME,
PROP_DEMANDS_ATTENTION,
PROP_URGENT,
PROP_SKIP_TASKBAR,
PROP_MUTTER_HINTS,
PROP_APPEARS_FOCUSED,
PROP_RESIZEABLE,
@@ -308,6 +309,9 @@ meta_window_get_property(GObject *object,
case PROP_URGENT:
g_value_set_boolean (value, win->wm_hints_urgent);
break;
case PROP_SKIP_TASKBAR:
g_value_set_boolean (value, win->skip_taskbar);
break;
case PROP_MUTTER_HINTS:
g_value_set_string (value, win->mutter_hints);
break;
@@ -468,6 +472,14 @@ meta_window_class_init (MetaWindowClass *klass)
FALSE,
G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_SKIP_TASKBAR,
g_param_spec_boolean ("skip-taskbar",
"Skip taskbar",
"Whether the skip-taskbar flag of WM_HINTS is set",
FALSE,
G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_MUTTER_HINTS,
g_param_spec_string ("mutter-hints",
@@ -659,53 +671,6 @@ maybe_leave_show_desktop_mode (MetaWindow *window)
}
}
MetaWindow*
meta_window_new (MetaDisplay *display,
Window xwindow,
gboolean must_be_viewable)
{
XWindowAttributes attrs;
MetaWindow *window;
meta_display_grab (display);
meta_error_trap_push (display); /* Push a trap over all of window
* creation, to reduce XSync() calls
*/
meta_error_trap_push_with_return (display);
if (XGetWindowAttributes (display->xdisplay,xwindow, &attrs))
{
if(meta_error_trap_pop_with_return (display) != Success)
{
meta_verbose ("Failed to get attributes for window 0x%lx\n",
xwindow);
meta_error_trap_pop (display);
meta_display_ungrab (display);
return NULL;
}
window = meta_window_new_with_attrs (display, xwindow,
must_be_viewable,
META_COMP_EFFECT_CREATE,
&attrs);
}
else
{
meta_error_trap_pop_with_return (display);
meta_verbose ("Failed to get attributes for window 0x%lx\n",
xwindow);
meta_error_trap_pop (display);
meta_display_ungrab (display);
return NULL;
}
meta_error_trap_pop (display);
meta_display_ungrab (display);
return window;
}
/* The MUTTER_WM_CLASS_FILTER environment variable is designed for
* performance and regression testing environments where we want to do
* tests with only a limited set of windows and ignore all other windows
@@ -816,12 +781,12 @@ meta_window_should_attach_to_parent (MetaWindow *window)
}
MetaWindow*
meta_window_new_with_attrs (MetaDisplay *display,
Window xwindow,
gboolean must_be_viewable,
MetaCompEffect effect,
XWindowAttributes *attrs)
meta_window_new (MetaDisplay *display,
Window xwindow,
gboolean must_be_viewable,
MetaCompEffect effect)
{
XWindowAttributes attrs;
MetaWindow *window;
GSList *tmp;
MetaWorkspace *space;
@@ -830,8 +795,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
MetaMoveResizeFlags flags;
MetaScreen *screen;
g_assert (attrs != NULL);
meta_verbose ("Attempting to manage 0x%lx\n", xwindow);
if (meta_display_xwindow_is_a_no_focus_window (display, xwindow))
@@ -841,12 +804,28 @@ meta_window_new_with_attrs (MetaDisplay *display,
return NULL;
}
meta_error_trap_push (display); /* Push a trap over all of window
* creation, to reduce XSync() calls
*/
/*
* This function executes without any server grabs held. This means that
* the window could have already gone away, or could go away at any point,
* so we must be careful with X error handling.
*/
if (!XGetWindowAttributes (display->xdisplay, xwindow, &attrs))
{
meta_verbose ("Failed to get attributes for window 0x%lx\n",
xwindow);
goto error;
}
screen = NULL;
for (tmp = display->screens; tmp != NULL; tmp = tmp->next)
{
MetaScreen *scr = tmp->data;
if (scr->xroot == attrs->root)
if (scr->xroot == attrs.root)
{
screen = tmp->data;
break;
@@ -856,14 +835,14 @@ meta_window_new_with_attrs (MetaDisplay *display,
g_assert (screen);
/* A black list of override redirect windows that we don't need to manage: */
if (attrs->override_redirect &&
if (attrs.override_redirect &&
(xwindow == screen->no_focus_window ||
xwindow == screen->flash_window ||
xwindow == screen->wm_sn_selection_window ||
attrs->class == InputOnly ||
attrs.class == InputOnly ||
/* any windows created via meta_create_offscreen_window: */
(attrs->x == -100 && attrs->y == -100
&& attrs->width == 1 && attrs->height == 1) ||
(attrs.x == -100 && attrs.y == -100
&& attrs.width == 1 && attrs.height == 1) ||
xwindow == screen->wm_cm_selection_window ||
xwindow == screen->guard_window ||
(display->compositor &&
@@ -873,34 +852,28 @@ meta_window_new_with_attrs (MetaDisplay *display,
)
) {
meta_verbose ("Not managing our own windows\n");
return NULL;
goto error;
}
if (maybe_filter_window (display, xwindow, must_be_viewable, attrs))
if (maybe_filter_window (display, xwindow, must_be_viewable, &attrs))
{
meta_verbose ("Not managing filtered window\n");
return NULL;
goto error;
}
/* Grab server */
meta_display_grab (display);
meta_error_trap_push (display); /* Push a trap over all of window
* creation, to reduce XSync() calls
*/
meta_verbose ("must_be_viewable = %d attrs->map_state = %d (%s)\n",
meta_verbose ("must_be_viewable = %d attrs.map_state = %d (%s)\n",
must_be_viewable,
attrs->map_state,
(attrs->map_state == IsUnmapped) ?
attrs.map_state,
(attrs.map_state == IsUnmapped) ?
"IsUnmapped" :
(attrs->map_state == IsViewable) ?
(attrs.map_state == IsViewable) ?
"IsViewable" :
(attrs->map_state == IsUnviewable) ?
(attrs.map_state == IsUnviewable) ?
"IsUnviewable" :
"(unknown)");
existing_wm_state = WithdrawnState;
if (must_be_viewable && attrs->map_state != IsViewable)
if (must_be_viewable && attrs.map_state != IsViewable)
{
/* Only manage if WM_STATE is IconicState or NormalState */
gulong state;
@@ -913,9 +886,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
(state == IconicState || state == NormalState)))
{
meta_verbose ("Deciding not to manage unmapped or unviewable window 0x%lx\n", xwindow);
meta_error_trap_pop (display);
meta_display_ungrab (display);
return NULL;
goto error;
}
existing_wm_state = state;
@@ -923,29 +894,26 @@ meta_window_new_with_attrs (MetaDisplay *display,
wm_state_to_string (existing_wm_state));
}
meta_error_trap_push_with_return (display);
/*
* XAddToSaveSet can only be called on windows created by a different client.
* with Mutter we want to be able to create manageable windows from within
* the process (such as a dummy desktop window), so we do not want this
* call failing to prevent the window from being managed -- wrap it in its
* own error trap (we use the _with_return() version here to ensure that
* XSync() is done on the pop, otherwise the error will not get caught).
* the process (such as a dummy desktop window). As we do not want this
* call failing to prevent the window from being managed, we call this
* before creating the return-checked error trap.
*/
meta_error_trap_push_with_return (display);
XAddToSaveSet (display->xdisplay, xwindow);
meta_error_trap_pop_with_return (display);
meta_error_trap_push_with_return (display);
event_mask = PropertyChangeMask | ColormapChangeMask;
if (attrs->override_redirect)
if (attrs.override_redirect)
event_mask |= StructureNotifyMask;
/* If the window is from this client (a menu, say) we need to augment
* the event mask, not replace it. For windows from other clients,
* attrs->your_event_mask will be empty at this point.
* attrs.your_event_mask will be empty at this point.
*/
XSelectInput (display->xdisplay, xwindow, attrs->your_event_mask | event_mask);
XSelectInput (display->xdisplay, xwindow, attrs.your_event_mask | event_mask);
{
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
@@ -967,11 +935,11 @@ meta_window_new_with_attrs (MetaDisplay *display,
#endif
/* Get rid of any borders */
if (attrs->border_width != 0)
if (attrs.border_width != 0)
XSetWindowBorderWidth (display->xdisplay, xwindow, 0);
/* Get rid of weird gravities */
if (attrs->win_gravity != NorthWestGravity)
if (attrs.win_gravity != NorthWestGravity)
{
XSetWindowAttributes set_attrs;
@@ -987,9 +955,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
{
meta_verbose ("Window 0x%lx disappeared just as we tried to manage it\n",
xwindow);
meta_error_trap_pop (display);
meta_display_ungrab (display);
return NULL;
goto error;
}
@@ -1018,22 +984,22 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->desc = g_strdup_printf ("0x%lx", window->xwindow);
window->override_redirect = attrs->override_redirect;
window->override_redirect = attrs.override_redirect;
/* avoid tons of stack updates */
meta_stack_freeze (window->screen->stack);
window->rect.x = attrs->x;
window->rect.y = attrs->y;
window->rect.width = attrs->width;
window->rect.height = attrs->height;
window->rect.x = attrs.x;
window->rect.y = attrs.y;
window->rect.width = attrs.width;
window->rect.height = attrs.height;
/* And border width, size_hints are the "request" */
window->border_width = attrs->border_width;
window->size_hints.x = attrs->x;
window->size_hints.y = attrs->y;
window->size_hints.width = attrs->width;
window->size_hints.height = attrs->height;
window->border_width = attrs.border_width;
window->size_hints.x = attrs.x;
window->size_hints.y = attrs.y;
window->size_hints.width = attrs.width;
window->size_hints.height = attrs.height;
/* initialize the remaining size_hints as if size_hints.flags were zero */
meta_set_normal_hints (window, NULL);
@@ -1041,9 +1007,9 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->saved_rect = window->rect;
window->user_rect = window->rect;
window->depth = attrs->depth;
window->xvisual = attrs->visual;
window->colormap = attrs->colormap;
window->depth = attrs.depth;
window->xvisual = attrs.visual;
window->colormap = attrs.colormap;
window->title = NULL;
window->icon_name = NULL;
@@ -1078,7 +1044,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->minimized = FALSE;
window->tab_unminimized = FALSE;
window->iconic = FALSE;
window->mapped = attrs->map_state != IsUnmapped;
window->mapped = attrs.map_state != IsUnmapped;
window->hidden = FALSE;
window->visible_to_compositor = FALSE;
window->pending_compositor_effect = effect;
@@ -1483,7 +1449,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
unminimize_window_and_all_transient_parents (window);
meta_error_trap_pop (display); /* pop the XSync()-reducing trap */
meta_display_ungrab (display);
window->constructing = FALSE;
@@ -1496,6 +1461,10 @@ meta_window_new_with_attrs (MetaDisplay *display,
g_signal_emit_by_name (window->display, "window-marked-urgent", window);
return window;
error:
meta_error_trap_pop (display);
return NULL;
}
/* This function should only be called from the end of meta_window_new_with_attrs () */
@@ -2090,23 +2059,35 @@ set_net_wm_state (MetaWindow *window)
if (window->fullscreen)
{
data[0] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[0]);
data[1] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[1]);
data[2] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[2]);
data[3] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[3]);
if (window->fullscreen_monitors[0] >= 0)
{
data[0] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[0]);
data[1] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[1]);
data[2] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[2]);
data[3] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[3]);
meta_verbose ("Setting _NET_WM_FULLSCREEN_MONITORS\n");
meta_error_trap_push (window->display);
XChangeProperty (window->display->xdisplay,
window->xwindow,
window->display->atom__NET_WM_FULLSCREEN_MONITORS,
XA_CARDINAL, 32, PropModeReplace,
(guchar*) data, 4);
meta_error_trap_pop (window->display);
meta_verbose ("Setting _NET_WM_FULLSCREEN_MONITORS\n");
meta_error_trap_push (window->display);
XChangeProperty (window->display->xdisplay,
window->xwindow,
window->display->atom__NET_WM_FULLSCREEN_MONITORS,
XA_CARDINAL, 32, PropModeReplace,
(guchar*) data, 4);
meta_error_trap_pop (window->display);
}
else
{
meta_verbose ("Clearing _NET_WM_FULLSCREEN_MONITORS\n");
meta_error_trap_push (window->display);
XDeleteProperty (window->display->xdisplay,
window->xwindow,
window->display->atom__NET_WM_FULLSCREEN_MONITORS);
meta_error_trap_pop (window->display);
}
}
}
@@ -2292,7 +2273,6 @@ idle_calc_showing (gpointer data)
GSList *should_hide;
GSList *unplaced;
GSList *displays;
MetaWindow *first_window;
guint queue_index = GPOINTER_TO_INT (data);
g_return_val_if_fail (queue_pending[queue_index] != NULL, FALSE);
@@ -2345,10 +2325,6 @@ idle_calc_showing (gpointer data)
should_show = g_slist_sort (should_show, stackcmp);
should_show = g_slist_reverse (should_show);
first_window = copy->data;
meta_display_grab (first_window->display);
tmp = unplaced;
while (tmp != NULL)
{
@@ -2421,8 +2397,6 @@ idle_calc_showing (gpointer data)
}
}
meta_display_ungrab (first_window->display);
g_slist_free (copy);
g_slist_free (unplaced);
@@ -5890,7 +5864,8 @@ meta_window_focus (MetaWindow *window,
window->desc, window->input, window->take_focus);
if (window->display->grab_window &&
window->display->grab_window->all_keys_grabbed)
window->display->grab_window->all_keys_grabbed &&
!window->display->grab_window->unmanaging)
{
meta_topic (META_DEBUG_FOCUS,
"Current focus window %s has global keygrab, not focusing window %s after all\n",
@@ -5961,6 +5936,25 @@ meta_window_focus (MetaWindow *window,
"Sending WM_TAKE_FOCUS to %s since take_focus = true\n",
window->desc);
if (!window->input)
{
/* The "Globally Active Input" window case, where the window
* doesn't want us to call XSetInputFocus on it, but does
* want us to send a WM_TAKE_FOCUS.
*
* Normally, we want to just leave the focus undisturbed until
* the window respnds to WM_TAKE_FOCUS, but if we're unmanaging
* the current focus window we *need* to move the focus away, so
* we focus the no_focus_window now (and set
* display->focus_window to that) before sending WM_TAKE_FOCUS.
*/
if (window->display->focus_window != NULL &&
window->display->focus_window->unmanaging)
meta_display_focus_the_no_focus_window (window->display,
window->screen,
timestamp);
}
meta_display_request_take_focus (window->display,
window,
timestamp);
@@ -8310,6 +8304,7 @@ recalc_window_features (MetaWindow *window)
gboolean old_has_resize_func;
gboolean old_has_shade_func;
gboolean old_always_sticky;
gboolean old_skip_taskbar;
old_has_close_func = window->has_close_func;
old_has_minimize_func = window->has_minimize_func;
@@ -8317,6 +8312,7 @@ recalc_window_features (MetaWindow *window)
old_has_resize_func = window->has_resize_func;
old_has_shade_func = window->has_shade_func;
old_always_sticky = window->always_sticky;
old_skip_taskbar = window->skip_taskbar;
/* Use MWM hints initially */
window->decorated = window->mwm_decorated;
@@ -8509,6 +8505,9 @@ recalc_window_features (MetaWindow *window)
window->skip_taskbar,
window->skip_pager);
if (old_skip_taskbar != window->skip_taskbar)
g_object_notify (G_OBJECT (window), "skip-taskbar");
/* FIXME:
* Lame workaround for recalc_window_features
* being used overzealously. The fix is to
@@ -9711,47 +9710,51 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,
switch (xev->evtype)
{
case XI_ButtonRelease:
meta_display_check_threshold_reached (window->display,
xev->root_x,
xev->root_y);
/* If the user was snap moving then ignore the button release
* because they may have let go of shift before releasing the
* mouse button and they almost certainly do not want a
* non-snapped movement to occur from the button release.
*/
if (!window->display->grab_last_user_action_was_snap)
if (xev->detail == 1 ||
xev->detail == meta_prefs_get_mouse_button_resize ())
{
if (meta_grab_op_is_moving (window->display->grab_op))
meta_display_check_threshold_reached (window->display,
xev->root_x,
xev->root_y);
/* If the user was snap moving then ignore the button
* release because they may have let go of shift before
* releasing the mouse button and they almost certainly do
* not want a non-snapped movement to occur from the button
* release.
*/
if (!window->display->grab_last_user_action_was_snap)
{
if (window->tile_mode != META_TILE_NONE)
meta_window_tile (window);
else if (xev->root == window->screen->xroot)
update_move (window,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y);
}
else if (meta_grab_op_is_resizing (window->display->grab_op))
{
if (xev->root == window->screen->xroot)
update_resize (window,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y,
TRUE);
if (meta_grab_op_is_moving (window->display->grab_op))
{
if (window->tile_mode != META_TILE_NONE)
meta_window_tile (window);
else if (xev->root == window->screen->xroot)
update_move (window,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y);
}
else if (meta_grab_op_is_resizing (window->display->grab_op))
{
if (xev->root == window->screen->xroot)
update_resize (window,
xev->mods.effective & ShiftMask,
xev->root_x,
xev->root_y,
TRUE);
/* If a tiled window has been dragged free with a
* mouse resize without snapping back to the tiled
* state, it will end up with an inconsistent tile
* mode on mouse release; cleaning the mode earlier
* would break the ability to snap back to the tiled
* state, so we wait until mouse release.
*/
update_tile_mode (window);
/* If a tiled window has been dragged free with a
* mouse resize without snapping back to the tiled
* state, it will end up with an inconsistent tile
* mode on mouse release; cleaning the mode earlier
* would break the ability to snap back to the tiled
* state, so we wait until mouse release.
*/
update_tile_mode (window);
}
}
meta_display_end_grab_op (window->display, xev->time);
}
meta_display_end_grab_op (window->display, xev->time);
break;
case XI_Motion:

View File

@@ -80,7 +80,8 @@ item(MULTIPLE)
item(TIMESTAMP)
item(VERSION)
item(ATOM_PAIR)
item(BACKLIGHT)
item(Backlight)
item(hotplug_mode_update)
/* Oddities: These are used, and we need atoms for them,
* but when we need all _NET_WM hints (i.e. when we're making

View File

@@ -78,6 +78,7 @@ MetaCompositor *meta_display_get_compositor (MetaDisplay *display);
GSList *meta_display_get_screens (MetaDisplay *display);
gboolean meta_display_has_shape (MetaDisplay *display);
gboolean meta_display_has_sync (MetaDisplay *display);
MetaScreen *meta_display_screen_for_root (MetaDisplay *display,
Window xroot);
@@ -88,6 +89,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

@@ -419,13 +419,13 @@ typedef struct
*/
GSList *bindings;
/** for keybindings that can have shift or not like Alt+Tab */
/* for keybindings that can have shift or not like Alt+Tab */
gboolean add_shift:1;
/** for keybindings that apply only to a window */
/* for keybindings that apply only to a window */
gboolean per_window:1;
/** for keybindings not added with meta_display_add_keybinding() */
/* for keybindings not added with meta_display_add_keybinding() */
gboolean builtin:1;
} MetaKeyPref;