Compare commits

...

66 Commits

Author SHA1 Message Date
bb9501dbdf compositor: Remove meta_compositor_window_[un]mapped
We no longer unmap the toplevel windows during normal operation. The
toplevel state is tied to the window's lifetime.

Call meta_compositor_add_window / meta_compositor_remove_window instead...
2013-12-09 15:49:50 -05:00
1db95bc32b Move _NET_WM_WINDOW_OPACITY handling to the standard window-props interface
This removes one X11 dependency that the MetaWindowActor interface has,
making it easier for us to use Wayland on this one...

https://bugzilla.gnome.org/show_bug.cgi?id=720106
2013-12-09 15:43:52 -05:00
93a8933282 compositor: Remove atom_x_root_pixmap
It's unused

https://bugzilla.gnome.org/show_bug.cgi?id=720106
2013-12-09 15:43:16 -05:00
5a63aaa5ac window-actor: Fix build
This was a bad rebase...
2013-12-09 14:17:06 -05:00
a3eb5e562a window-actor: Move signal handler connections to the meta-window setter 2013-12-09 14:07:25 -05:00
8a76383eca window-actor: Make the meta-window property construct-only
We don't deal with setting this property at all, and it's unlikely
to come up in future settings, so just don't allow setting it at all.

https://bugzilla.gnome.org/show_bug.cgi?id=678989
2013-12-09 14:06:13 -05:00
734deeb17c window-actor: Remove meta-screen property
This can be inferred from the window. Don't allow anybody to set it.

https://bugzilla.gnome.org/show_bug.cgi?id=678989
2013-12-09 14:06:13 -05:00
f8b4c28278 window-actor: Remove (private) xwindow property
This should make it easier to construct a MetaWindowActor from bindings.

https://bugzilla.gnome.org/show_bug.cgi?id=678989
2013-12-09 14:06:13 -05:00
3e179c07bc window: Add a simple meta_window_get_toplevel_xwindow utility
To replace all the places where we do:

  window->frame ? window->frame->xwindow : window->xwindow

or similar...
2013-12-09 14:06:13 -05:00
56aae17b46 window-actor: Remove outdated code path
The shadow is added in the paint step, not as a separate actor,
so the raise is a no-op. It also gets rid of an annoying misspelling
that's driving me crazy.
2013-12-09 14:06:12 -05:00
78741846a4 Update Chinese simplified translation 2013-12-07 15:02:43 +08:00
55180f5bb3 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.
2013-12-06 16:39:40 +01:00
62b884dd42 display: Fix checks for KeyPress/ButtonPress 2013-12-06 00:51:41 -05:00
3283018bfb Use the correct frame size during unmaximize
When unmaximizing, we changed bits of window state, then called out
to code that used the frame extents *before* we cleared old cached
extents. Clear the cache up-front as soon as we change the window
state.

https://bugzilla.gnome.org/show_bug.cgi?id=714707
2013-12-05 11:15:23 -05:00
55226ada8a 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-05 09:02:44 -05:00
ff790f7b39 window-props.c: React to changes to _GTK_FRAME_EXTENTS
When _GTK_FRAME_EXTENTS changes, we need to redo constraints on
the window - this matters in particular if the toolkit removes
invisible borders when a window is maximized, since otherwise
the maximized window will be positioned as if it still has
invisible borders.

https://bugzilla.gnome.org/show_bug.cgi?id=714707
2013-12-05 07:47:57 -05:00
899570d213 background-actor: Remove custom get_paint_volume
The paint volume should be based on what we paint, not what the content
wants to be painted as. Thus, it should be the allocation.
2013-12-03 14:32:28 -05:00
3b2506851c prefs: Properly add new META_KEYBINDING_ACTION_* value
In addition to 4373916d9d
2013-11-29 13:53:15 +01:00
9b88059e55 window: Proper argument naming for meta_window_client_rect_to_frame_rect 2013-11-29 13:52:18 +01:00
59168b2c64 window: Fix deprecated version of get_outer_rect 2013-11-29 09:12:16 +01:00
47144253e4 cullable: Turn cull_out / reset_culling into a separate interface
Instead of hardcoded knowledge of certain classes in MetaWindowGroup,
create a generic interface that all actors can implement to get parts of
their regions culled out during redraw, without needing any special
knowledge of how to handle a specific actor.

The names now are a bit suspect. MetaBackgroundGroup is a simple
MetaCullable that knows how to cull children, and MetaWindowGroup is the
"toplevel" cullable that computes the initial two regions. A future
cleanup here could be to merge MetaWindowGroup / MetaBackgroundGroup so
that we only have a generic MetaSimpleCullable, and move the "toplevel"
cullability to be a MetaCullableToplevel.

https://bugzilla.gnome.org/show_bug.cgi?id=714706
2013-11-25 15:08:22 -05:00
d8c66077f0 window-actor: Move the operations we need to do when we cull out here
Soon, we'll move this into a generic MetaCullable interface, but for
now, just put hardcoded knowledge in MetaWindowGroup.

https://bugzilla.gnome.org/show_bug.cgi?id=714706
2013-11-25 15:08:22 -05:00
59a01137e1 window-group: Decompose culling operations into two methods
This also fixes a bug in the translation of clip_region.

We will add an interface for this soon, so we can recursively cull like this...

https://bugzilla.gnome.org/show_bug.cgi?id=714706
2013-11-25 15:08:22 -05:00
ce3804ee04 display: Use MetaWindow for auto-raise callbacks
This allows us to autoraise Wayland windows... well, except for the
XQueryPointer, but we'll replace that soon.

https://bugzilla.gnome.org/show_bug.cgi?id=715030
2013-11-25 15:08:21 -05:00
f0bc53ce5a display: Fix logic for determining whether our focus was successful
In some cases, we can focus the frame window instead of the client
window, so make sure that our checks include that as well.

https://bugzilla.gnome.org/show_bug.cgi?id=715030
2013-11-25 15:08:21 -05:00
b8938e9d4d window-actor: Fix a copy/paste typo 2013-11-21 17:36:20 -05:00
7116d9cedb background-group: Fix cast warning 2013-11-21 16:07:51 -05:00
66fb86fd0c background-group: Use the Clutter iteration APIs 2013-11-21 16:07:51 -05:00
59cfbb07c8 background-group: Remove some unnecessary cruft 2013-11-21 16:07:51 -05:00
dc5bc3fea8 idle-monitor: Fix a GSList leak
https://bugzilla.gnome.org/show_bug.cgi?id=712833
2013-11-21 19:24:07 +01:00
fbbc32422e Rename meta_window_get_outer_rect() to meta_window_get_frame_rect()
For clarity, rename meta_window_get_outer_rect() to match terminology
we use elsewhere. The old function is left as a deprecated
compatibility wrapper.
2013-11-19 13:28:23 -05:00
fe8829f324 Stop passing around MetaFrameBorders
Instead of passing around MetaFrameBorders, compute it when we need it.
This also allows us to know that we are using MetaFrameBorders only for windows
with frames (where it is meaningful) and not for frameless windows, which
can have custom borders which we need to interpret differently.

https://bugzilla.gnome.org/show_bug.cgi?id=707194
2013-11-19 13:28:23 -05:00
b4036e061a MetaFrame: Cache borders
Cache the computed border size so we can fetch the border size at
any time without worrying that we'll be spending too much time in
the theme code (in some cases we might allocate a PangoFontDescription
or do other significant work.)

The main effort here is clearing the cache when various bits of window
state change that could potentially affect the computed borders.

https://bugzilla.gnome.org/show_bug.cgi?id=707194
2013-11-19 13:28:23 -05:00
4ee9f3563b Use utility functions to convert between frame and client rectangles
There are extensive places in the code where we convert between the client
rectangle and the frame rectangle. Instead of manually doing it use
new helper functions on MetaWindow and the existing meta_window_get_outer_rect().

This fixes a number of bugs where the computation was being done incorrectly,
most of these bugs are with the recently added custom frame extents, but
some relate to invisible borders or even simply to confusion between the
window and frame rectangle.

Switch the placement code to place the frame rectangle rather
than the client window - this simplifies things considerably.

https://bugzilla.gnome.org/show_bug.cgi?id=707194
2013-11-19 13:28:23 -05:00
c652a54f59 constraints: account for decorations when positioning modal dialogs
What we want to achieve is that the dialog is visually centered
on the parent, including the decorations for both, and making sure
that CSD/frame_extents are respected.

https://bugzilla.gnome.org/show_bug.cgi?id=707194
2013-11-19 13:28:23 -05:00
61881477ac Track the X Shape input region and use it for picking
We now track whether a window has an input shape specified via the X
Shape extension. Intersecting that with the bounding shape (as required
by the X Shape extension) we use the resulting rectangles to paint
window silhouettes when picking. As well as improving the correctness of
picking this should also be much more efficient because typically when
only picking solid rectangles then the need to actually render and issue
a read_pixels request can be optimized away and instead the picking is
done on the cpu.
2013-11-18 13:06:54 -05:00
4373916d9d Add keyboard shortcut for Always on Top, bug 704831 2013-11-16 22:48:28 +05:30
660d7df5ab Revert "Add keyboard shortcut for Always on Top"
This reverts commit b7e3f627f1.
2013-11-16 21:34:48 +05:30
b7e3f627f1 Add keyboard shortcut for Always on Top 2013-11-16 21:14:30 +05:30
ca5d115715 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:55:42 +01:00
21c46852cd Bump version to 3.11.2
Update NEWS.
2013-11-13 20:50:11 +01:00
10036832dd doc: Fix file globs
Any files matching the previously used globs are no longer distributed,
breaking distcheck. Match the actual sources in compositor/, core/, meta/
and ui/ instead.
2013-11-13 20:49:52 +01:00
25b5ea8b4f screen: Laters are not GSources
This warns with the new GLib when we destroy the screen.

https://bugzilla.gnome.org/show_bug.cgi?id=711731
2013-11-09 11:46:01 -05:00
20beaf7fe1 compositor: Clean up comment
So it seems that we were intentionally delaying the output window,
although I wonder why...
2013-11-05 09:15:23 -05:00
e72af50420 compositor: Initialize the plugin manager after initializing the output window
Plugins like gnome-shell may want to grab the output window immediately
before bouncing back to the mainloop.
2013-11-04 10:39:49 -05:00
ef4417b717 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:52:06 +00:00
cf943627e2 build: Make sure built-sources are introspected as needed 2013-10-31 00:09:15 +01:00
96543cb009 build: Do not ship generated source-files in tarball 2013-10-30 23:42:12 +01:00
fbb2207f8c Fix typo 2013-10-30 17:14:16 +01:00
cce8a4341b Bump version to 3.11.1
Update NEWS.
2013-10-30 16:34:59 +01:00
b82784ee46 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-10-29 16:26:00 -04:00
6b8959916c Mutter-Wayland: fix build failure
Bug https://bugzilla.gnome.org/show_bug.cgi?id=710565
2013-10-29 13:04:48 +00:00
ecc1830296 meta-cursor-tracker: Add missing include of Xcursor.h 2013-10-29 11:39:02 +01:00
497916aad7 Updated Dutch translation 2013-10-25 00:25:49 +02:00
e171a31ac5 monitor: expose min-backlight-step
Expose min-backlight-step so that gnome-settings-daemon can
support backlights with less than 10 steps without mutter
normalizing the brightness back to its original value

https://bugzilla.gnome.org/show_bug.cgi?id=710380
2013-10-21 23:22:41 +02:00
a9a10aaa20 MonitorConfig: Use new UPower API
The "changed" signal was removed. Use "notify" instead
to track just the lid-is-closed state.
2013-10-21 14:00:48 +02:00
656d079ffc screen: Name the guard window
So that extensons can recognize it, for the case where they
want to watch the window list.

https://bugzilla.gnome.org/show_bug.cgi?id=710346
2013-10-16 22:39:21 -04:00
d801f699af link mutter-wayland to mutter git repos 2013-10-16 15:37:48 +02:00
89d01d2c17 core: Remove old unused methods 2013-10-16 01:29:56 -04:00
ec284bc56a display: Fix whitespace / code style with autoraise stuff 2013-10-16 00:34:22 -04:00
db2e00d41c keybindings: Remove unused function 2013-10-15 23:38:48 -04:00
0a616c9fcb keybindings: Remove unused parameter from process_event 2013-10-15 23:38:47 -04:00
fed3cd9e82 keybindings: Drop an unnecessary check 2013-10-15 23:38:47 -04:00
d0d8a3d4ea window: Remove timestamp argument from change_workspace_by_index
It's unused, since we aren't activating the workspace.

https://bugzilla.gnome.org/show_bug.cgi?id=709776
2013-10-15 15:45:21 -04:00
bdf5f88349 display: Deduplicate cursor loading code
Rather than do the cursor -> name translation ourselves in two different
places, use the facilities in libXcursor to do it for us. Put the shared
piece of code in meta-cursor-tracker, and use it for both server-side and
client-side cursor loading.
2013-10-15 15:39:58 -04:00
809dbe16d6 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 21:26:36 +02:00
50 changed files with 2227 additions and 1959 deletions

View File

@ -8,3 +8,5 @@ EXTRA_DIST = HACKING MAINTAINERS rationales.txt
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}

24
NEWS
View File

@ -1,3 +1,27 @@
3.11.2
======
* Fix resize operations using mouse-button-modifier [Lionel; #710251]
* Misc. fixes and cleanups [Jasper, Rico, Florian; #711731]
Contributors:
Lionel Landwerlin, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz
3.11.1
======
* Don't require at least one output device to be connected [Giovanni; #709009]
* Name the guard window [Andrew; #710346]
* Use new UPower API [Bastien]
* Expose min-backlight-step [Asad; #710380]
* Don't focus the no-focus-window for globally active windows [Jasper; #710296]
* Misc. fixes and cleanups [Jasper, Rico, Olav, Magdalen; #709776]
Contributors:
Magdalen Berns, Giovanni Campagna, Asad Mehmood, Bastien Nocera,
Jasper St. Pierre, Rico Tzschichholz, Olav Vitters, Andrew Walton
Translations:
Reinout van Schouwen [nl]
3.10.1
======
* Don't apply fullscreen workarounds to CSD windows [Giovanni; #708718]

View File

@ -1,8 +1,9 @@
AC_PREREQ(2.50)
AC_CONFIG_MACRO_DIR([m4])
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [10])
m4_define([mutter_micro_version], [1])
m4_define([mutter_minor_version], [11])
m4_define([mutter_micro_version], [2])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@ -76,7 +77,7 @@ MUTTER_PC_MODULES="
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.15.90
cogl-1.0 >= 1.15.6
upower-glib > 0.9.11
upower-glib >= 0.99.0
gnome-desktop-3.0
"

View File

@ -49,8 +49,8 @@ FIXXREF_OPTIONS=
# Used for dependencies. The docs will be rebuilt if any of these change.
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
HFILE_GLOB=$(top_srcdir)/src/*.h
CFILE_GLOB=$(top_srcdir)/src/*.c
HFILE_GLOB=$(top_srcdir)/src/*/*.h
CFILE_GLOB=$(top_srcdir)/src/*/*.c
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h

View File

@ -96,8 +96,6 @@ meta_compositor_hide_window
meta_compositor_switch_workspace
meta_compositor_maximize_window
meta_compositor_unmaximize_window
meta_compositor_window_mapped
meta_compositor_window_unmapped
meta_compositor_sync_window_geometry
meta_compositor_set_updates_frozen
meta_compositor_queue_frame_drawn
@ -207,7 +205,6 @@ meta_key_binding_get_modifiers
meta_key_binding_get_mask
meta_key_binding_is_builtin
meta_keybindings_set_custom_handler
meta_keybindings_switch_window
meta_screen_ungrab_all_keys
meta_screen_grab_all_keys
</SECTION>
@ -389,6 +386,23 @@ MetaWindowActorPrivate
meta_window_actor_get_type
</SECTION>
<SECTION>
<FILE>meta-cullable</FILE>
<TITLE>MetaCullable</TITLE>
MetaCullable
MetaCullableInterface
meta_cullable_cull_out
meta_cullable_reset_culling
meta_cullable_cull_out_children
meta_cullable_reset_culling_children
<SUBSECTION Standard>
META_TYPE_CULLABLE
META_CULLABLE
META_IS_CULLABLE
META_CULLABLE_GET_IFACE
meta_cullable_get_type
</SECTION>
<SECTION>
<FILE>prefs</FILE>
MetaPreference
@ -542,7 +556,10 @@ meta_window_is_override_redirect
meta_window_is_skip_taskbar
meta_window_get_rect
meta_window_get_input_rect
meta_window_get_frame_rect
meta_window_get_outer_rect
meta_window_client_rect_to_frame_rect
meta_window_frame_rect_to_client_rect
meta_window_get_screen
meta_window_get_display
meta_window_get_xwindow

View File

@ -21,6 +21,7 @@ environment.</description>
-->
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" />
<download-page rdf:resource="http://download.gnome.org/sources/mutter/" />
<download-page rdf:resource="http://download.gnome.org/sources/mutter-wayland/" />
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />

230
po/nl.po
View File

@ -7,10 +7,9 @@
msgid ""
msgstr ""
"Project-Id-Version: mutter\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=mutter"
"&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-08-18 20:03+0000\n"
"PO-Revision-Date: 2013-10-12 00:32+0200\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-10-25 00:25+0200\n"
"PO-Revision-Date: 2013-10-25 00:23+0200\n"
"Last-Translator: Reinout van Schouwen <reinouts@gnome.org>\n"
"Language-Team: Dutch <vertaling@vrijschrift.org>\n"
"Language: nl\n"
@ -18,7 +17,6 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Virtaal 0.7.1\n"
"X-Project-Style: gnome\n"
#: ../src/50-mutter-navigation.xml.in.h:1
@ -211,16 +209,16 @@ msgstr "Weergave gesplitst op rechts"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: ../src/compositor/compositor.c:589
#: ../src/compositor/compositor.c:596
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
"\"."
msgstr ""
"Er is al een andere compositing manager actief op scherm %i van display %"
"s."
"Er is al een andere compositing manager actief op scherm %i van display "
"%s."
#: ../src/compositor/meta-background.c:1076
#: ../src/compositor/meta-background.c:1075
msgid "background texture could not be created from file"
msgstr "aanmaken achtergrondstructuur uit bestand mislukt"
@ -235,7 +233,6 @@ msgstr "Onbekende aanvraag voor vensterinformatie: %d"
#: ../src/core/delete.c:111
#, c-format
#| msgid "<tt>%s</tt> is not responding."
msgid "“%s” is not responding."
msgstr "%s reageert niet."
@ -281,7 +278,6 @@ msgstr ""
#: ../src/core/keybindings.c:1333
#, c-format
#| msgid "\"%s\" is not a valid value for focus attribute"
msgid "\"%s\" is not a valid accelerator\n"
msgstr "%s is geen geldige sneltoets\n"
@ -322,7 +318,7 @@ msgstr ""
"Kon geen thema vinden! Zorg ervoor dat %s bestaat en de gebruikelijke "
"thema's bevat.\n"
#: ../src/core/monitor.c:711
#: ../src/core/monitor.c:696
msgid "Built-in display"
msgstr "Ingebouwd beeldscherm"
@ -330,9 +326,8 @@ msgstr "Ingebouwd beeldscherm"
#. the vendor), it's Unknown followed by a size in inches,
#. like 'Unknown 15"'
#.
#: ../src/core/monitor.c:739
#: ../src/core/monitor.c:724
#, c-format
#| msgid "Unknown element %s"
msgid "Unknown %s"
msgstr "Onbekend %s"
@ -394,12 +389,12 @@ msgstr ""
msgid "Workspace %d"
msgstr "Werkblad %d"
#: ../src/core/screen.c:534
#: ../src/core/screen.c:540
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Scherm %d op display '%s' is ongeldig\n"
#: ../src/core/screen.c:550
#: ../src/core/screen.c:556
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@ -408,19 +403,19 @@ msgstr ""
"Scherm %d op display %s heeft al een window manager; probeer de optie: --"
"replace te gebruiken om de huidige window manager te vervangen.\n"
#: ../src/core/screen.c:577
#: ../src/core/screen.c:583
#, c-format
msgid ""
"Could not acquire window manager selection on screen %d display \"%s\"\n"
msgstr ""
"Kon window manager-selectie niet verkrijgen op scherm %d display %s\n"
#: ../src/core/screen.c:655
#: ../src/core/screen.c:661
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "Scherm %d op display %s heeft al een window manager\n"
#: ../src/core/screen.c:846
#: ../src/core/screen.c:853
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Kon scherm %d op display %s niet vrijmaken\n"
@ -516,7 +511,7 @@ msgid "Window manager error: "
msgstr "Fout van vensterbeheer:"
#. first time through
#: ../src/core/window.c:7533
#: ../src/core/window.c:7510
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -532,7 +527,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8257
#: ../src/core/window.c:8340
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -650,6 +645,9 @@ msgid ""
"static number of workspaces (determined by the num-workspaces key in org."
"gnome.desktop.wm.preferences)."
msgstr ""
"Bepaalt of werkbladen dynamisch worden beheerd of dat er een statisch aantal "
"werkbladen is (gegeven door de sleutel num-workspaces in org.gnome.desktop."
"wm.preferences)."
#: ../src/org.gnome.mutter.gschema.xml.in.h:9
msgid "Workspaces only on primary"
@ -672,10 +670,12 @@ msgid ""
"Determines whether the use of popup and highlight frame should be disabled "
"for window cycling."
msgstr ""
"Bepaalt of het gebruik van pop-up en markering van het kader uitgeschakeld "
"wordt voor het vensterbladeren."
#: ../src/org.gnome.mutter.gschema.xml.in.h:13
msgid "Delay focus changes until the pointer stops moving"
msgstr ""
msgstr "Aandacht vertragen totdat de muispijl stopt met bewegen"
#: ../src/org.gnome.mutter.gschema.xml.in.h:14
msgid ""
@ -683,16 +683,22 @@ msgid ""
"the focus will not be changed immediately when entering a window, but only "
"after the pointer stops moving."
msgstr ""
"Indien op true ingesteld en de aandachtsmodus is ofwel sloppy of "
"mouse, dan zal de aandacht niet direct veranderd worden bij het binnengaan "
"van een venster, maar slechts wanneer de muispijl stopt met bewegen."
#: ../src/org.gnome.mutter.gschema.xml.in.h:15
msgid "Draggable border width"
msgstr ""
msgstr "Sleepbare randbreedte"
#: ../src/org.gnome.mutter.gschema.xml.in.h:16
msgid ""
"The amount of total draggable borders. If the theme's visible borders are "
"not enough, invisible borders will be added to meet this value."
msgstr ""
"Het totaal aantal sleepbare randen. Als de zichtbare randen in het thema "
"onvoldoende zijn, worden onzichtbare randen toegevoegd om deze waarde te "
"bereiken."
#: ../src/org.gnome.mutter.gschema.xml.in.h:17
msgid "Auto maximize nearly monitor sized windows"
@ -957,13 +963,13 @@ msgid "Gradients should have at least two colors"
msgstr "Kleurverloop moet tenminste twee kleuren hebben"
#: ../src/ui/theme.c:1203
#, fuzzy, c-format
#, c-format
msgid ""
"GTK custom color specification must have color name and fallback in "
"parentheses, e.g. gtk:custom(foo,bar); could not parse \"%s\""
msgstr ""
"GTK-kleurspecificatie moet een sluithaakje hebben na de status, dus: gtk: "
"fg[NORMAL] waarbij NORMAL de stutus is; kon %s niet verwerken"
"Aangepaste GTK-kleurspecificatie moet een kleurnaam en terugvaloptie hebben "
"tussen haakjes, dus: gtk:custom(foo,bar); kon %s niet verwerken"
#: ../src/ui/theme.c:1219
#, c-format
@ -971,15 +977,17 @@ msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
"_ are valid"
msgstr ""
"Ongeldig teken %c in color_name-parameter van gtk:custom, alleen A-Za-z0-9-"
"_ zijn geldig"
#: ../src/ui/theme.c:1233
#, fuzzy, c-format
#, c-format
msgid ""
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
"fit the format"
msgstr ""
"Schaduwformaat is schaduw/basiskleur/factor, %s voldoet niet aan dit "
"formaat"
"Gtk:custom-formaat is gtk:custom(color_name,fallback), %s voldoet niet "
"aan dit formaat"
#: ../src/ui/theme.c:1278
#, c-format
@ -987,8 +995,8 @@ msgid ""
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
"where NORMAL is the state; could not parse \"%s\""
msgstr ""
"GTK-kleurspecificatie moet de toestand in rechte haken hebben, bijv. gtk:fg"
"[NORMAL] waarbij NORMAL de toestand is; kon %s niet verwerken"
"GTK-kleurspecificatie moet de toestand in rechte haken hebben, bijv. gtk:"
"fg[NORMAL] waarbij NORMAL de toestand is; kon %s niet verwerken"
#: ../src/ui/theme.c:1292
#, c-format
@ -996,8 +1004,8 @@ msgid ""
"GTK color specification must have a close bracket after the state, e.g. gtk:"
"fg[NORMAL] where NORMAL is the state; could not parse \"%s\""
msgstr ""
"GTK-kleurspecificatie moet een sluithaakje hebben na de status, dus: gtk: fg"
"[NORMAL] waarbij NORMAL de stutus is; kon %s niet verwerken"
"GTK-kleurspecificatie moet een sluithaakje hebben na de status, dus: gtk: "
"fg[NORMAL] waarbij NORMAL de stutus is; kon %s niet verwerken"
#: ../src/ui/theme.c:1303
#, c-format
@ -1222,59 +1230,59 @@ msgstr "Geen %s-attribuut op element <%s>"
msgid "Line %d character %d: %s"
msgstr "Regel %d teken %d: %s"
#: ../src/ui/theme-parser.c:479
#: ../src/ui/theme-parser.c:483
#, c-format
msgid "Attribute \"%s\" repeated twice on the same <%s> element"
msgstr "Attribuut %s twee keer herhaald op hetzelfde <%s>-element"
#: ../src/ui/theme-parser.c:503 ../src/ui/theme-parser.c:552
#: ../src/ui/theme-parser.c:507 ../src/ui/theme-parser.c:556
#, c-format
msgid "Attribute \"%s\" is invalid on <%s> element in this context"
msgstr "Attribuut %s is ongeldig op een <%s>-element in deze context"
#: ../src/ui/theme-parser.c:594
#: ../src/ui/theme-parser.c:598
#, c-format
msgid "Could not parse \"%s\" as an integer"
msgstr "Kon %s niet verwerken als geheel getal"
#: ../src/ui/theme-parser.c:603 ../src/ui/theme-parser.c:658
#: ../src/ui/theme-parser.c:607 ../src/ui/theme-parser.c:662
#, c-format
msgid "Did not understand trailing characters \"%s\" in string \"%s\""
msgstr "Niet begrepen: de laatste tekens %s in %s"
#: ../src/ui/theme-parser.c:613
#: ../src/ui/theme-parser.c:617
#, c-format
msgid "Integer %ld must be positive"
msgstr "Geheel getal %ld moet positief zijn"
#: ../src/ui/theme-parser.c:621
#: ../src/ui/theme-parser.c:625
#, c-format
msgid "Integer %ld is too large, current max is %d"
msgstr "Geheel getal %ld is te groot, huidige maximum is %d"
#: ../src/ui/theme-parser.c:649 ../src/ui/theme-parser.c:765
#: ../src/ui/theme-parser.c:653 ../src/ui/theme-parser.c:769
#, c-format
msgid "Could not parse \"%s\" as a floating point number"
msgstr "Kon %s niet als 'floating-point'-getal verwerken"
#: ../src/ui/theme-parser.c:680 ../src/ui/theme-parser.c:708
#: ../src/ui/theme-parser.c:684 ../src/ui/theme-parser.c:712
#, c-format
msgid "Boolean values must be \"true\" or \"false\" not \"%s\""
msgstr "Boolese waarde moet true of false zijn, niet %s"
#: ../src/ui/theme-parser.c:735
#: ../src/ui/theme-parser.c:739
#, c-format
msgid "Angle must be between 0.0 and 360.0, was %g\n"
msgstr "Hoek moet liggen tussen 0.0 en 360.0, maar was %g\n"
#: ../src/ui/theme-parser.c:798
#: ../src/ui/theme-parser.c:802
#, c-format
msgid "Alpha must be between 0.0 (invisible) and 1.0 (fully opaque), was %g\n"
msgstr ""
"Alpha moet liggen tussen 0.0 (onzichtbaar) en 1.0 (volledig ondoorzichtig), "
"maar was %g\n"
#: ../src/ui/theme-parser.c:863
#: ../src/ui/theme-parser.c:867
#, c-format
msgid ""
"Invalid title scale \"%s\" (must be one of xx-small,x-small,small,medium,"
@ -1283,60 +1291,60 @@ msgstr ""
"Ongeldige titel-schaal %s (u kunt kiezen uit: xx-small, x-small, small, "
"medium, large, x-large, xx-large)\n"
#: ../src/ui/theme-parser.c:1019 ../src/ui/theme-parser.c:1082
#: ../src/ui/theme-parser.c:1116 ../src/ui/theme-parser.c:1219
#: ../src/ui/theme-parser.c:1023 ../src/ui/theme-parser.c:1086
#: ../src/ui/theme-parser.c:1120 ../src/ui/theme-parser.c:1223
#, c-format
msgid "<%s> name \"%s\" used a second time"
msgstr "<%s>-naam %s een tweede keer gebruikt"
#: ../src/ui/theme-parser.c:1031 ../src/ui/theme-parser.c:1128
#: ../src/ui/theme-parser.c:1231
#: ../src/ui/theme-parser.c:1035 ../src/ui/theme-parser.c:1132
#: ../src/ui/theme-parser.c:1235
#, c-format
msgid "<%s> parent \"%s\" has not been defined"
msgstr "<%s>-ouder %s is niet gedefinieerd"
#: ../src/ui/theme-parser.c:1141
#: ../src/ui/theme-parser.c:1145
#, c-format
msgid "<%s> geometry \"%s\" has not been defined"
msgstr "<%s>-afmetingen %s is niet gedefinieerd"
#: ../src/ui/theme-parser.c:1154
#: ../src/ui/theme-parser.c:1158
#, c-format
msgid "<%s> must specify either a geometry or a parent that has a geometry"
msgstr "<%s> moet ofwel afmetingen specificeren, of een ouder met afmetingen"
#: ../src/ui/theme-parser.c:1196
#: ../src/ui/theme-parser.c:1200
msgid "You must specify a background for an alpha value to be meaningful"
msgstr ""
"U dient een achtergrond te specificeren voordat een alpha-waarde betekenis "
"heeft"
#: ../src/ui/theme-parser.c:1264
#: ../src/ui/theme-parser.c:1268
#, c-format
msgid "Unknown type \"%s\" on <%s> element"
msgstr "Onbekend type %s op <%s>-element"
#: ../src/ui/theme-parser.c:1275
#: ../src/ui/theme-parser.c:1279
#, c-format
msgid "Unknown style_set \"%s\" on <%s> element"
msgstr "Onbekende style_set %s op <%s>-element"
#: ../src/ui/theme-parser.c:1283
#: ../src/ui/theme-parser.c:1287
#, c-format
msgid "Window type \"%s\" has already been assigned a style set"
msgstr "Venstertype %s heeft reeds een stijlset toegewezen gekregen"
#: ../src/ui/theme-parser.c:1313 ../src/ui/theme-parser.c:1377
#: ../src/ui/theme-parser.c:1603 ../src/ui/theme-parser.c:2838
#: ../src/ui/theme-parser.c:2884 ../src/ui/theme-parser.c:3034
#: ../src/ui/theme-parser.c:3273 ../src/ui/theme-parser.c:3311
#: ../src/ui/theme-parser.c:3349 ../src/ui/theme-parser.c:3387
#: ../src/ui/theme-parser.c:1317 ../src/ui/theme-parser.c:1381
#: ../src/ui/theme-parser.c:1607 ../src/ui/theme-parser.c:2842
#: ../src/ui/theme-parser.c:2888 ../src/ui/theme-parser.c:3038
#: ../src/ui/theme-parser.c:3274 ../src/ui/theme-parser.c:3312
#: ../src/ui/theme-parser.c:3350 ../src/ui/theme-parser.c:3388
#, c-format
msgid "Element <%s> is not allowed below <%s>"
msgstr "Element <%s> is niet toegestaan onder <%s>"
#: ../src/ui/theme-parser.c:1427 ../src/ui/theme-parser.c:1441
#: ../src/ui/theme-parser.c:1486
#: ../src/ui/theme-parser.c:1431 ../src/ui/theme-parser.c:1445
#: ../src/ui/theme-parser.c:1490
msgid ""
"Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" "
"for buttons"
@ -1344,123 +1352,123 @@ msgstr ""
"Kan niet tegelijk button_width/button_height en aspect_ratio voor "
"knoppen opgeven."
#: ../src/ui/theme-parser.c:1450
#: ../src/ui/theme-parser.c:1454
#, c-format
msgid "Distance \"%s\" is unknown"
msgstr "Afstand %s is onbekend"
#: ../src/ui/theme-parser.c:1495
#: ../src/ui/theme-parser.c:1499
#, c-format
msgid "Aspect ratio \"%s\" is unknown"
msgstr "Verhouding %s is onbekend"
#: ../src/ui/theme-parser.c:1557
#: ../src/ui/theme-parser.c:1561
#, c-format
msgid "Border \"%s\" is unknown"
msgstr "Rand %s is onbekend"
#: ../src/ui/theme-parser.c:1868
#: ../src/ui/theme-parser.c:1872
#, c-format
msgid "No \"start_angle\" or \"from\" attribute on element <%s>"
msgstr "Geen start_angle- of from-attribuut op element <%s>"
#: ../src/ui/theme-parser.c:1875
#: ../src/ui/theme-parser.c:1879
#, c-format
msgid "No \"extent_angle\" or \"to\" attribute on element <%s>"
msgstr "Geen extent_angle- of to-attribuut op element <%s>"
#: ../src/ui/theme-parser.c:2115
#: ../src/ui/theme-parser.c:2119
#, c-format
msgid "Did not understand value \"%s\" for type of gradient"
msgstr "Niet begrepen: de waarde %s voor type kleurverloop"
#: ../src/ui/theme-parser.c:2193 ../src/ui/theme-parser.c:2568
#: ../src/ui/theme-parser.c:2197 ../src/ui/theme-parser.c:2572
#, c-format
msgid "Did not understand fill type \"%s\" for <%s> element"
msgstr "Niet begrepen: vul-type %s voor <%s>-element"
#: ../src/ui/theme-parser.c:2360 ../src/ui/theme-parser.c:2443
#: ../src/ui/theme-parser.c:2506
#: ../src/ui/theme-parser.c:2364 ../src/ui/theme-parser.c:2447
#: ../src/ui/theme-parser.c:2510
#, c-format
msgid "Did not understand state \"%s\" for <%s> element"
msgstr "Niet begrepen: status %s voor <%s>-element"
#: ../src/ui/theme-parser.c:2370 ../src/ui/theme-parser.c:2453
#: ../src/ui/theme-parser.c:2374 ../src/ui/theme-parser.c:2457
#, c-format
msgid "Did not understand shadow \"%s\" for <%s> element"
msgstr "Niet begrepen: schaduw %s voor <%s>-element"
#: ../src/ui/theme-parser.c:2380
#: ../src/ui/theme-parser.c:2384
#, c-format
msgid "Did not understand arrow \"%s\" for <%s> element"
msgstr "Niet begrepen: pijl %s voor <%s>-element"
#: ../src/ui/theme-parser.c:2694 ../src/ui/theme-parser.c:2790
#: ../src/ui/theme-parser.c:2698 ../src/ui/theme-parser.c:2794
#, c-format
msgid "No <draw_ops> called \"%s\" has been defined"
msgstr "Er zijn geen <draw_ops> genaamd %s gedefinieerd"
#: ../src/ui/theme-parser.c:2706 ../src/ui/theme-parser.c:2802
#: ../src/ui/theme-parser.c:2710 ../src/ui/theme-parser.c:2806
#, c-format
msgid "Including draw_ops \"%s\" here would create a circular reference"
msgstr "Hier draw_ops %s meenemen zou een circulaire verwijzing creëren"
#: ../src/ui/theme-parser.c:2917
#: ../src/ui/theme-parser.c:2921
#, c-format
msgid "Unknown position \"%s\" for frame piece"
msgstr "Onbekende positie %s voor kader-onderdeel"
#: ../src/ui/theme-parser.c:2925
#: ../src/ui/theme-parser.c:2929
#, c-format
msgid "Frame style already has a piece at position %s"
msgstr "Kader-stijl heeft al een onderdeel op positie %s"
#: ../src/ui/theme-parser.c:2942 ../src/ui/theme-parser.c:3019
#: ../src/ui/theme-parser.c:2946 ../src/ui/theme-parser.c:3023
#, c-format
msgid "No <draw_ops> with the name \"%s\" has been defined"
msgstr "Er zijn geen <draw_ops> met naam %s gedefinieerd"
#: ../src/ui/theme-parser.c:2972
#: ../src/ui/theme-parser.c:2976
#, c-format
msgid "Unknown function \"%s\" for button"
msgstr "Onbekende functie %s voor knop"
#: ../src/ui/theme-parser.c:2982
#: ../src/ui/theme-parser.c:2986
#, c-format
msgid "Button function \"%s\" does not exist in this version (%d, need %d)"
msgstr "Knopfunctie %s bestaat niet in deze versie (%d, %d benodigd)"
#: ../src/ui/theme-parser.c:2994
#: ../src/ui/theme-parser.c:2998
#, c-format
msgid "Unknown state \"%s\" for button"
msgstr "Onbekende status %s voor knop"
#: ../src/ui/theme-parser.c:3002
#: ../src/ui/theme-parser.c:3006
#, c-format
msgid "Frame style already has a button for function %s state %s"
msgstr "Kader-stijl heeft reeds een knop voor functie %s status %s"
#: ../src/ui/theme-parser.c:3073
#: ../src/ui/theme-parser.c:3077
#, c-format
msgid "\"%s\" is not a valid value for focus attribute"
msgstr "%s is geen geldige waarde voor focus-attribuut"
#: ../src/ui/theme-parser.c:3082
#: ../src/ui/theme-parser.c:3086
#, c-format
msgid "\"%s\" is not a valid value for state attribute"
msgstr "%s is geen geldige waarde voor state-attribuut"
#: ../src/ui/theme-parser.c:3092
#: ../src/ui/theme-parser.c:3096
#, c-format
msgid "A style called \"%s\" has not been defined"
msgstr "Een stijl genaamd %s is niet gedefinieerd"
#: ../src/ui/theme-parser.c:3113 ../src/ui/theme-parser.c:3136
#: ../src/ui/theme-parser.c:3117 ../src/ui/theme-parser.c:3140
#, c-format
msgid "\"%s\" is not a valid value for resize attribute"
msgstr "%s is geen geldige waarde voor resize-attribuut"
#: ../src/ui/theme-parser.c:3147
#: ../src/ui/theme-parser.c:3151
#, c-format
msgid ""
"Should not have \"resize\" attribute on <%s> element for maximized/shaded "
@ -1469,7 +1477,7 @@ msgstr ""
"Behoort geen resize-attribuut te hebben op <%s>-element voor "
"gemaximaliseerde/opgerolde toestanden"
#: ../src/ui/theme-parser.c:3161
#: ../src/ui/theme-parser.c:3165
#, c-format
msgid ""
"Should not have \"resize\" attribute on <%s> element for maximized states"
@ -1477,20 +1485,20 @@ msgstr ""
"Behoort geen resize-attribuut te hebben op <%s>-element voor "
"gemaximaliseerde toestand"
#: ../src/ui/theme-parser.c:3175 ../src/ui/theme-parser.c:3222
#: ../src/ui/theme-parser.c:3179 ../src/ui/theme-parser.c:3223
#, c-format
msgid "Style has already been specified for state %s resize %s focus %s"
msgstr ""
"Stijl is reeds gespecificeerd voor status %s grootte aanpassen %s aandacht %s"
#: ../src/ui/theme-parser.c:3186 ../src/ui/theme-parser.c:3197
#: ../src/ui/theme-parser.c:3208 ../src/ui/theme-parser.c:3233
#: ../src/ui/theme-parser.c:3244 ../src/ui/theme-parser.c:3255
#: ../src/ui/theme-parser.c:3190 ../src/ui/theme-parser.c:3201
#: ../src/ui/theme-parser.c:3212 ../src/ui/theme-parser.c:3234
#: ../src/ui/theme-parser.c:3245 ../src/ui/theme-parser.c:3256
#, c-format
msgid "Style has already been specified for state %s focus %s"
msgstr "Stijl is reeds gespecificeerd voor status %s aandacht %s"
#: ../src/ui/theme-parser.c:3294
#: ../src/ui/theme-parser.c:3295
msgid ""
"Can't have a two draw_ops for a <piece> element (theme specified a draw_ops "
"attribute and also a <draw_ops> element, or specified two elements)"
@ -1499,7 +1507,7 @@ msgstr ""
"specificeerde een draw_ops-attribuut en tevens een <draw_ops>-element, of "
"specificeerde twee elementen)"
#: ../src/ui/theme-parser.c:3332
#: ../src/ui/theme-parser.c:3333
msgid ""
"Can't have a two draw_ops for a <button> element (theme specified a draw_ops "
"attribute and also a <draw_ops> element, or specified two elements)"
@ -1508,7 +1516,7 @@ msgstr ""
"specificeerde een draw_ops-attribuut en tevens een <draw_ops>-element, of "
"specificeerde twee elementen)"
#: ../src/ui/theme-parser.c:3370
#: ../src/ui/theme-parser.c:3371
msgid ""
"Can't have a two draw_ops for a <menu_icon> element (theme specified a "
"draw_ops attribute and also a <draw_ops> element, or specified two elements)"
@ -1517,12 +1525,12 @@ msgstr ""
"specificeerde een draw_ops-attribuut en tevens een <draw_ops>-element, of "
"specificeerde twee elementen)"
#: ../src/ui/theme-parser.c:3434
#: ../src/ui/theme-parser.c:3435
#, c-format
msgid "Bad version specification '%s'"
msgstr "Foutieve opgave van versie: %s"
#: ../src/ui/theme-parser.c:3507
#: ../src/ui/theme-parser.c:3508
msgid ""
"\"version\" attribute cannot be used in metacity-theme-1.xml or metacity-"
"theme-2.xml"
@ -1530,18 +1538,18 @@ msgstr ""
"Het version-attribuut kan niet gebruikt worden in metacity-theme-1.xml of "
"metacity-theme-2.xml."
#: ../src/ui/theme-parser.c:3530
#: ../src/ui/theme-parser.c:3531
#, c-format
msgid "Theme requires version %s but latest supported theme version is %d.%d"
msgstr ""
"Het thema vereist versie %s, maar de recentste ondersteunde versie is %d.%d"
#: ../src/ui/theme-parser.c:3562
#: ../src/ui/theme-parser.c:3563
#, c-format
msgid "Outermost element in theme must be <metacity_theme> not <%s>"
msgstr "Buitenste element in thema moet zijn: <metacity_theme>, niet <%s>"
#: ../src/ui/theme-parser.c:3582
#: ../src/ui/theme-parser.c:3583
#, c-format
msgid ""
"Element <%s> is not allowed inside a name/author/date/description element"
@ -1549,12 +1557,12 @@ msgstr ""
"Element <%s> is niet toegestaan binnen een naam/auteur/datum/beschrijving "
"element"
#: ../src/ui/theme-parser.c:3587
#: ../src/ui/theme-parser.c:3588
#, c-format
msgid "Element <%s> is not allowed inside a <constant> element"
msgstr "Element <%s> is niet toegestaan binnen een <constant>-element"
#: ../src/ui/theme-parser.c:3599
#: ../src/ui/theme-parser.c:3600
#, c-format
msgid ""
"Element <%s> is not allowed inside a distance/border/aspect_ratio element"
@ -1562,38 +1570,38 @@ msgstr ""
"Element <%s> is niet toegestaan binnen de elementen distance/border/"
"aspect_ratio"
#: ../src/ui/theme-parser.c:3621
#: ../src/ui/theme-parser.c:3622
#, c-format
msgid "Element <%s> is not allowed inside a draw operation element"
msgstr "Element <%s> is niet toegestaan binnen een draw operation-element"
#: ../src/ui/theme-parser.c:3631 ../src/ui/theme-parser.c:3661
#: ../src/ui/theme-parser.c:3666 ../src/ui/theme-parser.c:3671
#: ../src/ui/theme-parser.c:3632 ../src/ui/theme-parser.c:3662
#: ../src/ui/theme-parser.c:3667 ../src/ui/theme-parser.c:3672
#, c-format
msgid "Element <%s> is not allowed inside a <%s> element"
msgstr "Element <%s> is niet toegestaan binnen een <%s>-element"
#: ../src/ui/theme-parser.c:3899
#: ../src/ui/theme-parser.c:3900
msgid "No draw_ops provided for frame piece"
msgstr "Geen draw_ops gegeven voor kader-onderdeel"
#: ../src/ui/theme-parser.c:3914
#: ../src/ui/theme-parser.c:3915
msgid "No draw_ops provided for button"
msgstr "Geen draw_ops gegeven voor knop"
#: ../src/ui/theme-parser.c:3968
#: ../src/ui/theme-parser.c:3969
#, c-format
msgid "No text is allowed inside element <%s>"
msgstr "Geen tekst toegestaan binnen element <%s>"
#: ../src/ui/theme-parser.c:4026 ../src/ui/theme-parser.c:4038
#: ../src/ui/theme-parser.c:4050 ../src/ui/theme-parser.c:4062
#: ../src/ui/theme-parser.c:4074
#: ../src/ui/theme-parser.c:4027 ../src/ui/theme-parser.c:4039
#: ../src/ui/theme-parser.c:4051 ../src/ui/theme-parser.c:4063
#: ../src/ui/theme-parser.c:4075
#, c-format
msgid "<%s> specified twice for this theme"
msgstr "<%s> twee keer gegeven voor dit thema"
#: ../src/ui/theme-parser.c:4336
#: ../src/ui/theme-parser.c:4337
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "Geen geldig bestand gevonden voor thema %s\n"

File diff suppressed because it is too large Load Diff

View File

@ -55,7 +55,8 @@ libmutter_la_SOURCES = \
compositor/meta-background-actor.c \
compositor/meta-background-actor-private.h \
compositor/meta-background-group.c \
compositor/meta-background-group-private.h \
compositor/meta-cullable.c \
compositor/meta-cullable.h \
compositor/meta-module.c \
compositor/meta-module.h \
compositor/meta-plugin.c \
@ -168,7 +169,9 @@ libmutter_la_SOURCES = \
ui/theme.c \
meta/theme.h \
ui/theme-private.h \
ui/ui.c \
ui/ui.c
nodist_libmutter_la_SOURCES = \
$(mutter_built_sources)
libmutter_la_LDFLAGS = -no-undefined
@ -249,7 +252,7 @@ Meta-$(api_version).gir: libmutter.la
@META_GIR@_FILES = \
mutter-enum-types.h \
$(libmutterinclude_base_headers) \
$(filter %.c,$(libmutter_la_SOURCES))
$(filter %.c,$(libmutter_la_SOURCES) $(nodist_libmutter_la_SOURCES))
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
endif

View File

@ -17,8 +17,6 @@ struct _MetaCompositor
{
MetaDisplay *display;
Atom atom_x_root_pixmap;
Atom atom_net_wm_window_opacity;
guint repaint_func_id;
ClutterActor *shadow_src;

View File

@ -42,15 +42,6 @@
* the call, so it may be necessary to readjust the display based on the
* old_rect to start the animation.
*
* meta_compositor_window_mapped() and meta_compositor_window_unmapped() are
* notifications when the toplevel window (frame or client window) is mapped or
* unmapped. That is, when the result of meta_window_toplevel_is_mapped()
* changes. The main use of this is to drop resources when a window is unmapped.
* A window will always be mapped before meta_compositor_show_window()
* is called and will not be unmapped until after meta_compositor_hide_window()
* is called. If the live_hidden_windows preference is set, windows will never
* be unmapped.
*
* # Containers #
*
* There's two containers in the stage that are used to place window actors, here
@ -175,31 +166,6 @@ process_damage (MetaCompositor *compositor,
meta_window_actor_process_damage (window_actor, event);
}
static void
process_property_notify (MetaCompositor *compositor,
XPropertyEvent *event,
MetaWindow *window)
{
MetaWindowActor *window_actor;
if (window == NULL)
return;
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (window_actor == NULL)
return;
/* Check for the opacity changing */
if (event->atom == compositor->atom_net_wm_window_opacity)
{
meta_window_actor_update_opacity (window_actor);
DEBUG_TRACE ("process_property_notify: net_wm_window_opacity\n");
return;
}
DEBUG_TRACE ("process_property_notify: unknown\n");
}
static Window
get_output_window (MetaScreen *screen)
{
@ -685,15 +651,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
clutter_actor_add_child (info->stage, info->window_group);
clutter_actor_add_child (info->stage, info->top_window_group);
info->plugin_mgr = meta_plugin_manager_new (screen);
/*
* Delay the creation of the overlay window as long as we can, to avoid
* blanking out the screen. This means that during the plugin loading, the
* overlay window is not accessible; if the plugin needs to access it
* directly, it should hook into the "show" signal on stage, and do
* its stuff there.
*/
info->output = get_output_window (screen);
XReparentWindow (xdisplay, xwin, info->output, 0, 0);
@ -714,6 +671,8 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
info->pending_input_region = None;
}
info->plugin_mgr = meta_plugin_manager_new (screen);
/* Map overlay window before redirecting windows offscreen so we catch their
* contents until we show the stage.
*/
@ -756,7 +715,7 @@ meta_shape_cow_for_window (MetaScreen *screen,
int width, height;
MetaRectangle rect;
meta_window_get_outer_rect (metaWindow, &rect);
meta_window_get_frame_rect (metaWindow, &rect);
window_bounds.x = rect.x;
window_bounds.y = rect.y;
@ -884,6 +843,18 @@ meta_compositor_window_shape_changed (MetaCompositor *compositor,
meta_window_actor_update_shape (window_actor);
}
void
meta_compositor_window_opacity_changed (MetaCompositor *compositor,
MetaWindow *window)
{
MetaWindowActor *window_actor;
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (!window_actor)
return;
meta_window_actor_update_opacity (window_actor);
}
/* Clutter makes the assumption that there is only one X window
* per stage, which is a valid assumption to make for a generic
* application toolkit. As such, it will ignore any events sent
@ -990,28 +961,19 @@ meta_compositor_process_event (MetaCompositor *compositor,
}
}
switch (event->type)
if (event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
{
case PropertyNotify:
process_property_notify (compositor, (XPropertyEvent *) event, window);
break;
default:
if (event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
/* Core code doesn't handle damage events, so we need to extract the MetaWindow
* ourselves
*/
if (window == NULL)
{
/* Core code doesn't handle damage events, so we need to extract the MetaWindow
* ourselves
*/
if (window == NULL)
{
Window xwin = ((XDamageNotifyEvent *) event)->drawable;
window = meta_display_lookup_x_window (compositor->display, xwin);
}
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
process_damage (compositor, (XDamageNotifyEvent *) event, window);
Window xwin = ((XDamageNotifyEvent *) event)->drawable;
window = meta_display_lookup_x_window (compositor->display, xwin);
}
break;
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
process_damage (compositor, (XDamageNotifyEvent *) event, window);
}
/* Clutter needs to know about MapNotify events otherwise it will
@ -1311,30 +1273,6 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
sync_actor_stacking (info);
}
void
meta_compositor_window_mapped (MetaCompositor *compositor,
MetaWindow *window)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
DEBUG_TRACE ("meta_compositor_window_mapped\n");
if (!window_actor)
return;
meta_window_actor_mapped (window_actor);
}
void
meta_compositor_window_unmapped (MetaCompositor *compositor,
MetaWindow *window)
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
DEBUG_TRACE ("meta_compositor_window_unmapped\n");
if (!window_actor)
return;
meta_window_actor_unmapped (window_actor);
}
void
meta_compositor_sync_window_geometry (MetaCompositor *compositor,
MetaWindow *window,
@ -1515,13 +1453,7 @@ on_shadow_factory_changed (MetaShadowFactory *factory,
MetaCompositor *
meta_compositor_new (MetaDisplay *display)
{
char *atom_names[] = {
"_XROOTPMAP_ID",
"_NET_WM_WINDOW_OPACITY",
};
Atom atoms[G_N_ELEMENTS(atom_names)];
MetaCompositor *compositor;
Display *xdisplay = meta_display_get_xdisplay (display);
if (!composite_at_least_version (display, 0, 3))
return NULL;
@ -1533,18 +1465,11 @@ meta_compositor_new (MetaDisplay *display)
if (g_getenv("META_DISABLE_MIPMAPS"))
compositor->no_mipmaps = TRUE;
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
False, atoms);
g_signal_connect (meta_shadow_factory_get_default (),
"changed",
G_CALLBACK (on_shadow_factory_changed),
compositor);
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);

View File

@ -6,9 +6,6 @@
#include <meta/screen.h>
#include <meta/meta-background-actor.h>
void meta_background_actor_set_clip_region (MetaBackgroundActor *self,
cairo_region_t *clip_region);
cairo_region_t *meta_background_actor_get_clip_region (MetaBackgroundActor *self);
#endif /* META_BACKGROUND_ACTOR_PRIVATE_H */

View File

@ -41,20 +41,35 @@
#include <meta/errors.h>
#include <meta/meta-background.h>
#include "meta-background-actor-private.h"
#include "meta-cullable.h"
struct _MetaBackgroundActorPrivate
{
cairo_region_t *clip_region;
};
G_DEFINE_TYPE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR);
static void cullable_iface_init (MetaCullableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR,
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
static void
set_clip_region (MetaBackgroundActor *self,
cairo_region_t *clip_region)
{
MetaBackgroundActorPrivate *priv = self->priv;
g_clear_pointer (&priv->clip_region, (GDestroyNotify) cairo_region_destroy);
if (clip_region)
priv->clip_region = cairo_region_copy (clip_region);
}
static void
meta_background_actor_dispose (GObject *object)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
meta_background_actor_set_clip_region (self, NULL);
set_clip_region (self, NULL);
G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object);
}
@ -104,26 +119,6 @@ meta_background_actor_get_preferred_height (ClutterActor *actor,
*natural_height_p = height;
}
static gboolean
meta_background_actor_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
ClutterContent *content;
gfloat width, height;
content = clutter_actor_get_content (actor);
if (!content)
return FALSE;
clutter_content_get_preferred_size (content, &width, &height);
clutter_paint_volume_set_width (volume, width);
clutter_paint_volume_set_height (volume, height);
return TRUE;
}
static void
meta_background_actor_class_init (MetaBackgroundActorClass *klass)
{
@ -136,7 +131,6 @@ meta_background_actor_class_init (MetaBackgroundActorClass *klass)
actor_class->get_preferred_width = meta_background_actor_get_preferred_width;
actor_class->get_preferred_height = meta_background_actor_get_preferred_height;
actor_class->get_paint_volume = meta_background_actor_get_paint_volume;
}
static void
@ -166,31 +160,27 @@ meta_background_actor_new (void)
return CLUTTER_ACTOR (self);
}
/**
* meta_background_actor_set_clip_region:
* @self: a #MetaBackgroundActor
* @clip_region: (allow-none): the area of the actor (in allocate-relative
* coordinates) that is visible.
*
* Sets the area of the background that is unobscured by overlapping windows.
* This is used to optimize and only paint the visible portions.
*/
void
meta_background_actor_set_clip_region (MetaBackgroundActor *self,
cairo_region_t *clip_region)
static void
meta_background_actor_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
MetaBackgroundActorPrivate *priv;
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (cullable);
set_clip_region (self, clip_region);
}
g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
static void
meta_background_actor_reset_culling (MetaCullable *cullable)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (cullable);
set_clip_region (self, NULL);
}
priv = self->priv;
g_clear_pointer (&priv->clip_region,
(GDestroyNotify)
cairo_region_destroy);
if (clip_region)
priv->clip_region = cairo_region_copy (clip_region);
static void
cullable_iface_init (MetaCullableInterface *iface)
{
iface->cull_out = meta_background_actor_cull_out;
iface->reset_culling = meta_background_actor_reset_culling;
}
/**

View File

@ -1,11 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef META_BACKGROUND_GROUP_PRIVATE_H
#define META_BACKGROUND_GROUP_PRIVATE_H
#include <meta/screen.h>
#include <meta/meta-background-group.h>
void meta_background_group_set_clip_region (MetaBackgroundGroup *self,
cairo_region_t *visible_region);
#endif /* META_BACKGROUND_GROUP_PRIVATE_H */

View File

@ -16,87 +16,43 @@
#include <config.h>
#include "compositor-private.h"
#include "clutter-utils.h"
#include "meta-background-actor-private.h"
#include "meta-background-group-private.h"
#include <meta/meta-background-group.h>
#include "meta-cullable.h"
G_DEFINE_TYPE (MetaBackgroundGroup, meta_background_group, CLUTTER_TYPE_ACTOR);
static void cullable_iface_init (MetaCullableInterface *iface);
struct _MetaBackgroundGroupPrivate
{
gpointer dummy;
};
static void
meta_background_group_dispose (GObject *object)
{
G_OBJECT_CLASS (meta_background_group_parent_class)->dispose (object);
}
static gboolean
meta_background_group_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
return clutter_paint_volume_set_from_allocation (volume, actor);
}
G_DEFINE_TYPE_WITH_CODE (MetaBackgroundGroup, meta_background_group, CLUTTER_TYPE_ACTOR,
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
static void
meta_background_group_class_init (MetaBackgroundGroupClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
}
actor_class->get_paint_volume = meta_background_group_get_paint_volume;
object_class->dispose = meta_background_group_dispose;
static void
meta_background_group_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
}
g_type_class_add_private (klass, sizeof (MetaBackgroundGroupPrivate));
static void
meta_background_group_reset_culling (MetaCullable *cullable)
{
meta_cullable_reset_culling_children (cullable);
}
static void
cullable_iface_init (MetaCullableInterface *iface)
{
iface->cull_out = meta_background_group_cull_out;
iface->reset_culling = meta_background_group_reset_culling;
}
static void
meta_background_group_init (MetaBackgroundGroup *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
META_TYPE_BACKGROUND_GROUP,
MetaBackgroundGroupPrivate);
}
/**
* meta_background_group_set_clip_region:
* @self: a #MetaBackgroundGroup
* @region: (allow-none): the parts of the background to paint
*
* Sets the area of the backgrounds that is unobscured by overlapping windows.
* This is used to optimize and only paint the visible portions.
*/
void
meta_background_group_set_clip_region (MetaBackgroundGroup *self,
cairo_region_t *region)
{
GList *children, *l;
children = clutter_actor_get_children (CLUTTER_ACTOR (self));
for (l = children; l; l = l->next)
{
ClutterActor *actor = l->data;
if (META_IS_BACKGROUND_ACTOR (actor))
{
meta_background_actor_set_clip_region (META_BACKGROUND_ACTOR (actor), region);
}
else if (META_IS_BACKGROUND_GROUP (actor))
{
int x, y;
if (!meta_actor_is_untransformed (actor, &x, &y))
continue;
cairo_region_translate (region, -x, -y);
meta_background_group_set_clip_region (META_BACKGROUND_GROUP (actor), region);
cairo_region_translate (region, x, y);
}
}
g_list_free (children);
}
ClutterActor *

View File

@ -0,0 +1,191 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Owen Taylor <otaylor@redhat.com>
* Ray Strode <rstrode@redhat.com>
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#include "config.h"
#include "meta-cullable.h"
#include "clutter-utils.h"
G_DEFINE_INTERFACE (MetaCullable, meta_cullable, CLUTTER_TYPE_ACTOR);
/**
* SECTION:meta-cullable
* @title: MetaCullable
* @short_description: CPU culling operations for efficient drawing
*
* When we are painting a stack of 5-10 large actors, the standard
* bottom-to-top method of drawing every actor results in a tremendous
* amount of overdraw. If these actors are painting textures like
* windows, it can easily max out the available memory bandwidth on a
* low-end graphics chipset. It's even worse if window textures are
* being accessed over the AGP bus.
*
* #MetaCullable is our solution. The basic technique applied here is to
* do a pre-pass before painting where we walk each actor from top to bottom
* and ask each actor to "cull itself out". We pass in a region it can copy
* to clip its drawing to, and the actor can subtract its fully opaque pixels
* so that actors underneath know not to draw there as well.
*/
/**
* meta_cullable_cull_out_children:
* @cullable: The #MetaCullable
* @unobscured_region: The unobscured region, as passed into cull_out()
* @clip_region: The clip region, as passed into cull_out()
*
* This is a helper method for actors that want to recurse over their
* child actors, and cull them out.
*
* See #MetaCullable and meta_cullable_cull_out() for more details.
*/
void
meta_cullable_cull_out_children (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
ClutterActor *actor = CLUTTER_ACTOR (cullable);
ClutterActor *child;
ClutterActorIter iter;
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_prev (&iter, &child))
{
int x, y;
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
continue;
/* If an actor has effects applied, then that can change the area
* it paints and the opacity, so we no longer can figure out what
* portion of the actor is obscured and what portion of the screen
* it obscures, so we skip the actor.
*
* This has a secondary beneficial effect: if a ClutterOffscreenEffect
* is applied to an actor, then our clipped redraws interfere with the
* caching of the FBO - even if we only need to draw a small portion
* of the window right now, ClutterOffscreenEffect may use other portions
* of the FBO later. So, skipping actors with effects applied also
* prevents these bugs.
*
* Theoretically, we should check clutter_actor_get_offscreen_redirect()
* as well for the same reason, but omitted for simplicity in the
* hopes that no-one will do that.
*/
if (clutter_actor_has_effects (child))
continue;
if (!META_IS_CULLABLE (child))
continue;
if (!meta_actor_is_untransformed (child, &x, &y))
continue;
/* Temporarily move to the coordinate system of the actor */
cairo_region_translate (unobscured_region, - x, - y);
cairo_region_translate (clip_region, - x, - y);
meta_cullable_cull_out (META_CULLABLE (child), unobscured_region, clip_region);
cairo_region_translate (unobscured_region, x, y);
cairo_region_translate (clip_region, x, y);
}
}
/**
* meta_cullable_reset_culling_children:
* @cullable: The #MetaCullable
*
* This is a helper method for actors that want to recurse over their
* child actors, and cull them out.
*
* See #MetaCullable and meta_cullable_reset_culling() for more details.
*/
void
meta_cullable_reset_culling_children (MetaCullable *cullable)
{
ClutterActor *actor = CLUTTER_ACTOR (cullable);
ClutterActor *child;
ClutterActorIter iter;
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
{
if (!META_IS_CULLABLE (child))
continue;
meta_cullable_reset_culling (META_CULLABLE (child));
}
}
static void
meta_cullable_default_init (MetaCullableInterface *iface)
{
}
/**
* meta_cullable_cull_out:
* @cullable: The #MetaCullable
* @unobscured_region: The unobscured region, in @cullable's space.
* @clip_region: The clip region, in @cullable's space.
*
* When #MetaWindowGroup is painted, we walk over its direct cullable
* children from top to bottom and ask themselves to "cull out". Cullables
* can use @unobscured_region and @clip_region to clip their drawing. Actors
* interested in eliminating overdraw should copy the @clip_region and only
* paint those parts, as everything else has been obscured by actors above it.
*
* Actors that may have fully opaque parts should also subtract out a region
* that is fully opaque from @unobscured_region and @clip_region.
*
* @unobscured_region and @clip_region are extremely similar. The difference
* is that @clip_region starts off with the stage's clip, if Clutter detects
* that we're doing a clipped redraw. @unobscured_region, however, starts off
* with the full stage size, so actors that may want to record what parts of
* their window are unobscured for e.g. scheduling repaints can do so.
*
* Actors that have children can also use the meta_cullable_cull_out_children()
* helper method to do a simple cull across all their children.
*/
void
meta_cullable_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
META_CULLABLE_GET_IFACE (cullable)->cull_out (cullable, unobscured_region, clip_region);
}
/**
* meta_cullable_reset_culling:
* @cullable: The #MetaCullable
*
* Actors that copied data in their cull_out() implementation can now
* reset their data, as the paint is now over. Additional paints may be
* done by #ClutterClone or similar, and they should not be affected by
* the culling operation.
*/
void
meta_cullable_reset_culling (MetaCullable *cullable)
{
META_CULLABLE_GET_IFACE (cullable)->reset_culling (cullable);
}

View File

@ -0,0 +1,68 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Written by:
* Owen Taylor <otaylor@redhat.com>
* Ray Strode <rstrode@redhat.com>
* Jasper St. Pierre <jstpierre@mecheye.net>
*/
#ifndef __META_CULLABLE_H__
#define __META_CULLABLE_H__
#include <clutter/clutter.h>
G_BEGIN_DECLS
#define META_TYPE_CULLABLE (meta_cullable_get_type ())
#define META_CULLABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CULLABLE, MetaCullable))
#define META_IS_CULLABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CULLABLE))
#define META_CULLABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), META_TYPE_CULLABLE, MetaCullableInterface))
typedef struct _MetaCullable MetaCullable;
typedef struct _MetaCullableInterface MetaCullableInterface;
struct _MetaCullableInterface
{
GTypeInterface g_iface;
void (* cull_out) (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region);
void (* reset_culling) (MetaCullable *cullable);
};
GType meta_cullable_get_type (void);
void meta_cullable_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region);
void meta_cullable_reset_culling (MetaCullable *cullable);
/* Utility methods for implementations */
void meta_cullable_cull_out_children (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region);
void meta_cullable_reset_culling_children (MetaCullable *cullable);
G_END_DECLS
#endif /* __META_CULLABLE_H__ */

View File

@ -72,6 +72,7 @@ struct _MetaShapedTexturePrivate
cairo_region_t *clip_region;
cairo_region_t *opaque_region;
cairo_region_t *input_shape_region;
guint tex_width, tex_height;
@ -394,45 +395,60 @@ meta_shaped_texture_pick (ClutterActor *actor,
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
MetaShapedTexturePrivate *priv = stex->priv;
if (!clutter_actor_should_pick_paint (actor) ||
(priv->clip_region && cairo_region_is_empty (priv->clip_region)))
return;
/* If there is no region then use the regular pick */
if (priv->mask_texture == NULL)
if (priv->input_shape_region == NULL)
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)->pick (actor, color);
else if (clutter_actor_should_pick_paint (actor))
else
{
CoglTexture *paint_tex;
ClutterActorBox alloc;
guint tex_width, tex_height;
int n_rects;
float *rectangles;
int i;
CoglPipeline *pipeline;
CoglContext *ctx;
CoglFramebuffer *fb;
CoglColor cogl_color;
paint_tex = COGL_TEXTURE (priv->texture);
/* Note: We don't bother trying to intersect the pick and clip regions
* since needing to copy the region, do the intersection, and probably
* increase the number of rectangles seems more likely to have a negative
* effect.
*
* NB: Most of the time when just using rectangles for picking then
* picking shouldn't involve any rendering, and minimizing the number of
* rectangles has more benefit than reducing the area of the pick
* region.
*/
if (paint_tex == NULL)
return;
n_rects = cairo_region_num_rectangles (priv->input_shape_region);
rectangles = g_alloca (sizeof (float) * 4 * n_rects);
tex_width = cogl_texture_get_width (paint_tex);
tex_height = cogl_texture_get_height (paint_tex);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
int pos = i * 4;
if (tex_width == 0 || tex_height == 0) /* no contents yet */
return;
cairo_region_get_rectangle (priv->input_shape_region, i, &rect);
rectangles[pos] = rect.x;
rectangles[pos + 1] = rect.y;
rectangles[pos + 2] = rect.x + rect.width;
rectangles[pos + 3] = rect.y + rect.height;
}
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
fb = cogl_get_draw_framebuffer ();
cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
pipeline = get_masked_pipeline (ctx);
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
pipeline = cogl_pipeline_new (ctx);
cogl_pipeline_set_color (pipeline, &cogl_color);
clutter_actor_get_allocation_box (actor, &alloc);
cogl_framebuffer_draw_rectangle (fb, pipeline,
0, 0,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1);
cogl_framebuffer_draw_rectangles (fb, pipeline,
rectangles, n_rects);
cogl_object_unref (pipeline);
}
}
@ -691,6 +707,41 @@ meta_shaped_texture_get_texture (MetaShapedTexture *stex)
return COGL_TEXTURE (stex->priv->texture);
}
/**
* meta_shaped_texture_set_input_shape_region:
* @stex: a #MetaShapedTexture
* @shape_region: the region of the texture that should respond to
* input.
*
* Determines what region of the texture should accept input. For
* X based windows this is defined by the ShapeInput region of the
* window.
*/
void
meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
cairo_region_t *shape_region)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
if (priv->input_shape_region != NULL)
{
cairo_region_destroy (priv->input_shape_region);
priv->input_shape_region = NULL;
}
if (shape_region != NULL)
{
cairo_region_reference (shape_region);
priv->input_shape_region = shape_region;
}
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
/**
* meta_shaped_texture_set_clip_region:
* @stex: a #MetaShapedTexture

View File

@ -55,14 +55,6 @@ void meta_window_actor_set_updates_frozen (MetaWindowActor *self,
void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
gboolean no_delay_frame);
cairo_region_t *meta_window_actor_get_obscured_region (MetaWindowActor *self);
void meta_window_actor_set_clip_region (MetaWindowActor *self,
cairo_region_t *clip_region);
void meta_window_actor_set_clip_region_beneath (MetaWindowActor *self,
cairo_region_t *beneath_region);
void meta_window_actor_reset_clip_regions (MetaWindowActor *self);
void meta_window_actor_set_unobscured_region (MetaWindowActor *self,
cairo_region_t *unobscured_region);

View File

@ -32,6 +32,7 @@
#include "meta-texture-rectangle.h"
#include "region-utils.h"
#include "monitor-private.h"
#include "meta-cullable.h"
enum {
POSITION_CHANGED,
@ -45,7 +46,6 @@ static guint signals[LAST_SIGNAL] = {0};
struct _MetaWindowActorPrivate
{
MetaWindow *window;
Window xwindow;
MetaScreen *screen;
ClutterActor *actor;
@ -68,10 +68,10 @@ struct _MetaWindowActorPrivate
Damage damage;
guint8 opacity;
/* A region that matches the shape of the window, including frame bounds */
cairo_region_t *shape_region;
/* If the window has an input shape, a region that matches the shape */
cairo_region_t *input_region;
/* The opaque region, from _NET_WM_OPAQUE_REGION, intersected with
* the shape region. */
cairo_region_t *opaque_region;
@ -109,7 +109,6 @@ struct _MetaWindowActorPrivate
GList *frames;
guint visible : 1;
guint mapped : 1;
guint argb32 : 1;
guint disposed : 1;
guint redecorating : 1;
@ -152,8 +151,6 @@ struct _FrameData
enum
{
PROP_META_WINDOW = 1,
PROP_META_SCREEN,
PROP_X_WINDOW,
PROP_NO_SHADOW,
PROP_SHADOW_CLASS
};
@ -189,7 +186,10 @@ static void do_send_frame_timings (MetaWindowActor *self,
gint refresh_interval,
gint64 presentation_time);
G_DEFINE_TYPE (MetaWindowActor, meta_window_actor, CLUTTER_TYPE_ACTOR);
static void cullable_iface_init (MetaCullableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (MetaWindowActor, meta_window_actor, CLUTTER_TYPE_ACTOR,
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
static void
frame_data_free (FrameData *frame)
@ -219,33 +219,12 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
"MetaWindow",
"The displayed MetaWindow",
META_TYPE_WINDOW,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class,
PROP_META_WINDOW,
pspec);
pspec = g_param_spec_pointer ("meta-screen",
"MetaScreen",
"MetaScreen",
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
g_object_class_install_property (object_class,
PROP_META_SCREEN,
pspec);
pspec = g_param_spec_ulong ("x-window",
"Window",
"Window",
0,
G_MAXULONG,
0,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
g_object_class_install_property (object_class,
PROP_X_WINDOW,
pspec);
pspec = g_param_spec_boolean ("no-shadow",
"No shadow",
"Do not add shaddow to this window",
@ -288,7 +267,6 @@ meta_window_actor_init (MetaWindowActor *self)
priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
META_TYPE_WINDOW_ACTOR,
MetaWindowActorPrivate);
priv->opacity = 0xff;
priv->shadow_class = NULL;
}
@ -299,11 +277,9 @@ window_decorated_notify (MetaWindow *mw,
{
MetaWindowActor *self = META_WINDOW_ACTOR (data);
MetaWindowActorPrivate *priv = self->priv;
MetaFrame *frame = meta_window_get_frame (mw);
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window new_xwindow;
/*
* Basically, we have to reconstruct the the internals of this object
@ -311,11 +287,6 @@ window_decorated_notify (MetaWindow *mw,
*/
priv->redecorating = TRUE;
if (frame)
new_xwindow = meta_frame_get_xwindow (frame);
else
new_xwindow = meta_window_get_xwindow (mw);
meta_window_actor_detach (self);
/*
@ -330,8 +301,6 @@ window_decorated_notify (MetaWindow *mw,
priv->damage = None;
}
priv->xwindow = new_xwindow;
/*
* Recreate the contents.
*/
@ -346,18 +315,30 @@ window_appears_focused_notify (MetaWindow *mw,
clutter_actor_queue_redraw (CLUTTER_ACTOR (data));
}
static gboolean
is_non_opaque (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
MetaWindow *window = priv->window;
return priv->argb32 || (window->opacity != 0xFF);
}
static void
meta_window_actor_constructed (GObject *object)
{
MetaWindowActor *self = META_WINDOW_ACTOR (object);
MetaWindowActorPrivate *priv = self->priv;
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
Window xwindow = priv->xwindow;
MetaWindow *window = priv->window;
MetaScreen *screen = meta_window_get_screen (window);
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
XRenderPictFormat *format;
Window xwindow;
xwindow = meta_window_get_toplevel_xwindow (window);
priv->screen = screen;
priv->damage = XDamageCreate (xdisplay, xwindow,
XDamageReportBoundingBox);
@ -380,19 +361,6 @@ meta_window_actor_constructed (GObject *object)
* We will release it in dispose().
*/
g_object_ref (priv->actor);
g_signal_connect_object (window, "notify::decorated",
G_CALLBACK (window_decorated_notify), self, 0);
g_signal_connect_object (window, "notify::appears-focused",
G_CALLBACK (window_appears_focused_notify), self, 0);
}
else
{
/*
* This is the case where existing window is gaining/loosing frame.
* Just ensure the actor is top most (i.e., above shadow).
*/
clutter_actor_set_child_above_sibling (CLUTTER_ACTOR (self), priv->actor, NULL);
}
meta_window_actor_update_opacity (self);
@ -432,6 +400,7 @@ meta_window_actor_dispose (GObject *object)
g_clear_pointer (&priv->unobscured_region, cairo_region_destroy);
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
g_clear_pointer (&priv->input_region, cairo_region_destroy);
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
g_clear_pointer (&priv->shadow_clip, cairo_region_destroy);
@ -484,17 +453,12 @@ meta_window_actor_set_property (GObject *object,
switch (prop_id)
{
case PROP_META_WINDOW:
{
if (priv->window)
g_object_unref (priv->window);
priv->window = g_value_dup_object (value);
}
break;
case PROP_META_SCREEN:
priv->screen = g_value_get_pointer (value);
break;
case PROP_X_WINDOW:
priv->xwindow = g_value_get_ulong (value);
priv->window = g_value_dup_object (value);
g_signal_connect_object (priv->window, "notify::decorated",
G_CALLBACK (window_decorated_notify), self, 0);
g_signal_connect_object (priv->window, "notify::appears-focused",
G_CALLBACK (window_appears_focused_notify), self, 0);
break;
case PROP_NO_SHADOW:
{
@ -540,12 +504,6 @@ meta_window_actor_get_property (GObject *object,
case PROP_META_WINDOW:
g_value_set_object (value, priv->window);
break;
case PROP_META_SCREEN:
g_value_set_pointer (value, priv->screen);
break;
case PROP_X_WINDOW:
g_value_set_ulong (value, priv->xwindow);
break;
case PROP_NO_SHADOW:
g_value_set_boolean (value, priv->no_shadow);
break;
@ -643,7 +601,7 @@ clip_shadow_under_window (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
return (priv->argb32 || priv->opacity != 0xff) && priv->window->frame;
return is_non_opaque (self) && priv->window->frame;
}
static void
@ -669,6 +627,7 @@ meta_window_actor_paint (ClutterActor *actor)
MetaShadowParams params;
cairo_rectangle_int_t shape_bounds;
cairo_region_t *clip = priv->shadow_clip;
MetaWindow *window = priv->window;
meta_window_actor_get_shape_bounds (self, &shape_bounds);
meta_window_actor_get_shadow_params (self, appears_focused, &params);
@ -692,7 +651,7 @@ meta_window_actor_paint (ClutterActor *actor)
params.y_offset + shape_bounds.y,
shape_bounds.width,
shape_bounds.height,
(clutter_actor_get_paint_opacity (actor) * params.opacity * priv->opacity) / (255 * 255),
(clutter_actor_get_paint_opacity (actor) * params.opacity * window->opacity) / (255 * 255),
clip,
clip_shadow_under_window (self)); /* clip_strictly - not just as an optimization */
@ -779,10 +738,10 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
return TRUE;
/*
* Do not add shadows to ARGB windows; eventually we should generate a
* shadow from the input shape for such windows.
* Do not add shadows to non-opaque windows; eventually we should generate
* a shadow from the input shape for such windows.
*/
if (priv->argb32 || priv->opacity != 0xff)
if (is_non_opaque (self))
return FALSE;
/*
@ -813,20 +772,6 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
return FALSE;
}
/**
* meta_window_actor_get_x_window: (skip)
* @self: a #MetaWindowActor
*
*/
Window
meta_window_actor_get_x_window (MetaWindowActor *self)
{
if (!self)
return None;
return self->priv->xwindow;
}
/**
* meta_window_actor_get_meta_window:
* @self: a #MetaWindowActor
@ -994,7 +939,7 @@ meta_window_actor_damage_all (MetaWindowActor *self)
texture = meta_shaped_texture_get_texture (META_SHAPED_TEXTURE (priv->actor));
if (!priv->mapped || priv->needs_pixmap)
if (priv->needs_pixmap)
return;
redraw_queued = meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor),
@ -1083,7 +1028,7 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
{
queue_send_frame_messages_timeout (self);
}
else if (priv->mapped && !priv->needs_pixmap)
else
{
const cairo_rectangle_int_t clip = { 0, 0, 1, 1 };
clutter_actor_queue_redraw_with_clip (priv->actor, &clip);
@ -1115,9 +1060,6 @@ meta_window_actor_queue_create_pixmap (MetaWindowActor *self)
priv->needs_pixmap = TRUE;
if (!priv->mapped)
return;
if (is_frozen (self))
return;
@ -1331,7 +1273,7 @@ meta_window_actor_should_unredirect (MetaWindowActor *self)
if (meta_window_requested_dont_bypass_compositor (metaWindow))
return FALSE;
if (priv->opacity != 0xff)
if (metaWindow->opacity != 0xFF)
return FALSE;
if (metaWindow->shape_region != NULL)
@ -1362,7 +1304,7 @@ meta_window_actor_set_redirected (MetaWindowActor *self, gboolean state)
MetaDisplay *display = meta_window_get_display (metaWindow);
Display *xdisplay = meta_display_get_xdisplay (display);
Window xwin = meta_window_actor_get_x_window (self);
Window xwin = meta_window_get_toplevel_xwindow (metaWindow);
if (state)
{
@ -1616,22 +1558,10 @@ meta_window_actor_new (MetaWindow *window)
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaWindowActor *self;
MetaWindowActorPrivate *priv;
MetaFrame *frame;
Window top_window;
ClutterActor *window_group;
frame = meta_window_get_frame (window);
if (frame)
top_window = meta_frame_get_xwindow (frame);
else
top_window = meta_window_get_xwindow (window);
meta_verbose ("add window: Meta %p, xwin 0x%x\n", window, (guint)top_window);
self = g_object_new (META_TYPE_WINDOW_ACTOR,
"meta-window", window,
"x-window", top_window,
"meta-screen", screen,
"meta-window", window,
NULL);
priv = self->priv;
@ -1639,10 +1569,6 @@ meta_window_actor_new (MetaWindow *window)
priv->last_width = -1;
priv->last_height = -1;
priv->mapped = meta_window_toplevel_is_mapped (priv->window);
if (priv->mapped)
meta_window_actor_queue_create_pixmap (self);
meta_window_actor_set_updates_frozen (self,
meta_window_updates_are_frozen (priv->window));
@ -1676,34 +1602,6 @@ meta_window_actor_new (MetaWindow *window)
return self;
}
void
meta_window_actor_mapped (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
g_return_if_fail (!priv->mapped);
priv->mapped = TRUE;
meta_window_actor_queue_create_pixmap (self);
}
void
meta_window_actor_unmapped (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
g_return_if_fail (priv->mapped);
priv->mapped = FALSE;
if (meta_window_actor_effect_in_progress (self))
return;
meta_window_actor_detach (self);
priv->needs_pixmap = FALSE;
}
/**
* meta_window_actor_get_obscured_region:
* @self: a #MetaWindowActor
@ -1714,12 +1612,13 @@ meta_window_actor_unmapped (MetaWindowActor *self)
* Return value: (transfer none): the area obscured by the window,
* %NULL is the same as an empty region.
*/
cairo_region_t *
static cairo_region_t *
meta_window_actor_get_obscured_region (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
MetaWindow *window = priv->window;
if (priv->back_pixmap && priv->opacity == 0xff && !priv->window->shaded)
if (priv->back_pixmap && window->opacity != 0xFF && !priv->window->shaded)
return priv->opaque_region;
else
return NULL;
@ -1803,7 +1702,7 @@ meta_window_actor_set_unobscured_region (MetaWindowActor *self,
* not drawn in this frame.
* This will be set before painting then unset afterwards.
*/
void
static void
meta_window_actor_set_clip_region (MetaWindowActor *self,
cairo_region_t *clip_region)
{
@ -1825,7 +1724,7 @@ meta_window_actor_set_clip_region (MetaWindowActor *self,
* shadow hid by the window itself. This will be set before painting
* then unset afterwards.
*/
void
static void
meta_window_actor_set_clip_region_beneath (MetaWindowActor *self,
cairo_region_t *beneath_region)
{
@ -1845,16 +1744,38 @@ meta_window_actor_set_clip_region_beneath (MetaWindowActor *self,
}
}
/**
* meta_window_actor_reset_clip_regions:
* @self: a #MetaWindowActor
*
* Unsets the regions set by meta_window_actor_set_clip_region() and
* meta_window_actor_set_clip_region_beneath()
*/
void
meta_window_actor_reset_clip_regions (MetaWindowActor *self)
static void
meta_window_actor_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
/* Don't do any culling for the unredirected window */
if (self == info->unredirected_window)
return;
meta_window_actor_set_unobscured_region (self, unobscured_region);
meta_window_actor_set_clip_region (self, clip_region);
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self)) == 0xff)
{
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (self);
if (obscured_region)
{
cairo_region_subtract (unobscured_region, obscured_region);
cairo_region_subtract (clip_region, obscured_region);
}
}
meta_window_actor_set_clip_region_beneath (self, clip_region);
}
static void
meta_window_actor_reset_culling (MetaCullable *cullable)
{
MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
MetaWindowActorPrivate *priv = self->priv;
meta_shaped_texture_set_clip_region (META_SHAPED_TEXTURE (priv->actor),
@ -1862,6 +1783,13 @@ meta_window_actor_reset_clip_regions (MetaWindowActor *self)
g_clear_pointer (&priv->shadow_clip, cairo_region_destroy);
}
static void
cullable_iface_init (MetaCullableInterface *iface)
{
iface->cull_out = meta_window_actor_cull_out;
iface->reset_culling = meta_window_actor_reset_culling;
}
static void
check_needs_pixmap (MetaWindowActor *self)
{
@ -1870,15 +1798,12 @@ check_needs_pixmap (MetaWindowActor *self)
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
MetaCompositor *compositor;
Window xwindow = priv->xwindow;
if (!priv->needs_pixmap)
return;
if (!priv->mapped)
return;
if (xwindow == meta_screen_get_xroot (screen) ||
xwindow == clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)))
return;
@ -1936,7 +1861,7 @@ check_needs_pixmap (MetaWindowActor *self)
if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
g_warning ("NOTE: Not using GLX TFP!\n");
/* ::size-changed is supposed to refer to meta_window_get_outer_rect().
/* ::size-changed is supposed to refer to meta_window_get_frame_rect().
* Emitting it here works pretty much OK because a new value of the
* *input* rect (which is the outer rect with the addition of invisible
* borders) forces a new pixmap and we get here. In the rare case where
@ -1964,9 +1889,6 @@ check_needs_shadow (MetaWindowActor *self)
gboolean should_have_shadow;
gboolean appears_focused;
if (!priv->mapped)
return;
/* Calling meta_window_actor_has_shadow() here at every pre-paint is cheap
* and avoids the need to explicitly handle window type changes, which
* we would do if tried to keep track of when we might be adding or removing
@ -2032,7 +1954,7 @@ meta_window_actor_process_damage (MetaWindowActor *self,
if (meta_window_is_fullscreen (priv->window) && g_list_last (info->windows)->data == self && !priv->unredirected)
{
MetaRectangle window_rect;
meta_window_get_outer_rect (priv->window, &window_rect);
meta_window_get_frame_rect (priv->window, &window_rect);
if (window_rect.x == event->area.x &&
window_rect.y == event->area.y &&
@ -2070,7 +1992,7 @@ meta_window_actor_process_damage (MetaWindowActor *self,
return;
}
if (!priv->mapped || priv->needs_pixmap)
if (priv->needs_pixmap)
return;
redraw_queued = meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor),
@ -2256,9 +2178,46 @@ meta_window_actor_update_shape_region (MetaWindowActor *self,
priv->shape_region = region;
g_clear_pointer (&priv->shadow_shape, meta_window_shape_unref);
meta_window_actor_invalidate_shadow (self);
}
static void
meta_window_actor_update_input_region (MetaWindowActor *self,
cairo_rectangle_int_t *client_area)
{
MetaWindowActorPrivate *priv = self->priv;
MetaShapedTexture *stex = META_SHAPED_TEXTURE (priv->actor);
cairo_region_t *region = NULL;
if (priv->window->frame != NULL && priv->window->input_region != NULL)
{
region = meta_frame_get_frame_bounds (priv->window->frame);
cairo_region_subtract_rectangle (region, client_area);
/* input_region is in client window coordinates, so translate the
* input region into that coordinate system and back */
cairo_region_translate (region, -client_area->x, -client_area->y);
cairo_region_union (region, priv->window->input_region);
cairo_region_translate (region, client_area->x, client_area->y);
}
else if (priv->window->input_region != NULL)
{
region = cairo_region_reference (priv->window->input_region);
}
else
{
/* If we don't have a shape on the server, that means that
* we have an implicit shape of one rectangle covering the
* entire window. */
region = cairo_region_create_rectangle (client_area);
}
meta_shaped_texture_set_input_shape_region (stex, region);
cairo_region_destroy (region);
}
static void
meta_window_actor_update_opaque_region (MetaWindowActor *self)
{
@ -2302,9 +2261,6 @@ check_needs_reshape (MetaWindowActor *self)
MetaFrameBorders borders;
cairo_rectangle_int_t client_area;
if (!priv->mapped)
return;
if (!priv->needs_reshape)
return;
@ -2319,10 +2275,10 @@ check_needs_reshape (MetaWindowActor *self)
client_area.height = priv->window->rect.height;
meta_window_actor_update_shape_region (self, &client_area);
meta_window_actor_update_input_region (self, &client_area);
meta_window_actor_update_opaque_region (self);
priv->needs_reshape = FALSE;
meta_window_actor_invalidate_shadow (self);
}
void
@ -2567,23 +2523,9 @@ void
meta_window_actor_update_opacity (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
MetaDisplay *display = meta_screen_get_display (priv->screen);
MetaCompositor *compositor = meta_display_get_compositor (display);
Window xwin = meta_window_get_xwindow (priv->window);
gulong value;
guint8 opacity;
MetaWindow *window = priv->window;
if (meta_prop_get_cardinal (display, xwin,
compositor->atom_net_wm_window_opacity,
&value))
{
opacity = (guint8)((gfloat)value * 255.0 / ((gfloat)0xffffffff));
}
else
opacity = 255;
self->priv->opacity = opacity;
clutter_actor_set_opacity (self->priv->actor, opacity);
clutter_actor_set_opacity (self->priv->actor, window->opacity);
}
void

View File

@ -11,8 +11,8 @@
#include "compositor-private.h"
#include "meta-window-actor-private.h"
#include "meta-window-group.h"
#include "meta-background-actor-private.h"
#include "meta-background-group-private.h"
#include "window-private.h"
#include "meta-cullable.h"
struct _MetaWindowGroupClass
{
@ -26,7 +26,10 @@ struct _MetaWindowGroup
MetaScreen *screen;
};
G_DEFINE_TYPE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_ACTOR);
static void cullable_iface_init (MetaCullableInterface *iface);
G_DEFINE_TYPE_WITH_CODE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_ACTOR,
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
/* Help macros to scale from OpenGL <-1,1> coordinates system to
* window coordinates ranging [0,window-size]. Borrowed from clutter-utils.c
@ -86,6 +89,27 @@ painting_untransformed (MetaWindowGroup *window_group,
return meta_actor_vertices_are_untransformed (vertices, width, height, x_origin, y_origin);
}
static void
meta_window_group_cull_out (MetaCullable *cullable,
cairo_region_t *unobscured_region,
cairo_region_t *clip_region)
{
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
}
static void
meta_window_group_reset_culling (MetaCullable *cullable)
{
meta_cullable_reset_culling_children (cullable);
}
static void
cullable_iface_init (MetaCullableInterface *iface)
{
iface->cull_out = meta_window_group_cull_out;
iface->reset_culling = meta_window_group_reset_culling;
}
static void
meta_window_group_paint (ClutterActor *actor)
{
@ -94,13 +118,13 @@ meta_window_group_paint (ClutterActor *actor)
ClutterActorIter iter;
ClutterActor *child;
cairo_rectangle_int_t visible_rect, clip_rect;
int paint_x_offset, paint_y_offset;
int paint_x_origin, paint_y_origin;
int actor_x_origin, actor_y_origin;
int paint_x_offset, paint_y_offset;
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen);
ClutterActor *stage = clutter_actor_get_stage (actor);
MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen);
/* Start off by treating all windows as completely unobscured, so damage anywhere
* in a window queues redraws, but confine it more below. */
@ -134,9 +158,6 @@ meta_window_group_paint (ClutterActor *actor)
return;
}
paint_x_offset = paint_x_origin - actor_x_origin;
paint_y_offset = paint_y_origin - actor_y_origin;
visible_rect.x = visible_rect.y = 0;
visible_rect.width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
visible_rect.height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
@ -154,134 +175,54 @@ meta_window_group_paint (ClutterActor *actor)
clip_region = cairo_region_create_rectangle (&clip_rect);
paint_x_offset = paint_x_origin - actor_x_origin;
paint_y_offset = paint_y_origin - actor_y_origin;
cairo_region_translate (clip_region, -paint_x_offset, -paint_y_offset);
if (info->unredirected_window != NULL)
{
cairo_rectangle_int_t unredirected_rect;
MetaWindow *window = meta_window_actor_get_meta_window (info->unredirected_window);
meta_window_get_outer_rect (window, (MetaRectangle *)&unredirected_rect);
meta_window_get_frame_rect (window, (MetaRectangle *)&unredirected_rect);
cairo_region_subtract_rectangle (unobscured_region, &unredirected_rect);
cairo_region_subtract_rectangle (clip_region, &unredirected_rect);
}
/* We walk the list from top to bottom (opposite of painting order),
* and subtract the opaque area of each window out of the visible
* region that we pass to the windows below.
*/
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_prev (&iter, &child))
{
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
continue;
if (info->unredirected_window != NULL &&
child == CLUTTER_ACTOR (info->unredirected_window))
continue;
/* If an actor has effects applied, then that can change the area
* it paints and the opacity, so we no longer can figure out what
* portion of the actor is obscured and what portion of the screen
* it obscures, so we skip the actor.
*
* This has a secondary beneficial effect: if a ClutterOffscreenEffect
* is applied to an actor, then our clipped redraws interfere with the
* caching of the FBO - even if we only need to draw a small portion
* of the window right now, ClutterOffscreenEffect may use other portions
* of the FBO later. So, skipping actors with effects applied also
* prevents these bugs.
*
* Theoretically, we should check clutter_actor_get_offscreen_redirect()
* as well for the same reason, but omitted for simplicity in the
* hopes that no-one will do that.
*/
if (clutter_actor_has_effects (child))
continue;
if (META_IS_WINDOW_ACTOR (child))
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
int x, y;
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
continue;
x += paint_x_offset;
y += paint_y_offset;
/* Temporarily move to the coordinate system of the actor */
cairo_region_translate (unobscured_region, - x, - y);
cairo_region_translate (clip_region, - x, - y);
meta_window_actor_set_unobscured_region (window_actor, unobscured_region);
meta_window_actor_set_clip_region (window_actor, clip_region);
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
{
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
if (obscured_region)
{
cairo_region_subtract (unobscured_region, obscured_region);
cairo_region_subtract (clip_region, obscured_region);
}
}
meta_window_actor_set_clip_region_beneath (window_actor, clip_region);
cairo_region_translate (unobscured_region, x, y);
cairo_region_translate (clip_region, x, y);
}
else if (META_IS_BACKGROUND_ACTOR (child) ||
META_IS_BACKGROUND_GROUP (child))
{
int x, y;
if (!meta_actor_is_untransformed (child, &x, &y))
continue;
x += paint_x_offset;
y += paint_y_offset;
cairo_region_translate (clip_region, - x, - y);
if (META_IS_BACKGROUND_GROUP (child))
meta_background_group_set_clip_region (META_BACKGROUND_GROUP (child), clip_region);
else
meta_background_actor_set_clip_region (META_BACKGROUND_ACTOR (child), clip_region);
cairo_region_translate (clip_region, x, y);
}
}
meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region);
cairo_region_destroy (unobscured_region);
cairo_region_destroy (clip_region);
CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
/* Now that we are done painting, unset the visible regions (they will
* mess up painting clones of our actors)
*/
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
{
if (META_IS_WINDOW_ACTOR (child))
{
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
meta_window_actor_reset_clip_regions (window_actor);
}
else if (META_IS_BACKGROUND_ACTOR (child))
{
MetaBackgroundActor *background_actor = META_BACKGROUND_ACTOR (child);
meta_background_actor_set_clip_region (background_actor, NULL);
}
}
meta_cullable_reset_culling (META_CULLABLE (window_group));
}
/* 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

@ -11,29 +11,9 @@
* MetaWindowGroup:
*
* This class is a subclass of ClutterActor with special handling for
* MetaWindowActor/MetaBackgroundActor/MetaBackgroundGroup when painting
* children.
*
* When we are painting a stack of 5-10 maximized windows, the
* standard bottom-to-top method of drawing every actor results in a
* tremendous amount of overdraw and can easily max out the available
* memory bandwidth on a low-end graphics chipset. It's even worse if
* window textures are being accessed over the AGP bus.
*
* The basic technique applied here is to do a pre-pass before painting
* where we walk window from top to bottom and compute the visible area
* at each step by subtracting out the windows above it. The visible
* area is passed to MetaWindowActor which uses it to clip the portion of
* the window which drawn and avoid redrawing the shadow if it is completely
* obscured.
*
* A caveat is that this is ineffective if applications are using ARGB
* visuals, since we have no way of knowing whether a window obscures
* the windows behind it or not. Alternate approaches using the depth
* or stencil buffer rather than client side regions might be able to
* handle alpha windows, but the combination of glAlphaFunc and stenciling
* tends not to be efficient except on newer cards. (And on newer cards
* we have lots of memory and bandwidth.)
* #MetaCullable when painting children. It uses code similar to
* meta_cullable_cull_out_children(), but also has additional special
* cases for the undirected window, and similar.
*/
#define META_TYPE_WINDOW_GROUP (meta_window_group_get_type ())

View File

@ -118,8 +118,6 @@ typedef struct
{
MetaRectangle orig;
MetaRectangle current;
MetaFrameBorders *borders;
gboolean must_free_borders;
ActionType action_type;
gboolean is_user_action;
@ -195,7 +193,6 @@ static gboolean constrain_partially_onscreen (MetaWindow *window,
static void setup_constraint_info (ConstraintInfo *info,
MetaWindow *window,
MetaFrameBorders *orig_borders,
MetaMoveResizeFlags flags,
int resize_gravity,
const MetaRectangle *orig,
@ -204,13 +201,12 @@ static void place_window_if_needed (MetaWindow *window,
ConstraintInfo *info);
static void update_onscreen_requirements (MetaWindow *window,
ConstraintInfo *info);
static void extend_by_frame (MetaRectangle *rect,
const MetaFrameBorders *borders);
static void unextend_by_frame (MetaRectangle *rect,
const MetaFrameBorders *borders);
static inline void get_size_limits (const MetaWindow *window,
const MetaFrameBorders *borders,
gboolean include_frame,
static void extend_by_frame (MetaWindow *window,
MetaRectangle *rect);
static void unextend_by_frame (MetaWindow *window,
MetaRectangle *rect);
static inline void get_size_limits (MetaWindow *window,
gboolean include_frame,
MetaRectangle *min_size,
MetaRectangle *max_size);
@ -280,7 +276,6 @@ do_all_constraints (MetaWindow *window,
void
meta_window_constrain (MetaWindow *window,
MetaFrameBorders *orig_borders,
MetaMoveResizeFlags flags,
int resize_gravity,
const MetaRectangle *orig,
@ -303,7 +298,6 @@ meta_window_constrain (MetaWindow *window,
setup_constraint_info (&info,
window,
orig_borders,
flags,
resize_gravity,
orig,
@ -333,19 +327,11 @@ meta_window_constrain (MetaWindow *window,
* if this was a user move or user move-and-resize operation.
*/
update_onscreen_requirements (window, &info);
/* Ew, what an ugly way to do things. Destructors (in a real OOP language,
* not gobject-style--gobject would be more pain than it's worth) or
* smart pointers would be so much nicer here. *shrug*
*/
if (info.must_free_borders)
g_free (info.borders);
}
static void
setup_constraint_info (ConstraintInfo *info,
MetaWindow *window,
MetaFrameBorders *orig_borders,
MetaMoveResizeFlags flags,
int resize_gravity,
const MetaRectangle *orig,
@ -357,18 +343,6 @@ setup_constraint_info (ConstraintInfo *info,
info->orig = *orig;
info->current = *new;
/* Create a fake frame geometry if none really exists */
if (orig_borders && !window->fullscreen)
{
info->borders = orig_borders;
info->must_free_borders = FALSE;
}
else
{
info->borders = g_new0 (MetaFrameBorders, 1);
info->must_free_borders = TRUE;
}
if (flags & META_IS_MOVE_ACTION && flags & META_IS_RESIZE_ACTION)
info->action_type = ACTION_MOVE_AND_RESIZE;
else if (flags & META_IS_RESIZE_ACTION)
@ -519,11 +493,12 @@ place_window_if_needed(MetaWindow *window,
!window->minimized &&
!window->fullscreen)
{
MetaRectangle placed_rect = info->orig;
MetaRectangle placed_rect;
MetaWorkspace *cur_workspace;
const MetaMonitorInfo *monitor_info;
meta_window_place (window, info->borders, info->orig.x, info->orig.y,
meta_window_get_frame_rect (window, &placed_rect);
meta_window_place (window, info->orig.x, info->orig.y,
&placed_rect.x, &placed_rect.y);
did_placement = TRUE;
@ -541,6 +516,7 @@ place_window_if_needed(MetaWindow *window,
meta_workspace_get_onmonitor_region (cur_workspace,
monitor_info->number);
meta_window_frame_rect_to_client_rect (window, &placed_rect, &placed_rect);
info->current.x = placed_rect.x;
info->current.y = placed_rect.y;
@ -586,10 +562,6 @@ place_window_if_needed(MetaWindow *window,
(window->maximize_vertically_after_placement ?
META_MAXIMIZE_VERTICAL : 0), &info->current);
/* maximization may have changed frame geometry */
if (!window->fullscreen)
meta_frame_calc_borders (window->frame, info->borders);
if (window->fullscreen_after_placement)
{
window->saved_rect = info->current;
@ -649,7 +621,7 @@ update_onscreen_requirements (MetaWindow *window,
/* The require onscreen/on-single-monitor and titlebar_visible
* stuff is relative to the outer window, not the inner
*/
extend_by_frame (&info->current, info->borders);
extend_by_frame (window, &info->current);
/* Update whether we want future constraint runs to require the
* window to be on fully onscreen.
@ -682,10 +654,13 @@ update_onscreen_requirements (MetaWindow *window,
*/
if (window->frame && window->decorated)
{
MetaFrameBorders borders;
MetaRectangle titlebar_rect;
meta_frame_calc_borders (window->frame, &borders);
titlebar_rect = info->current;
titlebar_rect.height = info->borders->visible.top;
titlebar_rect.height = borders.visible.top;
old = window->require_titlebar_visible;
window->require_titlebar_visible =
meta_rectangle_overlaps_with_region (info->usable_screen_region,
@ -698,39 +673,33 @@ update_onscreen_requirements (MetaWindow *window,
}
/* Don't forget to restore the position of the window */
unextend_by_frame (&info->current, info->borders);
unextend_by_frame (window, &info->current);
}
static void
extend_by_frame (MetaRectangle *rect,
const MetaFrameBorders *borders)
extend_by_frame (MetaWindow *window,
MetaRectangle *rect)
{
rect->x -= borders->visible.left;
rect->y -= borders->visible.top;
rect->width += borders->visible.left + borders->visible.right;
rect->height += borders->visible.top + borders->visible.bottom;
meta_window_client_rect_to_frame_rect (window, rect, rect);
}
static void
unextend_by_frame (MetaRectangle *rect,
const MetaFrameBorders *borders)
unextend_by_frame (MetaWindow *window,
MetaRectangle *rect)
{
rect->x += borders->visible.left;
rect->y += borders->visible.top;
rect->width -= borders->visible.left + borders->visible.right;
rect->height -= borders->visible.top + borders->visible.bottom;
meta_window_frame_rect_to_client_rect (window, rect, rect);
}
static inline void
get_size_limits (const MetaWindow *window,
const MetaFrameBorders *borders,
gboolean include_frame,
get_size_limits (MetaWindow *window,
gboolean include_frame,
MetaRectangle *min_size,
MetaRectangle *max_size)
{
/* We pack the results into MetaRectangle structs just for convienience; we
* don't actually use the position of those rects.
*/
min_size->x = min_size->y = max_size->x = max_size->y = 0;
min_size->width = window->size_hints.min_width;
min_size->height = window->size_hints.min_height;
max_size->width = window->size_hints.max_width;
@ -738,22 +707,8 @@ get_size_limits (const MetaWindow *window,
if (include_frame)
{
int fw = borders->visible.left + borders->visible.right;
int fh = borders->visible.top + borders->visible.bottom;
min_size->width += fw;
min_size->height += fh;
/* Do check to avoid overflow (e.g. max_size->width & max_size->height
* may be set to G_MAXINT by meta_set_normal_hints()).
*/
if (max_size->width < (G_MAXINT - fw))
max_size->width += fw;
else
max_size->width = G_MAXINT;
if (max_size->height < (G_MAXINT - fh))
max_size->height += fh;
else
max_size->height = G_MAXINT;
meta_window_client_rect_to_frame_rect (window, min_size, min_size);
meta_window_client_rect_to_frame_rect (window, max_size, max_size);
}
}
@ -765,18 +720,28 @@ constrain_modal_dialog (MetaWindow *window,
{
int x, y;
MetaWindow *parent = meta_window_get_transient_for (window);
MetaRectangle child_rect, parent_rect;
gboolean constraint_already_satisfied;
if (!meta_window_is_attached_dialog (window))
return TRUE;
x = parent->rect.x + (parent->rect.width / 2 - info->current.width / 2);
y = parent->rect.y + (parent->rect.height / 2 - info->current.height / 2);
if (parent->frame)
{
x += parent->frame->rect.x;
y += parent->frame->rect.y;
}
/* We want to center the dialog on the parent, including the decorations
for both of them. info->current is in client X window coordinates, so we need
to convert them to frame coordinates, apply the centering and then
convert back to client.
*/
child_rect = info->current;
extend_by_frame (window, &child_rect);
meta_window_get_frame_rect (parent, &parent_rect);
child_rect.x = parent_rect.x + (parent_rect.width / 2 - child_rect.width / 2);
child_rect.y = parent_rect.y + (parent_rect.height / 2 - child_rect.height / 2);
unextend_by_frame (window, &child_rect);
x = child_rect.x;
y = child_rect.y;
constraint_already_satisfied = (x == info->current.x) && (y == info->current.y);
@ -841,19 +806,19 @@ constrain_maximization (MetaWindow *window,
active_workspace_struts = window->screen->active_workspace->all_struts;
target_size = info->current;
extend_by_frame (&target_size, info->borders);
extend_by_frame (window, &target_size);
meta_rectangle_expand_to_avoiding_struts (&target_size,
&info->entire_monitor,
direction,
active_workspace_struts);
}
/* Now make target_size = maximized size of client window */
unextend_by_frame (&target_size, info->borders);
unextend_by_frame (window, &target_size);
/* Check min size constraints; max size constraints are ignored for maximized
* windows, as per bug 327543.
*/
get_size_limits (window, info->borders, FALSE, &min_size, &max_size);
get_size_limits (window, FALSE, &min_size, &max_size);
hminbad = target_size.width < min_size.width && window->maximized_horizontally;
vminbad = target_size.height < min_size.height && window->maximized_vertically;
if (hminbad || vminbad)
@ -907,12 +872,12 @@ constrain_tiling (MetaWindow *window,
* use an external function for the actual calculation
*/
meta_window_get_current_tile_area (window, &target_size);
unextend_by_frame (&target_size, info->borders);
unextend_by_frame (window, &target_size);
/* Check min size constraints; max size constraints are ignored as for
* maximized windows.
*/
get_size_limits (window, info->borders, FALSE, &min_size, &max_size);
get_size_limits (window, FALSE, &min_size, &max_size);
hminbad = target_size.width < min_size.width;
vminbad = target_size.height < min_size.height;
if (hminbad || vminbad)
@ -955,7 +920,7 @@ constrain_fullscreen (MetaWindow *window,
monitor = info->entire_monitor;
get_size_limits (window, info->borders, FALSE, &min_size, &max_size);
get_size_limits (window, FALSE, &min_size, &max_size);
too_big = !meta_rectangle_could_fit_rect (&monitor, &min_size);
too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor);
if (too_big || too_small)
@ -1064,7 +1029,7 @@ constrain_size_limits (MetaWindow *window,
return TRUE;
/* Determine whether constraint is already satisfied; exit if it is */
get_size_limits (window, info->borders, FALSE, &min_size, &max_size);
get_size_limits (window, FALSE, &min_size, &max_size);
/* We ignore max-size limits for maximized windows; see #327543 */
if (window->maximized_horizontally)
max_size.width = MAX (max_size.width, info->current.width);
@ -1256,8 +1221,8 @@ do_screen_and_monitor_relative_constraints (
/* Determine whether constraint applies; exit if it doesn't */
how_far_it_can_be_smushed = info->current;
get_size_limits (window, info->borders, TRUE, &min_size, &max_size);
extend_by_frame (&info->current, info->borders);
get_size_limits (window, TRUE, &min_size, &max_size);
extend_by_frame (window, &info->current);
if (info->action_type != ACTION_MOVE)
{
@ -1277,7 +1242,7 @@ do_screen_and_monitor_relative_constraints (
&info->current);
if (exit_early || constraint_satisfied || check_only)
{
unextend_by_frame (&info->current, info->borders);
unextend_by_frame (window, &info->current);
return constraint_satisfied;
}
@ -1301,7 +1266,7 @@ do_screen_and_monitor_relative_constraints (
info->fixed_directions,
&info->current);
unextend_by_frame (&info->current, info->borders);
unextend_by_frame (window, &info->current);
return TRUE;
}
@ -1414,8 +1379,11 @@ constrain_titlebar_visible (MetaWindow *window,
*/
if (window->frame)
{
bottom_amount = info->current.height + info->borders->visible.bottom;
vert_amount_onscreen = info->borders->visible.top;
MetaFrameBorders borders;
meta_frame_calc_borders (window->frame, &borders);
bottom_amount = info->current.height + borders.visible.bottom;
vert_amount_onscreen = borders.visible.top;
}
else
bottom_amount = vert_amount_offscreen;
@ -1489,8 +1457,11 @@ constrain_partially_onscreen (MetaWindow *window,
*/
if (window->frame)
{
bottom_amount = info->current.height + info->borders->visible.bottom;
vert_amount_onscreen = info->borders->visible.top;
MetaFrameBorders borders;
meta_frame_calc_borders (window->frame, &borders);
bottom_amount = info->current.height + borders.visible.bottom;
vert_amount_onscreen = borders.visible.top;
}
else
bottom_amount = vert_amount_offscreen;

View File

@ -39,7 +39,6 @@ typedef enum
} MetaMoveResizeFlags;
void meta_window_constrain (MetaWindow *window,
MetaFrameBorders *orig_borders,
MetaMoveResizeFlags flags,
int resize_gravity,
const MetaRectangle *orig,

View File

@ -171,6 +171,7 @@ meta_core_queue_frame_resize (Display *xdisplay,
MetaWindow *window = get_window (xdisplay, frame_xwindow);
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
meta_window_frame_size_changed (window);
}
void
@ -279,8 +280,7 @@ meta_core_lower_beneath_grab_window (Display *xdisplay,
return;
changes.stack_mode = Below;
changes.sibling = grab_window->frame ? grab_window->frame->xwindow
: grab_window->xwindow;
changes.sibling = meta_window_get_toplevel_xwindow (grab_window);
meta_stack_tracker_record_lower_below (screen->stack_tracker,
xwindow,
@ -469,26 +469,6 @@ meta_core_change_workspace (Display *xdisplay,
new_workspace));
}
int
meta_core_get_num_workspaces (Screen *xscreen)
{
MetaScreen *screen;
screen = meta_screen_for_x_screen (xscreen);
return meta_screen_get_n_workspaces (screen);
}
int
meta_core_get_active_workspace (Screen *xscreen)
{
MetaScreen *screen;
screen = meta_screen_for_x_screen (xscreen);
return meta_workspace_index (screen->active_workspace);
}
void
meta_core_show_window_menu (Display *xdisplay,
Window frame_xwindow,

View File

@ -153,8 +153,6 @@ void meta_core_change_workspace (Display *xdisplay,
Window frame_xwindow,
int new_workspace);
int meta_core_get_num_workspaces (Screen *xscreen);
int meta_core_get_active_workspace (Screen *xscreen);
int meta_core_get_frame_workspace (Display *xdisplay,
Window frame_xwindow);
const char* meta_core_get_workspace_name_with_index (Display *xdisplay,

View File

@ -51,7 +51,6 @@
#include <meta/compositor.h>
#include <meta/compositor-mutter.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include "mutter-enum-types.h"
#include "meta-idle-monitor-private.h"
@ -118,12 +117,6 @@ typedef struct
guint ping_timeout_id;
} MetaPingData;
typedef struct
{
MetaDisplay *display;
Window xwindow;
} MetaAutoRaiseData;
typedef struct
{
MetaDisplay *display;
@ -1586,23 +1579,10 @@ reset_ignored_crossing_serials (MetaDisplay *display)
static gboolean
window_raise_with_delay_callback (void *data)
{
MetaWindow *window;
MetaAutoRaiseData *auto_raise;
MetaWindow *window = data;
auto_raise = data;
meta_topic (META_DEBUG_FOCUS,
"In autoraise callback for window 0x%lx\n",
auto_raise->xwindow);
auto_raise->display->autoraise_timeout_id = 0;
auto_raise->display->autoraise_window = NULL;
window = meta_display_lookup_x_window (auto_raise->display,
auto_raise->xwindow);
if (window == NULL)
return FALSE;
window->display->autoraise_timeout_id = 0;
window->display->autoraise_window = NULL;
/* If we aren't already on top, check whether the pointer is inside
* the window and raise the window if so.
@ -1611,6 +1591,7 @@ window_raise_with_delay_callback (void *data)
{
int x, y, root_x, root_y;
Window root, child;
MetaRectangle frame_rect;
unsigned int mask;
gboolean same_screen;
gboolean point_in_window;
@ -1622,9 +1603,8 @@ window_raise_with_delay_callback (void *data)
&root_x, &root_y, &x, &y, &mask);
meta_error_trap_pop (window->display);
point_in_window =
(window->frame && POINT_IN_RECT (root_x, root_y, window->frame->rect)) ||
(window->frame == NULL && POINT_IN_RECT (root_x, root_y, window->rect));
meta_window_get_frame_rect (window, &frame_rect);
point_in_window = POINT_IN_RECT (root_x, root_y, frame_rect);
if (same_screen && point_in_window)
meta_window_raise (window);
else
@ -1639,7 +1619,8 @@ window_raise_with_delay_callback (void *data)
static void
meta_display_mouse_mode_focus (MetaDisplay *display,
MetaWindow *window,
guint32 timestamp) {
guint32 timestamp)
{
if (window->type != META_WINDOW_DESKTOP)
{
meta_topic (META_DEBUG_FOCUS,
@ -1678,7 +1659,8 @@ meta_display_mouse_mode_focus (MetaDisplay *display,
}
static gboolean
window_focus_on_pointer_rest_callback (gpointer data) {
window_focus_on_pointer_rest_callback (gpointer data)
{
MetaFocusData *focus_data;
MetaDisplay *display;
MetaScreen *screen;
@ -1723,9 +1705,9 @@ window_focus_on_pointer_rest_callback (gpointer data) {
goto out;
window =
meta_stack_get_default_focus_window_at_point (screen->stack,
screen->active_workspace,
None, root_x, root_y);
meta_stack_get_default_focus_window_at_point (screen->stack,
screen->active_workspace,
None, root_x, root_y);
if (window == NULL)
goto out;
@ -1733,7 +1715,7 @@ window_focus_on_pointer_rest_callback (gpointer data) {
timestamp = meta_display_get_current_time_roundtrip (display);
meta_display_mouse_mode_focus (display, window, timestamp);
out:
out:
display->focus_timeout_id = 0;
return FALSE;
}
@ -1742,17 +1724,11 @@ void
meta_display_queue_autoraise_callback (MetaDisplay *display,
MetaWindow *window)
{
MetaAutoRaiseData *auto_raise_data;
meta_topic (META_DEBUG_FOCUS,
"Queuing an autoraise timeout for %s with delay %d\n",
window->desc,
meta_prefs_get_auto_raise_delay ());
auto_raise_data = g_new (MetaAutoRaiseData, 1);
auto_raise_data->display = window->display;
auto_raise_data->xwindow = window->xwindow;
if (display->autoraise_timeout_id != 0)
g_source_remove (display->autoraise_timeout_id);
@ -1760,8 +1736,7 @@ meta_display_queue_autoraise_callback (MetaDisplay *display,
g_timeout_add_full (G_PRIORITY_DEFAULT,
meta_prefs_get_auto_raise_delay (),
window_raise_with_delay_callback,
auto_raise_data,
g_free);
window, NULL);
display->autoraise_window = window;
}
@ -2126,6 +2101,19 @@ handle_window_focus_event (MetaDisplay *display,
}
}
static gboolean
window_has_xwindow (MetaWindow *window,
Window xwindow)
{
if (window->xwindow == xwindow)
return TRUE;
if (window->frame && window->frame->xwindow == xwindow)
return TRUE;
return FALSE;
}
/**
* event_callback:
* @event: The event that just happened
@ -2181,7 +2169,7 @@ event_callback (XEvent *event,
if (event->xany.serial > display->focus_serial &&
display->focus_window &&
display->focus_window->xwindow != display->server_focus_window)
!window_has_xwindow (display->focus_window, display->server_focus_window))
{
meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed\n",
display->focus_window->desc);
@ -2304,7 +2292,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)
{
@ -2436,15 +2424,15 @@ event_callback (XEvent *event,
{
gboolean north, south;
gboolean west, east;
int root_x, root_y;
MetaRectangle frame_rect;
MetaGrabOp op;
meta_window_get_position (window, &root_x, &root_y);
meta_window_get_frame_rect (window, &frame_rect);
west = device_event->root_x < (root_x + 1 * window->rect.width / 3);
east = device_event->root_x > (root_x + 2 * window->rect.width / 3);
north = device_event->root_y < (root_y + 1 * window->rect.height / 3);
south = device_event->root_y > (root_y + 2 * window->rect.height / 3);
west = device_event->root_x < (frame_rect.x + 1 * frame_rect.width / 3);
east = device_event->root_x > (frame_rect.x + 2 * frame_rect.width / 3);
north = device_event->root_y < (frame_rect.y + 1 * frame_rect.height / 3);
south = device_event->root_y > (frame_rect.y + 2 * frame_rect.height / 3);
if (north && west)
op = META_GRAB_OP_RESIZING_NW;
@ -3859,85 +3847,6 @@ meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
return is_a_no_focus_window;
}
Cursor
meta_display_create_x_cursor (MetaDisplay *display,
MetaCursor cursor)
{
Cursor xcursor;
guint glyph = XC_num_glyphs;
const char *name = NULL;
switch (cursor)
{
case META_CURSOR_DEFAULT:
glyph = XC_left_ptr;
break;
case META_CURSOR_NORTH_RESIZE:
glyph = XC_top_side;
break;
case META_CURSOR_SOUTH_RESIZE:
glyph = XC_bottom_side;
break;
case META_CURSOR_WEST_RESIZE:
glyph = XC_left_side;
break;
case META_CURSOR_EAST_RESIZE:
glyph = XC_right_side;
break;
case META_CURSOR_SE_RESIZE:
glyph = XC_bottom_right_corner;
break;
case META_CURSOR_SW_RESIZE:
glyph = XC_bottom_left_corner;
break;
case META_CURSOR_NE_RESIZE:
glyph = XC_top_right_corner;
break;
case META_CURSOR_NW_RESIZE:
glyph = XC_top_left_corner;
break;
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
glyph = XC_fleur;
break;
case META_CURSOR_BUSY:
glyph = XC_watch;
break;
case META_CURSOR_DND_IN_DRAG:
name = "dnd-none";
break;
case META_CURSOR_DND_MOVE:
name = "dnd-move";
break;
case META_CURSOR_DND_COPY:
name = "dnd-copy";
break;
case META_CURSOR_DND_UNSUPPORTED_TARGET:
name = "dnd-none";
break;
case META_CURSOR_POINTING_HAND:
glyph = XC_hand2;
break;
case META_CURSOR_CROSSHAIR:
glyph = XC_crosshair;
break;
case META_CURSOR_IBEAM:
glyph = XC_xterm;
break;
default:
g_assert_not_reached ();
glyph = 0; /* silence compiler */
break;
}
if (name != NULL)
xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
else
xcursor = XCreateFontCursor (display->xdisplay, glyph);
return xcursor;
}
static Cursor
xcursor_for_op (MetaDisplay *display,
MetaGrabOp op)
@ -4099,7 +4008,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
* key grab on the RootWindow.
*/
if (grab_window)
grab_xwindow = grab_window->frame ? grab_window->frame->xwindow : grab_window->xwindow;
grab_xwindow = meta_window_get_toplevel_xwindow (grab_window);
else
grab_xwindow = screen->xroot;
@ -4627,6 +4536,7 @@ meta_display_queue_retheme_all_windows (MetaDisplay *display)
MetaWindow *window = tmp->data;
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
meta_window_frame_size_changed (window);
if (window->frame)
{
meta_frame_queue_draw (window->frame);
@ -5808,25 +5718,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);

View File

@ -985,7 +985,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
{
MetaRectangle *new_rect;
new_rect = g_new (MetaRectangle, 1);
meta_window_get_outer_rect (cur_window, new_rect);
meta_window_get_frame_rect (cur_window, new_rect);
obscuring_windows = g_slist_prepend (obscuring_windows, new_rect);
window_stacking =
g_slist_prepend (window_stacking, GINT_TO_POINTER (stack_position));
@ -1010,7 +1010,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
{
MetaRectangle cur_rect;
MetaWindow *cur_window = cur_window_iter->data;
meta_window_get_outer_rect (cur_window, &cur_rect);
meta_window_get_frame_rect (cur_window, &cur_rect);
/* Check if we want to use this window's edges for edge
* resistance (note that dock edges are considered screen edges
@ -1151,7 +1151,7 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
MetaRectangle old_outer, proposed_outer, new_outer;
gboolean is_resize;
meta_window_get_outer_rect (window, &old_outer);
meta_window_get_frame_rect (window, &old_outer);
proposed_outer = old_outer;
proposed_outer.x += (*new_x - old_x);
@ -1237,7 +1237,7 @@ meta_window_edge_resistance_for_resize (MetaWindow *window,
int proposed_outer_width, proposed_outer_height;
gboolean is_resize;
meta_window_get_outer_rect (window, &old_outer);
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);
meta_rectangle_resize_with_gravity (&old_outer,

View File

@ -68,6 +68,7 @@ meta_window_ensure_frame (MetaWindow *window)
frame->mapped = FALSE;
frame->is_flashing = FALSE;
frame->borders_cached = FALSE;
meta_verbose ("Framing window %s: visual %s default, depth %d default depth %d\n",
window->desc,
@ -327,9 +328,23 @@ meta_frame_calc_borders (MetaFrame *frame,
if (frame == NULL)
meta_frame_borders_clear (borders);
else
meta_ui_get_frame_borders (frame->window->screen->ui,
frame->xwindow,
borders);
{
if (!frame->borders_cached)
{
meta_ui_get_frame_borders (frame->window->screen->ui,
frame->xwindow,
&frame->cached_borders);
frame->borders_cached = TRUE;
}
*borders = frame->cached_borders;
}
}
void
meta_frame_clear_cached_borders (MetaFrame *frame)
{
frame->borders_cached = FALSE;
}
gboolean

View File

@ -41,6 +41,8 @@ struct _MetaFrame
*/
MetaRectangle rect;
MetaFrameBorders cached_borders; /* valid if borders_cached is set */
/* position of client, size of frame */
int child_x;
int child_y;
@ -50,6 +52,7 @@ struct _MetaFrame
guint mapped : 1;
guint need_reapply_frame_shape : 1;
guint is_flashing : 1; /* used by the visual bell flash */
guint borders_cached : 1;
};
void meta_window_ensure_frame (MetaWindow *window);
@ -68,6 +71,8 @@ gboolean meta_frame_sync_to_window (MetaFrame *frame,
gboolean need_move,
gboolean need_resize);
void meta_frame_clear_cached_borders (MetaFrame *frame);
cairo_region_t *meta_frame_get_frame_bounds (MetaFrame *frame);
void meta_frame_get_mask (MetaFrame *frame,

View File

@ -1277,7 +1277,7 @@ meta_window_grab_keys (MetaWindow *window)
}
meta_window_change_keygrabs (window,
window->frame ? window->frame->xwindow : window->xwindow,
meta_window_get_toplevel_xwindow (window),
TRUE);
window->keys_grabbed = TRUE;
@ -1580,7 +1580,7 @@ meta_window_grab_all_keys (MetaWindow *window,
window->desc);
meta_window_focus (window, timestamp);
grabwindow = window->frame ? window->frame->xwindow : window->xwindow;
grabwindow = meta_window_get_toplevel_xwindow (window);
meta_topic (META_DEBUG_KEYBINDINGS,
"Grabbing all keys on window %s\n", window->desc);
@ -1835,7 +1835,6 @@ invoke_handler_by_name (MetaDisplay *display,
invoke_handler (display, screen, handler, window, event, NULL);
}
/* now called from only one place, may be worth merging */
static gboolean
process_event (MetaKeyBinding *bindings,
int n_bindings,
@ -1843,7 +1842,6 @@ process_event (MetaKeyBinding *bindings,
MetaScreen *screen,
MetaWindow *window,
XIDeviceEvent *event,
KeySym keysym,
gboolean on_window)
{
int i;
@ -1861,7 +1859,6 @@ process_event (MetaKeyBinding *bindings,
MetaKeyHandler *handler = bindings[i].handler;
if ((!on_window && handler->flags & META_KEY_BINDING_PER_WINDOW) ||
event->evtype != XI_KeyPress ||
bindings[i].keycode != event->detail ||
((event->mods.effective & 0xff & ~(display->ignored_modifier_mask)) !=
bindings[i].mask) ||
@ -1928,7 +1925,7 @@ process_overlay_key (MetaDisplay *display,
*/
if (process_event (display->key_bindings,
display->n_key_bindings,
display, screen, NULL, event, keysym,
display, screen, NULL, event,
FALSE))
{
/* As normally, after we've handled a global key
@ -2192,7 +2189,7 @@ meta_display_process_key_event (MetaDisplay *display,
/* Do the normal keybindings */
return process_event (display->key_bindings,
display->n_key_bindings,
display, screen, window, event, keysym,
display, screen, window, event,
!all_keys_grabbed && window);
}
@ -3140,6 +3137,20 @@ handle_maximize_horizontally (MetaDisplay *display,
}
}
static void
handle_always_on_top (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
XIDeviceEvent *event,
MetaKeyBinding *binding,
gpointer dummy)
{
if (window->wm_state_above == FALSE)
meta_window_make_above (window);
else
meta_window_unmake_above (window);
}
/* Move a window to a corner; to_bottom/to_right are FALSE for the
* top or left edge, or TRUE for the bottom/right edge. xchange/ychange
* are FALSE if that dimension is not to be changed, TRUE otherwise.
@ -3157,17 +3168,17 @@ handle_move_to_corner_backend (MetaDisplay *display,
gpointer dummy)
{
MetaRectangle work_area;
MetaRectangle outer;
MetaRectangle frame_rect;
int orig_x, orig_y;
int new_x, new_y;
meta_window_get_work_area_all_monitors (window, &work_area);
meta_window_get_outer_rect (window, &outer);
meta_window_get_frame_rect (window, &frame_rect);
meta_window_get_position (window, &orig_x, &orig_y);
if (xchange) {
new_x = work_area.x + (to_right ?
work_area.width - outer.width :
work_area.width - frame_rect.width :
0);
} else {
new_x = orig_x;
@ -3175,7 +3186,7 @@ handle_move_to_corner_backend (MetaDisplay *display,
if (ychange) {
new_y = work_area.y + (to_bottom ?
work_area.height - outer.height :
work_area.height - frame_rect.height :
0);
} else {
new_y = orig_y;
@ -3284,12 +3295,12 @@ handle_move_to_center (MetaDisplay *display,
gpointer dummy)
{
MetaRectangle work_area;
MetaRectangle outer;
MetaRectangle frame_rect;
int orig_x, orig_y;
int frame_width, frame_height;
meta_window_get_work_area_all_monitors (window, &work_area);
meta_window_get_outer_rect (window, &outer);
meta_window_get_frame_rect (window, &frame_rect);
meta_window_get_position (window, &orig_x, &orig_y);
frame_width = (window->frame ? window->frame->child_x : 0);
@ -3297,8 +3308,8 @@ handle_move_to_center (MetaDisplay *display,
meta_window_move_resize (window,
TRUE,
work_area.x + (work_area.width +frame_width -outer.width )/2,
work_area.y + (work_area.height+frame_height-outer.height)/2,
work_area.x + (work_area.width +frame_width -frame_rect.width )/2,
work_area.y + (work_area.height+frame_height-frame_rect.height)/2,
window->rect.width,
window->rect.height);
}
@ -3991,8 +4002,8 @@ handle_raise_or_lower (MetaDisplay *display,
if (above->mapped)
{
meta_window_get_outer_rect (window, &win_rect);
meta_window_get_outer_rect (above, &above_rect);
meta_window_get_frame_rect (window, &win_rect);
meta_window_get_frame_rect (above, &above_rect);
/* Check if obscured */
if (meta_rectangle_intersect (&win_rect, &above_rect, &tmp))
@ -4132,28 +4143,6 @@ meta_keybindings_set_custom_handler (const gchar *name,
return TRUE;
}
/**
* meta_keybindings_switch_window: (skip)
* @display: a #MetaDisplay
* @screen: a #MetaScreen
* @event_window: a #MetaWindow
* @event: a #XIDeviceEvent
* @binding: a #MetaKeyBinding
*
*/
void
meta_keybindings_switch_window (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *event_window,
XIDeviceEvent *event,
MetaKeyBinding *binding)
{
gint backwards = (binding->handler->flags & META_KEY_BINDING_IS_REVERSED) != 0;
do_choose_window (display, screen, event_window, event, binding,
backwards, FALSE);
}
static void
init_builtin_key_bindings (MetaDisplay *display)
{
@ -4675,6 +4664,13 @@ init_builtin_key_bindings (MetaDisplay *display)
META_KEYBINDING_ACTION_MAXIMIZE_HORIZONTALLY,
handle_maximize_horizontally, 0);
add_builtin_keybinding (display,
"always-on-top",
common_keybindings,
META_KEY_BINDING_PER_WINDOW,
META_KEYBINDING_ACTION_ALWAYS_ON_TOP,
handle_always_on_top, 0);
add_builtin_keybinding (display,
"move-to-corner-nw",
common_keybindings,

View File

@ -37,7 +37,9 @@
#include <gdk/gdk.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.h>
#include "meta-cursor-tracker-private.h"
#include "screen-private.h"
@ -69,6 +71,106 @@ enum {
static guint signals[LAST_SIGNAL];
static void
translate_meta_cursor (MetaCursor cursor,
guint *glyph_out,
const char **name_out)
{
guint glyph = XC_num_glyphs;
const char *name = NULL;
switch (cursor)
{
case META_CURSOR_DEFAULT:
glyph = XC_left_ptr;
break;
case META_CURSOR_NORTH_RESIZE:
glyph = XC_top_side;
break;
case META_CURSOR_SOUTH_RESIZE:
glyph = XC_bottom_side;
break;
case META_CURSOR_WEST_RESIZE:
glyph = XC_left_side;
break;
case META_CURSOR_EAST_RESIZE:
glyph = XC_right_side;
break;
case META_CURSOR_SE_RESIZE:
glyph = XC_bottom_right_corner;
break;
case META_CURSOR_SW_RESIZE:
glyph = XC_bottom_left_corner;
break;
case META_CURSOR_NE_RESIZE:
glyph = XC_top_right_corner;
break;
case META_CURSOR_NW_RESIZE:
glyph = XC_top_left_corner;
break;
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
glyph = XC_fleur;
break;
case META_CURSOR_BUSY:
glyph = XC_watch;
break;
case META_CURSOR_DND_IN_DRAG:
name = "dnd-none";
break;
case META_CURSOR_DND_MOVE:
name = "dnd-move";
break;
case META_CURSOR_DND_COPY:
name = "dnd-copy";
break;
case META_CURSOR_DND_UNSUPPORTED_TARGET:
name = "dnd-none";
break;
case META_CURSOR_POINTING_HAND:
glyph = XC_hand2;
break;
case META_CURSOR_CROSSHAIR:
glyph = XC_crosshair;
break;
case META_CURSOR_IBEAM:
glyph = XC_xterm;
break;
default:
g_assert_not_reached ();
glyph = 0; /* silence compiler */
break;
}
*glyph_out = glyph;
*name_out = name;
}
static Cursor
load_cursor_on_server (MetaDisplay *display,
MetaCursor cursor)
{
Cursor xcursor;
guint glyph;
const char *name;
translate_meta_cursor (cursor, &glyph, &name);
if (name != NULL)
xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
else
xcursor = XCreateFontCursor (display->xdisplay, glyph);
return xcursor;
}
Cursor
meta_display_create_x_cursor (MetaDisplay *display,
MetaCursor cursor)
{
return load_cursor_on_server (display, cursor);
}
static void
meta_cursor_tracker_init (MetaCursorTracker *self)
{

View File

@ -842,6 +842,8 @@ on_bus_acquired (GDBusConnection *connection,
for (iter = devices; iter; iter = iter->next)
on_device_added (device_manager, iter->data, manager);
g_slist_free (devices);
g_signal_connect_object (device_manager, "device-added",
G_CALLBACK (on_device_added), manager, 0);
g_signal_connect_object (device_manager, "device-removed",

View File

@ -99,8 +99,9 @@ static gboolean meta_monitor_config_assign_crtcs (MetaConfiguration *config,
GPtrArray *crtcs,
GPtrArray *outputs);
static void power_client_changed_cb (UpClient *client,
gpointer user_data);
static void power_client_changed_cb (UpClient *client,
GParamSpec *pspec,
gpointer user_data);
static void
free_output_key (MetaOutputKey *key)
@ -232,7 +233,7 @@ meta_monitor_config_init (MetaMonitorConfig *self)
self->up_client = up_client_new ();
self->lid_is_closed = up_client_get_lid_is_closed (self->up_client);
g_signal_connect_object (self->up_client, "changed",
g_signal_connect_object (self->up_client, "notify::lid-is-closed",
G_CALLBACK (power_client_changed_cb), self, 0);
}
@ -816,6 +817,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 +841,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 +1251,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)
@ -1335,8 +1361,9 @@ turn_off_laptop_display (MetaMonitorConfig *self,
}
static void
power_client_changed_cb (UpClient *client,
gpointer user_data)
power_client_changed_cb (UpClient *client,
GParamSpec *pspec,
gpointer user_data)
{
MetaMonitorManager *manager = meta_monitor_manager_get ();
MetaMonitorConfig *self = user_data;

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

@ -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
@ -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

@ -806,6 +806,9 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_new_take_string (make_display_name (manager, output)));
g_variant_builder_add (&properties, "{sv}", "backlight",
g_variant_new_int32 (output->backlight));
g_variant_builder_add (&properties, "{sv}", "min-backlight-step",
g_variant_new_int32 ((output->backlight_max - output->backlight_min) ?
100 / (output->backlight_max - output->backlight_min) : -1));
g_variant_builder_add (&properties, "{sv}", "primary",
g_variant_new_boolean (output->is_primary));
g_variant_builder_add (&properties, "{sv}", "presentation",

View File

@ -47,34 +47,18 @@ northwestcmp (gconstpointer a, gconstpointer b)
{
MetaWindow *aw = (gpointer) a;
MetaWindow *bw = (gpointer) b;
MetaRectangle a_frame;
MetaRectangle b_frame;
int from_origin_a;
int from_origin_b;
int ax, ay, bx, by;
/* we're interested in the frame position for cascading,
* not meta_window_get_position()
*/
if (aw->frame)
{
ax = aw->frame->rect.x;
ay = aw->frame->rect.y;
}
else
{
ax = aw->rect.x;
ay = aw->rect.y;
}
if (bw->frame)
{
bx = bw->frame->rect.x;
by = bw->frame->rect.y;
}
else
{
bx = bw->rect.x;
by = bw->rect.y;
}
meta_window_get_frame_rect (aw, &a_frame);
meta_window_get_frame_rect (bw, &b_frame);
ax = a_frame.x;
ay = a_frame.y;
bx = b_frame.x;
by = b_frame.y;
/* probably there's a fast good-enough-guess we could use here. */
from_origin_a = sqrt (ax * ax + ay * ay);
@ -90,7 +74,6 @@ northwestcmp (gconstpointer a, gconstpointer b)
static void
find_next_cascade (MetaWindow *window,
MetaFrameBorders *borders,
/* visible windows on relevant workspaces */
GList *windows,
int x,
@ -102,6 +85,7 @@ find_next_cascade (MetaWindow *window,
GList *sorted;
int cascade_x, cascade_y;
int x_threshold, y_threshold;
MetaRectangle frame_rect;
int window_width, window_height;
int cascade_stage;
MetaRectangle work_area;
@ -120,10 +104,13 @@ find_next_cascade (MetaWindow *window,
* manually cascade.
*/
#define CASCADE_FUZZ 15
if (borders)
if (window->frame)
{
x_threshold = MAX (borders->visible.left, CASCADE_FUZZ);
y_threshold = MAX (borders->visible.top, CASCADE_FUZZ);
MetaFrameBorders borders;
meta_frame_calc_borders (window->frame, &borders);
x_threshold = MAX (borders.visible.left, CASCADE_FUZZ);
y_threshold = MAX (borders.visible.top, CASCADE_FUZZ);
}
else
{
@ -143,30 +130,25 @@ find_next_cascade (MetaWindow *window,
cascade_y = MAX (0, work_area.y);
/* Find first cascade position that's not used. */
window_width = window->frame ? window->frame->rect.width : window->rect.width;
window_height = window->frame ? window->frame->rect.height : window->rect.height;
meta_window_get_frame_rect (window, &frame_rect);
window_width = frame_rect.width;
window_height = frame_rect.height;
cascade_stage = 0;
tmp = sorted;
while (tmp != NULL)
{
MetaWindow *w;
MetaRectangle w_frame_rect;
int wx, wy;
w = tmp->data;
/* we want frame position, not window position */
if (w->frame)
{
wx = w->frame->rect.x;
wy = w->frame->rect.y;
}
else
{
wx = w->rect.x;
wy = w->rect.y;
}
meta_window_get_frame_rect (w, &w_frame_rect);
wx = w_frame_rect.x;
wy = w_frame_rect.y;
if (ABS (wx - cascade_x) < x_threshold &&
ABS (wy - cascade_y) < y_threshold)
@ -223,22 +205,12 @@ find_next_cascade (MetaWindow *window,
g_list_free (sorted);
/* Convert coords to position of window, not position of frame. */
if (borders == NULL)
{
*new_x = cascade_x;
*new_y = cascade_y;
}
else
{
*new_x = cascade_x + borders->visible.left;
*new_y = cascade_y + borders->visible.top;
}
*new_x = cascade_x;
*new_y = cascade_y;
}
static void
find_most_freespace (MetaWindow *window,
MetaFrameBorders *borders,
/* visible windows on relevant workspaces */
MetaWindow *focus_window,
int x,
@ -250,29 +222,25 @@ find_most_freespace (MetaWindow *window,
int max_area;
int max_width, max_height, left, right, top, bottom;
int left_space, right_space, top_space, bottom_space;
int frame_size_left, frame_size_top;
MetaRectangle work_area;
MetaRectangle avoid;
MetaRectangle outer;
frame_size_left = borders ? borders->visible.left : 0;
frame_size_top = borders ? borders->visible.top : 0;
MetaRectangle frame_rect;
meta_window_get_work_area_current_monitor (focus_window, &work_area);
meta_window_get_outer_rect (focus_window, &avoid);
meta_window_get_outer_rect (window, &outer);
meta_window_get_frame_rect (focus_window, &avoid);
meta_window_get_frame_rect (window, &frame_rect);
/* Find the areas of choosing the various sides of the focus window */
max_width = MIN (avoid.width, outer.width);
max_height = MIN (avoid.height, outer.height);
max_width = MIN (avoid.width, frame_rect.width);
max_height = MIN (avoid.height, frame_rect.height);
left_space = avoid.x - work_area.x;
right_space = work_area.width - (avoid.x + avoid.width - work_area.x);
top_space = avoid.y - work_area.y;
bottom_space = work_area.height - (avoid.y + avoid.height - work_area.y);
left = MIN (left_space, outer.width);
right = MIN (right_space, outer.width);
top = MIN (top_space, outer.height);
bottom = MIN (bottom_space, outer.height);
left = MIN (left_space, frame_rect.width);
right = MIN (right_space, frame_rect.width);
top = MIN (top_space, frame_rect.height);
bottom = MIN (bottom_space, frame_rect.height);
/* Find out which side of the focus_window can show the most of the window */
side = META_LEFT;
@ -304,39 +272,56 @@ find_most_freespace (MetaWindow *window,
switch (side)
{
case META_LEFT:
*new_y = avoid.y + frame_size_top;
if (left_space > outer.width)
*new_x = avoid.x - outer.width + frame_size_left;
*new_y = avoid.y;
if (left_space > frame_rect.width)
*new_x = avoid.x - frame_rect.width;
else
*new_x = work_area.x + frame_size_left;
*new_x = work_area.x;
break;
case META_RIGHT:
*new_y = avoid.y + frame_size_top;
if (right_space > outer.width)
*new_x = avoid.x + avoid.width + frame_size_left;
*new_y = avoid.y;
if (right_space > frame_rect.width)
*new_x = avoid.x + avoid.width;
else
*new_x = work_area.x + work_area.width - outer.width + frame_size_left;
*new_x = work_area.x + work_area.width - frame_rect.width;
break;
case META_TOP:
*new_x = avoid.x + frame_size_left;
if (top_space > outer.height)
*new_y = avoid.y - outer.height + frame_size_top;
*new_x = avoid.x;
if (top_space > frame_rect.height)
*new_y = avoid.y - frame_rect.height;
else
*new_y = work_area.y + frame_size_top;
*new_y = work_area.y;
break;
case META_BOTTOM:
*new_x = avoid.x + frame_size_left;
if (bottom_space > outer.height)
*new_y = avoid.y + avoid.height + frame_size_top;
*new_x = avoid.x;
if (bottom_space > frame_rect.height)
*new_y = avoid.y + avoid.height;
else
*new_y = work_area.y + work_area.height - outer.height + frame_size_top;
*new_y = work_area.y + work_area.height - frame_rect.height;
break;
}
}
static gboolean
window_overlaps_focus_window (MetaWindow *window)
{
MetaWindow *focus_window;
MetaRectangle window_frame, focus_frame, overlap;
focus_window = window->display->focus_window;
if (focus_window == NULL)
return FALSE;
meta_window_get_frame_rect (window, &window_frame);
meta_window_get_frame_rect (focus_window, &focus_frame);
return meta_rectangle_intersect (&window_frame,
&focus_frame,
&overlap);
}
static void
avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
MetaFrameBorders *borders,
int *x,
int *y)
{
@ -355,18 +340,17 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
*/
MetaWindow *focus_window;
MetaRectangle overlap;
focus_window = window->display->focus_window;
/* denied_focus_and_not_transient is only set when focus_window != NULL */
if (window->denied_focus_and_not_transient &&
window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
meta_window_same_application (window, focus_window) &&
meta_rectangle_intersect (&window->rect,
&focus_window->rect,
&overlap))
window_overlaps_focus_window (window))
{
find_most_freespace (window, borders, focus_window, *x, *y, x, y);
find_most_freespace (window, focus_window, *x, *y, x, y);
meta_topic (META_DEBUG_PLACEMENT,
"Dialog window %s was denied focus but may be modal "
"to the focus window; had to move it to avoid the "
@ -409,7 +393,7 @@ rectangle_overlaps_some_window (MetaRectangle *rect,
case META_WINDOW_UTILITY:
case META_WINDOW_TOOLBAR:
case META_WINDOW_MENU:
meta_window_get_outer_rect (other, &other_rect);
meta_window_get_frame_rect (other, &other_rect);
if (meta_rectangle_intersect (rect, &other_rect, &dest))
return TRUE;
@ -427,20 +411,14 @@ leftmost_cmp (gconstpointer a, gconstpointer b)
{
MetaWindow *aw = (gpointer) a;
MetaWindow *bw = (gpointer) b;
MetaRectangle a_frame;
MetaRectangle b_frame;
int ax, bx;
/* we're interested in the frame position for cascading,
* not meta_window_get_position()
*/
if (aw->frame)
ax = aw->frame->rect.x;
else
ax = aw->rect.x;
if (bw->frame)
bx = bw->frame->rect.x;
else
bx = bw->rect.x;
meta_window_get_frame_rect (aw, &a_frame);
meta_window_get_frame_rect (bw, &b_frame);
ax = a_frame.x;
bx = b_frame.x;
if (ax < bx)
return -1;
@ -455,20 +433,14 @@ topmost_cmp (gconstpointer a, gconstpointer b)
{
MetaWindow *aw = (gpointer) a;
MetaWindow *bw = (gpointer) b;
MetaRectangle a_frame;
MetaRectangle b_frame;
int ay, by;
/* we're interested in the frame position for cascading,
* not meta_window_get_position()
*/
if (aw->frame)
ay = aw->frame->rect.y;
else
ay = aw->rect.y;
if (bw->frame)
by = bw->frame->rect.y;
else
by = bw->rect.y;
meta_window_get_frame_rect (aw, &a_frame);
meta_window_get_frame_rect (bw, &b_frame);
ay = a_frame.y;
by = b_frame.y;
if (ay < by)
return -1;
@ -506,7 +478,6 @@ center_tile_rect_in_area (MetaRectangle *rect,
*/
static gboolean
find_first_fit (MetaWindow *window,
MetaFrameBorders *borders,
/* visible windows on relevant workspaces */
GList *windows,
int monitor,
@ -540,15 +511,8 @@ find_first_fit (MetaWindow *window,
right_sorted = g_list_copy (windows);
right_sorted = g_list_sort (right_sorted, topmost_cmp);
right_sorted = g_list_sort (right_sorted, leftmost_cmp);
rect.width = window->rect.width;
rect.height = window->rect.height;
if (borders)
{
rect.width += borders->visible.left + borders->visible.right;
rect.height += borders->visible.top + borders->visible.bottom;
}
meta_window_get_frame_rect (window, &rect);
#ifdef WITH_VERBOSE_MODE
{
@ -570,11 +534,6 @@ find_first_fit (MetaWindow *window,
{
*new_x = rect.x;
*new_y = rect.y;
if (borders)
{
*new_x += borders->visible.left;
*new_y += borders->visible.top;
}
retval = TRUE;
@ -586,23 +545,18 @@ find_first_fit (MetaWindow *window,
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
MetaRectangle outer_rect;
MetaRectangle frame_rect;
meta_window_get_outer_rect (w, &outer_rect);
meta_window_get_frame_rect (w, &frame_rect);
rect.x = outer_rect.x;
rect.y = outer_rect.y + outer_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 (borders)
{
*new_x += borders->visible.left;
*new_y += borders->visible.top;
}
retval = TRUE;
@ -617,23 +571,18 @@ find_first_fit (MetaWindow *window,
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
MetaRectangle outer_rect;
MetaRectangle frame_rect;
meta_window_get_outer_rect (w, &outer_rect);
meta_window_get_frame_rect (w, &frame_rect);
rect.x = outer_rect.x + outer_rect.width;
rect.y = outer_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 (borders)
{
*new_x += borders->visible.left;
*new_y += borders->visible.top;
}
retval = TRUE;
@ -652,7 +601,6 @@ find_first_fit (MetaWindow *window,
void
meta_window_place (MetaWindow *window,
MetaFrameBorders *borders,
int x,
int y,
int *new_x,
@ -661,13 +609,6 @@ meta_window_place (MetaWindow *window,
GList *windows;
const MetaMonitorInfo *xi;
/* frame member variables should NEVER be used in here, only
* MetaFrameBorders. But remember borders == NULL
* for undecorated windows. Also, this function should
* NEVER have side effects other than computing the
* placement coordinates.
*/
meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
windows = NULL;
@ -756,7 +697,7 @@ meta_window_place (MetaWindow *window,
{
meta_topic (META_DEBUG_PLACEMENT,
"Not placing window with PPosition or USPosition set\n");
avoid_being_obscured_as_second_modal_dialog (window, borders, &x, &y);
avoid_being_obscured_as_second_modal_dialog (window, &x, &y);
goto done_no_constraints;
}
}
@ -775,29 +716,27 @@ meta_window_place (MetaWindow *window,
if (parent)
{
int w;
MetaRectangle frame_rect, parent_frame_rect;
meta_window_get_position (parent, &x, &y);
w = parent->rect.width;
meta_window_get_frame_rect (window, &frame_rect);
meta_window_get_frame_rect (parent, &parent_frame_rect);
y = parent_frame_rect.y;
/* center of parent */
x = x + w / 2;
x = parent_frame_rect.x + parent_frame_rect.width / 2;
/* center of child over center of parent */
x -= window->rect.width / 2;
x -= frame_rect.width / 2;
/* "visually" center window over parent, leaving twice as
* much space below as on top.
*/
y += (parent->rect.height - window->rect.height)/3;
/* put top of child's frame, not top of child's client */
if (borders)
y += borders->visible.top;
y += (parent_frame_rect.height - frame_rect.height)/3;
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s over transient parent\n",
window->desc);
avoid_being_obscured_as_second_modal_dialog (window, borders, &x, &y);
avoid_being_obscured_as_second_modal_dialog (window, &x, &y);
goto done;
}
@ -813,6 +752,9 @@ meta_window_place (MetaWindow *window,
{
/* Center on current monitor */
int w, h;
MetaRectangle frame_rect;
meta_window_get_frame_rect (window, &frame_rect);
/* Warning, this function is a round trip! */
xi = meta_screen_get_current_monitor_info (window->screen);
@ -820,8 +762,8 @@ meta_window_place (MetaWindow *window,
w = xi->rect.width;
h = xi->rect.height;
x = (w - window->rect.width) / 2;
y = (h - window->rect.height) / 2;
x = (w - frame_rect.width) / 2;
y = (h - frame_rect.height) / 2;
x += xi->rect.x;
y += xi->rect.y;
@ -865,7 +807,7 @@ meta_window_place (MetaWindow *window,
x = xi->rect.x;
y = xi->rect.y;
if (find_first_fit (window, borders, windows,
if (find_first_fit (window, windows,
xi->number,
x, y, &x, &y))
goto done_check_denied_focus;
@ -878,17 +820,17 @@ meta_window_place (MetaWindow *window,
!window->fullscreen)
{
MetaRectangle workarea;
MetaRectangle outer;
MetaRectangle frame_rect;
meta_window_get_work_area_for_monitor (window,
xi->number,
&workarea);
meta_window_get_outer_rect (window, &outer);
meta_window_get_frame_rect (window, &frame_rect);
/* If the window is bigger than the screen, then automaximize. Do NOT
* auto-maximize the directions independently. See #419810.
*/
if (outer.width >= workarea.width && outer.height >= workarea.height)
if (frame_rect.width >= workarea.width && frame_rect.height >= workarea.height)
{
window->maximize_horizontally_after_placement = TRUE;
window->maximize_vertically_after_placement = TRUE;
@ -899,7 +841,7 @@ meta_window_place (MetaWindow *window,
* fully overlapping window (e.g. starting multiple terminals)
* */
if (x == xi->rect.x && y == xi->rect.y)
find_next_cascade (window, borders, windows, x, y, &x, &y);
find_next_cascade (window, windows, x, y, &x, &y);
done_check_denied_focus:
/* If the window is being denied focus and isn't a transient of the
@ -909,17 +851,14 @@ meta_window_place (MetaWindow *window,
*/
if (window->denied_focus_and_not_transient)
{
gboolean found_fit;
MetaWindow *focus_window;
MetaRectangle overlap;
gboolean found_fit;
focus_window = window->display->focus_window;
g_assert (focus_window != NULL);
/* No need to do anything if the window doesn't overlap at all */
found_fit = !meta_rectangle_intersect (&window->rect,
&focus_window->rect,
&overlap);
found_fit = !window_overlaps_focus_window (window);
/* Try to do a first fit again, this time only taking into account the
* focus window.
@ -933,7 +872,7 @@ meta_window_place (MetaWindow *window,
x = xi->rect.x;
y = xi->rect.y;
found_fit = find_first_fit (window, borders, focus_window_list,
found_fit = find_first_fit (window, focus_window_list,
xi->number,
x, y, &x, &y);
g_list_free (focus_window_list);
@ -943,7 +882,7 @@ meta_window_place (MetaWindow *window,
* as possible.
*/
if (!found_fit)
find_most_freespace (window, borders, focus_window, x, y, &x, &y);
find_most_freespace (window, focus_window, x, y, &x, &y);
}
done:

View File

@ -28,7 +28,6 @@
#include "frame.h"
void meta_window_place (MetaWindow *window,
MetaFrameBorders *borders,
int x,
int y,
int *new_x,

View File

@ -476,6 +476,9 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
CWEventMask|CWOverrideRedirect|CWBackPixel,
&attributes);
/* https://bugzilla.gnome.org/show_bug.cgi?id=710346 */
XStoreName (xdisplay, guard_window, "mutter guard window");
{
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
@ -856,9 +859,9 @@ meta_screen_free (MetaScreen *screen,
screen->wm_sn_selection_window);
if (screen->work_area_later != 0)
g_source_remove (screen->work_area_later);
meta_later_remove (screen->work_area_later);
if (screen->check_fullscreen_later != 0)
g_source_remove (screen->check_fullscreen_later);
meta_later_remove (screen->check_fullscreen_later);
if (screen->monitor_infos)
g_free (screen->monitor_infos);
@ -1525,7 +1528,7 @@ meta_screen_tab_popup_create (MetaScreen *screen,
if (show_type == META_TAB_SHOW_INSTANTLY ||
!entries[i].hidden ||
!meta_window_get_icon_geometry (window, &r))
meta_window_get_outer_rect (window, &r);
meta_window_get_frame_rect (window, &r);
entries[i].rect = r;
@ -1908,7 +1911,7 @@ meta_screen_get_monitor_for_window (MetaScreen *screen,
{
MetaRectangle window_rect;
meta_window_get_outer_rect (window, &window_rect);
meta_window_get_frame_rect (window, &window_rect);
return meta_screen_get_monitor_for_rect (screen, &window_rect);
}

View File

@ -1465,7 +1465,7 @@ window_contains_point (MetaWindow *window,
{
MetaRectangle rect;
meta_window_get_outer_rect (window, &rect);
meta_window_get_frame_rect (window, &rect);
return POINT_IN_RECT (root_x, root_y, rect);
}

View File

@ -352,6 +352,12 @@ struct _MetaWindow
/* if non-NULL, the opaque region _NET_WM_OPAQUE_REGION */
cairo_region_t *opaque_region;
/* the input shape region for picking */
cairo_region_t *input_region;
/* _NET_WM_WINDOW_OPACITY */
guint opacity;
/* if TRUE, the we have the new form of sync request counter which
* also handles application frames */
guint extended_sync_request_counter : 1;
@ -512,6 +518,7 @@ void meta_window_update_fullscreen_monitors (MetaWindow *window,
unsigned long left,
unsigned long right);
/* args to move are window pos, not frame pos */
void meta_window_move (MetaWindow *window,
gboolean user_op,
@ -655,6 +662,8 @@ void meta_window_recalc_features (MetaWindow *window);
void meta_window_recalc_window_type (MetaWindow *window);
void meta_window_frame_size_changed (MetaWindow *window);
void meta_window_stack_just_below (MetaWindow *window,
MetaWindow *below_this_one);
@ -682,8 +691,16 @@ void meta_window_set_opaque_region (MetaWindow *window,
cairo_region_t *region);
void meta_window_update_opaque_region_x11 (MetaWindow *window);
void meta_window_set_input_region (MetaWindow *window,
cairo_region_t *region);
void meta_window_update_input_region_x11 (MetaWindow *window);
void meta_window_set_shape_region (MetaWindow *window,
cairo_region_t *region);
void meta_window_update_shape_region_x11 (MetaWindow *window);
void meta_window_set_opacity (MetaWindow *window,
guint opacity);
Window meta_window_get_toplevel_xwindow (MetaWindow *window);
#endif

View File

@ -316,6 +316,9 @@ reload_gtk_frame_extents (MetaWindow *window,
{
window->has_custom_frame_extents = FALSE;
}
if (!initial)
meta_window_queue(window, META_QUEUE_MOVE_RESIZE);
}
static void
@ -1706,6 +1709,20 @@ reload_bypass_compositor (MetaWindow *window,
window->bypass_compositor = requested_value;
}
static void
reload_window_opacity (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
int requested_value = 0xFF;
if (value->type != META_PROP_VALUE_INVALID)
requested_value = (int) value->v.cardinal;
meta_window_set_opacity (window, requested_value);
}
#define RELOAD_STRING(var_name, propname) \
static void \
reload_ ## var_name (MetaWindow *window, \
@ -1808,6 +1825,7 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
{ display->atom__NET_WM_STRUT, META_PROP_VALUE_INVALID, reload_struts, FALSE, FALSE },
{ display->atom__NET_WM_STRUT_PARTIAL, META_PROP_VALUE_INVALID, reload_struts, FALSE, FALSE },
{ display->atom__NET_WM_BYPASS_COMPOSITOR, META_PROP_VALUE_CARDINAL, reload_bypass_compositor, FALSE, FALSE },
{ display->atom__NET_WM_WINDOW_OPACITY, META_PROP_VALUE_CARDINAL, reload_window_opacity, TRUE, TRUE },
{ 0 },
};

View File

@ -1194,12 +1194,15 @@ meta_window_new_with_attrs (MetaDisplay *display,
meta_display_register_x_window (display, &window->xwindow, window);
meta_window_update_shape_region_x11 (window);
meta_window_update_input_region_x11 (window);
/* Assign this #MetaWindow a sequence number which can be used
* for sorting.
*/
window->stable_sequence = ++display->window_sequence_counter;
window->opacity = 0xFF;
/* assign the window to its group, or create a new group if needed
*/
window->group = NULL;
@ -1444,9 +1447,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
set_net_wm_state (window);
}
if (screen->display->compositor)
meta_compositor_add_window (screen->display->compositor, window);
/* Sync stack changes */
meta_stack_thaw (window->screen->stack);
@ -1669,8 +1669,6 @@ meta_window_unmanage (MetaWindow *window,
if (window->visible_to_compositor)
meta_compositor_hide_window (window->display->compositor, window,
META_COMP_EFFECT_DESTROY);
meta_compositor_remove_window (window->display->compositor, window);
}
if (window->display->window_with_menu == window)
@ -1869,6 +1867,8 @@ meta_window_unmanage (MetaWindow *window,
meta_window_ungrab_keys (window);
meta_display_ungrab_window_buttons (window->display, window->xwindow);
meta_display_ungrab_focus_window_button (window->display, window);
if (window->display->autoraise_window == window)
meta_display_remove_autoraise_callback (window->display);
meta_display_unregister_x_window (window->display, window->xwindow);
@ -2791,8 +2791,8 @@ static gboolean
windows_overlap (const MetaWindow *w1, const MetaWindow *w2)
{
MetaRectangle w1rect, w2rect;
meta_window_get_outer_rect (w1, &w1rect);
meta_window_get_outer_rect (w2, &w2rect);
meta_window_get_frame_rect (w1, &w1rect);
meta_window_get_frame_rect (w2, &w2rect);
return meta_rectangle_overlap (&w1rect, &w2rect);
}
@ -3138,7 +3138,7 @@ meta_window_show (MetaWindow *window)
if (toplevel_now_mapped != toplevel_was_mapped)
{
if (window->display->compositor)
meta_compositor_window_mapped (window->display->compositor, window);
meta_compositor_add_window (window->display->compositor, window);
}
if (!window->visible_to_compositor)
@ -3287,13 +3287,7 @@ meta_window_hide (MetaWindow *window)
if (toplevel_now_mapped != toplevel_was_mapped)
{
if (window->display->compositor)
{
/* As above, we may be *mapping* live hidden windows */
if (toplevel_now_mapped)
meta_compositor_window_mapped (window->display->compositor, window);
else
meta_compositor_window_unmapped (window->display->compositor, window);
}
meta_compositor_remove_window (window->display->compositor, window);
}
set_net_wm_state (window);
@ -3593,11 +3587,11 @@ meta_window_maximize (MetaWindow *window,
MetaRectangle old_rect;
MetaRectangle new_rect;
meta_window_get_outer_rect (window, &old_rect);
meta_window_get_frame_rect (window, &old_rect);
meta_window_move_resize_now (window);
meta_window_get_outer_rect (window, &new_rect);
meta_window_get_frame_rect (window, &new_rect);
meta_compositor_maximize_window (window->display->compositor,
window,
&old_rect,
@ -3656,7 +3650,7 @@ meta_window_get_all_monitors (MetaWindow *window, gsize *length)
int i;
monitors = g_array_new (FALSE, FALSE, sizeof (int));
meta_window_get_outer_rect (window, &window_rect);
meta_window_get_frame_rect (window, &window_rect);
for (i = 0; i < window->screen->n_monitor_infos; i++)
{
@ -3689,7 +3683,7 @@ meta_window_is_screen_sized (MetaWindow *window)
int screen_width, screen_height;
meta_screen_get_size (window->screen, &screen_width, &screen_height);
meta_window_get_outer_rect (window, &window_rect);
meta_window_get_frame_rect (window, &window_rect);
if (window_rect.x == 0 && window_rect.y == 0 &&
window_rect.width == screen_width && window_rect.height == screen_height)
@ -3718,7 +3712,7 @@ meta_window_is_monitor_sized (MetaWindow *window)
{
MetaRectangle window_rect, monitor_rect;
meta_window_get_outer_rect (window, &window_rect);
meta_window_get_frame_rect (window, &window_rect);
meta_screen_get_monitor_geometry (window->screen, window->monitor->number, &monitor_rect);
if (meta_rectangle_equal (&window_rect, &monitor_rect))
@ -3786,11 +3780,11 @@ meta_window_tile (MetaWindow *window)
MetaRectangle old_rect;
MetaRectangle new_rect;
meta_window_get_outer_rect (window, &old_rect);
meta_window_get_frame_rect (window, &old_rect);
meta_window_move_resize_now (window);
meta_window_get_outer_rect (window, &new_rect);
meta_window_get_frame_rect (window, &new_rect);
meta_compositor_maximize_window (window->display->compositor,
window,
&old_rect,
@ -3819,7 +3813,7 @@ meta_window_can_tile_side_by_side (MetaWindow *window)
{
int monitor;
MetaRectangle tile_area;
MetaFrameBorders borders;
MetaRectangle client_rect;
if (!meta_window_can_tile_maximized (window))
return FALSE;
@ -3833,13 +3827,10 @@ meta_window_can_tile_side_by_side (MetaWindow *window)
tile_area.width /= 2;
meta_frame_calc_borders (window->frame, &borders);
meta_window_frame_rect_to_client_rect (window, &tile_area, &client_rect);
tile_area.width -= (borders.visible.left + borders.visible.right);
tile_area.height -= (borders.visible.top + borders.visible.bottom);
return tile_area.width >= window->size_hints.min_width &&
tile_area.height >= window->size_hints.min_height;
return client_rect.width >= window->size_hints.min_width &&
client_rect.height >= window->size_hints.min_height;
}
static void
@ -3900,8 +3891,10 @@ meta_window_unmaximize_internal (MetaWindow *window,
{
MetaRectangle target_rect;
MetaRectangle work_area;
MetaRectangle old_rect;
meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area);
meta_window_get_frame_rect (window, &old_rect);
meta_topic (META_DEBUG_WINDOW_OPS,
"Unmaximizing %s%s\n",
@ -3915,6 +3908,12 @@ meta_window_unmaximize_internal (MetaWindow *window,
window->maximized_vertically =
window->maximized_vertically && !unmaximize_vertically;
/* recalc_window_features() will eventually clear the cached frame
* extents, but we need the correct frame extents in the code below,
* so invalidate the old frame extents manually up front.
*/
meta_window_frame_size_changed (window);
/* Unmaximize to the saved_rect position in the direction(s)
* being unmaximized.
*/
@ -3959,9 +3958,7 @@ meta_window_unmaximize_internal (MetaWindow *window,
if (window->display->compositor)
{
MetaRectangle old_rect, new_rect;
meta_window_get_outer_rect (window, &old_rect);
MetaRectangle new_rect;
meta_window_move_resize_internal (window,
META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION,
@ -3971,7 +3968,7 @@ meta_window_unmaximize_internal (MetaWindow *window,
target_rect.width,
target_rect.height);
meta_window_get_outer_rect (window, &new_rect);
meta_window_get_frame_rect (window, &new_rect);
meta_compositor_unmaximize_window (window->display->compositor,
window,
&old_rect,
@ -4076,6 +4073,7 @@ meta_window_set_above (MetaWindow *window,
window->wm_state_above = new_value;
meta_window_update_layer (window);
set_net_wm_state (window);
meta_window_frame_size_changed (window);
g_object_notify (G_OBJECT (window), "above");
}
@ -4215,6 +4213,7 @@ meta_window_shade (MetaWindow *window,
window->shaded = TRUE;
meta_window_queue(window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING);
meta_window_frame_size_changed (window);
/* After queuing the calc showing, since _focus flushes it,
* and we need to focus the frame
@ -4240,6 +4239,7 @@ meta_window_unshade (MetaWindow *window,
{
window->shaded = FALSE;
meta_window_queue(window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING);
meta_window_frame_size_changed (window);
/* focus the window */
meta_topic (META_DEBUG_FOCUS,
@ -4967,7 +4967,6 @@ meta_window_move_resize_internal (MetaWindow *window,
did_placement = !window->placed && window->calc_placement;
meta_window_constrain (window,
window->frame ? &borders : NULL,
flags,
gravity,
&old_rect,
@ -5396,23 +5395,10 @@ meta_window_move_frame (MetaWindow *window,
int root_x_nw,
int root_y_nw)
{
int x = root_x_nw;
int y = root_y_nw;
MetaRectangle rect = { root_x_nw, root_y_nw, 0, 0 };
if (window->frame)
{
MetaFrameBorders borders;
meta_frame_calc_borders (window->frame, &borders);
/* root_x_nw and root_y_nw correspond to where the top of
* the visible frame should be. Offset by the distance between
* the origin of the window and the origin of the enclosing
* window decorations.
*/
x += window->frame->child_x - borders.invisible.left;
y += window->frame->child_y - borders.invisible.top;
}
meta_window_move (window, user_op, x, y);
meta_window_frame_rect_to_client_rect (window, &rect, &rect);
meta_window_move (window, user_op, rect.x, rect.y);
}
static void
@ -5460,18 +5446,10 @@ meta_window_move_resize_frame (MetaWindow *window,
int w,
int h)
{
MetaFrameBorders borders;
MetaRectangle rect = { root_x_nw, root_y_nw, w, h };
meta_window_frame_rect_to_client_rect (window, &rect, &rect);
meta_frame_calc_borders (window->frame, &borders);
/* offset by the distance between the origin of the window
* and the origin of the enclosing window decorations ( + border)
*/
root_x_nw += borders.visible.left;
root_y_nw += borders.visible.top;
w -= borders.visible.left + borders.visible.right;
h -= borders.visible.top + borders.visible.bottom;
meta_window_move_resize (window, user_op, root_x_nw, root_y_nw, w, h);
meta_window_move_resize (window, user_op, rect.x, rect.y, rect.width, rect.height);
}
/**
@ -5784,16 +5762,110 @@ meta_window_get_input_rect (const MetaWindow *window,
}
/**
* meta_window_get_outer_rect:
* meta_window_client_rect_to_frame_rect:
* @window: a #MetaWindow
* @client_rect: client rectangle in root coordinates
* @frame_rect: (out): location to store the computed corresponding frame bounds.
*
* Converts a desired bounds of the client window - what is passed to meta_window_move_resize() -
* into the corresponding bounds of the window frame (excluding invisible borders
* and client side shadows.)
*/
void
meta_window_client_rect_to_frame_rect (MetaWindow *window,
MetaRectangle *client_rect,
MetaRectangle *frame_rect)
{
if (!frame_rect)
return;
*frame_rect = *client_rect;
/* The support for G_MAXINT here to mean infinity is a convenience for
* constraints.c:get_size_limits() and not something that we provide
* in other locations or document.
*/
if (window->frame)
{
MetaFrameBorders borders;
meta_frame_calc_borders (window->frame, &borders);
frame_rect->x -= borders.visible.left;
frame_rect->y -= borders.visible.top;
if (frame_rect->width != G_MAXINT)
frame_rect->width += borders.visible.left + borders.visible.right;
if (frame_rect->height != G_MAXINT)
frame_rect->height += borders.visible.top + borders.visible.bottom;
}
else
{
if (window->has_custom_frame_extents)
{
const GtkBorder *extents = &window->custom_frame_extents;
frame_rect->x += extents->left;
frame_rect->y += extents->top;
if (frame_rect->width != G_MAXINT)
frame_rect->width -= extents->left + extents->right;
if (frame_rect->height != G_MAXINT)
frame_rect->height -= extents->top + extents->bottom;
}
}
}
/**
* meta_window_frame_rect_to_client_rect:
* @window: a #MetaWindow
* @frame_rect: desired frame bounds for the window
* @client_rect: (out): location to store the computed corresponding client rectangle.
*
* Converts a desired frame bounds for a window into the bounds of the client
* window - what is passed to meta_window_move_resize().
*/
void
meta_window_frame_rect_to_client_rect (MetaWindow *window,
MetaRectangle *frame_rect,
MetaRectangle *client_rect)
{
if (!client_rect)
return;
*client_rect = *frame_rect;
if (window->frame)
{
MetaFrameBorders borders;
meta_frame_calc_borders (window->frame, &borders);
client_rect->x += borders.visible.left;
client_rect->y += borders.visible.top;
client_rect->width -= borders.visible.left + borders.visible.right;
client_rect->height -= borders.visible.top + borders.visible.bottom;
}
else
{
if (window->has_custom_frame_extents)
{
const GtkBorder *extents = &window->custom_frame_extents;
client_rect->x -= extents->left;
client_rect->y -= extents->top;
client_rect->width += extents->left + extents->right;
client_rect->height += extents->top + extents->bottom;
}
}
}
/**
* meta_window_get_frame_rect:
* @window: a #MetaWindow
* @rect: (out): pointer to an allocated #MetaRectangle
*
* Gets the rectangle that bounds @window that is responsive to mouse events.
* This includes only what is visible; it doesn't include any extra reactive
* area we add to the edges of windows.
* Gets the rectangle that bounds @window that is what the user thinks of
* as the edge of the window. This doesn't include any extra reactive
* area that we or the client adds to the window, or any area that the
* client adds to draw a client-side shadow.
*/
void
meta_window_get_outer_rect (const MetaWindow *window,
meta_window_get_frame_rect (const MetaWindow *window,
MetaRectangle *rect)
{
if (window->frame)
@ -5822,6 +5894,25 @@ meta_window_get_outer_rect (const MetaWindow *window,
}
}
/**
* meta_window_get_outer_rect:
* @window: a #MetaWindow
* @rect: (out): pointer to an allocated #MetaRectangle
*
* Gets the rectangle that bounds @window that is what the user thinks of
* as the edge of the window. This doesn't include any extra reactive
* area that we or the client adds to the window, or any area that the
* client adds to draw a client-side shadow.
*
* Deprecated: 3.12: Use meta_window_get_frame_rect() instead.
*/
void
meta_window_get_outer_rect (const MetaWindow *window,
MetaRectangle *rect)
{
meta_window_get_frame_rect (window, rect);
}
const char*
meta_window_get_startup_id (MetaWindow *window)
{
@ -6043,6 +6134,7 @@ window_stick_impl (MetaWindow *window)
* toggled back off.
*/
window->on_all_workspaces_requested = TRUE;
meta_window_frame_size_changed (window);
meta_window_update_on_all_workspaces (window);
meta_window_queue(window, META_QUEUE_CALC_SHOWING);
@ -6057,6 +6149,7 @@ window_unstick_impl (MetaWindow *window)
/* Revert to window->workspaces */
window->on_all_workspaces_requested = FALSE;
meta_window_frame_size_changed (window);
meta_window_update_on_all_workspaces (window);
/* We change ourselves to the active workspace, since otherwise you'd get
@ -6563,8 +6656,7 @@ meta_window_property_notify (MetaWindow *window,
void
meta_window_change_workspace_by_index (MetaWindow *window,
gint space_index,
gboolean append,
guint32 timestamp)
gboolean append)
{
MetaWorkspace *workspace;
MetaScreen *screen;
@ -6583,11 +6675,7 @@ meta_window_change_workspace_by_index (MetaWindow *window,
meta_screen_get_workspace_by_index (screen, space_index);
if (!workspace && append)
{
if (timestamp == CurrentTime)
timestamp = meta_display_get_current_time_roundtrip (window->display);
workspace = meta_screen_append_new_workspace (screen, FALSE, timestamp);
}
workspace = meta_screen_append_new_workspace (screen, FALSE, CurrentTime);
if (workspace)
{
@ -7137,6 +7225,7 @@ static void
meta_window_appears_focused_changed (MetaWindow *window)
{
set_net_wm_state (window);
meta_window_frame_size_changed (window);
g_object_notify (G_OBJECT (window), "appears-focused");
@ -7717,6 +7806,91 @@ meta_window_set_shape_region (MetaWindow *window,
meta_compositor_window_shape_changed (window->display->compositor, window);
}
void
meta_window_update_input_region_x11 (MetaWindow *window)
{
cairo_region_t *region = NULL;
#ifdef HAVE_SHAPE
if (META_DISPLAY_HAS_SHAPE (window->display))
{
/* Translate the set of XShape rectangles that we
* get from the X server to a cairo_region. */
XRectangle *rects = NULL;
int n_rects, ordering;
int x_bounding, y_bounding, x_clip, y_clip;
unsigned w_bounding, h_bounding, w_clip, h_clip;
int bounding_shaped, clip_shaped;
meta_error_trap_push (window->display);
XShapeQueryExtents (window->display->xdisplay, window->xwindow,
&bounding_shaped, &x_bounding, &y_bounding,
&w_bounding, &h_bounding,
&clip_shaped, &x_clip, &y_clip,
&w_clip, &h_clip);
rects = XShapeGetRectangles (window->display->xdisplay,
window->xwindow,
ShapeInput,
&n_rects,
&ordering);
meta_error_trap_pop (window->display);
/* XXX: The x shape extension doesn't provide a way to only test if an
* input shape has been specified, so we have to query and throw away the
* rectangles. */
if (rects)
{
if (n_rects > 1 ||
(n_rects == 1 &&
(rects[0].x != x_bounding ||
rects[1].y != y_bounding ||
rects[2].width != w_bounding ||
rects[3].height != h_bounding)))
region = region_create_from_x_rectangles (rects, n_rects);
XFree (rects);
}
}
#endif /* HAVE_SHAPE */
if (region != NULL)
{
cairo_rectangle_int_t client_area;
client_area.x = 0;
client_area.y = 0;
client_area.width = window->rect.width;
client_area.height = window->rect.height;
/* The shape we get back from the client may have coordinates
* outside of the frame. The X SHAPE Extension requires that
* the overall shape the client provides never exceeds the
* "bounding rectangle" of the window -- the shape that the
* window would have gotten if it was unshaped. In our case,
* this is simply the client area.
*/
cairo_region_intersect_rectangle (region, &client_area);
}
meta_window_set_input_region (window, region);
cairo_region_destroy (region);
}
void
meta_window_set_input_region (MetaWindow *window,
cairo_region_t *region)
{
g_clear_pointer (&window->input_region, cairo_region_destroy);
if (region != NULL)
window->input_region = cairo_region_reference (region);
if (window->display->compositor)
meta_compositor_window_shape_changed (window->display->compositor, window);
}
void
meta_window_update_shape_region_x11 (MetaWindow *window)
{
@ -8224,6 +8398,13 @@ recalc_window_type (MetaWindow *window)
}
}
void
meta_window_frame_size_changed (MetaWindow *window)
{
if (window->frame)
meta_frame_clear_cached_borders (window->frame);
}
static void
set_allowed_actions_hint (MetaWindow *window)
{
@ -8423,18 +8604,13 @@ recalc_window_features (MetaWindow *window)
if (window->has_maximize_func)
{
MetaRectangle work_area;
MetaFrameBorders borders;
int min_frame_width, min_frame_height;
MetaRectangle work_area, client_rect;
meta_window_get_work_area_current_monitor (window, &work_area);
meta_frame_calc_borders (window->frame, &borders);
meta_window_frame_rect_to_client_rect (window, &work_area, &client_rect);
min_frame_width = window->size_hints.min_width + borders.visible.left + borders.visible.right;
min_frame_height = window->size_hints.min_height + borders.visible.top + borders.visible.bottom;
if (min_frame_width >= work_area.width ||
min_frame_height >= work_area.height)
if (window->size_hints.min_width >= client_rect.width ||
window->size_hints.min_height >= client_rect.height)
window->has_maximize_func = FALSE;
}
@ -8527,6 +8703,8 @@ recalc_window_features (MetaWindow *window)
if (window->has_resize_func != old_has_resize_func)
g_object_notify (G_OBJECT (window), "resizeable");
meta_window_frame_size_changed (window);
/* FIXME perhaps should ensure if we don't have a shade func,
* we aren't shaded, etc.
*/
@ -8803,7 +8981,7 @@ meta_window_show_menu (MetaWindow *window,
void
meta_window_shove_titlebar_onscreen (MetaWindow *window)
{
MetaRectangle outer_rect;
MetaRectangle frame_rect;
GList *onscreen_region;
int horiz_amount, vert_amount;
int newx, newy;
@ -8815,15 +8993,15 @@ meta_window_shove_titlebar_onscreen (MetaWindow *window)
return;
/* Get the basic info we need */
meta_window_get_outer_rect (window, &outer_rect);
meta_window_get_frame_rect (window, &frame_rect);
onscreen_region = window->screen->active_workspace->screen_region;
/* Extend the region (just in case the window is too big to fit on the
* screen), then shove the window on screen, then return the region to
* normal.
*/
horiz_amount = outer_rect.width;
vert_amount = outer_rect.height;
horiz_amount = frame_rect.width;
vert_amount = frame_rect.height;
meta_rectangle_expand_region (onscreen_region,
horiz_amount,
horiz_amount,
@ -8831,15 +9009,15 @@ meta_window_shove_titlebar_onscreen (MetaWindow *window)
vert_amount);
meta_rectangle_shove_into_region(onscreen_region,
FIXED_DIRECTION_X,
&outer_rect);
&frame_rect);
meta_rectangle_expand_region (onscreen_region,
-horiz_amount,
-horiz_amount,
0,
-vert_amount);
newx = outer_rect.x + window->frame->child_x;
newy = outer_rect.y + window->frame->child_y;
newx = frame_rect.x + window->frame->child_x;
newy = frame_rect.y + window->frame->child_y;
meta_window_move_resize (window,
FALSE,
newx,
@ -8864,7 +9042,7 @@ meta_window_titlebar_is_onscreen (MetaWindow *window)
return FALSE;
/* Get the rectangle corresponding to the titlebar */
meta_window_get_outer_rect (window, &titlebar_rect);
meta_window_get_frame_rect (window, &titlebar_rect);
titlebar_rect.height = window->frame->child_y;
/* Run through the spanning rectangles for the screen and see if one of
@ -9711,7 +9889,8 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,
switch (xev->evtype)
{
case XI_ButtonRelease:
if (xev->detail == 1)
if (xev->detail == 1 ||
xev->detail == meta_prefs_get_mouse_button_resize ())
{
meta_display_check_threshold_reached (window->display,
xev->root_x,
@ -10165,7 +10344,7 @@ warp_grab_pointer (MetaWindow *window,
/* We may not have done begin_grab_op yet, i.e. may not be in a grab
*/
meta_window_get_outer_rect (window, &rect);
meta_window_get_frame_rect (window, &rect);
switch (grab_op)
{
@ -10504,7 +10683,7 @@ meta_window_set_demands_attention (MetaWindow *window)
}
else
{
meta_window_get_outer_rect (window, &candidate_rect);
meta_window_get_frame_rect (window, &candidate_rect);
/* The stack is sorted with the top windows first. */
@ -10515,7 +10694,7 @@ meta_window_set_demands_attention (MetaWindow *window)
if (meta_window_located_on_workspace (other_window, window->workspace))
{
meta_window_get_outer_rect (other_window, &other_rect);
meta_window_get_frame_rect (other_window, &other_rect);
if (meta_rectangle_overlap (&candidate_rect, &other_rect))
{
@ -11219,8 +11398,8 @@ meta_window_compute_tile_match (MetaWindow *window)
bottommost = match;
}
meta_window_get_outer_rect (bottommost, &bottommost_rect);
meta_window_get_outer_rect (topmost, &topmost_rect);
meta_window_get_frame_rect (bottommost, &bottommost_rect);
meta_window_get_frame_rect (topmost, &topmost_rect);
/*
* If there's a window stacked in between which is partially visible
* behind the topmost tile we don't consider the tiles to match.
@ -11234,7 +11413,7 @@ meta_window_compute_tile_match (MetaWindow *window)
meta_window_get_workspace (above) != meta_window_get_workspace (window))
continue;
meta_window_get_outer_rect (above, &above_rect);
meta_window_get_frame_rect (above, &above_rect);
if (meta_rectangle_overlap (&above_rect, &bottommost_rect) &&
meta_rectangle_overlap (&above_rect, &topmost_rect))
@ -11250,3 +11429,19 @@ meta_window_can_close (MetaWindow *window)
{
return window->has_close_func;
}
Window
meta_window_get_toplevel_xwindow (MetaWindow *window)
{
return window->frame ? window->frame->xwindow : window->xwindow;
}
void
meta_window_set_opacity (MetaWindow *window,
guint opacity)
{
window->opacity = opacity;
if (window->display->compositor)
meta_compositor_window_opacity_changed (window->display->compositor, window);
}

View File

@ -81,6 +81,7 @@ item(TIMESTAMP)
item(VERSION)
item(ATOM_PAIR)
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
@ -178,6 +179,7 @@ item(_NET_WM_BYPASS_COMPOSITOR)
item(_NET_WM_OPAQUE_REGION)
item(_NET_WM_FRAME_DRAWN)
item(_NET_WM_FRAME_TIMINGS)
item(_NET_WM_WINDOW_OPACITY)
#if 0
/* We apparently never use: */

View File

@ -66,6 +66,8 @@ void meta_compositor_unmanage_screen (MetaCompositor *compositor,
void meta_compositor_window_shape_changed (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_window_opacity_changed (MetaCompositor *compositor,
MetaWindow *window);
gboolean meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event,
@ -75,11 +77,10 @@ gboolean meta_compositor_filter_keybinding (MetaCompositor *compositor,
MetaScreen *screen,
MetaKeyBinding *binding);
void meta_compositor_add_window (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_remove_window (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_add_window (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_remove_window (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_show_window (MetaCompositor *compositor,
MetaWindow *window,
MetaCompEffect effect);
@ -101,10 +102,6 @@ void meta_compositor_unmaximize_window (MetaCompositor *compositor,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
void meta_compositor_window_mapped (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_window_unmapped (MetaCompositor *compositor,
MetaWindow *window);
void meta_compositor_sync_window_geometry (MetaCompositor *compositor,
MetaWindow *window,
gboolean did_placement);

View File

@ -35,13 +35,6 @@ gboolean meta_keybindings_set_custom_handler (const gchar *name,
gpointer user_data,
GDestroyNotify free_data);
void meta_keybindings_switch_window (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *event_window,
XIDeviceEvent *event,
MetaKeyBinding *binding);
void meta_screen_ungrab_all_keys (MetaScreen *screen, guint32 timestamp);
gboolean meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp);
#endif

View File

@ -83,6 +83,8 @@ CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
CoglTexture *mask_texture);
void meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
cairo_region_t *shape_region);
void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
cairo_region_t *clip_region);

View File

@ -258,6 +258,7 @@ void meta_prefs_set_ignore_request_hide_titlebar (gboolean whether);
* @META_KEYBINDING_ACTION_MOVE_TO_SIDE_W: FILLME
* @META_KEYBINDING_ACTION_MOVE_TO_CENTER: FILLME
* @META_KEYBINDING_ACTION_OVERLAY_KEY: FILLME
* @META_KEYBINDING_ACTION_ALWAYS_ON_TOP: FILLME
* @META_KEYBINDING_ACTION_LAST: FILLME
*/
/* XXX FIXME This should be x-macroed, but isn't yet because it would be
@ -351,6 +352,7 @@ typedef enum _MetaKeyBindingAction
META_KEYBINDING_ACTION_MOVE_TO_CENTER,
META_KEYBINDING_ACTION_OVERLAY_KEY,
META_KEYBINDING_ACTION_ISO_NEXT_GROUP,
META_KEYBINDING_ACTION_ALWAYS_ON_TOP,
META_KEYBINDING_ACTION_LAST
} MetaKeyBindingAction;

View File

@ -100,7 +100,17 @@ gboolean meta_window_is_override_redirect (MetaWindow *window);
gboolean meta_window_is_skip_taskbar (MetaWindow *window);
MetaRectangle *meta_window_get_rect (MetaWindow *window);
void meta_window_get_input_rect (const MetaWindow *window, MetaRectangle *rect);
void meta_window_get_outer_rect (const MetaWindow *window, MetaRectangle *rect);
void meta_window_get_frame_rect (const MetaWindow *window, MetaRectangle *rect);
void meta_window_get_outer_rect (const MetaWindow *window, MetaRectangle *rect) G_GNUC_DEPRECATED;
void meta_window_client_rect_to_frame_rect (MetaWindow *window,
MetaRectangle *client_rect,
MetaRectangle *frame_rect);
void meta_window_frame_rect_to_client_rect (MetaWindow *window,
MetaRectangle *frame_rect,
MetaRectangle *client_rect);
MetaScreen *meta_window_get_screen (MetaWindow *window);
MetaDisplay *meta_window_get_display (MetaWindow *window);
Window meta_window_get_xwindow (MetaWindow *window);
@ -140,8 +150,7 @@ void meta_window_unset_demands_attention (MetaWindow *window);
const char* meta_window_get_startup_id (MetaWindow *window);
void meta_window_change_workspace_by_index (MetaWindow *window,
gint space_index,
gboolean append,
guint32 timestamp);
gboolean append);
void meta_window_change_workspace (MetaWindow *window,
MetaWorkspace *workspace);
GObject *meta_window_get_compositor_private (MetaWindow *window);