Compare commits

...

270 Commits

Author SHA1 Message Date
cb5e1e2776 Bump version to 3.10.0.1
Update NEWS
2013-09-25 20:00:16 +02:00
e965cf32d4 MetaWindowActor: fix updates with multiple size changes in one frame
We must set x11_size_changed even if we are frozen, as every window
size change makes the X server drop the pixmap, and we might lose
the information at the next thaw() if the window changes size
twice in one frame (so we would keep drawing with the old pixmap
until something else causes another resize)
2013-09-25 19:23:58 +02:00
ce5e0b20b5 Bump version to 3.10.0
Update NEWS
2013-09-24 14:09:29 +02:00
90854a0f80 configure: update dependencies for clutter packages
Make sure that clutter is at the right minimum version for the API
we use, and that it is built with the right configure flags, by
checking for subpackage .pcs too.

https://bugzilla.gnome.org/show_bug.cgi?id=708210
2013-09-20 23:07:49 +02:00
2d9dc143fc Bump version to 3.9.92
Update NEWS
2013-09-17 10:13:29 +02:00
1e52d2aa9c Cherry-pick translation updates from master 2013-09-17 10:13:29 +02:00
2734c8547f Fix distcheck
Remove a warning that makes us fail with -Werror
2013-09-17 09:49:17 +02:00
cc0b093f7a MonitorConfig: fix hole filling in the laptop lid automatic configuration
Need two passes, because the order we traverse the array is
alphabetical on connector name, not left to right, so we might
see a monitor on the right before we get the offset from disabling
the primary monitor.

https://bugzilla.gnome.org/show_bug.cgi?id=707473
2013-09-16 22:43:07 +02:00
d25275fa8d MonitorConfig: remove holes generated by disabling the laptop lid
No, holes in the framebuffer are not a good a thing: windows can
get lost there, and the user can get very confused.
Instead, compact the monitors that where previously after.

https://bugzilla.gnome.org/show_bug.cgi?id=707473
2013-09-16 22:43:00 +02:00
389e04c715 MetaIdleMonitor: fire immediately watches that are already expired
The XSync semantics mandate that alarms already expired will not
fire until the counter is reset and the alarm triggered again, so
clients traditionally called get_idle_time() first to see if they
should install the alarm.
This is inherently racy, as by the time the call is handled by
mutter and the reply received the idle time could be different.
Instead, if we see that the watch would have fired in the past,
fire it immediately.

This is a behavior change, but it's a compatible one, as all legacy
clients are calling get_idle_time() first, and it was perfectly
possible for the idle time counter to trigger the alarm right
after the get_idle_time() call.

https://bugzilla.gnome.org/show_bug.cgi?id=707302
2013-09-16 22:42:22 +02:00
24074a81d0 mutter-launch: fix for more systemd API changes
Modern systemd changed the semantics of sd_session_get_tty() to
return the full path, rather than just the tty name.

Reviewed by Ray Strode in IRC.
2013-09-16 17:30:45 +02:00
c0e7f6d9bf wayland: remove some wl_signal usage
It was a left-over from the initial code import from weston.

https://bugzilla.gnome.org/show_bug.cgi?id=707863
2013-09-16 14:51:13 +02:00
9a13b857f4 wayland: implement stacked popups
Allow multiple popups from the same clients to be stacked under
the same pointer grab.
This is necessary to implement submenus.

https://bugzilla.gnome.org/show_bug.cgi?id=707863
2013-09-16 14:51:13 +02:00
776a86a65f wayland: heavily refactor pointer grabs
Grabs are now slice allocated structures that are handled by
whoever starts the grab. They contain a generic grab structure
with the interface and a backpointer to the MetaWaylandPointer.
The grab interface has been changed to pass full clutter events,
which allowed to remove the confusion between grab->focus and
pointer->focus. Invidual grabs are now required to keep their
focus, and choose whoever gets the events.

https://bugzilla.gnome.org/show_bug.cgi?id=707863
2013-09-16 14:51:12 +02:00
76e2455d1b wayland: implement support for popup surfaces
Popup surfaces are mapped into override_redirect surfaces
of a DROPDOWN_MENU type, with the addition of a special pointer
grab.

https://bugzilla.gnome.org/show_bug.cgi?id=707863
2013-09-16 14:51:12 +02:00
81d9797544 wayland: implement transient hints for wayland clients
wl_shell supports a set_transient() map request that is equivalent
to setting WM_TRANSIENT_FOR in X11, so implement that.

https://bugzilla.gnome.org/show_bug.cgi?id=707401
2013-09-16 14:48:57 +02:00
12d6c70000 MetaWaylandSurface: cache the surface type until the first commit
Once the sizing is properly wired up, we need to make sure that
the size at the initial map is correct, and not always 0, 0 because
the buffer is not yet converted into a CoglTexture by MetaShapedTexture,
otherwise we end up sending out configure events at 1 x 1.
To do so, we cache the surface type in the initial state until the
first commit.

https://bugzilla.gnome.org/show_bug.cgi?id=707401
2013-09-16 14:46:35 +02:00
a7eaf43e18 wayland: implement resizing and maximization for wayland clients
To properly resize clients, we need to send them configure events
with the size we computed from the constraint system, and
then check if the new size they ask is compatible with
our expectation.

Note that this does not handle interactive resizing yet, it
merely makes the API calls work for wayland clients.

https://bugzilla.gnome.org/show_bug.cgi?id=707401
2013-09-16 14:46:34 +02:00
514fec7275 display: include wayland clients in the tab list
Make sure that meta_display_list_windows() returns wayland windows
too, by keeping a separate hash for wayland clients.
This fixes a crash in the alt-tab code of gnome-shell.

Reviewed by drago01 in IRC.
2013-09-16 11:29:36 +02:00
42a5f4f479 MetaShapedTexture: don't intersect a region with an uninitialized clip
If we skip getting the clip rectangle because we don't have an
allocation or a texture, don't intersect with the visible region.
This avoids a pixman warning of an invalid rectangle.

Reviewed by drago01 in IRC.
2013-09-16 11:28:12 +02:00
6c1feedbdf Fixup previous MetaCursorTracker commit
I had it fixed locally, then it was lost in a bad rebase.
2013-09-16 10:06:44 +02:00
2d21fbbd35 wayland: disable extended barriers support
We don't have actual pointer barriers implemented, so this is a
quick workaround to trigger the fallback paths in the shell, for
the hot corner and the message tray.
To be reverted after 3.10
2013-09-16 09:34:27 +02:00
7baf687499 MetaCursorTracker: add support for loading cursors from the theme
Not only this way we get the right Adwaita cursor as the default
(instead of shipping our own in png format), but we also add
support for all MetaCursors as root cursor (which most important
should allow us to have I-beams in shell entries)

https://bugzilla.gnome.org/show_bug.cgi?id=707573
2013-09-16 09:31:44 +02:00
a3e44d13d1 wayland: implement HW cursors
Use the DRM API and libgbm to upload cursor buffers to the
appropriate HW plane, saving on GL calls and compositing.

https://bugzilla.gnome.org/show_bug.cgi?id=707573
2013-09-16 09:27:48 +02:00
65db8efbe8 MonitorManager: add a KMS backend
Using the new Cogl API to actually modeset (because we can't
use the DRM API directly without controlling buffer swap), we
can finally have a KMS monitor backend, which means full display
configuration when running on bare metal.

https://bugzilla.gnome.org/show_bug.cgi?id=706308
2013-09-16 00:34:48 +02:00
e48a5cd5f2 mutter-launch: Use the correct binary name for the help message as well 2013-09-15 20:28:24 +02:00
698bb24848 mutter-launch: Use correct binary name in error messages 2013-09-15 20:25:39 +02:00
67fff237e6 MonitorConfig: fix memory leak
https://bugzilla.gnome.org/show_bug.cgi?id=708070
2013-09-14 17:07:32 +02:00
b9247b4b2f shaped-texture: Fix memory leak
https://bugzilla.gnome.org/show_bug.cgi?id=708070
2013-09-14 17:07:32 +02:00
0394b4a82b window: Fix memory leak
https://bugzilla.gnome.org/show_bug.cgi?id=708070
2013-09-14 17:07:32 +02:00
ff7c85c599 workspace: Add missing chain-up for finalize()
https://bugzilla.gnome.org/show_bug.cgi?id=708070
2013-09-14 17:07:32 +02:00
c316ad17a4 Drop man pages for removed utilities
Commit 8c1c77482d removed mutter-message,
mutter-theme-viewer, and mutter-theme-viewer; this drops their man pages
as well.

https://bugzilla.gnome.org/show_bug.cgi?id=706579
2013-09-12 13:26:34 +02:00
fc108d5052 Fixup previous commit
Had a wrong cursor name.
2013-09-12 10:33:26 +02:00
8c0d38a1a1 display: add support for more cursor types
These cursors are used by gnome-shell, supporting them allows
to reduce GDK usage in the shell.

Also, make meta_screen_set_cursor() public.

https://bugzilla.gnome.org/show_bug.cgi?id=707919
2013-09-12 10:18:20 +02:00
2f9c6c4146 mutter-launch: adapt to systemd API change
The API was changed during the patch review.

(Yes, we were depending on API which was sitting in a patch not
yet reviewed... you know, vertical integration!)

https://bugzilla.gnome.org/show_bug.cgi?id=707929
2013-09-11 20:36:38 +02:00
72ca2b218d wayland: die when gnome-session asks us to
At logout, we want to die when gnome-session tells us. Previously,
we were relying on the X server going down (killed by GDM at the
end of the session), but we can't use that in wayland.

https://bugzilla.gnome.org/show_bug.cgi?id=706421
2013-09-11 16:01:24 +02:00
7360aece74 wayland: don't require Clutter backend variables to be set from outside
When running under mutter-launch, we can assume we're running on
bare metal, and set the clutter backend appropriately.

https://bugzilla.gnome.org/show_bug.cgi?id=706421
2013-09-11 16:01:09 +02:00
b5f3238f6f Stop messing with process groups
We can be launched by gnome-session now, which implies gdb must be
attached from outside, and the Ctrl-C problem is gone.

https://bugzilla.gnome.org/show_bug.cgi?id=706421
2013-09-11 16:01:09 +02:00
227fb56103 Set DISPLAY and WAYLAND_DISPLAY for dbus activated services and for autostarted apps
Call the appropriate method on gnome-session so that autostarted
and bus activated apps see the X server and wayland socket.

https://bugzilla.gnome.org/show_bug.cgi?id=706421
2013-09-11 16:01:09 +02:00
5ae52473c9 Don't translate debug logs and warnings
Warnings that are going to the journal should be not translated:
they're not user visible, and translating them would just make
bug reporting harder (as now the developers need to understand
what the warning is saying)

https://bugzilla.gnome.org/show_bug.cgi?id=707897
2013-09-11 16:01:09 +02:00
7b537d6b8f Fix regression in mutter-wayland translations
Switching meta/util.h to gi18n.h was wrong, mutter is a library
and needs gi18n-lib.h, but that cannot be included from a public
header (since it depends on config.h or command line options),
so split util.h into a public and a private part.

https://bugzilla.gnome.org/show_bug.cgi?id=707897
2013-09-11 16:01:07 +02:00
4494888b82 Add an option to run as a wayland compositor
Move the option from the mutter binary to libmutter, and
rename from --nested to --wayland.
This allows gnome-shell to drop the set_is_wayland_compositor()
call.

https://bugzilla.gnome.org/show_bug.cgi?id=707897
2013-09-11 16:00:47 +02:00
004ee2d3b5 MetaPluginManager: don't require plugins to pass events to clutter
We don't want the shell to know if it's running on ClutterX11 or
not, so we should forward the event ourselves.

https://bugzilla.gnome.org/show_bug.cgi?id=707482
2013-09-10 17:26:15 +02:00
168ea64a45 wayland: use symbolic constants for interface version
Replace magic numbers scattered around the code with proper
macros collected in one header file.

https://bugzilla.gnome.org/show_bug.cgi?id=707851
2013-09-10 15:55:11 +02:00
73ee491281 wayland: fix interface versioning
Add MIN(...) with the interface version actually implemented
to all resource constructor, so that we never risk seeing requests
we don't implement (and consequently segfault)

https://bugzilla.gnome.org/show_bug.cgi?id=707851
2013-09-10 15:54:42 +02:00
95a9655412 wayland: fix deprecation warnings
Replace the deprecated APIs with the modern variants (which
also give us full control on the versioning).
Also, note that we only support version 2 of wl_seat. Version
3 is for multiple pointer/keyboards for a client, but
we don't implement that yet. If a client requests version 3
of wl_seat or make a version 3 request, it will get a protocol error.

https://bugzilla.gnome.org/show_bug.cgi?id=707851
2013-09-10 15:54:37 +02:00
72b6699efb util: fix warnings when compiling gnome-shell-wayland
Replace our version of the gettext macros with those in glib,
so that they don't conflict with gnome-shell.

https://bugzilla.gnome.org/show_bug.cgi?id=707851
2013-09-10 13:47:30 +02:00
3e341e83d9 mutter-launch: remove PAM usage
Left-overs from the weston-launch import

https://bugzilla.gnome.org/show_bug.cgi?id=707584
2013-09-09 18:09:08 +02:00
5b3340e585 MetaCursorTracker: add methods for setting the cursor visibility
clutter_stage_show_cursor()/hide_cursor() only works in the X11
backend (where someone else is in charge of showing the cursor),
and even then, it has confusing effects when running nested wayland,
so an abstraction layer is needed.

https://bugzilla.gnome.org/show_bug.cgi?id=707474
2013-09-09 18:04:07 +02:00
6f4f611ba8 MetaCursorTracker: extend with query pointer abilities
We need an abstraction in gnome-shell for XQueryPointer, and
MetaCursorTracker seems a good place for it.

https://bugzilla.gnome.org/show_bug.cgi?id=707474
2013-09-09 18:04:07 +02:00
450afbaf51 wayland: reimplement keyboard state handling properly
We can't rely on clutter's xkb_state, because that's updated
when events are pulled from the kernel, not when we see them.
Instead, use the new clutter API to get the full modifier state
from the event (which, as a side effect, also works when clutter
is using the X11 backend for running nested).

https://bugzilla.gnome.org/show_bug.cgi?id=706963
2013-09-09 17:59:45 +02:00
28708e4317 MetaWaylandSeat: don't use use events to count pressed buttons
Use the modifier mask instead, as events can get lost if there
is a clutter grab or if some other actor is capturing events.

https://bugzilla.gnome.org/show_bug.cgi?id=706124
2013-09-09 17:59:45 +02:00
9f64f2cf4f Rename META_POWER_SAVE_UNKNOWN to UNSUPPORTED
It conveys more clearly what this value means.

https://bugzilla.gnome.org/show_bug.cgi?id=707649
2013-09-09 15:33:53 +02:00
2b1eb206d3 Monitor: don't shortcut set_power_save if the value is the same as the old one
We don't get notifications from X11 when the mode is reset, so
our cached value can get stale. To work around that, always forward
requests to the backend (and let it deal with ignoring the change
if wanted)

https://bugzilla.gnome.org/show_bug.cgi?id=707649
2013-09-09 15:33:53 +02:00
a6dc454c49 wayland: constraint the pointer onto visible monitors when running on evdev
Use the new Clutter hook to make sure the pointer never enters
the dead area caused by the different monitor sizes.

You don't realize how much X is doing for you until you lose it...

https://bugzilla.gnome.org/show_bug.cgi?id=706655
2013-09-09 12:08:47 +02:00
c2bf44fa19 Bump version to 3.9.91
Update NEWS
2013-09-05 11:01:53 +02:00
2d67b01c3a window-actor: Use more conservative paint volume
We know which part of the window is not obscured, so take advantaged of that
to limit the size of the paint volume that we report.
2013-09-04 20:08:24 +02:00
6014d31dea Don't create a dummy texture for the texture pipeline template
The meta_create_texture_pipeline function used to create a dummy 1x1
texture so that it could make sure that the all of the state that
affects the shader generation would be set on the template pipeline so
that Cogl could share the pipeline's shader with any other pipelines
that are just rendering a texture. This is no longer necessary because
the only thing that affects the shader generation is the texture type,
not the actual texture data and Cogl now has a function to explicitly
set the texture type which we can use instead. Additionally even if
the template mechanism is not used at all Cogl will still end up
reusing the same shader because it now has a shader cache which is
indexed by the pipeline state so pipeline's don't strictly need to
share ancestry in order to take advantage of it. However we still
might as well use the function because if there is a common ancestry
it is faster to look up the shader because Cogl doesn't need to hash
the pipeline state.

https://bugzilla.gnome.org/show_bug.cgi?id=707458
(cherry picked from commit c5bf60eab4)
2013-09-04 15:29:04 +01:00
bf78f067a2 Make sure to always call va_end 2013-09-03 16:10:10 -04:00
ddb9929dad compositor: Remove some uninitialized variables 2013-09-03 16:10:10 -04:00
2098ec2d16 theme-parser: Remove a duplicate paste
How did this sneak in there?
2013-09-03 16:10:10 -04:00
97eece6607 display: Add some missing breaks
If we somehow get an event with a wrong device ID, we should not
be comparing bad event IDs.
2013-09-03 16:10:10 -04:00
7ac9a6e241 compositor: initial has_window to FALSE in sync_actor_stacking
Spotted by Jasper, discussed on IRC.
2013-09-03 16:09:05 -04:00
b53bf0e8c2 Fix distcheck
Missing translation files, missing dists and some -Werrors.
2013-09-03 17:00:18 +02:00
a26ded47d9 Add a private gtk-mutter protocol
Add a new interface, gtk_shell, than can be used by gtk to
retrieve a surface extension called gtk_surface, which will be
used to communicate with mutter all the GTK extensions to EWMH

https://bugzilla.gnome.org/show_bug.cgi?id=707128

Add support for GTK application menus

To do so, we need to be able to set surface state before creating
the MetaWindow, so we introduce MetaWaylandSurfaceInitialState as
a staging area.
The gtk-shell-surface implementation would either write to the
initial state, or directly to the window.

At the same, implement set_title and set_class too, because it's
easy enough.

https://bugzilla.gnome.org/show_bug.cgi?id=707128
2013-09-03 10:57:28 -04:00
cad9e14463 Move surface state tracking and surface interface to a separate file
Move everything surface related from meta-wayland.c to meta-wayland-surface.c

https://bugzilla.gnome.org/show_bug.cgi?id=707128
2013-09-03 10:57:28 -04:00
806d5939e3 wayland: split headers and distribute structure definitions
Instead of having all structures in one huge headers, move them
in the appropriate place, and create one header for surface state.

https://bugzilla.gnome.org/show_bug.cgi?id=707128
2013-09-03 10:57:28 -04:00
0f0c23fbab wayland: generalize ShellSurface to SurfaceExtension
We want to implement new shells and new extension interfaces
for wl_surface, so generalize the book-keeping structures.

https://bugzilla.gnome.org/show_bug.cgi?id=707128
2013-09-03 10:57:28 -04:00
5d1fcc26c0 Update .gitignore 2013-09-03 10:57:28 -04:00
cbe5b6b3bc meta-wayland: intersect the damage region with the window size before applying
According to the wayland documentation, damage outside the
window size is ignored.
This happened with xwayland+wlshm (causing a GL error when calling
TexSubImage2D), probably due to not resizing the buffer
until we receive the corresponding X event.
Might also be an off-by-one in xwayland, as the window size did
not actually change.

Note: we might want to take the configure_notify path instead,
and keep the GL/clutter size consistent with wayland rather than
X, because in the end that's what matters for events and composition.

https://bugzilla.gnome.org/show_bug.cgi?id=706289
2013-09-03 10:16:47 -04:00
590cf4e832 MonitorXrandr: check the event timestamps before reconfiguring
If, checking the event timestamps, we see that a new configuration
was explicitly requested by an another XRandR client, don't proceed to
apply the intended configuration again, even if looking at the
EDIDs it appears that the outputs changed.
This works around some buggy Xorg drivers (qxl, vbox) that generate
a new serial number everytime the user resizes the host window.

https://bugzilla.gnome.org/show_bug.cgi?id=706735
2013-09-02 17:36:03 +02:00
22ca820c44 idle-monitor: fix event propagation to devices
device_id_max is set to the device_id in ensure_device_monitor(), but we
will loop only to (device_id_max - 1) when propagating the sync XEvent
down, missing the device correspondng to device_id_max.

https://bugzilla.gnome.org/show_bug.cgi?id=707250
2013-09-01 17:51:10 -07:00
b1206ceb66 wayland: Ensure that opaque / input regions are set at commit time
The protocol specification says that opaque / input regions should be
considered pending state and should only be actually swapped out when
the surface is committed, so it can be set atomically.
2013-08-31 13:29:02 -04:00
ad4053ab84 wayland: fix pointer focus for destroyed surfaces
We had an assertion in meta_wayland_surface_free() that after
a repick() we would not choose the freed surface, but that didn't
consider surfaces destroyed while holding the implicit pointer
grab (ie, because the user clicked on the X button). In that case,
we need to bypass the grab infrastructure and explicitly unfocus
the dead surface.

https://bugzilla.gnome.org/show_bug.cgi?id=706982
2013-08-30 16:07:00 +02:00
7bd4e6ecb0 weston-launch: Don't segfault if passed no arguments
Probably not exploitable since I think Linux always puts NULL there,
but let's actually check.
2013-08-30 08:26:31 -04:00
deeb1db1ac wayland: don't free surfaces that have a window associated
After a MetaWaylandSurface is associated with a MetaWindow, it
should be freed only when the MetaWindow is unmanaged. For wayland
clients, the window is unmanaged when the resource is destroyed,
but for X11 clients we want to wait for the unmap event.

https://bugzilla.gnome.org/show_bug.cgi?id=705917
2013-08-30 10:37:25 +02:00
7eb4bfbea3 wayland: implement support for plugin modality
Calling XIGrabDevice has no effect under wayland, because the
xserver is getting events from us. Instead, we need to use our
own interfaces for grabs.
At the same time, we can simplify the public API, as plugins
should always listen for events using clutter.

https://bugzilla.gnome.org/show_bug.cgi?id=705917
2013-08-30 10:37:25 +02:00
59b274f12f MetaWaylandKeyboard: use the new clutter-evdev support for xkbcommon
We need to track the full xkb_state to have the necessary information
to send to the clients, otherwise they may get confused and lock
or invert the modifiers. In the evdev backend, we just retrieve the
same state object that clutter is using, while in the other backends
we fake the state using what clutter is providing (which is a subset
of what X11 provides, which would be necessary to have full state)

https://bugzilla.gnome.org/show_bug.cgi?id=705862
2013-08-30 10:37:25 +02:00
e311cef013 Add keybindings for switching VTs
Once mutter is started from weston-launch on its own VT, there is
no way to change VT again (for example to actually start an application),
because the keyboard is put in raw mode.
So introduce some keybindings mimicking the standard X ones (Ctrl+Alt+Fn)
that switch the VT manually when activated.

https://bugzilla.gnome.org/show_bug.cgi?id=705861
2013-08-30 10:32:55 +02:00
e72f81c24f wayland: add TTY and DRM master management
Now that we have a setuid launcher binary, we can make use of
using a private protocol through the socket we're passed at startup.

We also use the new hook in clutter-evdev to ask mutter-launch for
the FDs of the input devices we need, and we emulate the old X
DRM lock with a nested GMainContext without sources.

In the future, mutter-launch will be replaced with the new logind
API currently in development.

https://bugzilla.gnome.org/show_bug.cgi?id=705861
2013-08-30 10:32:55 +02:00
96fa518576 mutter-launch: augment with VT and TTY handling
Set the TTY mode appropriately at startup, and clean it up
when the compositor exits. Also, take control of VT switching,
including the calls to drmSetMaster and drmDropMaster as appropriate.
In the future, we the kernel implements the mute evdev ioctl,
we'll also make sure that input devices are appropriately released.

https://bugzilla.gnome.org/show_bug.cgi?id=705861
2013-08-30 10:32:55 +02:00
e263b3624c mutter-launch: use systemd to obtain the TTY
Using the command line or an environment variable is dangerous,
as those can be spoofed to gain access to other sessions.

https://bugzilla.gnome.org/show_bug.cgi?id=705861
2013-08-30 10:32:55 +02:00
1c34f0b342 mutter-launch: make sure that the spawned binaries sees the right libraries
Being a setuid binary, our LD_LIBRARY_PATH is cleared by glibc at
startup, but we need the spawned binary to see it, otherwise
jhbuild doesn't work, so hardcode it using the configured libdir.

https://bugzilla.gnome.org/show_bug.cgi?id=705861
2013-08-30 10:32:55 +02:00
2d27873f98 mutter-launch: simplify by removing features we don't need
Remove the ability to launch as a different user, which we don't
need because we're spawned by gdm or by the user manually on the
command line.
At the same time, require an active local session, and remove
the ability to run from anywhere by being in the right user group
(which automatically gives you root-like privileges)

https://bugzilla.gnome.org/show_bug.cgi?id=705861
2013-08-30 10:32:55 +02:00
fd40a12213 wayland: import weston-launch setuid launcher
To run mutter as a display server, one needs to acquire and
release the DRM master, which is only possible for root, so
we take advantage of weston-launch, a small setuid helper binary
written for the weston project. We import our own slightly
modified copy of it, because weston-launch only launches weston,
for security reasons.

https://bugzilla.gnome.org/show_bug.cgi?id=705861
2013-08-30 10:32:55 +02:00
57406e0a9e shaped-texture: Actually fetch rectangles from the blended_region
We checked for the blended region but actually fetched rectangles from
the clip region.
2013-08-29 18:35:18 -04:00
1987cbb764 window-actor: Fix build 2013-08-29 17:16:15 -04:00
705978405b shaped-texture: Fix build 2013-08-29 17:14:11 -04:00
daba05f6a7 background: Rename visible_region to clip_region
This does better reflect what this region is used for.

https://bugzilla.gnome.org/show_bug.cgi?id=703332
2013-08-29 17:08:57 -04:00
1a7984be43 window-actor: Use g_clear_pointer 2013-08-29 17:05:41 -04:00
1b3c77d53a shaped-texture: Remove an unnecessary set to NULL 2013-08-29 17:05:36 -04:00
5b0f0d9e5b shaped-texture: Remove bad comment
We do not assume ownership of the clip region anymore.
2013-08-29 17:04:55 -04:00
9816659fa9 meta-window-actor: Fix spacing 2013-08-29 17:04:50 -04:00
3b1b611634 meta-window-actor: Throttle obscured frame synced apps
We must send frame_drawn and frame_timing messages to even when
we don't actually queue a redraw on screen to comply with the
WM sync spec.

So throttle such apps to down to a ~100ms interval.

https://bugzilla.gnome.org/show_bug.cgi?id=703332
2013-08-29 17:04:36 -04:00
f08921bd0c meta-shaped-texture: Don't queue redraws for obscured regions
When we get a damage event we update the window by calling
meta_shaped_texture_update_area which queues a redraw on the actor.
We can avoid that for obscured regions by comparing the damage area to
our visible area.

This patch causes _NET_WM_FRAME_DRAWN messages to be not sent in some cases
where they should be sent; they will be added back in a later commit.

https://bugzilla.gnome.org/show_bug.cgi?id=703332
2013-08-29 17:03:48 -04:00
0089b5769c shaped-texture: Turn blending off when drawing entirely opaque regions
When drawing entirely opaque regions, we traditionally kept blending on
simply because it made the code more convenient and obvious to handle.
However, this can cause lots of performance issues on GPUs that aren't
too powerful, as they have to readback the buffer underneath.

Keep track of the opaque region set by windows (through _NET_WM_OPAQUE_REGION,
Wayland opaque_region hints, standard RGB32 frame masks or similar), and draw
those rectangles separately through a different path with blending turned off.

https://bugzilla.gnome.org/show_bug.cgi?id=707019
2013-08-29 15:31:53 -04:00
452be05ea0 shaped-texture: Use non-deprecated cogl APIs
https://bugzilla.gnome.org/show_bug.cgi?id=707019
2013-08-29 15:31:53 -04:00
69f038f7c7 shaped-texture: Simplify pipeline creation
Split out pipeline creation to a separate function so that we don't
have so much dense code in the paint function itself, and remove some
indentation levels.

Also, don't use our own template for the unmasked pipeline, since it
has nothing different from the default pipeline template.

We also don't store the pipelines anymore since their creation isn't
really helping us; we set the mask texture and paint texture on every
paint anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=707019
2013-08-29 15:31:52 -04:00
2d35e07fae wayland: Add support for set_opaque_region / set_input_region
https://bugzilla.gnome.org/show_bug.cgi?id=707019
2013-08-29 15:31:52 -04:00
95e2d26d03 window-actor: Mark all Wayland clients as argb32
https://bugzilla.gnome.org/show_bug.cgi?id=707019
2013-08-29 15:26:49 -04:00
f506e090ea monitor: Use a more sane dummy configuration for nested mode 2013-08-29 15:26:49 -04:00
0697b53826 wayland-private: Remove unused buffer fields 2013-08-28 15:28:34 -04:00
7d9141c56f Revert "MetaWaylandKeyboard: use the new clutter-evdev support for xkbcommon"
This reverts commit 519a06b93d.
Depends on unreviewed stuff and breaks the build.
2013-08-28 18:04:01 +02:00
519a06b93d MetaWaylandKeyboard: use the new clutter-evdev support for xkbcommon
We need to track the full xkb_state to have the necessary information
to send to the clients, otherwise they may get confused and lock
or invert the modifiers. In the evdev backend, we just retrieve the
same state object that clutter is using, while in the other backends
we fake the state using what clutter is providing (which is a subset
of what X11 provides, which would be necessary to have full state)

https://bugzilla.gnome.org/show_bug.cgi?id=705862
2013-08-28 17:45:25 +02:00
0cceddab75 MetaWayland: install an X io error handler
This way can detect X disconnections correctly, crash with a core
dump and reset the tty.

https://bugzilla.gnome.org/show_bug.cgi?id=706962
2013-08-28 17:21:18 +02:00
c9830c13b4 screen: Remove unused variable 2013-08-27 08:56:06 -04:00
9a4783e364 Integrate the monitor manager with wayland
Use the right backend when running as a wayland compositor,
export the data to wayland clients, and use it to keep the stage
appropriately sized.
2013-08-27 10:09:39 +02:00
aa15c09d54 Merge tag 'xrandr_branch_point' into wayland-kms-base
Conflicts:
	src/Makefile.am
	src/core/display.c
	src/core/screen-private.h
	src/core/screen.c
2013-08-27 10:07:39 +02:00
62d908be42 MonitorManager: return the new backlight after changing
Modify the interface of ChangeBacklight to return the new value,
to account for rounding to HW limits.

https://bugzilla.gnome.org/show_bug.cgi?id=706729
2013-08-27 09:58:50 +02:00
6526e9882b idle-monitor: Fix a warning when a callback removes the user active watch
The user active watch is a one-fire watch, but it is valid in the API
for the callback to explicitly remove the watch itself. In that case,
the watch will be invalid after the user removes it, and the memory
potentially freed. So make sure to not dereference the watch after
the callback is called.

https://bugzilla.gnome.org/show_bug.cgi?id=706825
2013-08-27 09:57:06 +02:00
ab72352c47 background: don't save pixbuf in user data
https://bugzilla.gnome.org/show_bug.cgi?id=706777
2013-08-27 09:57:06 +02:00
f09b9573f0 window: ignore skip-taskbar hint on parentless dialogs
Dialogs that don't have a parent should not be skip-taskbar,
otherwise they get lost and there is no way to recover them
(because they're not autoraised when activating the parent),
but toolkits and applications set the hint anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=673399
2013-08-27 09:57:06 +02:00
3d3ae40f79 Bump version to 3.9.90
gnome-shell requires mutter and mutter-wayland at the same version
to build. Also update NEWS, cherry-picked from master.
2013-08-27 09:51:56 +02:00
ea3d2b4759 wayland: make parallel installable with regular mutter
Modify all visible instances of mutter with mutter-wayland
(libraries, folders, pkgconfig, etc.), so that the wayland
branch can be installed alongside the usual X11 mutter.

https://bugzilla.gnome.org/show_bug.cgi?id=705497
2013-08-26 15:00:29 +02:00
542a0886cf Remove files no one cares about anymore
mutter-plugins.pc has been replaced by libmutter.pc, and the
wm properties in the control center are long gone.

https://bugzilla.gnome.org/show_bug.cgi?id=705497
2013-08-26 15:00:29 +02:00
bd3d5df9ce Remove HAVE_WAYLAND ifdefs
Wayland support is always enabled now.

https://bugzilla.gnome.org/show_bug.cgi?id=705497
2013-08-26 15:00:29 +02:00
91cdfab495 build: make wayland support unconditional
In the wayland branch of mutter, we want to build a wayland version
of the mutter libraries, and that's much easier if we just build
wayland support unconditionally.
The define is kept to avoid a huge diff, but should be removed
in a later patch.
Also, wayland support can still be disable at runtime, by
launching mutter without the --nested switch.

https://bugzilla.gnome.org/show_bug.cgi?id=705497
2013-08-26 15:00:29 +02:00
1617323dca MetaShapedTexture: don't include private headers in public ones
Private headers are not installed, so they can't be referenced
from public ones.

https://bugzilla.gnome.org/show_bug.cgi?id=705497
2013-08-26 15:00:29 +02:00
bbf9358eba window: Fix a compiler warning 2013-08-23 23:09:58 -04:00
9682a2aea4 window-group: Fix compiler warning 2013-08-23 22:11:37 -04:00
c9fbb51775 wayland: Fix build when building without Wayland 2013-08-23 22:05:11 -04:00
aa6d887214 wayland-private: Ignore deprecations around legacy_buffer
yes, it's deprecated, that's why it's marked legacy. now shush.
2013-08-23 22:00:52 -04:00
13312527de Update .gitignore 2013-08-23 18:23:33 -04:00
9bd366f2a6 MonitorXrandr: skip CRTC reconfigurations that have no effect
If we're attempting to reconfigure the CRTCs to the same parameter,
skip the X call, as in some drivers a modeset can take time and
cause flicker.

https://bugzilla.gnome.org/show_bug.cgi?id=706672
2013-08-23 18:06:02 +02:00
5de346bfef MonitorXrandr: Fix segv when accessing possible_clones
This code requires a double pass and the segv happens later
when trying to iterate over the array.

https://bugzilla.gnome.org/show_bug.cgi?id=706598
2013-08-23 16:40:43 +02:00
2af20b77b6 MonitorXrandr: fix reading the current DPMS level
Add missing break statements, to avoid falling always through
to the invalid case.

https://bugzilla.gnome.org/show_bug.cgi?id=706582
2013-08-23 16:40:43 +02:00
9affbf10a6 MetaIdleMonitor: add wayland support
Keep a timer source that we reset when we capture an event in
MetaWayland, and fire watches accordingly.

https://bugzilla.gnome.org/show_bug.cgi?id=706005
2013-08-23 16:34:02 +02:00
c0acf3ae6d MetaIdleMonitor: add a DBus interface for the idle monitor
To allow other clients (gnome-session, gnome-settings-daemon)
to monitor user activity, introduce a DBus interface for the
idle monitor inside mutter.

https://bugzilla.gnome.org/show_bug.cgi?id=706005
2013-08-23 16:34:02 +02:00
2c1b20e15f Add a new helper for tracking user idle activity
When running as a wayland compositor, we can't use the xserver's
IDLETIME, because that's updated only in response to X events.
But we have all the events ourselves, so we can just run the timer
in process.

https://bugzilla.gnome.org/show_bug.cgi?id=706005
2013-08-23 16:34:02 +02:00
77290b6736 Update .gitignore 2013-08-20 17:04:43 -04:00
876f81db12 compositor: fix focusing the stage window
We can't use the X11 stage window, if clutter is not using the X11
backend (and even if it was, it would be bogus when the xwayland
server is not the one clutter is talking to). Instead, we introduce
the concept of "focus type", which we use to differentiate the
various meanings of None in the focus_xwindow field.

https://bugzilla.gnome.org/show_bug.cgi?id=706364
2013-08-20 14:41:24 +02:00
75f3ae14b5 MetaPlugin: simplify the modal API
Remove grab window and cursor from the API, and just grab always
on the stage window with no cursor.
This is mainly to remove the X11 usage in the public API, in preparation
for implementing this in wayland.

https://bugzilla.gnome.org/show_bug.cgi?id=705917
2013-08-20 14:25:49 +02:00
d26f248b0f wayland: fix a compiler warning
Implicit declaration of memset

https://bugzilla.gnome.org/show_bug.cgi?id=706363
2013-08-20 14:13:49 +02:00
eeb3dfc991 MonitorManager: emit a DBus signal when we change the display configuration
Using out-of-band notifications from the wayland protocol or from
X is racy, in that the client could ask for the new resources before
we have them.
Instead, with a signal, we are sure that when the client asks for
it, it will get the right values.

https://bugzilla.gnome.org/show_bug.cgi?id=706382
2013-08-20 14:08:50 +02:00
e66db2eab3 MonitorManager: extend the API with physical sizes
These will be needed in the new display panel designs to show
the diagonal length and physical aspect ratio.

https://bugzilla.gnome.org/show_bug.cgi?id=706322
2013-08-20 14:08:50 +02:00
2ae7454f36 Add MetaCursorTracker, a new helper for tracking the cursor sprite
Under X, we need to use XFixes to watch the cursor changing, while
on wayland, we're in charge of setting and painting the cursor.
MetaCursorTracker provides the abstraction layer for gnome-shell,
which can thus drop ShellXFixesCursor. In the future, it may grow
the ability to watch for pointer position too, especially if
CursorEvents are added to the next version of XInput2, and thus
it would also replace the PointerWatcher we use for gnome-shell's
magnifier.

https://bugzilla.gnome.org/show_bug.cgi?id=705911
2013-08-19 16:09:53 +02:00
4fd3c63da9 ui: restrict gtk to only use the x11 backend
We use GTK as a way to get the X11 connection for our internal
use, so we need it to keep using X.

https://bugzilla.gnome.org/show_bug.cgi?id=706303
2013-08-19 15:42:37 +02:00
909a6607c5 MonitorXrandr: try harder to get decent product/serial IDs
If the EDID does not include free-form product name and serial
number, use the numeric IDs instead, like gnome-desktop did.

https://bugzilla.gnome.org/show_bug.cgi?id=706233
2013-08-19 09:45:31 +02:00
1bde397edf Updated POTFILES.in 2013-08-18 22:03:23 +02:00
015c05fbf6 MonitorXrandr: fix setting gamma ramps
The value passed to XRRCrtcSetGamma must be allocated with
XRRAllocGamma (because it relies on the locations of green and blue),
otherwise garbage is sent on the wire.

https://bugzilla.gnome.org/show_bug.cgi?id=706231
2013-08-18 12:11:42 +02:00
8ad5ccd2f8 MonitorConfig: switch to the real configuration file
Forgot to do before pushing...
2013-08-18 01:10:00 +02:00
115cc870c7 build: Fix srcdir != builddir 2013-08-17 19:05:50 -04:00
3112794d83 MonitorXrandr: update the internal data structures after applying
We were relying on the XRandR events from the X server to update
the configuration, but we were calling meta_monitor_config_update_current()
immediately after, so the MonitorConfig would be updated with the
old configuration (and we would save that to disk!)

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:48:31 +02:00
3528b067d0 MonitorXrandr: follow the right order in applying the new configuration
First disable CRTCs that should be off in the new configuration,
then resize the framebuffer, then enable the new CRTCs.
If we don't do that, and we're making the screen smaller, X complains
with a BadMatch.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:47:53 +02:00
0986b660be MonitorXrandr: resize the framebuffer prior to setting the CRTC configuration
Otherwise X11 will trim the new configuration and disable outputs
outside the screen.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:47:53 +02:00
3bb5086173 Monitor: restore correct display name handling
Now that we have the right values from the EDID, we can load
the PNP database and find the proper vendor name, to show in
the control center UI.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:47:53 +02:00
69467842ab MonitorXrandr: implement correct EDID parsing
To provide valid values for the vendor, product and serial fields
we need to read the EDID and parse it.
Parser kindly provided by gnome-desktop.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:47:53 +02:00
57077435ed MonitorManager: add EDID properties to the output DBus description
Add "edid-file", if we have one (in the KMS case, where we can point
people to the right sysfs file), or "edid" with inline data.
These are needed by colord to build the default ICC profile for
uncalibrated displays.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:47:53 +02:00
46de0ed462 MonitorManager: split the XRandR parts in a subclass
Instead of keeping a forest of if backend else ..., use a subclass
and virtual functions to discriminate between XRandR and the
dummy backend (which lives in the parent class togheter with the
common code)

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:47:53 +02:00
5086626805 MetaPlugin: add a UI hook for confirming display changes
We want to show a dialog when a display change happens from the
control center. To do so, add a new vfunc to MetaPlugin and
call it when a configuration change is requested via DBus.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:47:53 +02:00
bbbcd8c631 MonitorConfig: handle changes in the laptop lid
This way we don't need to track the current and previous
configuration in gnome-settings-daemon, when we already do so
in mutter.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:47:53 +02:00
3b61b85f2c MonitorManager: add gamma support
Add GetCrtcGamma() and SetCrtcGamma(), that wrap the similarly
named XRandR API. These are used by GnomeRR inside the color
plugin of the control center (and may go away if the color
plugin decides to do something different under wayland)

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:47:53 +02:00
cd20f1bc0b MonitorManager: ignore configuration changes that disable all outputs
If we compute a screen size of 0 in either direction, we crash
later on, as it is invalid for clutter, cogl and X.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:47:53 +02:00
8b52782ed4 MonitorManager: add support for backlight
GnomeRR needs that too.
The backlight is exported as a normalized 0-100 value, or -1 if not
supported. Clamping to HW limits is handled by the backend.
Changing backlight uses a different method call, to avoid recomputing
the full display configuration every time the user presses the
backlight keys.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:47:53 +02:00
849050be95 MonitorManager: further extend the dummy backend
The default configuration is extended, which is only possible
if there are as many CRTCs as outputs, so make sure that's true.

Also, add more and bigger modes, so that different sizes will
be chosen for the three outputs.
A nice side effect of this is that with a real 1920x1080 + 1600x900
layout, if you disable the VGA you get a stage that matches the
screen size, which triggers the legacy fullscreen path in the
outside mutter.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:47:52 +02:00
5c27a91684 MonitorManager: store the presentation mode bit in XRandR
Use a private output property to store if the output is in
presentation mode or not, so that this information is not lost
after the configuration read back from the server.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:34:16 +02:00
764c472edb MonitorConfig: add support for default configurations
Activate the presentation bit on new hotplugged monitors, while
making a fully extended setup when running for the first time.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:34:16 +02:00
d0529b7482 MonitorConfig: add CRTC assignment
Ripped off libgnome-desktop, trimming the parts that checked
that the configuration was plausible, as that should be done
in gnome-control-center before asking mutter for a change.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:34:15 +02:00
8f4621240a MonitorManager: add support for persistent monitor configurations
Add a new object, MetaMonitorConfig, that takes care of converting
between the logical configurations stored in monitors.xml and
the HW resources exposed by MonitorManager.
This commit includes loading and saving of configurations, but
still missing is the actual CRTC assignments and a default
configuration when none is found in the file.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:33:37 +02:00
e039add240 MonitorManager: add support for DPMS levels
To the XRandR and dummy backend (and as usual the dummy backend
has no effect)

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:33:37 +02:00
dbd8d4d598 MonitorManager: inherit directly from DisplayConfig instead of handling signals
This way we can handle properties too.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:33:37 +02:00
522542c486 MonitorManager: fix handling of output transform
Read the current transform from XRandR, and expose the transforms
that are really supported on the bus.
The dummy backend now advertises all transforms, since it doesn't
actually apply them.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:33:35 +02:00
fc67c707e4 default plugin: add a random color background on each monitor
Instead of a full white background, make one with a random color.
This way the different "monitors" are visible and it's easier
to debug the DBus API.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:32:44 +02:00
c354e7e81b DisplayConfig: make the dummy backend writable
Add a number of dummy outputs and modes to the dummy backend,
and implement the writing bits.
The only visible effect is that you can change the screen size,
which resizes the output window.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:32:43 +02:00
bf40409d97 Reverse handling of XRandR events between Screen and MonitorManager
Now MonitorManager does its own handling of XRandR events, which
means we no longer handle ConfigureNotify on the root window.
MetaScreen reacts to MonitorManager::monitor-changed and updates
its internal state, including the new size.

This paves the way for doing display configuration using only
the dummy backend, which would allow testing wl_output interfaces.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:31:10 +02:00
57d083730e DisplayConfig: add the write side of the API
Implement ApplyConfiguration in terms of XRandR calls.
Error checking is done before actually committing the configuration.

If mutter is using one of the other monitor config backends, an
error is reported and nothing happens.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:31:09 +02:00
dc242e46c2 Extend the DBus XRandR protocol to expose cloning restriction
Turns out that even if two outputs say that they can be controlled
by a given CRTC, you can't configure them in the same CRTC unless
they are marked as "possible clones" one of the other.
This can further restrict the configuration options, so we need
to expose this limitation in the DBus API.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:22:54 +02:00
7e1d1003c9 Add the write side of the DBus protocol too
This is just in the documentation for now, to attract wider feedback
before we start looking at how to implement this for real.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:22:54 +02:00
3bb33d384f Introduce a new DBus interface for display configuration
This new interface will be used by the control center and possibly
the settings daemon to configure the screens. It is designed to
resemble a simplified XRandR, while still exposing all the quirks
of the hardware, so that the panel can limit the user choices
appropriately.

To do so, MetaMonitorMode needs to track CRTCs, outputs and modes,
so the low level objects have been decoupled from the high-level
MetaMonitorInfo, which is used by core and API and offers a simplified
view of HW, that hides away the details of what is cloned and how.
This is still not efficient as it should be, because on every
HW change we drop all data structures and rebuild them from scratch
(which is not expensive because there aren't many of them, but
at least in the XRandR path it involves a few sync X calls)

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:22:54 +02:00
214f31257b Rework and consolidate monitor handling in MetaScreen
Consolidate all places that deal with output configuration in
MetaScreen, which gets it either from XRandR or from a dummy static configuration.
We still need to read the Xinerama config, even when running xwayland,
because we need the indices for _NET_WM_FULLSCREEN_MONITORS, but
now we do it only when needed.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-18 00:22:54 +02:00
bfc87d13cb MetaWindowActor: fix reference counting issue
We need to use g_signal_connect_object(), rather than g_signal_connect(),
because the window actor can be destroyed before the window emits
the final notify::appears-focused inside unmanage, if the plugin
decides that it doesn't want to animate the destruction (which
happens with dialogs and the default plugin)

https://bugzilla.gnome.org/show_bug.cgi?id=706207
2013-08-18 00:22:07 +02:00
506ddc3d6c MetaWindowActor: fix reference counting issue
We need to use g_signal_connect_object(), rather than g_signal_connect(),
because the window actor can be destroyed before the window emits
the final notify::appears-focused inside unmanage, if the plugin
decides that it doesn't want to animate the destruction (which
happens with dialogs and the default plugin)

https://bugzilla.gnome.org/show_bug.cgi?id=706207
2013-08-18 00:16:59 +02:00
24564c77d6 build: Fix srcdir != builddir
Need to ensure the wayland/ directory exists in $(builddir), and find
the headers there too.
2013-08-17 18:03:10 -04:00
18a21b67c2 wayland: move XWayland support code to its own file
Given that xwayland code is already split in meta-xwayland, it
makes sense to have there the implementation of the private
xserver protocol too.

https://bugzilla.gnome.org/show_bug.cgi?id=705816
2013-08-15 17:42:19 +02:00
3803fd9511 wayland: don't use fork() and SIGCHLD to spawn processes
It is a very bad idea in a glib program (especially one heavily
using glib child watching facilities, like gnome-shell) to handle
SIGCHLD. While we're there, let's also use g_spawn_async, which
solves some malloc-after-fork problems and makes the code generally
cleaner.

https://bugzilla.gnome.org/show_bug.cgi?id=705816
2013-08-15 17:41:34 +02:00
152d896f75 MetaWindowActor/wayland: make sure the mapped bit is correctly set
Otherwise it stays FALSE for OR windows, causing the shape region
to be empty and the actor culled from drawing.

https://bugzilla.gnome.org/show_bug.cgi?id=706078
2013-08-15 17:41:34 +02:00
2f3a5f2001 MetaWaylandSeat: correct logic to set the current / focused surface
The current surface refers to the surface right below the pointer
(according to the pick performed by clutter), while the focus surface
is the one receiving events. They can be out of sync in case of
grabs, in which case we should keep trying to focus the current
surface.

https://bugzilla.gnome.org/show_bug.cgi?id=706077
2013-08-15 17:41:34 +02:00
c3e8646af3 Updated POTFILES.in 2013-08-13 21:10:02 +02:00
8c17b670fb keybindings: always acknowledge events to the X server
https://bugzilla.gnome.org/show_bug.cgi?id=666101
2013-08-13 11:18:48 -04:00
0e098249b1 Merge remote-tracking branch 'origin/master' into wayland 2013-08-13 10:44:09 -04:00
12d2e1f600 Support _GTK_FRAME_EXTENTS
https://bugzilla.gnome.org/show_bug.cgi?id=705766
2013-08-13 10:40:15 -04:00
c20b007985 Reintroduce mutter binary
I accidentally deleted one too many things.
2013-08-13 10:16:01 -04:00
ef480e9120 theme: Fix build breakage 2013-08-13 09:50:59 -04:00
8c1c77482d Remove old, deprecated utilities that nobody has used in a million years
https://bugzilla.gnome.org/show_bug.cgi?id=704437
2013-08-13 09:39:02 -04:00
e633606ca9 menu: Remove support for icon items from the window menu
We don't show these by default, and it uses deprecated API.
This also removes our only use of the stock icons, so remove
those as well.

https://bugzilla.gnome.org/show_bug.cgi?id=704437
2013-08-13 09:39:01 -04:00
9a5f243f73 wayland: refactor window destruction and focus
The previous code was leaving focus fields dirty in MetaWaylandPointer
and MetaWaylandKeyboard at time (which could crash the X server
because of invalid object IDs)
The new code is more tighly integrated in the normal X11 code
for handling keyboard focus (meaning that the core idea of input
focus is also correct now), so that meta_window_unmanage() can
do the right thing. As a side benefit, clicking on wayland clients
now unfocus X11 clients.
For the mouse focus, we need to clear the surface pointer when
the metawindowactor is destroyed (even if the actual actor is
kept alive for effects), so that a repick finds a different pointer
focus.

https://bugzilla.gnome.org/show_bug.cgi?id=705859
2013-08-13 09:42:55 +02:00
03f55b9485 wayland: fix a #warning
Remove window_surfaces, as the FIXME asks for. We don't need it
because we can obtain the surface from the MetaWindow, and
follow the wayland compositor path for both types of clients.

https://bugzilla.gnome.org/show_bug.cgi?id=705818
2013-08-13 09:42:55 +02:00
ef9ef87d91 configure: Complete fix for removing clutter-wayland-compositor 2013-08-12 14:43:23 -04:00
0ee2c21da7 meta-wayland: Remove get_surface_rect
It's the same as get_input_rect, which we already have in window.
2013-08-12 12:13:45 -04:00
9b966561c4 configure.ac: Remove clutter-wayland-compositor dependency
It's not necessary.
2013-08-12 12:08:58 -04:00
8c0779a9db wayland: add missing file
A Makefile.am is required for the protocol/ directory

https://bugzilla.gnome.org/show_bug.cgi?id=705815
2013-08-12 09:49:17 +02:00
2c901cc015 wayland: implement shell surface move interface
This implements the shell surface move interface so now it's possible to
use the mouse to interactively move wayland based windows around the
screen.
2013-08-10 19:13:49 -04:00
85e66f69fa wayland: support left click to raise wayland surfaces
This adds support for raising wayland surfaces when clicked with the
left mouse button.
2013-08-10 19:13:49 -04:00
a5585327dc wayland: Add an actor for the cursor
When running Mutter under Cogl's KMS backend no cursor will be
provided so instead this makes it so the cursor will be painted as a
CoglTexture that gets moved in response to mouse motion events. The
painting is done in a subclass of ClutterStage so that we can
guarantee that the cursor will be painted on top of everything else.

This patch adds support for the set_cursor method on the pointer
interface so that clients can change the cursor image.

The set_pointer method sets a surface and a hotspot position to use
for the cursor image. The surface's buffer is converted to a
CoglTexture and attached to a pipeline to paint directly via Cogl. If
a new buffer is attached to the surface the image will be updated. The
cursor reverts back to the default image whenever to the pointer focus
is moved off of any surface.

The image for the pointer is taken from X. It gets installed into
a fixed data location for mutter.
2013-08-10 19:13:49 -04:00
268ebb1b18 wayland: Add basic input support
This copies the basic input support from the Clayland demo compositor.
It adds a basic wl_seat implementation which can convert Clutter mouse
events to Wayland events. For this to work all of the wayland surface
actors need to be made reactive.

The wayland keyboard input focus surface is updated whenever Mutter
sees a FocusIn event so that it will stay in synch with whatever
surface Mutter wants as the focus. Wayland surfaces don't get this
event so for now it will just give them focus whenever they are
clicked as a hack to test the code.

Authored-by: Neil Roberts <neil@linux.intel.com>
Authored-by: Giovanni Campagna <gcampagna@src.gnome.org>
2013-08-10 19:13:49 -04:00
40e820f551 Add support for stacking X and Wayland windows together
This breaks down the assumptions in stack-tracker.c and stack.c that
Mutter is only stacking X windows.

The stack tracker now tracks windows using a MetaStackWindow structure
which is a union with a type member so that X windows can be
distinguished from Wayland windows.

Some notable changes are:

Queued stack tracker operations that affect Wayland windows will not be
associated with an X serial number.

If an operation only affects a Wayland window and there are no queued
stack tracker operations ("unvalidated predictions") then the operation
is applied immediately since there is no server involved with changing
the stacking for Wayland windows.

The stack tracker can no longer respond to X events by turning them into
stack operations and discarding the predicted operations made prior to
that event because operations based on X events don't know anything
about the stacking of Wayland windows.

Instead of discarding old predictions the new approach is to trust the
predictions but whenever we receive an event from the server that
affects stacking we cross-reference with the predicted stack and check
for consistency. So e.g. if we have an event that says ADD window A then
we apply the predictions (up to the serial for that event) and verify
the predicted state includes a window A. Similarly if an event says
RAISE_ABOVE(B, C) we can apply the predictions (up to the serial for
that event) and verify that window B is above C.

If we ever receive spurious stacking events (with a serial older than we
would expect) or find an inconsistency (some things aren't possible to
predict from the compositor) then we hit a re-synchronization code-path
that will query the X server for the full stacking order and then use
that stack to walk through our combined stack and force the X windows to
match the just queried stack but avoiding disrupting the relative
stacking of Wayland windows. This will be relatively expensive but
shouldn't be hit for compositor initiated restacking operations where
our predictions should be accurate.

The code in core/stack.c that deals with synchronizing the window stack
with the X server had to be updated quite heavily. In general the patch
avoids changing the fundamental approach being used but most of the code
did need some amount of re-factoring to consider what re-stacking
operations actually involve X or not and when we need to restack X
windows we sometimes need to search for a suitable X sibling to restack
relative too since the closest siblings may be Wayland windows.
2013-08-10 19:13:49 -04:00
f9a11b3b18 wayland: Adds basic hybrid X + Wayland support
This adds support for running mutter as a hybrid X and Wayland
compositor. It runs a headless XWayland server for X applications
that presents wayland surfaces back to mutter which mutter can then
composite.

This aims to not break Mutter's existing support for the traditional X
compositing model which means a single build of Mutter can be
distributed supporting the traditional model and the new Wayland based
compositing model.

TODO: although building with --disable-wayland has at least been tested,
I still haven't actually verified that running as a traditional
compositor isn't broken currently.

Note: At this point no input is supported

Note: multiple authors have contributed to this patch:
Authored-by: Robert Bragg <robert@linux.intel.com>
Authored-by: Neil Roberts <neil@linux.intel.com>
Authored-by: Rico Tzschichholz.
Authored-by: Giovanni Campagna <gcampagna@src.gnome.org>
2013-08-10 19:13:48 -04:00
bd3c357212 Adds a --nested option
This adds a --nested option to request that mutter no longer run as a
classic X compositor with an output window mapped on the X Composite
Overlay Window and also not assume it is running directly under X.

The intention is that in this mode Mutter will itself launch a headless
X server and display output will be handled by Clutter and Cogl. This
will enable running Mutter nested as an application within an X session.

This patch introduces an internal meta_is_wayland_compositor() function
as a means to condition the way mutter operates when running as a
traditional X compositor vs running as a wayland compositor where the
compositor and display server are combined into a single process.

Later we also expect to add a --kms option as another way of enabling
this wayland compositor mode that will assume full control of the
display hardware instead of running as a nested application.
2013-08-10 19:13:48 -04:00
b4d108dac6 configure: Adds --with-xwayland-path option
This adds a --with-xwayland-path configure option that can be used to
specify the absolute path of a headless X server binary supporting
the wayland xserver protocol.
2013-08-10 19:13:48 -04:00
6585a5760b configure: Adds --enable-wayland config option
This adds a --enable-wayland configure option to enable building mutter
as a hybrid X and Wayland compositor. By default the option is disabled.
If enabled then HAVE_WAYLAND is defined for C code and as an automake
conditional.

This copies the xserver.xml wayland protocol into a protocol/ directory
since wayland support will depend on this protocol for communicating
with an xwayland X server. Copying the spec like this is consistent with
Weston so we don't need a configure option to locate an external spec.
2013-08-10 19:13:48 -04:00
531be6c413 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-08-10 19:13:48 -04:00
f0c503b5a9 hack autogen to allow automake 1.13 2013-08-10 19:13:48 -04:00
6fdc23d0b7 Updated Norwegian bokmål translation 2013-08-08 22:14:40 +02:00
4862872c78 window-actor: Fix doc comment
https://bugzilla.gnome.org/show_bug.cgi?id=703332
2013-08-05 16:29:37 +02:00
ae2e4c5114 l10n: Update Japanese translation 2013-08-03 23:38:51 +09:00
06b5be2d13 Bump version to 3.9.5
Update NEWS.
2013-07-30 14:27:06 +02:00
56fb8a81b3 display: Export the timestamp of the event as well
When passing on keybindings, make sure to pass the timestamp
of the event as well as the deviceid and the action.

https://bugzilla.gnome.org/show_bug.cgi?id=704858
2013-07-25 14:23:51 +02:00
90a3d613ca meta-window-group: Fix previous commit 2013-07-18 16:33:50 +02:00
c2af13cf31 meta-window-group: Fix compile warning 2013-07-18 16:24:24 +02:00
b0cf0b2442 display: Fix compilation error
Whoops, I didn't mean to push that last commit, but let's
not break the build.
2013-07-17 21:04:55 -04:00
1c569c2d0e Remove application-based preference
It's hardcoded to FALSE.
2013-07-17 21:03:59 -04:00
e3855c77af meta-window-group: Use clutter's iteration API
Use the clutter iteration API instead of copying the list of children.
This is more efficent.

https://bugzilla.gnome.org/show_bug.cgi?id=703332
2013-07-17 19:37:13 +02:00
21fe5be026 display: Ignore _NET_WM_USER_TIME PropertyNotifies
These are spammy as well.

https://bugzilla.gnome.org/show_bug.cgi?id=703970
2013-07-15 12:47:46 -04:00
57bc974a57 display: Ignore XSyncAlarmNotify in meta_spew_event
https://bugzilla.gnome.org/show_bug.cgi?id=703970
2013-07-15 12:47:46 -04:00
3b51405255 main: Don't select for touch events on the stage
GNOME Shell's actors aren't touch capable, so we need to make sure that
they get the fallback pointer emulated events for now. This fixes the top
bar and other elements not working on a touchscreen without a grab.

https://bugzilla.gnome.org/show_bug.cgi?id=697192
2013-07-15 12:47:46 -04:00
73dbb4b9a5 window-actor: Remove another unused field 2013-07-15 12:20:26 -04:00
51acc3ee31 window-actor: Remove unused description
The desc field would never get filled in, as we can't have a window
actor without a MetaWindow, also, so remove the storage for the field.
2013-07-15 12:20:26 -04:00
a6f206f07c window-actor: Remove a field we don't use 2013-07-15 12:20:13 -04:00
9504fdd2cb Bump version to 3.9.4
Update NEWS.
2013-07-10 18:35:17 +02:00
b76c3312e9 Revert "background: Allow using sliced textures"
This reverts commit f743539886.

( accidentally pushed this when trying to push commit
  b7840bec7d )
2013-07-01 07:33:19 -04:00
fd7db8e6b3 Revert "background: downscale background to fit in texture limits"
This reverts commit 15e01152da.

( accidentally pushed this when trying to push commit
  b7840bec7d )
2013-07-01 07:31:25 -04:00
b7840bec7d background: Allow using sliced textures for file based backgrounds
Some cards have 2k texture limits, which can be smaller than
commonly sized backgrounds.

One way to get around this problem is to use Cogl's "sliced texture"
feature, that transparently uses several hardware textures under the hood.

This commit changes background textures loaded from file to potentially
use slicing.  Based on a patch by Jasper St. Pierre
<jstpierre@mecheye.net>.

https://bugzilla.gnome.org/show_bug.cgi?id=702283
2013-07-01 07:28:59 -04:00
f743539886 background: Allow using sliced textures
https://bugzilla.gnome.org/show_bug.cgi?id=702283
2013-07-01 07:28:32 -04:00
15e01152da background: downscale background to fit in texture limits
Some cards have 2k texture limits, which can be smaller than
commonly sized backgrounds.

This commit downscales the background in this situation, so that
it won't fail to load.

https://bugzilla.gnome.org/show_bug.cgi?id=702283
2013-07-01 07:28:32 -04:00
2103ff6a5c window: Don't force attached dialogs to be border-only
Originally attached dialogs did not have a titlebar, which the code
still assumes though it hasn't been true for a while; nowadays, the
actual look of attached dialogs is controlled by the theme.
As GTK+ recently gained the ability to set custom titlebars, we need
to support attached dialogs with either full borders (WM decorations)
or border-only (GTK+ titlebar).
Just remove the left-over assumption to make it work as expected.

https://bugzilla.gnome.org/show_bug.cgi?id=702764
2013-06-24 20:19:33 +02:00
8ab136b7ea window: Make sure override_redirect window have correct monitor info
We need to update window->monitor on override_redirect windows as well, other
wise they may end up with an invalid struct which triggers and assert when
meta_window_is_monitor_sized is called.

https://bugzilla.gnome.org/show_bug.cgi?id=702564
2013-06-24 17:32:22 +02:00
5205821fb9 window: Reuse current pointer position for monitor checks
Avoid a round trip to the xserver we already have the current position
anyway. Querying from the server on every move can cause the compositor to
stall during movement.
2013-06-23 21:24:41 +02:00
7187206ef5 screen: Allow reusing the current position when quering the monitor
Add new api (meta_screen_get_current_monitor_for_pos and
meta_screen_get_current_monitor_info_for_pos) that allow querying the monitor
without a roundtrip by reusing the passed in cursor position.
2013-06-23 21:24:41 +02:00
96221e6c04 compositor: Add an API to query if the stage is focused
gnome-shell needs to know whether the stage window is focused so
it can synchronize between stage window focus and Clutter key actor
focus. Track all X windows, even those without MetaWindows, when
tracking the focus window, and add a compositor-level API to determine
when the stage is focused.

https://bugzilla.gnome.org/show_bug.cgi?id=700735
2013-06-20 17:21:54 -04:00
7fdfbad6d4 display: Ensure that we ignore our own focus events for focus predictions
When we set the input focus, we first set the predicted window,
and then try to process focus events. But as XI_FocusOut on the
existing window comes before XI_FocusIn on the new window, we'll
see the focus out on the old window and think the focus is going
to nothing, which makes mutter think the prediction failed.

This didn't really matter as nothing paid attention to the focus
window changing, but with gnome-shell's focus rework, we'll try
and drop keyboard focus in events like these.

Fix this by making sure that we ignore focus window changes of our
own cause when updating the focus window field, by ignoring all
focus events that have a serial the same as the focus request or
lower. Note that if mutter doens't make any requests after the
focus request, this could be racy, as another client could steal
the focus, but mutter would ignore it as the serial was the same.
Bump the serial by making a dummy ChangeProperty request to a
mutter-controlled window in this case.

https://bugzilla.gnome.org/show_bug.cgi?id=701017
2013-06-20 17:21:54 -04:00
2a5b068863 compositor: Prevent an error in application code from keeping unredirect on permanently
We substract one from the unredirect counter when enable_unredirect_for_screen
gets called. It is an unsigned integer so substracting one from zero (which means enable) would overflow and thus keep it peramently enabled.

This should never happen because it means there is an unmatched
enable / disable pair somewhere. So in addition to fixing it add a
warning when this case gets triggered.

https://bugzilla.gnome.org/show_bug.cgi?id=701224
2013-06-18 22:18:38 +02:00
0c505faded make the window shadows lighter
Subtler shadows look more refined.

https://bugzilla.gnome.org/show_bug.cgi?id=702141
2013-06-18 17:26:24 +01:00
b2dd4f33f7 Bump version to 3.9.3
Update NEWS.
2013-06-18 16:40:02 +02:00
47b21b3547 Use new clutter_stage_set_paint_callback() function for after-paint notification
Commit 4f2bb583bf changed things so that the compositor used
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT
to get after-paint notification and send _NET_WM_FRAME_DRAWN, but this
doesn't actually work, since Clutter will already have blocked for
VBlank before calling post-paint functions.

The result is that frame synced toolkits like GTK 3.8 will normally
only be able to draw every other frame.

Since ::paint doesn't work either, a new function
clutter_stage_set_paint_callback() has been added to Clutter
(and will be included in the 1.14 branch)

https://bugzilla.gnome.org/show_bug.cgi?id=698794
2013-06-03 13:21:54 -04:00
c119f98bac keybindings: Make sure events are always reported to the grab window
We have no need for normally reported events during grabs. In fact, it
might be harmful. A plugin might grab the keyboard through
meta_begin_modal_for_plugin() and then expect events to be reported to
the grab window they provide. If meanwhile this XIGrabDevice is
issued, events might start being reported normally to one other of our
windows breaking the plugin event processing.

In particular, on an empty workspace, we set input focus to our
no_focus_window. Then, if gnome-shell calls
meta_begin_modal_for_plugin() and meta_display_freeze_keyboard(), in
that order, input events will start being reported to no_focus_window.

There are two issues with this. One is that no_focus_window isn't
selecting for XI input events and thus the server discards them
completely. But even if that is fixed, events being reported to any
window other than the one gnome-shell expects - the clutter stage
window - means that events will stop reaching it.

https://bugzilla.gnome.org/show_bug.cgi?id=701219
2013-05-29 21:36:09 +02:00
d20078574e Bump version to 3.9.2
Update NEWS.
2013-05-28 17:23:25 +02:00
26bd4fde5c Updated Norwegian bokmål translation 2013-05-28 09:48:06 +02:00
2af49e503f keybindings: Grab and emit a signal when XK_ISO_Next_Group is pressed
This will make it possible to implement input source switching in
gnome-shell using the popular modifiers-only keybinding that's
implemented on the X server through an XKB option.

https://bugzilla.gnome.org/show_bug.cgi?id=697002
2013-05-27 13:56:04 +02:00
6ea6af6eb4 prefs: Track the XKB 'grp:' option in gsettings as a keybinding pref
We'll use the value of this option to establish a passive grab on the
keycode/modifier combos generating XK_ISO_Next_Group.

https://bugzilla.gnome.org/show_bug.cgi?id=697002
2013-05-27 13:55:57 +02:00
10df80762c keybindings: Add API to freeze/unfreeze the keyboard
We'll use this in gnome-shell to freeze the keyboard right before
switching input source and unfreeze it after that's finished so that
we don't lose any key events to the wrong input source.

https://bugzilla.gnome.org/show_bug.cgi?id=697001
2013-05-27 13:55:52 +02:00
f86032d700 prefs: Fix binding remaining grabbed after clearing all strokes
If a binding is updated with a clear set of strokes (effectively
disabling it) we aren't signaling that the binding changed and thus
the previous strokes will continue to be grabbed.

This fixes that and tries to do a better effort at checking if the
binding changed or not.

https://bugzilla.gnome.org/show_bug.cgi?id=697000
2013-05-27 13:55:33 +02:00
a8eb33f6fd Updated slovak translation 2013-05-25 21:58:43 +02:00
bd19de9429 compositor: Add an API to focus the stage X window
gnome-shell has traditionally just called XSetInputFocus when wanting to
set the input focus to the stage window, but this might cause strange,
hard-to-reproduce bugs because of an interference with mutter's focus
prediction. Add API to allow gnome-shell to focus the stage window that
also updates mutter's internal focus prediction state.

https://bugzilla.gnome.org/show_bug.cgi?id=700735
2013-05-24 17:43:37 -04:00
2ca2838548 display: Consolidate code calling XSetInputFocus into a new function
At the same time, rename set_focus_window and add a comment so we're
not confused about which function does what.

https://bugzilla.gnome.org/show_bug.cgi?id=700735
2013-05-24 17:43:37 -04:00
df8234c5e3 window: Properly handle focusing override redirect windows
If an app pops up an OR window and sets input focus to it, like
Steam does, we'll think the focus window is null, causing us to
think the app is not focused.

OR windows should not be special if they get input focus, where
the input focus would be set to NULL. Instead, the window should
be marked as focused.

https://bugzilla.gnome.org/show_bug.cgi?id=647706
2013-05-22 13:46:15 -04:00
d03ffd801e display: Use XI2 constants for mode/detail focus event values
This makes no functional difference, except conceptual clarity.

https://bugzilla.gnome.org/show_bug.cgi?id=647706
2013-05-22 13:46:15 -04:00
7a4c808e43 display: clean up focus_window vs expected_focus_window
Mutter previously defined display->focus_window as the window that the
server says is focused, but kept display->expected_focus_window to
indicate the window that we have requested to be focused. But it turns
out that "expected_focus_window" was almost always what we wanted.

Make MetaDisplay do a better job of tracking focus-related requests
and events, and change display->focus_window to be our best guess of
the "currently" focused window (ie, the window that will be focused at
the time when the server processes the next request we send it).

https://bugzilla.gnome.org/show_bug.cgi?id=647706
2013-05-22 13:46:15 -04:00
4f1d62170b test-focus: test program for focus window management
https://bugzilla.gnome.org/show_bug.cgi?id=647706
2013-05-22 13:46:15 -04:00
e10804727d compositor: remove the overlay_group concept
The hierarchy handling is handled in the shell by adding stuff
directly to the uiGroup, and we have a dedicated actor for
the overview there, so we don't need this anymore.

https://bugzilla.gnome.org/show_bug.cgi?id=700735
2013-05-22 18:36:05 +02:00
e430e051b7 window: Clean up the set_focused_internal function
Move things out of an indentation layer, and reshuffle
things around.

https://bugzilla.gnome.org/show_bug.cgi?id=647706
2013-05-22 12:35:04 -04:00
696d9d2fa9 window: Merge got_focus/lost_focus to a new function
Make it a static function for now, but this will be a private
function soon, replacing meta_window_lost_focus. This should
contain no functional changes, only cosmetic indentation changes,
so best viewed with ignorews=1 or -w or -b, you know the drill.

https://bugzilla.gnome.org/show_bug.cgi?id=647706
2013-05-22 12:35:04 -04:00
f6dd081acd window: Refactor "got focus" code
Just move this out to a separate function.

https://bugzilla.gnome.org/show_bug.cgi?id=647706
2013-05-22 12:35:04 -04:00
eddd6f8e9b Updated Norwegian bokmål translation 2013-05-20 14:46:56 +02:00
dfa4c7d670 compositor: Fix regression of shaded windows
Fix issues drawing shaded window shadows.

https://bugzilla.gnome.org/show_bug.cgi?id=693714
2013-05-15 16:52:28 +02:00
a487d4dd01 window: Eliminate a potential race condition with _NET_WM_MOVERESIZE
Clients using _NET_WM_MOVERESIZE to start a drag operation may encounter
a race condition if the user presses and releases a mouse button very
fast, getting "stuck" in a grab state. While this is easily fixed with
the user pressing the button or hitting Escape as the EWMH spec suggests,
its's still a bit of annoyance for users.

After starting a grab operation, check that the button is actually pressed
by the client, and if not, cancel the grab operation. This prevents the
stuck grab in a race-free way, although it requires an extra round-trip
to the server.

With client-side decorations becoming more popular, the use of
_NET_WM_MOVERESIZE is on the rise, thus this bug is seen more frequently
than before.

https://bugzilla.gnome.org/show_bug.cgi?id=699777
2013-05-14 14:46:20 -04:00
c2ecdd0524 prefs: Add support for string-array preferences
As we only had one string-array preference so far, we didn't bother
with adding a generic way to handle string-array preferences, and
just handled the preference in question explicitly. However we are
going to parse another string-array setting, so generalize the
existing code to make it reusable for that case.

https://bugzilla.gnome.org/show_bug.cgi?id=700223
2013-05-13 22:15:13 +02:00
50b9042ac2 window: Add an accessor for whether the window can close
The shell will use this to determine whether to show a close
button in the overview.

https://bugzilla.gnome.org/show_bug.cgi?id=699269
2013-05-09 15:34:37 -04:00
f5e75de330 ui: add missing delimiter in GTK-Doc comment block
g-ir-scanner will emit more warnings regarding broken GTK-Doc
syntax in the near future, which due to --warn-error being used
would break the build:

'''
ui/theme.c:1883: Warning: Meta: missing ":" at column 20:
 * @tokens_p: (out) The resulting tokens
                   ^
g-ir-scanner: compile: gcc -Wall -Wno-deprecated-declarations ...
g-ir-scanner: link: /bin/sh ../libtool --mode=link --tag=CC gcc ...
libtool: link: gcc -o /home/dieterv/gnome.org/checkout/mutter/...
<unknown>:: Fatal: Meta: warnings configured as fatal
<unknown>:: Fatal: Meta: warnings configured as fatal

make[4]: *** [Meta-3.0.gir] Error 1
'''

https://bugzilla.gnome.org/show_bug.cgi?id=699636
2013-05-04 00:23:11 +02:00
1ffe1eae4d Bump version to 3.9.1
Update NEWS.
2013-04-30 23:28:26 +02:00
970a446bd8 window: Add missing chain-up for finalize()
https://bugzilla.gnome.org/show_bug.cgi?id=698710
2013-04-29 14:58:31 +02:00
8880dffbdb background: Fix memory leak
https://bugzilla.gnome.org/show_bug.cgi?id=698710
2013-04-29 14:58:30 +02:00
5b6621811c barrier: Fix memory leak
https://bugzilla.gnome.org/show_bug.cgi?id=698710
2013-04-29 14:58:28 +02:00
c2a9ccb7e2 Let the UI layer (via the core) construct the frame mask
This essentially just moves install_corners() from the compositor, through
the core, into the UI layer where it arguably should have been anyway,
leaving behind stub functions which call through the various layers. This
removes the compositor's special knowledge of how rounded corners work,
replacing it with "ask the UI for an alpha mask".

The computation of border widths and heights changes a bit, because the
width and height used in install_corners() are the
meta_window_get_outer_rect() (which includes the visible borders but not
the invisible ones), whereas the more readily-available rectangle is the
MetaFrame.rect (which includes both). Computing the same width and height
as meta_window_get_outer_rect() involves compensating for the invisible
borders, but the UI layer is the authority on those anyway, so it seems
clearer to have it do the calculations from scratch.

Bug: https://bugzilla.gnome.org/show_bug.cgi?id=697758
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
2013-04-17 13:35:06 +01:00
4608cb6027 Fix use of uninitialized variables
If mutter is going to -Werror by default, then it can play footloose
and fancy free with this sorta stuff.

https://bugzilla.gnome.org/show_bug.cgi?id=698179
2013-04-17 11:58:43 +02:00
ad61676af0 Bump version to 3.8.1
Update NEWS.
2013-04-16 20:38:36 +02:00
c7c1225393 MetaFrames: factor out MetaUIFrame accessors for borders, corner radiuses
This makes it a bit simpler for other functions on a MetaUIFrame to
get this information.

Bug: https://bugzilla.gnome.org/show_bug.cgi?id=697758
Reviewed-by: Jasper St. Pierre <jstpierre@mecheye.net>
Signed-off-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
2013-04-12 17:55:00 +01:00
c7dc6928a9 keybindings: Fix ungrabbing of keys
XUngrabKey() doesn't work for XI2 grabs and XI2 doesn't provide API
with similar functionality. As such, we have to refactor the code a
bit to be able to call XIUngrabKeycode() for each key binding, then
reload keybindings and finally grab the new ones.

https://bugzilla.gnome.org/show_bug.cgi?id=697003
2013-04-10 10:49:24 +02:00
7cfaa6a6a8 Updated Uyghur translation
Signed-off-by: Gheyret Kenji <gheyret@gmail.com>
2013-04-06 18:45:17 +09:00
673a9e2521 Updated Norwegian bokmål translation 2013-04-03 14:11:24 +02:00
9ef4ac00df Updated Hebrew translation. 2013-04-03 08:28:28 +03:00
173 changed files with 28035 additions and 12483 deletions

21
.gitignore vendored
View File

@ -23,7 +23,7 @@ src/50-mutter-navigation.xml
src/50-mutter-system.xml
src/50-mutter-windows.xml
src/mutter-wm.desktop
src/mutter.desktop
src/mutter-wayland.desktop
*.o
*.a
*.lo
@ -46,13 +46,13 @@ POTFILES
po/*.pot
50-metacity-desktop-key.xml
50-metacity-key.xml
inlinepixbufs.h
libmutter.pc
mutter
mutter-theme-viewer
mutter.desktop
libmutter-wayland.pc
mutter-wayland
mutter-launch
org.gnome.mutter.gschema.valid
org.gnome.mutter.gschema.xml
org.gnome.mutter.wayland.gschema.valid
org.gnome.mutter.wayland.gschema.xml
testasyncgetprop
testboxes
testgradient
@ -62,6 +62,7 @@ mutter-message
mutter-window-demo
focus-window
test-attached
test-focus
test-gravity
test-resizing
test-size-hints
@ -74,7 +75,15 @@ src/mutter-enum-types.[ch]
src/stamp-mutter-enum-types.h
src/mutter-marshal.[ch]
src/stamp-mutter-marshal.h
src/meta-dbus-xrandr.[ch]
src/meta-dbus-idle-monitor.[ch]
src/mutter-plugins.pc
src/wayland/gtk-shell-protocol.c
src/wayland/gtk-shell-client-protocol.h
src/wayland/gtk-shell-server-protocol.h
src/wayland/xserver-protocol.c
src/wayland/xserver-client-protocol.h
src/wayland/xserver-server-protocol.h
doc/reference/*.args
doc/reference/*.bak
doc/reference/*.hierarchy

View File

@ -1,5 +1,5 @@
SUBDIRS=src po doc
SUBDIRS=src protocol po doc
EXTRA_DIST = HACKING MAINTAINERS rationales.txt

177
NEWS
View File

@ -1,3 +1,180 @@
3.10.0.1
========
* Fix bug when a window changed size twice in a single frame - this
can happen with GTK+ client-side decorations [Giovanni, Owen; #708367]
Contributors:
Giovanni Campagna, Owen Taylor
3.10.0
======
* Update dependencies [Giovanni; #708210]
3.9.92
======
* Constrain the pointer position onto visible monitors [Giovanni; #706655]
* Fix keyboard state handling in face of event compression [Giovanni; #706963]
* Extend the MetaCursorTracker API with query pointer and cursor visibility [Giovanni; #707474]
* Be stricter in checking and exposing the wayland protocol version [#707851]
* Don't require plugins to pass event to Clutter [Giovanni; #707482]
* Move the --wayland option from the binary to the library [Giovanni; #707897]
* Implement running from gnome-session (environment variable setting, process group
handling, Clutter backend variables) [Giovanni; #706421]
* Add support for more cursor types [Giovanni; #707919]
* Drop man pages for removed utilities [Kalev; #706579]
* Implement monitor configuration on KMS [Giovanni; #706308]
* Implement HW cursors [Giovanni; #707573]
* Implement minimal support for resizing and maximizing wayland clients [Giovanni; #707401]
* Implement transient hints for wayland clients [Giovanni; #707401]
* Implement popup menu surfaces and grabs [Giovanni; #707863]
* Immediately fire idle watches that are already expired [Giovanni; #707302]
* Remove holes generated by disabling the laptop lid [Giovanni; #707473]
* Misc bug fixes [Giovanni, Pavel, Adel; #707649, #706124, #707584, #707851, #707929,
#708070]
Contributors:
Adel Gadllah, Giovanni Campagna, Kalev Lember, Pavel Vasin
Translations:
Мирослав Николић po/sr, sr@latin.po, Мирослав Николић [sr, sr@latin],
Chao-Hsiung Liao [zh_HK, zh_TW], Yuri Myasoedov [ru],
Ville-Pekka Vainio [fi], Changwoo Ryu [ko], A S Alam [pa],
Mattias Põldaru [et], Rūdolfs Mazurs [lv], Ihar Hrachyshka [be],
Nilamdyuti Goswami [as], Andika Triwidada [id], Baurzhan Muftakhidinov [kk],
Benjamin Steinwender [de]
3.9.91
======
* Drop man pages for removed utilities [Kalev; #706579]
* Add support for idle tracking [Giovanni, Cosimo; #706005, #707250]
* Skip CRTC reconfigurations that have no effect [Giovanni; #706672]
* Ignore skip-taskbar hints on parentless dialogs [Giovanni; #673399]
* Don't save pixbuf data in user data [Tim; #706777]
* Don't queue redraws for obscured regions [Adel; #703332]
* Suppor the opaque region hints for wayland clients [Jasper; #707019]
* Turn blending off when drawing entirely opaque regions [Jasper; #707019]
* Check event timestamps before reconfiguring [Giovanni; #706735]
* Merge the DBus API for display configuration in the wayland branch [Giovanni]
* Install an X IO error handler for XWayland [Giovanni; #706962]
* Use the clutter xkbcommon integration for the wayland keyboard [Giovanni; #705862]
* Add a setuid helper for running on KMS+evdev [Giovanni, Colin; #705861]
* Add keybindings for switching VT [Giovanni; #705861]
* Implement plugin modality when running as a wayland compositor [Giovanni; #705917]
* Add support for the application menu for wayland clients [Giovanni; #707128]
* Several Coverity spotted fixes [Jasper]
* Don't create a dummy texture for the texture template [Neil; #707458]
* Use a more conservative paint volume for obscured windows [Adel]
* Misc bug fixes [Giovanni, Colin, Seán, Jasper, Cosimo; #706582, #706598,
#706787, #706729, #706825, #707081, #707090, #707267, #706982, #706289]
Contributors:
Giovanni Campagna, Cosimo Cecchi, Adel Gadllah, Colin Guthrie, Kalev Lember,
Tim Lunn, Jasper St. Pierre, Neil Roberts, Rico Tzschichholz, Seán de Búrca
Translations:
Piotr Drąg [pl], Alexandre Franke [fr], Kjartan Maraas [nb],
Milo Casagrande [it], Balázs Úr [hu], Seán de Búrca [ga], Fran Diéguez [gl],
Daniel Mustieles [es], Aurimas Černius [lt], Gil Forcada [ca]
3.9.90
======
* First release from the wayland branch, includes basic support for running
as a wayland compositor [Robert, Neil, Giovanni]
* Add support for _GTK_FRAME_EXTENTS [Jasper; #705766]
* Fix quick consecutive <super> presses breaking keyboard input [Alban; #666101]
* Work towards running as wayland compositor [Giovanni]
- Add DBus API for display configuration
[#705670, #706231, #706233, #706322, #706382]
- Add abstraction layer for cursor tracking [#705911]
- Add support for plugin modality under wayland [#705917]
* Disable GTK+ scaling [Alexander; #706388]
* Disable blending while updating tower [Robert]
* Misc bug fixes and cleanups [Adel, Jasper, Giovanni, Colin, Rico, Florian;
#703332, #704437, #706207]
Contributors:
Robert Bragg, Giovanni Campagna, Alban Crequy, Adel Gadllah,
Alexander Larsson, Florian Müllner, Jasper St. Pierre, Neil Roberts,
Rico Tzschichholz, Colin Walters
Translations:
Jiro Matsuzawa [ja], Kjartan Maraas [nb], Matej Urbančič [sl],
Marek Černocký [cs], Daniel Mustieles [es], Rafael Ferreira [pt_BR],
Yaron Shahrabani [he], Ján Kyselica [sk]
3.9.5
=====
* Don't select for touch events on the stage [Jasper; #697192]
* Don't queue redraws for obscured regions [Adel; #703332]
* Export timestamp of global keybinding events [Bastien; #704858]
* Misc bug fixes and cleanups [Jasper, Rico; #703970]
Contributors:
Adel Gadllah, Bastien Nocera, Jasper St. Pierre, Rico Tzschichholz
3.9.4
=====
* Tweak window shadows [Allan; #702141]
* Ignore our own focus events for focus prediction [Jasper; #701017]
* Add API to query if the stage is focused [Jasper; #700735]
* Add API to query the monitor for a given position [Adel]
* Don't force attached dialogs to be border-only [Florian; #702764]
* Allow slicing of backgrounds to avoid texture size limits [Ray; #702283]
* Miscellaneous bug fixes and cleanups [Adel; #701224, #702564]
Contributors:
Allan Day, Adel Gadllah, Florian Müllner, Jasper St. Pierre, Ray Strode
3.9.3
=====
* Ensure events are always reported to the grab window [Rui; #701219]
* Use new clutter_stage_set_paint_callback() function to prevent dropping
frames with frame synced toolkits [Owen; #698794]
Contributors:
Rui Matos, Owen W. Taylor
3.9.2
=====
* Add meta_window_can_close() function [Jasper; #699269]
* Add support for string-array preferences [Florian; #700223]
* Fix a potential race condition with _NET_WM_MOVERESIZE [Jasper; #699777]
* Fix shade window action [Stef; #693714]
* Remove overlay_group [Giovanni; #700735]
* Improve tracking of the focus window [Dan, Jasper; #647706]
* Add API to freeze/unfreeze the keyboard [Rui; #697001]
* Grab and emit a signal when XK_ISO_Next_Group is pressed [Rui; #697002]
* Misc bug fixes and cleanups [Dieter, Jasper, Rui; #699636, #700735, #697000]
Contributors:
Giovanni Campagna, Rui Matos, Florian Müllner, Jasper St. Pierre,
Dieter Verfaillie, Stef Walter, Dan Winship
Translations:
Kjartan Maraas [nb], Ján Kyselica [sk]
3.9.1
=====
* Fix miscellaneous memory leaks [Pavel; #698710]
* Misc fixes and cleanups [Stef, Simon; #698179, #697758]
Contributors:
Simon McVittie, Pavel Vasin, Stef Walter
3.8.1
=====
* Fix crash when getting default font [Bastien; #696814]
* Fix ungrabbing of keybindings [Rui; #697003]
* Misc fixes and cleanups [Jasper, Simon; #697758]
Contributors:
Jasper Lievisse Adriaanse, Rui Matos, Simon McVittie, Bastien Nocera
Translations:
Guillaume Desmottes [fr], Shankar Prasad [kn], Bruce Cowan [en_GB],
Andika Triwidada [id], Yaron Shahrabani [he], Kjartan Maraas [nb],
Gheyret Kenji [ug]
3.8.0
=====
* Address major memory leak when changing backgrounds [Ray; #696157]

View File

@ -5,7 +5,7 @@ srcdir=`dirname $0`
test -z "$srcdir" && srcdir=.
PKG_NAME="mutter"
REQUIRED_AUTOMAKE_VERSION=1.10
REQUIRED_AUTOMAKE_VERSION=1.13
(test -f $srcdir/configure.ac \
&& test -d $srcdir/src) || {

View File

@ -1,8 +1,8 @@
AC_PREREQ(2.50)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [8])
m4_define([mutter_micro_version], [0])
m4_define([mutter_minor_version], [10])
m4_define([mutter_micro_version], [0.1])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@ -15,10 +15,14 @@ AC_INIT([mutter], [mutter_version],
AC_CONFIG_SRCDIR(src/core/display.c)
AC_CONFIG_HEADERS(config.h)
AM_INIT_AUTOMAKE([1.11 no-dist-gzip dist-xz tar-ustar])
AM_INIT_AUTOMAKE([1.11 foreign no-dist-gzip dist-xz tar-ustar])
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
AM_MAINTAINER_MODE([enable])
# Change pkglibdir and pkgdatadir to mutter-wayland instead of mutter
PACKAGE="mutter-wayland"
AC_SUBST([PACKAGE], [$PACKAGE])
MUTTER_MAJOR_VERSION=mutter_major_version
MUTTER_MINOR_VERSION=mutter_minor_version
MUTTER_MICRO_VERSION=mutter_micro_version
@ -34,7 +38,7 @@ AC_SUBST(MUTTER_PLUGIN_DIR)
# Honor aclocal flags
AC_SUBST(ACLOCAL_AMFLAGS, "\${ACLOCAL_FLAGS}")
GETTEXT_PACKAGE=mutter
GETTEXT_PACKAGE=mutter-wayland
AC_SUBST(GETTEXT_PACKAGE)
AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE,"$GETTEXT_PACKAGE",[Name of default gettext domain])
@ -73,8 +77,10 @@ MUTTER_PC_MODULES="
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.13.5
$CLUTTER_PACKAGE >= 1.15.94
cogl-1.0 >= 1.13.3
upower-glib > 0.9.11
gnome-desktop-3.0
"
GLIB_GSETTINGS
@ -113,14 +119,32 @@ AC_ARG_ENABLE(shape,
[disable mutter's use of the shaped window extension]),,
enable_shape=auto)
## Wayland support requires the xserver.xml protocol extension found in the weston
## repository but since there aren't currently established conventions for
## installing and discovering these we simply require a location to be given
## explicitly...
AC_ARG_WITH([wayland-protocols],
[AS_HELP_STRING([--with-wayland-protocols], [Location for wayland extension protocol specs])],
[
],
[])
AC_ARG_WITH([xwayland-path],
[AS_HELP_STRING([--with-xwayland-path], [Absolute path for an X Wayland server])],
[XWAYLAND_PATH="$withval"],
[XWAYLAND_PATH="$bindir/Xorg"])
AM_GLIB_GNU_GETTEXT
## here we get the flags we'll actually use
# GRegex requires Glib-2.14.0
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
# gtk_window_set_icon_name requires gtk2+-2.6.0
PKG_CHECK_MODULES(MUTTER_MESSAGE, gtk+-3.0)
PKG_CHECK_MODULES(MUTTER_WINDOW_DEMO, gtk+-3.0)
PKG_CHECK_MODULES(MUTTER_LAUNCH, libdrm libsystemd-login)
saved_LIBS="$LIBS"
LIBS="$LIBS $MUTTER_LAUNCH"
AC_CHECK_FUNCS([sd_session_get_vt])
LIBS="$saved_LIBS"
# Unconditionally use this dir to avoid a circular dep with gnomecc
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
@ -185,20 +209,18 @@ if test x$found_introspection != xno; then
AC_SUBST(META_GIR)
fi
AC_MSG_CHECKING([Xcursor])
if $PKG_CONFIG xcursor; then
have_xcursor=yes
else
have_xcursor=no
fi
AC_MSG_RESULT($have_xcursor)
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor"
if test x$have_xcursor = xyes; then
echo "Building with Xcursor"
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xcursor"
AC_DEFINE(HAVE_XCURSOR, , [Building with Xcursor support])
fi
# We always build with wayland enabled
AC_DEFINE(HAVE_WAYLAND, , [Building with Wayland support])
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
AS_IF([test "x$WAYLAND_SCANNER" = "xno"],
AC_MSG_ERROR([Could not find wayland-scanner in your PATH, required for parsing wayland extension protocols]))
AC_SUBST([WAYLAND_SCANNER])
AC_SUBST(XWAYLAND_PATH)
MUTTER_PC_MODULES="$MUTTER_PC_MODULES clutter-wayland-1.0 clutter-wayland-compositor-1.0 clutter-egl-1.0 wayland-server libdrm"
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
PKG_CHECK_EXISTS([xi >= 1.6.99.1],
@ -307,9 +329,6 @@ if test "x$found_xsync" = "xyes"; then
fi
MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
MUTTER_MESSAGE_LIBS="$MUTTER_MESSAGE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
MUTTER_PROPS_LIBS="$MUTTER_PROPS_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
found_sm=no
case "$MUTTER_LIBS" in
@ -439,11 +458,9 @@ doc/man/Makefile
doc/reference/Makefile
doc/reference/meta-docs.sgml
src/Makefile
src/wm-tester/Makefile
src/libmutter.pc
src/mutter-plugins.pc
src/tools/Makefile
src/libmutter-wayland.pc
src/compositor/plugins/Makefile
protocol/Makefile
po/Makefile.in
])
@ -459,7 +476,7 @@ fi
dnl ==========================================================================
echo "
mutter-$VERSION
mutter-wayland-$VERSION
prefix: ${prefix}
source code location: ${srcdir}

View File

@ -1,4 +1,3 @@
man_MANS = mutter.1 mutter-theme-viewer.1 \
mutter-window-demo.1 mutter-message.1
man_MANS = mutter.1
EXTRA_DIST = $(man_MANS)

View File

@ -1,60 +0,0 @@
.\" Hey, EMACS: -*- nroff -*-
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.\" -----
.\" This file was confirmed to be licenced under the GPL
.\" by its author and copyright holder, Akira TAGOH, on June 1st 2008:
.\"
.\" > I'm comfortable with DFSG-free. that sounds great if you think it's
.\" > useful and worth containing it in upstream.
.\" ...
.\" > Right I know. any licenses that is DFSG-free, I'm ok with whatever,
.\" > since I have contributed that for Debian. so GPL is no problem for me.
.\" -----
.TH MUTTER\-MESSAGE 1 "28 August 2002"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
.\" .nh disable hyphenation
.\" .hy enable hyphenation
.\" .ad l left justify
.\" .ad b justify to both left and right margins
.\" .nf disable filling
.\" .fi enable filling
.\" .br insert line break
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
MUTTER\-MESSAGE \- a command to send a message to Mutter
.SH SYNOPSIS
.B MUTTER\-MESSAGE
[restart|reload\-theme|enable\-keybindings|disable\-keybindings]
.SH DESCRIPTION
This manual page documents briefly the
.B mutter\-message\fP.
This manual page was written for the Debian distribution
because the original program does not have a manual page.
.PP
.\" TeX users may be more comfortable with the \fB<whatever>\fP and
.\" \fI<whatever>\fP escape sequences to invode bold face and italics,
.\" respectively.
\fBmutter\-message\fP send a specified message to \fBmutter\fP(1).
.SH OPTIONS
.TP
.B restart
Restart \fBmutter\fP(1) which is running.
.TP
.B reload-theme
Reload a theme which is specified on gsettings database.
.TP
.B enable-keybindings
Enable all of keybindings which is specified on gsettings database.
.TP
.B disable-keybindings
Disable all of keybindings which is specified on gsettings database.
.SH SEE ALSO
.BR mutter (1)
.SH AUTHOR
This manual page was written by Akira TAGOH <tagoh@debian.org>,
for the Debian GNU/Linux system (but may be used by others).

View File

@ -1,43 +0,0 @@
.\" In .TH, FOO should be all caps, SECTION should be 1-8, maybe w/ subsection
.\" other parms are allowed: see man(7), man(1)
.\"
.\" Based on template provided by Tom Christiansen <tchrist@jhereg.perl.com>.
.\"
.TH MUTTER-THEME-VIEWER 1 "1 June 2004"
.SH NAME
mutter-theme-viewer \- view mutter themes
.SH SYNOPSIS
.B mutter-theme-viewer
[
.I THEMENAME
]
.SH DESCRIPTION
.\" Putting a newline after each sentence can generate better output.
.B mutter-theme-viewer
allows you to preview any installed Mutter theme.
.PP
When designing a new Mutter theme, you can use
.B mutter-theme-viewer
to measure the performance of a window frame option, and to preview
the option.
.SH OPTIONS
.TP
.I THEMENAME
Name of the theme to be shown (\fIAtlanta\fR by default).
It is case-sensitive.
.SH FILES
.br
.nf
.TP
.I /usr/share/themes
system themes directory
.TP
.I /usr/share/themes/*/mutter-1/mutter-theme-1.xml
theme specification file
.SH AUTHOR
This manual page was written by Jose M. Moya <josem@die.upm.es>, for
the Debian GNU/Linux system (but may be used by others).
.SH "SEE ALSO"
.\" Always quote multiple words for .SH
.BR mutter (1),
.BR mutter-window-demo (1).

View File

@ -1,25 +0,0 @@
.\" In .TH, FOO should be all caps, SECTION should be 1-8, maybe w/ subsection
.\" other parms are allowed: see man(7), man(1)
.\"
.\" Based on template provided by Tom Christiansen <tchrist@jhereg.perl.com>.
.\"
.TH MUTTER-WINDOW-DEMO 1 "1 June 2004"
.SH NAME
mutter-window-demo \- demo of window features
.SH SYNOPSIS
.B mutter-window-demo
.SH DESCRIPTION
.\" Putting a newline after each sentence can generate better output.
This program demonstrates various kinds of windows that window
managers and window manager themes should handle.
.PP
Be sure to tear off the menu and toolbar, those are also a special
kind of window.
.SH AUTHOR
This manual page was written by Jose M. Moya <josem@die.upm.es>, for
the Debian GNU/Linux system (but may be used by others).
.SH "SEE ALSO"
.\" Always quote multiple words for .SH
.BR x-window-manager (1),
.BR mutter (1),
.BR mutter-theme-viewer (1).

View File

@ -140,7 +140,7 @@ expand_content_files= \
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
GTKDOC_CFLAGS=$(MUTTER_CFLAGS)
GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter.la
GTKDOC_LIBS=$(MUTTER_LIBS) $(top_builddir)/src/libmutter-wayland.la
# This includes the standard gtk-doc make rules, copied by gtkdocize.
include $(top_srcdir)/gtk-doc.make

View File

@ -409,7 +409,6 @@ meta_prefs_get_theme
meta_prefs_get_titlebar_font
meta_prefs_get_num_workspaces
meta_prefs_get_dynamic_workspaces
meta_prefs_get_application_based
meta_prefs_get_disable_workarounds
meta_prefs_get_auto_raise
meta_prefs_get_auto_raise_delay

View File

@ -44,6 +44,7 @@ is
it
ja
ka
kk
kn
ko
ku

View File

@ -12,6 +12,7 @@ src/core/display.c
src/core/errors.c
src/core/keybindings.c
src/core/main.c
src/core/monitor.c
src/core/mutter.c
src/core/prefs.c
src/core/screen.c
@ -20,15 +21,12 @@ src/core/util.c
src/core/window.c
src/core/window-props.c
src/core/xprops.c
src/mutter.desktop.in
src/mutter-wm.desktop.in
src/mutter-wayland.desktop.in
src/org.gnome.mutter.gschema.xml.in
src/tools/mutter-message.c
src/org.gnome.mutter.wayland.gschema.xml.in
src/ui/frames.c
src/ui/menu.c
src/ui/metaaccellabel.c
src/ui/resizepopup.c
src/ui/theme.c
src/ui/theme-parser.c
src/ui/theme-viewer.c

499
po/as.po

File diff suppressed because it is too large Load Diff

441
po/be.po
View File

@ -1,10 +1,10 @@
# Ihar Hrachyshka <ihar.hrachyshka@gmail.com>, 2011.
# Ihar Hrachyshka <ihar.hrachyshka@gmail.com>, 2011, 2013.
msgid ""
msgstr ""
"Project-Id-Version: mutter.master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-03-01 15:50+0000\n"
"POT-Creation-Date: 2013-08-18 20:03+0000\n"
"PO-Revision-Date: 2012-10-13 17:44+0300\n"
"Last-Translator: Ігар Грачышка <ihar.hrachyshka@gmail.com>\n"
"Language-Team: Belarusian <i18n-bel-gnome@googlegroups.com>\n"
@ -206,7 +206,7 @@ msgstr "Падзяліць прагляд справа"
#. 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:507
#: ../src/compositor/compositor.c:589
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
@ -214,11 +214,11 @@ msgid ""
msgstr ""
"Іншы кампазітны кіраўнік вокнаў ужо абслугоўвае экран %i дысплея \"%s\"."
#: ../src/compositor/meta-background.c:1111
#: ../src/compositor/meta-background.c:1076
msgid "background texture could not be created from file"
msgstr "не ўдалося стварыць фонавую тэкстуру з файла"
#: ../src/core/bell.c:320
#: ../src/core/bell.c:322
msgid "Bell event"
msgstr "Падзея з сігналам"
@ -251,18 +251,18 @@ msgstr "_Пачакаць"
msgid "_Force Quit"
msgstr "_Змусіць да выхаду"
#: ../src/core/display.c:401
#: ../src/core/display.c:421
#, c-format
msgid "Missing %s extension required for compositing"
msgstr ""
"Адсутнічае пашырэнне \"%s\", патрэбнае для ажыццяўлення кампазітнага вываду"
#: ../src/core/display.c:493
#: ../src/core/display.c:513
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Не ўдалося адкрыць X-дысплей аконнай сістэмы \"%s\"\n"
#: ../src/core/keybindings.c:929
#: ../src/core/keybindings.c:1136
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -271,41 +271,41 @@ msgstr ""
"Нейкая іншая праграма ўжо выкарыстоўвае як скарот клавішу %s з "
"мадыфікатарамі %x\n"
#: ../src/core/keybindings.c:1129
#: ../src/core/keybindings.c:1333
#, c-format
msgid "\"%s\" is not a valid accelerator\n"
msgstr "\"%s\" - гэта хібны клавіятурны скарот\n"
#: ../src/core/main.c:196
#: ../src/core/main.c:197
msgid "Disable connection to session manager"
msgstr "Выключыць злучэнне з кіраўніком сеансаў"
#: ../src/core/main.c:202
#: ../src/core/main.c:203
msgid "Replace the running window manager"
msgstr "Замяніць дзейнага кіраўніка вокнаў"
#: ../src/core/main.c:208
#: ../src/core/main.c:209
msgid "Specify session management ID"
msgstr "Вызначыць ідэнтыфікатар для кіравання сеансам"
#: ../src/core/main.c:213
#: ../src/core/main.c:214
msgid "X Display to use"
msgstr "Патрэбны X-дысплей"
#: ../src/core/main.c:219
#: ../src/core/main.c:220
msgid "Initialize session from savefile"
msgstr "Ініцыяваць сеанс з файла"
#: ../src/core/main.c:225
#: ../src/core/main.c:226
msgid "Make X calls synchronous"
msgstr "Сінхронна выконваць выклікі X-сістэмы"
#: ../src/core/main.c:494
#: ../src/core/main.c:534
#, c-format
msgid "Failed to scan themes directory: %s\n"
msgstr "Не ўдалося праглядзець каталог з матывамі аздаблення: %s\n"
#: ../src/core/main.c:510
#: ../src/core/main.c:550
#, c-format
msgid ""
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
@ -313,6 +313,19 @@ msgstr ""
"Не ўдалося адшукаць матыў аздаблення! Праверце, каб каталог %s існаваў і "
"змяшчаў звычайныя матывы.\n"
#: ../src/core/monitor.c:711
msgid "Built-in display"
msgstr "Убудаваны дысплей"
#. TRANSLATORS: this is a monitor name (in case we don't know
#. the vendor), it's Unknown followed by a size in inches,
#. like 'Unknown 15"'
#.
#: ../src/core/monitor.c:739
#, c-format
msgid "Unknown %s"
msgstr "Невядомы %s"
#: ../src/core/mutter.c:40
#, c-format
msgid ""
@ -337,7 +350,7 @@ msgstr "Вывесці нумар версіі праграмы"
msgid "Mutter plugin to use"
msgstr "Патрэбны плугін Mutter"
#: ../src/core/prefs.c:1087
#: ../src/core/prefs.c:1202
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -345,12 +358,12 @@ msgstr ""
"Асаблівыя паводзіны для некаторых хібных праграм выключаныя. Некаторыя "
"праграмы могуць перастаць працаваць, як мае быць.\n"
#: ../src/core/prefs.c:1162
#: ../src/core/prefs.c:1277
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Не ўдалося разабраць азначэнне шрыфту \"%s\" з GSettings-ключа %s\n"
#: ../src/core/prefs.c:1228
#: ../src/core/prefs.c:1343
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -359,7 +372,7 @@ msgstr ""
"Значэнне \"%s\", знойдзенае ў базе канфігурацыйных даных, не азначае "
"мадыфікатар мышынай кнопкі\n"
#: ../src/core/prefs.c:1780
#: ../src/core/prefs.c:1909
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@ -368,17 +381,17 @@ msgstr ""
"Значэнне \"%s\", знойдзенае ў базе канфігурацыйных даных, не азначае "
"клавіятурны скарот \"%s\"\n"
#: ../src/core/prefs.c:1879
#: ../src/core/prefs.c:1999
#, c-format
msgid "Workspace %d"
msgstr "Прастора працы %d"
#: ../src/core/screen.c:673
#: ../src/core/screen.c:534
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Экран %d на дысплеі \"%s\" хібны\n"
#: ../src/core/screen.c:689
#: ../src/core/screen.c:550
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@ -387,19 +400,19 @@ msgstr ""
"Экран %d на дысплеі \"%s\" ужо мае аконнага кіраўніка. Каб замяніць яго "
"новым, дадайце опцыю --replace.\n"
#: ../src/core/screen.c:716
#: ../src/core/screen.c:577
#, c-format
msgid ""
"Could not acquire window manager selection on screen %d display \"%s\"\n"
msgstr ""
"Не ўдалося пераняць вылучэнне кіраўніка вокнаў для экрана %d дысплея \"%s\"\n"
#: ../src/core/screen.c:794
#: ../src/core/screen.c:655
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "Экран %d на дысплеі \"%s\" ужо мае кіраўніка вокнаў\n"
#: ../src/core/screen.c:979
#: ../src/core/screen.c:846
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Не ўдалося вызваліць экран %d на дысплеі \"%s\"\n"
@ -460,46 +473,45 @@ msgstr ""
"Гэтыя вокны не падтрымліваюць функцыі захавання дзейнага ладу працы, і таму "
"іх прыйдзецца запусціць уручную пасля наступнага ўваходу ў сістэму."
#: ../src/core/util.c:80
#: ../src/core/util.c:84
#, c-format
msgid "Failed to open debug log: %s\n"
msgstr "Не ўдалося адкрыць адладачны журнал: %s\n"
#: ../src/core/util.c:90
#: ../src/core/util.c:94
#, c-format
msgid "Failed to fdopen() log file %s: %s\n"
msgstr "Не ўдалося выканаць fdopen() для журнальнага файла %s: %s\n"
#: ../src/core/util.c:96
#: ../src/core/util.c:100
#, c-format
msgid "Opened log file %s\n"
msgstr "Журнальны файл %s адкрыты\n"
#: ../src/core/util.c:115 ../src/tools/mutter-message.c:149
#, c-format
#: ../src/core/util.c:119
msgid "Mutter was compiled without support for verbose mode\n"
msgstr ""
"Праграма \"Mutter\" была скампіляваная без падтрымкі падрабязнага "
"пратакаліравання\n"
#: ../src/core/util.c:259
#: ../src/core/util.c:264
msgid "Window manager: "
msgstr "Кіраўнік вокнаў: "
#: ../src/core/util.c:407
#: ../src/core/util.c:414
msgid "Bug in window manager: "
msgstr "Хіба ў кіраўніку вокнаў: "
#: ../src/core/util.c:438
#: ../src/core/util.c:445
msgid "Window manager warning: "
msgstr "Перасцярога ад кіраўніка вокнаў: "
#: ../src/core/util.c:466
#: ../src/core/util.c:473
msgid "Window manager error: "
msgstr "Памылка кіраўніка вокнаў: "
#. first time through
#: ../src/core/window.c:7539
#: ../src/core/window.c:7533
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -515,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:8263
#: ../src/core/window.c:8257
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -525,22 +537,22 @@ msgstr ""
"памеру, але разам з гэтым прызначыла для сябе мінімальны памер %d x %d і "
"максімальны памер %d x %d. Такія паводзіны не маюць сэнсу.\n"
#: ../src/core/window-props.c:318
#: ../src/core/window-props.c:347
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "Праграма прызначыла памылковае значэнне _NET_WM_PID %lu\n"
#: ../src/core/window-props.c:434
#: ../src/core/window-props.c:463
#, c-format
msgid "%s (on %s)"
msgstr "%s (на %s)"
#: ../src/core/window-props.c:1517
#: ../src/core/window-props.c:1546
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "Для %2$s вызначана хібнае акно WM_TRANSIENT_FOR 0x%1$lx.\n"
#: ../src/core/window-props.c:1528
#: ../src/core/window-props.c:1557
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "WM_TRANSIENT_FOR акно 0x%lx для %s стварыла б цыкл.\n"
@ -689,7 +701,8 @@ msgstr ""
#: ../src/org.gnome.mutter.gschema.xml.in.h:17
msgid "Auto maximize nearly monitor sized windows"
msgstr "Аўтаматычна максімалізаваць вокны, якія расцягнутыя амаль на ўвесь экран"
msgstr ""
"Аўтаматычна максімалізаваць вокны, якія расцягнутыя амаль на ўвесь экран"
#: ../src/org.gnome.mutter.gschema.xml.in.h:18
msgid ""
@ -707,109 +720,104 @@ msgstr "Выбраць акно з выплыўнога акенца"
msgid "Cancel tab popup"
msgstr "Закрыць выплыўное акенца"
#: ../src/tools/mutter-message.c:123
#, c-format
msgid "Usage: %s\n"
msgstr "Правілы выкарыстання: %s\n"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:69
#: ../src/ui/menu.c:67
msgid "Mi_nimize"
msgstr "_Мінімалізаваць"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:71
#: ../src/ui/menu.c:69
msgid "Ma_ximize"
msgstr "Масімалізаваць"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:73
#: ../src/ui/menu.c:71
msgid "Unma_ximize"
msgstr "Скасаваць масімалізацыю"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:75
#: ../src/ui/menu.c:73
msgid "Roll _Up"
msgstr "_Скруціць акно ў загаловак"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:77
#: ../src/ui/menu.c:75
msgid "_Unroll"
msgstr "Расруціць акно з загалоўка"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:79
#: ../src/ui/menu.c:77
msgid "_Move"
msgstr "_Перамясціць акно"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:81
#: ../src/ui/menu.c:79
msgid "_Resize"
msgstr "_Змяніць памер акна"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:83
#: ../src/ui/menu.c:81
msgid "Move Titlebar On_screen"
msgstr "Перамясціць загаловак акна па _экране"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
msgid "Always on _Top"
msgstr "Заўсёды _наверсе"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:90
#: ../src/ui/menu.c:88
msgid "_Always on Visible Workspace"
msgstr "Заўсёды на _бачнай прасторы працы"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:92
#: ../src/ui/menu.c:90
msgid "_Only on This Workspace"
msgstr "_Толькі на гэтай прасторы працы"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:94
#: ../src/ui/menu.c:92
msgid "Move to Workspace _Left"
msgstr "Перамясціць на прастору працы з_лева"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:96
#: ../src/ui/menu.c:94
msgid "Move to Workspace R_ight"
msgstr "Перамясціць на прастору працы с_права"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:98
#: ../src/ui/menu.c:96
msgid "Move to Workspace _Up"
msgstr "Перамясціць на прастору працы з_верху"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:100
#: ../src/ui/menu.c:98
msgid "Move to Workspace _Down"
msgstr "Перамясціць на прастору працы з_нізу"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:104
#: ../src/ui/menu.c:102
msgid "_Close"
msgstr "_Закрыць акно"
#: ../src/ui/menu.c:204
#: ../src/ui/menu.c:202
#, c-format
msgid "Workspace %d%n"
msgstr "Прастора працы %d%n"
#: ../src/ui/menu.c:214
#: ../src/ui/menu.c:212
#, c-format
msgid "Workspace 1_0"
msgstr "Прастора працы 1_0"
#: ../src/ui/menu.c:216
#: ../src/ui/menu.c:214
#, c-format
msgid "Workspace %s%d"
msgstr "Прастора працы %s%d"
#: ../src/ui/menu.c:397
#: ../src/ui/menu.c:384
msgid "Move to Another _Workspace"
msgstr "П_ерамясціць на іншую прастору працы"
@ -911,49 +919,49 @@ msgstr "Mod5"
msgid "%d x %d"
msgstr "%d x %d"
#: ../src/ui/theme.c:235
#: ../src/ui/theme.c:236
msgid "top"
msgstr "верхнюю"
#: ../src/ui/theme.c:237
#: ../src/ui/theme.c:238
msgid "bottom"
msgstr "ніжнюю"
#: ../src/ui/theme.c:239
#: ../src/ui/theme.c:240
msgid "left"
msgstr "левую"
#: ../src/ui/theme.c:241
#: ../src/ui/theme.c:242
msgid "right"
msgstr "правую"
#: ../src/ui/theme.c:269
#: ../src/ui/theme.c:270
#, c-format
msgid "frame geometry does not specify \"%s\" dimension"
msgstr "апісанне геаметрыі рамкі акна не вызначае %s граніцу"
#: ../src/ui/theme.c:288
#: ../src/ui/theme.c:289
#, c-format
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
msgstr ""
"апісанне геаметрыі рамкі акна не вызначае %s граніцу для аблямоўкі \"%s\""
#: ../src/ui/theme.c:325
#: ../src/ui/theme.c:326
#, c-format
msgid "Button aspect ratio %g is not reasonable"
msgstr "Прапорцыі кнопкі %g не маюць сэнсу"
#: ../src/ui/theme.c:337
#: ../src/ui/theme.c:338
#, c-format
msgid "Frame geometry does not specify size of buttons"
msgstr "Апісанне геаметрыі рамкі акна не вызначае памер кнопак"
#: ../src/ui/theme.c:1050
#: ../src/ui/theme.c:1051
#, c-format
msgid "Gradients should have at least two colors"
msgstr "Градыент мусіць мець прынамсі два колеры"
#: ../src/ui/theme.c:1202
#: ../src/ui/theme.c:1203
#, c-format
msgid ""
"GTK custom color specification must have color name and fallback in "
@ -962,7 +970,7 @@ msgstr ""
"Уласная спецыфікацыя колеру GTK мусіць змяшчаць назвы асноўнага і запаснога "
"колераў у дужках, напрыклад, gtk:custom(foo,bar). Не ўдалося разабраць \"%s\""
#: ../src/ui/theme.c:1218
#: ../src/ui/theme.c:1219
#, c-format
msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
@ -971,7 +979,7 @@ msgstr ""
"Хібны знак \"%c\" у параметры color_name спецыфікацыі gtk:custom, дазволеныя "
"толькі A-Za-z0-9-_"
#: ../src/ui/theme.c:1232
#: ../src/ui/theme.c:1233
#, c-format
msgid ""
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
@ -980,7 +988,7 @@ msgstr ""
"Фармат gtk:custom: \"gtk:custom(назваолеруапасны_колер)\"; \"%s\" не "
"адпавядае фармату"
#: ../src/ui/theme.c:1277
#: ../src/ui/theme.c:1278
#, c-format
msgid ""
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
@ -989,7 +997,7 @@ msgstr ""
"Спецыфікацыя колеру GTK мусіць мець стан у квадратных дужках, напрыклад, gtk:"
"fg[NORMAL], дзе NORMAL - гэта стан. Не ўдалося разабраць \"%s\""
#: ../src/ui/theme.c:1291
#: ../src/ui/theme.c:1292
#, c-format
msgid ""
"GTK color specification must have a close bracket after the state, e.g. gtk:"
@ -999,17 +1007,17 @@ msgstr ""
"напрыклад, gtk:fg[NORMAL], дзе NORMAL - гэта стан. Не ўдалося разабраць \"%s"
"\""
#: ../src/ui/theme.c:1302
#: ../src/ui/theme.c:1303
#, c-format
msgid "Did not understand state \"%s\" in color specification"
msgstr "Незразумелы стан \"%s\" у спецыфікацыі колеру"
#: ../src/ui/theme.c:1315
#: ../src/ui/theme.c:1316
#, c-format
msgid "Did not understand color component \"%s\" in color specification"
msgstr "Незразумелы складнік колеру \"%s\" у спецыфікацыі колеру"
#: ../src/ui/theme.c:1344
#: ../src/ui/theme.c:1345
#, c-format
msgid ""
"Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the "
@ -1018,58 +1026,58 @@ msgstr ""
"Фармат змяшанага колеру - \"blend/bg_color/fg_color/alpha\". \"%s\" не "
"адпавядае фармату."
#: ../src/ui/theme.c:1355
#: ../src/ui/theme.c:1356
#, c-format
msgid "Could not parse alpha value \"%s\" in blended color"
msgstr "Не ўдалося разабраць значэнне альфа \"%s\" ў змяшаным колеры"
#: ../src/ui/theme.c:1365
#: ../src/ui/theme.c:1366
#, c-format
msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
msgstr ""
"Значэнне альфа \"%s\" у змяшаным колеры не ўваходзіць у дыяпазон ад 0.0 да "
"1.0"
#: ../src/ui/theme.c:1412
#: ../src/ui/theme.c:1413
#, c-format
msgid ""
"Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
msgstr ""
"Фармат ценю - \"shade/base_color/factor\". \"%s\" не адпавядае фармату."
#: ../src/ui/theme.c:1423
#: ../src/ui/theme.c:1424
#, c-format
msgid "Could not parse shade factor \"%s\" in shaded color"
msgstr "Не ўдалося разабраць каэфіцыент ценю \"%s\" у зацененым колеры"
#: ../src/ui/theme.c:1433
#: ../src/ui/theme.c:1434
#, c-format
msgid "Shade factor \"%s\" in shaded color is negative"
msgstr "Каэфіцыент ценю \"%s\" у зацененым колеры адмоўны"
#: ../src/ui/theme.c:1462
#: ../src/ui/theme.c:1463
#, c-format
msgid "Could not parse color \"%s\""
msgstr "Не ўдалося разабраць колер \"%s\""
#: ../src/ui/theme.c:1779
#: ../src/ui/theme.c:1780
#, c-format
msgid "Coordinate expression contains character '%s' which is not allowed"
msgstr "Каардынатны выраз змяшчае забаронены знак \"%s\""
#: ../src/ui/theme.c:1806
#: ../src/ui/theme.c:1807
#, c-format
msgid ""
"Coordinate expression contains floating point number '%s' which could not be "
"parsed"
msgstr "Каардынатны выраз змяшчае незразумелы лік з нефіксаванай коскай \"%s\""
#: ../src/ui/theme.c:1820
#: ../src/ui/theme.c:1821
#, c-format
msgid "Coordinate expression contains integer '%s' which could not be parsed"
msgstr "Каардынатны выраз змяшчае незразумелы цэлы лік \"%s\""
#: ../src/ui/theme.c:1941
#: ../src/ui/theme.c:1942
#, c-format
msgid ""
"Coordinate expression contained unknown operator at the start of this text: "
@ -1077,17 +1085,17 @@ msgid ""
msgstr ""
"Каардынатны выраз змяшчае невядомы аператар у пачатку гэтага тэксту: \"%s\""
#: ../src/ui/theme.c:1998
#: ../src/ui/theme.c:1999
#, c-format
msgid "Coordinate expression was empty or not understood"
msgstr "Каардынатны выраз пусты ці незразумелы"
#: ../src/ui/theme.c:2111 ../src/ui/theme.c:2121 ../src/ui/theme.c:2155
#: ../src/ui/theme.c:2112 ../src/ui/theme.c:2122 ../src/ui/theme.c:2156
#, c-format
msgid "Coordinate expression results in division by zero"
msgstr "Каардынатны выраз вымагае дзялення на нуль"
#: ../src/ui/theme.c:2163
#: ../src/ui/theme.c:2164
#, c-format
msgid ""
"Coordinate expression tries to use mod operator on a floating-point number"
@ -1095,24 +1103,24 @@ msgstr ""
"Каардынатны выраз спрабуе ўжыць аператар дзялення па модулі для ліку з "
"нефіксаванай коскай"
#: ../src/ui/theme.c:2219
#: ../src/ui/theme.c:2220
#, c-format
msgid ""
"Coordinate expression has an operator \"%s\" where an operand was expected"
msgstr ""
"У каардынатным выразе ўжыты аператар \"%s\" там, дзе мусіў быць аперанд"
#: ../src/ui/theme.c:2228
#: ../src/ui/theme.c:2229
#, c-format
msgid "Coordinate expression had an operand where an operator was expected"
msgstr "У каардынатным выразе ўжыты аперанд там, дзе мусіў быць аператар"
#: ../src/ui/theme.c:2236
#: ../src/ui/theme.c:2237
#, c-format
msgid "Coordinate expression ended with an operator instead of an operand"
msgstr "Каардынатны выраз заканчваецца аператарам, а не аперандам"
#: ../src/ui/theme.c:2246
#: ../src/ui/theme.c:2247
#, c-format
msgid ""
"Coordinate expression has operator \"%c\" following operator \"%c\" with no "
@ -1121,41 +1129,41 @@ msgstr ""
"У каардынатным выразе за аператарам \"%c\" ідзе аператар \"%c\", але паміж "
"імі няма аперанда"
#: ../src/ui/theme.c:2397 ../src/ui/theme.c:2442
#: ../src/ui/theme.c:2398 ../src/ui/theme.c:2443
#, c-format
msgid "Coordinate expression had unknown variable or constant \"%s\""
msgstr "У каардынатным выразе невядомая зменная альбо канстанта \"%s\""
#: ../src/ui/theme.c:2496
#: ../src/ui/theme.c:2497
#, c-format
msgid "Coordinate expression parser overflowed its buffer."
msgstr "Прылада для разбору каардынатных выразаў перапоўніла свой буфер."
#: ../src/ui/theme.c:2525
#: ../src/ui/theme.c:2526
#, c-format
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
msgstr ""
"У каардынатным выразе ўжытыя дужкі, якія закрываюцца, але няма тых, якія б "
"адкрываліся"
#: ../src/ui/theme.c:2589
#: ../src/ui/theme.c:2590
#, c-format
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
msgstr ""
"У каардынатным выразе ўжытыя дужкі, якія адкрываюцца, але няма тых, якія б "
"закрываліся"
#: ../src/ui/theme.c:2600
#: ../src/ui/theme.c:2601
#, c-format
msgid "Coordinate expression doesn't seem to have any operators or operands"
msgstr "У каардынатным выразе няма ні аператараў, ні аперандаў"
#: ../src/ui/theme.c:2813 ../src/ui/theme.c:2833 ../src/ui/theme.c:2853
#: ../src/ui/theme.c:2814 ../src/ui/theme.c:2834 ../src/ui/theme.c:2854
#, c-format
msgid "Theme contained an expression that resulted in an error: %s\n"
msgstr "Матыў аздаблення змяшчае выраз, які стаў прычынай памылкі: %s\n"
#: ../src/ui/theme.c:4499
#: ../src/ui/theme.c:4500
#, c-format
msgid ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
@ -1164,25 +1172,25 @@ msgstr ""
"Для гэтага стылю рамкі трэба вызначыць <button function=\"%s\" state=\"%s\" "
"draw_ops=\"whatever\"/>"
#: ../src/ui/theme.c:5010 ../src/ui/theme.c:5035
#: ../src/ui/theme.c:5011 ../src/ui/theme.c:5036
#, c-format
msgid ""
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
msgstr ""
"Няма <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"што-небудзь\"/>"
#: ../src/ui/theme.c:5083
#: ../src/ui/theme.c:5082
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Не ўдалося загрузіць матыў аздаблення \"%s\": %s\n"
#: ../src/ui/theme.c:5219 ../src/ui/theme.c:5226 ../src/ui/theme.c:5233
#: ../src/ui/theme.c:5240 ../src/ui/theme.c:5247
#: ../src/ui/theme.c:5218 ../src/ui/theme.c:5225 ../src/ui/theme.c:5232
#: ../src/ui/theme.c:5239 ../src/ui/theme.c:5246
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "Для матыву аздаблення \"%2$s\" не прызначана <%1$s>"
#: ../src/ui/theme.c:5255
#: ../src/ui/theme.c:5254
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@ -1191,7 +1199,7 @@ msgstr ""
"Стыль рамкі не вызначаны для вокнаў тыпу \"%s\" для матыву аздаблення \"%s"
"\". Дадайце <window type=\"%s\" style_set=\"штосьці\"/>."
#: ../src/ui/theme.c:5662 ../src/ui/theme.c:5724 ../src/ui/theme.c:5787
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
#, c-format
msgid ""
"User-defined constants must begin with a capital letter; \"%s\" does not"
@ -1199,7 +1207,7 @@ msgstr ""
"Назвы канстантаў, вызначаных карыстальнікам, мусяць пачынацца з вялікай "
"літары. \"%s\" не адпавядае гэтаму патрабаванню."
#: ../src/ui/theme.c:5670 ../src/ui/theme.c:5732 ../src/ui/theme.c:5795
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "Канстанта \"%s\" ужо азначана"
@ -1585,207 +1593,8 @@ msgstr "Выкарыстанне тэксту ўнутры элемента <%s>
msgid "<%s> specified twice for this theme"
msgstr "<%s> двойчы вызначаны для гэтага матыву аздаблення"
#: ../src/ui/theme-parser.c:4334
#: ../src/ui/theme-parser.c:4336
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "Памылка пошуку правільнага файла для матыву аздаблення %s\n"
#: ../src/ui/theme-viewer.c:99
msgid "_Windows"
msgstr "_Вокны"
#: ../src/ui/theme-viewer.c:100
msgid "_Dialog"
msgstr "_Дыялогавае акенца"
#: ../src/ui/theme-viewer.c:101
msgid "_Modal dialog"
msgstr "_Мадальнае дыялогавае акенца"
#: ../src/ui/theme-viewer.c:102
msgid "_Utility"
msgstr "_Дапаможная праграма"
#: ../src/ui/theme-viewer.c:103
msgid "_Splashscreen"
msgstr "_Экранная застаўка"
#: ../src/ui/theme-viewer.c:104
msgid "_Top dock"
msgstr "_Верхняя ўбудова"
#: ../src/ui/theme-viewer.c:105
msgid "_Bottom dock"
msgstr "_Ніжняя ўбудова"
#: ../src/ui/theme-viewer.c:106
msgid "_Left dock"
msgstr "_Левая ўбудова"
#: ../src/ui/theme-viewer.c:107
msgid "_Right dock"
msgstr "_Правая ўбудова"
#: ../src/ui/theme-viewer.c:108
msgid "_All docks"
msgstr "_Усе ўбудовы"
#: ../src/ui/theme-viewer.c:109
msgid "Des_ktop"
msgstr "_Стол"
#: ../src/ui/theme-viewer.c:115
msgid "Open another one of these windows"
msgstr "Адкрыць чарговае з гэтых вокнаў"
#: ../src/ui/theme-viewer.c:117
msgid "This is a demo button with an 'open' icon"
msgstr "Гэта дэманстрацыйная кнопка са значком \"Адкрыць\""
#: ../src/ui/theme-viewer.c:119
msgid "This is a demo button with a 'quit' icon"
msgstr "Гэта дэманстрацыйная кнопка са значком \"Выйсці\""
#: ../src/ui/theme-viewer.c:248
msgid "This is a sample message in a sample dialog"
msgstr "Гэта ўзорнае паведамленне ва ўзорным дыялогавым акенцы"
#: ../src/ui/theme-viewer.c:328
#, c-format
msgid "Fake menu item %d\n"
msgstr "Несапраўдны пункт меню %d\n"
#: ../src/ui/theme-viewer.c:363
msgid "Border-only window"
msgstr "Акно толькі з аблямоўкай"
#: ../src/ui/theme-viewer.c:365
msgid "Bar"
msgstr "Стужка"
#: ../src/ui/theme-viewer.c:382
msgid "Normal Application Window"
msgstr "Звычайнае акно праграмы"
#: ../src/ui/theme-viewer.c:386
msgid "Dialog Box"
msgstr "Дыялогавае акенца"
#: ../src/ui/theme-viewer.c:390
msgid "Modal Dialog Box"
msgstr "Мадальнае дыялогавае акенца"
#: ../src/ui/theme-viewer.c:394
msgid "Utility Palette"
msgstr "Дапаможная палітра"
#: ../src/ui/theme-viewer.c:398
msgid "Torn-off Menu"
msgstr "Адчэпленае меню"
#: ../src/ui/theme-viewer.c:402
msgid "Border"
msgstr "Аблямоўка"
#: ../src/ui/theme-viewer.c:406
msgid "Attached Modal Dialog"
msgstr "Прычапленае мадальнае дыялогавае акенца"
#: ../src/ui/theme-viewer.c:737
#, c-format
msgid "Button layout test %d"
msgstr "Выпрабаванне размяшчэння кнопак %d"
#: ../src/ui/theme-viewer.c:766
#, c-format
msgid "%g milliseconds to draw one window frame"
msgstr "%g мілісекунд, каб намаляваць адну рамку акна"
#: ../src/ui/theme-viewer.c:811
#, c-format
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
msgstr "Правілы карыстання: metacity-theme-viewer [НАЗВА_МАТЫВУ]\n"
#: ../src/ui/theme-viewer.c:818
#, c-format
msgid "Error loading theme: %s\n"
msgstr "Памылка загрузкі матыву аздаблення: %s\n"
#: ../src/ui/theme-viewer.c:824
#, c-format
msgid "Loaded theme \"%s\" in %g seconds\n"
msgstr "Матыў аздаблення \"%s\" загружаны за %g секунд\n"
#: ../src/ui/theme-viewer.c:869
msgid "Normal Title Font"
msgstr "Звычайны шрыфт загалоўка"
#: ../src/ui/theme-viewer.c:875
msgid "Small Title Font"
msgstr "Маленькі шрыфт загалоўка"
#: ../src/ui/theme-viewer.c:881
msgid "Large Title Font"
msgstr "Вялікі шрыфт загалоўка"
#: ../src/ui/theme-viewer.c:886
msgid "Button Layouts"
msgstr "Размяшчэнне кнопак"
#: ../src/ui/theme-viewer.c:891
msgid "Benchmark"
msgstr "Выпрабаванне"
#: ../src/ui/theme-viewer.c:947
msgid "Window Title Goes Here"
msgstr "Месца для загалоўка акна"
#: ../src/ui/theme-viewer.c:1053
#, c-format
msgid ""
"Drew %d frames in %g client-side seconds (%g milliseconds per frame) and %g "
"seconds wall clock time including X server resources (%g milliseconds per "
"frame)\n"
msgstr ""
"Намалявана %d рамак цягам %g секунд кліенцкага часу (%g мілісекунд на рамку) "
"і %g секунд каляндарнага часу, уключна з рэсурсамі X-сервера (%g мілісекунд "
"на рамку)\n"
#: ../src/ui/theme-viewer.c:1273
msgid "position expression test returned TRUE but set error"
msgstr "выпрабаванне выразу пазіцыі вярнула TRUE, але паведаміла аб памылцы"
#: ../src/ui/theme-viewer.c:1275
msgid "position expression test returned FALSE but didn't set error"
msgstr ""
"выпрабаванне выразу пазіцыі вярнула FALSE, але не паведаміла аб памылцы"
#: ../src/ui/theme-viewer.c:1279
msgid "Error was expected but none given"
msgstr "Чакалася памылка, але звесткі не атрыманыя"
#: ../src/ui/theme-viewer.c:1281
#, c-format
msgid "Error %d was expected but %d given"
msgstr "Чакалася памылка %d, але атрымана %d"
#: ../src/ui/theme-viewer.c:1287
#, c-format
msgid "Error not expected but one was returned: %s"
msgstr "Атрымана нечаканая памылка: %s"
#: ../src/ui/theme-viewer.c:1291
#, c-format
msgid "x value was %d, %d was expected"
msgstr "X-значэнне было %d, а чакалася %d"
#: ../src/ui/theme-viewer.c:1294
#, c-format
msgid "y value was %d, %d was expected"
msgstr "Y-значэнне было %d, а чакалася %d"
#: ../src/ui/theme-viewer.c:1359
#, c-format
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
msgstr ""
"%d каардынатных выразаў разабраныя за %g секунд (у сярэднім %g секунд)\n"

610
po/de.po

File diff suppressed because it is too large Load Diff

231
po/et.po
View File

@ -14,8 +14,8 @@ msgstr ""
"Project-Id-Version: mutter MASTER\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-03-12 18:53+0000\n"
"PO-Revision-Date: 2013-03-12 20:55+0300\n"
"POT-Creation-Date: 2013-09-10 15:25+0000\n"
"PO-Revision-Date: 2013-09-11 23:20+0300\n"
"Last-Translator: Mattias Põldaru <mahfiaz@gmail.com>\n"
"Language-Team: Estonian <>\n"
"Language: et\n"
@ -23,6 +23,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
"X-Generator: Poedit 1.5.4\n"
msgid "Navigation"
msgstr "Navigeerimine"
@ -249,6 +250,17 @@ msgid ""
msgstr ""
"Teemat ei leitud! Veendu, et %s on olemas ja sisaldab harilikke teemasid.\n"
msgid "Built-in display"
msgstr "Sisseehitatud kuva"
#. TRANSLATORS: this is a monitor name (in case we don't know
#. the vendor), it's Unknown followed by a size in inches,
#. like 'Unknown 15"'
#.
#, c-format
msgid "Unknown %s"
msgstr "Tundmatu %s"
#, c-format
msgid ""
"mutter %s\n"
@ -381,7 +393,6 @@ msgstr "Tõrge logifaili %s avamisel funktsiooniga fdopen(): %s\n"
msgid "Opened log file %s\n"
msgstr "Avati logifail %s\n"
#, c-format
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter kompileeriti ilma jutuka režiimi toeta\n"
@ -572,10 +583,6 @@ msgstr "Akna valimine tabulaatori hüpikaknalt"
msgid "Cancel tab popup"
msgstr "Tabulaatori hüpikakna katkestamine"
#, c-format
msgid "Usage: %s\n"
msgstr "Kasutamine: %s\n"
#. Translators: Translate this string the same way as you do in libwnck!
msgid "Mi_nimize"
msgstr "_Minimeeri"
@ -1281,159 +1288,151 @@ msgstr "Selle teema jaoks on <%s> määratud kaks korda"
msgid "Failed to find a valid file for theme %s\n"
msgstr "Tõrge %s teema jaoks korrektse faili leidmisel\n"
msgid "_Windows"
msgstr "_Aknad"
#~ msgid "Usage: %s\n"
#~ msgstr "Kasutamine: %s\n"
msgid "_Dialog"
msgstr "_Dialoog"
#~ msgid "_Windows"
#~ msgstr "_Aknad"
msgid "_Modal dialog"
msgstr "_Modaaldialoog"
#~ msgid "_Dialog"
#~ msgstr "_Dialoog"
msgid "_Utility"
msgstr "_Utiliit"
#~ msgid "_Modal dialog"
#~ msgstr "_Modaaldialoog"
msgid "_Splashscreen"
msgstr "_Käivitusekraan"
#~ msgid "_Utility"
#~ msgstr "_Utiliit"
msgid "_Top dock"
msgstr "Ü_lemine dokk"
#~ msgid "_Splashscreen"
#~ msgstr "_Käivitusekraan"
msgid "_Bottom dock"
msgstr "_Alumine dokk"
#~ msgid "_Top dock"
#~ msgstr "Ü_lemine dokk"
msgid "_Left dock"
msgstr "_Vasak dokk"
#~ msgid "_Bottom dock"
#~ msgstr "_Alumine dokk"
msgid "_Right dock"
msgstr "_Parem dokk"
#~ msgid "_Left dock"
#~ msgstr "_Vasak dokk"
msgid "_All docks"
msgstr "_Kõik dokid"
#~ msgid "_Right dock"
#~ msgstr "_Parem dokk"
msgid "Des_ktop"
msgstr "_Töölaud"
#~ msgid "_All docks"
#~ msgstr "_Kõik dokid"
msgid "Open another one of these windows"
msgstr "Ava neist akendest järgmine"
#~ msgid "Des_ktop"
#~ msgstr "_Töölaud"
msgid "This is a demo button with an 'open' icon"
msgstr "See on näidisnupp koos 'ava' ikooniga"
#~ msgid "Open another one of these windows"
#~ msgstr "Ava neist akendest järgmine"
msgid "This is a demo button with a 'quit' icon"
msgstr "See on näidisnupp koos 'lõpeta' ikooniga"
#~ msgid "This is a demo button with an 'open' icon"
#~ msgstr "See on näidisnupp koos 'ava' ikooniga"
msgid "This is a sample message in a sample dialog"
msgstr "See on näidisteade näidisdialoogis"
#~ msgid "This is a demo button with a 'quit' icon"
#~ msgstr "See on näidisnupp koos 'lõpeta' ikooniga"
#, c-format
msgid "Fake menu item %d\n"
msgstr "Võltsitud menüüpunkt %d\n"
#~ msgid "This is a sample message in a sample dialog"
#~ msgstr "See on näidisteade näidisdialoogis"
msgid "Border-only window"
msgstr "Ainult raamiga aken"
#~ msgid "Fake menu item %d\n"
#~ msgstr "Võltsitud menüüpunkt %d\n"
msgid "Bar"
msgstr "Riba"
#~ msgid "Border-only window"
#~ msgstr "Ainult raamiga aken"
msgid "Normal Application Window"
msgstr "Tavaline rakenduseaken"
#~ msgid "Bar"
#~ msgstr "Riba"
msgid "Dialog Box"
msgstr "Dialoogikast"
#~ msgid "Normal Application Window"
#~ msgstr "Tavaline rakenduseaken"
msgid "Modal Dialog Box"
msgstr "Modaalne dialoogikast"
#~ msgid "Dialog Box"
#~ msgstr "Dialoogikast"
msgid "Utility Palette"
msgstr "Rakendite palett"
#~ msgid "Modal Dialog Box"
#~ msgstr "Modaalne dialoogikast"
msgid "Torn-off Menu"
msgstr "Ärarebitav menüü"
#~ msgid "Utility Palette"
#~ msgstr "Rakendite palett"
msgid "Border"
msgstr "Raam"
#~ msgid "Torn-off Menu"
#~ msgstr "Ärarebitav menüü"
msgid "Attached Modal Dialog"
msgstr "Kinnistatud modaaldialoog"
#~ msgid "Border"
#~ msgstr "Raam"
#, c-format
msgid "Button layout test %d"
msgstr "Nuppude paigutuse test %d"
#~ msgid "Attached Modal Dialog"
#~ msgstr "Kinnistatud modaaldialoog"
#, c-format
msgid "%g milliseconds to draw one window frame"
msgstr "%g millisekundit kulub ühe akna raami joonistamiseks"
#~ msgid "Button layout test %d"
#~ msgstr "Nuppude paigutuse test %d"
#, c-format
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
msgstr "Kasutamine: metacity-theme-viewer [TEEMANIMI]\n"
#~ msgid "%g milliseconds to draw one window frame"
#~ msgstr "%g millisekundit kulub ühe akna raami joonistamiseks"
#, c-format
msgid "Error loading theme: %s\n"
msgstr "Viga teema laadimisel: %s\n"
#~ msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
#~ msgstr "Kasutamine: metacity-theme-viewer [TEEMANIMI]\n"
#, c-format
msgid "Loaded theme \"%s\" in %g seconds\n"
msgstr "Teema \"%s\" laaditi %g sekundiga\n"
#~ msgid "Error loading theme: %s\n"
#~ msgstr "Viga teema laadimisel: %s\n"
msgid "Normal Title Font"
msgstr "Tiitli tavasuurusega kirjatüüp"
#~ msgid "Loaded theme \"%s\" in %g seconds\n"
#~ msgstr "Teema \"%s\" laaditi %g sekundiga\n"
msgid "Small Title Font"
msgstr "Tiitli väike kirjatüüp"
#~ msgid "Normal Title Font"
#~ msgstr "Tiitli tavasuurusega kirjatüüp"
msgid "Large Title Font"
msgstr "Tiitli suur kirjatüüp"
#~ msgid "Small Title Font"
#~ msgstr "Tiitli väike kirjatüüp"
msgid "Button Layouts"
msgstr "Nuppude paigutus"
#~ msgid "Large Title Font"
#~ msgstr "Tiitli suur kirjatüüp"
msgid "Benchmark"
msgstr "Jõudlus"
#~ msgid "Button Layouts"
#~ msgstr "Nuppude paigutus"
msgid "Window Title Goes Here"
msgstr "Siia tuleb akna pealkiri"
#~ msgid "Benchmark"
#~ msgstr "Jõudlus"
#, c-format
msgid ""
"Drew %d frames in %g client-side seconds (%g milliseconds per frame) and %g "
"seconds wall clock time including X server resources (%g milliseconds per "
"frame)\n"
msgstr ""
"Joonistati %d kaadrit %g kliendi-kella sekundiga (%g millisekundit kaadrile) "
"ja %g sekundiga seinakella järgi, millesse on kaasatud X-serveri "
"ressursikasutus (%g millisekundit kaadrile)\n"
#~ msgid "Window Title Goes Here"
#~ msgstr "Siia tuleb akna pealkiri"
msgid "position expression test returned TRUE but set error"
msgstr "asukoha avaldise kontroll tagastas TÕENE, aga määras vea"
#~ msgid ""
#~ "Drew %d frames in %g client-side seconds (%g milliseconds per frame) and "
#~ "%g seconds wall clock time including X server resources (%g milliseconds "
#~ "per frame)\n"
#~ msgstr ""
#~ "Joonistati %d kaadrit %g kliendi-kella sekundiga (%g millisekundit "
#~ "kaadrile) ja %g sekundiga seinakella järgi, millesse on kaasatud X-"
#~ "serveri ressursikasutus (%g millisekundit kaadrile)\n"
msgid "position expression test returned FALSE but didn't set error"
msgstr "asukoha avaldise kontroll tagastas VÄÄR, aga ei määranud viga"
#~ msgid "position expression test returned TRUE but set error"
#~ msgstr "asukoha avaldise kontroll tagastas TÕENE, aga määras vea"
msgid "Error was expected but none given"
msgstr "Oodati viga, aga ühtegi ei edastatud"
#~ msgid "position expression test returned FALSE but didn't set error"
#~ msgstr "asukoha avaldise kontroll tagastas VÄÄR, aga ei määranud viga"
#, c-format
msgid "Error %d was expected but %d given"
msgstr "Oodati viga %d, aga edastati viga %d"
#~ msgid "Error was expected but none given"
#~ msgstr "Oodati viga, aga ühtegi ei edastatud"
#, c-format
msgid "Error not expected but one was returned: %s"
msgstr "Viga ei oodatud, aga üks edastati: %s"
#~ msgid "Error %d was expected but %d given"
#~ msgstr "Oodati viga %d, aga edastati viga %d"
#, c-format
msgid "x value was %d, %d was expected"
msgstr "x väärtus oli %d, oodati väärtust %d"
#~ msgid "Error not expected but one was returned: %s"
#~ msgstr "Viga ei oodatud, aga üks edastati: %s"
#, c-format
msgid "y value was %d, %d was expected"
msgstr "y väärtus oli %d, oodati väärtust %d"
#~ msgid "x value was %d, %d was expected"
#~ msgstr "x väärtus oli %d, oodati väärtust %d"
#, c-format
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
msgstr ""
"%d koordinaatide avaldis töödeldi %g sekundiga (keskmine %g sekundit)\n"
#~ msgid "y value was %d, %d was expected"
#~ msgstr "y väärtus oli %d, oodati väärtust %d"
#~ msgid ""
#~ "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
#~ msgstr ""
#~ "%d koordinaatide avaldis töödeldi %g sekundiga (keskmine %g sekundit)\n"
#~ msgid "Minimize window"
#~ msgstr "Akna minimeerimine"

512
po/fi.po

File diff suppressed because it is too large Load Diff

201
po/he.po
View File

@ -9,8 +9,8 @@ msgid ""
msgstr ""
"Project-Id-Version: metacity.HEAD.he\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-02-21 19:11+0200\n"
"PO-Revision-Date: 2013-02-21 19:14+0200\n"
"POT-Creation-Date: 2013-04-03 08:27+0300\n"
"PO-Revision-Date: 2013-04-03 08:28+0200\n"
"Last-Translator: Yaron Shahrabani <sh.yaron@gmail.com>\n"
"Language-Team: Hebrew <he@li.org>\n"
"Language: he\n"
@ -209,16 +209,16 @@ msgstr "פיצול הצפייה מימין"
#. 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:507
#: ../src/compositor/compositor.c:568
#, c-format
msgid "Another compositing manager is already running on screen %i on display \"%s\"."
msgstr "מנהל תצוגת חלונות אחר כבר פועל במסך %i בתצוגה „%s“."
#: ../src/compositor/meta-background.c:1116
#: ../src/compositor/meta-background.c:1064
msgid "background texture could not be created from file"
msgstr "לא ניתן ליצור מרקם רקע מקובץ"
#: ../src/core/bell.c:320
#: ../src/core/bell.c:322
msgid "Bell event"
msgstr "אירוע פעמון"
@ -248,51 +248,56 @@ msgstr "ה_מתנה"
msgid "_Force Quit"
msgstr "_אילוץ סגירה"
#: ../src/core/display.c:392
#: ../src/core/display.c:401
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Missing %s extension required for compositing"
#: ../src/core/display.c:484
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Failed to open X Window System display '%s'\n"
#: ../src/core/keybindings.c:876
#: ../src/core/keybindings.c:935
#, c-format
msgid "Some other program is already using the key %s with modifiers %x as a binding\n"
msgstr "תכנית אחרת כבר משתמשת במקש %s עם המקש %x כצירוף\n"
#: ../src/core/main.c:196
#: ../src/core/keybindings.c:1135
#, c-format
msgid "\"%s\" is not a valid accelerator\n"
msgstr "\"%s\" אינו מקש האצה תקני\n"
#: ../src/core/main.c:197
msgid "Disable connection to session manager"
msgstr "Disable connection to session manager"
#: ../src/core/main.c:202
#: ../src/core/main.c:203
msgid "Replace the running window manager"
msgstr "Replace the running window manager"
#: ../src/core/main.c:208
#: ../src/core/main.c:209
msgid "Specify session management ID"
msgstr "Specify session management ID"
#: ../src/core/main.c:213
#: ../src/core/main.c:214
msgid "X Display to use"
msgstr "X Display to use"
#: ../src/core/main.c:219
#: ../src/core/main.c:220
msgid "Initialize session from savefile"
msgstr "Initialize session from savefile"
#: ../src/core/main.c:225
#: ../src/core/main.c:226
msgid "Make X calls synchronous"
msgstr "Make X calls synchronous"
#: ../src/core/main.c:494
#: ../src/core/main.c:534
#, c-format
msgid "Failed to scan themes directory: %s\n"
msgstr "Failed to scan themes directory: %s\n"
#: ../src/core/main.c:510
#: ../src/core/main.c:550
#, c-format
msgid "Could not find a theme! Be sure %s exists and contains the usual themes.\n"
msgstr "Could not find a theme! Be sure %s exists and contains the usual themes.\n"
@ -318,51 +323,51 @@ msgstr "Print version"
msgid "Mutter plugin to use"
msgstr "תוסף ה־mutter לשימוש"
#: ../src/core/prefs.c:1087
#: ../src/core/prefs.c:1095
msgid "Workarounds for broken applications disabled. Some applications may not behave properly.\n"
msgstr "Workarounds for broken applications disabled. Some applications may not behave properly.\n"
#: ../src/core/prefs.c:1162
#: ../src/core/prefs.c:1170
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Could not parse font description \"%s\" from GSettings key %s\n"
#: ../src/core/prefs.c:1228
#: ../src/core/prefs.c:1236
#, c-format
msgid "\"%s\" found in configuration database is not a valid value for mouse button modifier\n"
msgstr "\"%s\" found in configuration database is not a valid value for mouse button modifier\n"
#: ../src/core/prefs.c:1780
#: ../src/core/prefs.c:1788
#, c-format
msgid "\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"
msgstr "\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"
#: ../src/core/prefs.c:1879
#: ../src/core/prefs.c:1887
#, c-format
msgid "Workspace %d"
msgstr "סביבת עבודה %d"
#: ../src/core/screen.c:673
#: ../src/core/screen.c:691
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Screen %d on display '%s' is invalid\n"
#: ../src/core/screen.c:689
#: ../src/core/screen.c:707
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager; try using the --replace option to replace the current window manager.\n"
msgstr "Screen %d on display \"%s\" already has a window manager; try using the --replace option to replace the current window manager.\n"
#: ../src/core/screen.c:716
#: ../src/core/screen.c:734
#, c-format
msgid "Could not acquire window manager selection on screen %d display \"%s\"\n"
msgstr "Could not acquire window manager selection on screen %d display \"%s\"\n"
#: ../src/core/screen.c:794
#: ../src/core/screen.c:812
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "Screen %d on display \"%s\" already has a window manager\n"
#: ../src/core/screen.c:979
#: ../src/core/screen.c:998
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Could not release screen %d on display \"%s\"\n"
@ -421,45 +426,45 @@ msgstr "Unknown element %s"
msgid "These windows do not support &quot;save current setup&quot; and will have to be restarted manually next time you log in."
msgstr "חלונות אלו אינם תומכים ב&quot;שמירת ההגדרות הנוכחיות&quot;, ויהיה צורך באתחול ידני בכניסה הבאה שלך."
#: ../src/core/util.c:80
#: ../src/core/util.c:84
#, c-format
msgid "Failed to open debug log: %s\n"
msgstr "Failed to open debug log: %s\n"
#: ../src/core/util.c:90
#: ../src/core/util.c:94
#, c-format
msgid "Failed to fdopen() log file %s: %s\n"
msgstr "Failed to fdopen() log file %s: %s\n"
#: ../src/core/util.c:96
#: ../src/core/util.c:100
#, c-format
msgid "Opened log file %s\n"
msgstr "Opened log file %s\n"
#: ../src/core/util.c:115
#: ../src/core/util.c:119
#: ../src/tools/mutter-message.c:149
#, c-format
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter הודר ללא תמיכה במצב פירוט\n"
#: ../src/core/util.c:259
#: ../src/core/util.c:264
msgid "Window manager: "
msgstr "Window manager: "
#: ../src/core/util.c:407
#: ../src/core/util.c:412
msgid "Bug in window manager: "
msgstr "Bug in window manager: "
#: ../src/core/util.c:438
#: ../src/core/util.c:443
msgid "Window manager warning: "
msgstr "Window manager warning: "
#: ../src/core/util.c:466
#: ../src/core/util.c:471
msgid "Window manager error: "
msgstr "Window manager error: "
#. first time through
#: ../src/core/window.c:7504
#: ../src/core/window.c:7596
#, c-format
msgid "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER window as specified in the ICCCM.\n"
msgstr "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER window as specified in the ICCCM.\n"
@ -471,7 +476,7 @@ msgstr "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADE
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8228
#: ../src/core/window.c:8320
#, c-format
msgid "Window %s sets an MWM hint indicating it isn't resizable, but sets min size %d x %d and max size %d x %d; this doesn't make much sense.\n"
msgstr "Window %s sets an MWM hint indicating it isn't resizable, but sets min size %d x %d and max size %d x %d; this doesn't make much sense.\n"
@ -811,247 +816,247 @@ msgstr "Mod5"
msgid "%d x %d"
msgstr "%d x %d"
#: ../src/ui/theme.c:235
#: ../src/ui/theme.c:236
msgid "top"
msgstr "top"
#: ../src/ui/theme.c:237
#: ../src/ui/theme.c:238
msgid "bottom"
msgstr "bottom"
#: ../src/ui/theme.c:239
#: ../src/ui/theme.c:240
msgid "left"
msgstr "left"
#: ../src/ui/theme.c:241
#: ../src/ui/theme.c:242
msgid "right"
msgstr "right"
#: ../src/ui/theme.c:269
#: ../src/ui/theme.c:270
#, c-format
msgid "frame geometry does not specify \"%s\" dimension"
msgstr "frame geometry does not specify \"%s\" dimension"
#: ../src/ui/theme.c:288
#: ../src/ui/theme.c:289
#, c-format
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
msgstr "frame geometry does not specify dimension \"%s\" for border \"%s\""
#: ../src/ui/theme.c:325
#: ../src/ui/theme.c:326
#, c-format
msgid "Button aspect ratio %g is not reasonable"
msgstr "Button aspect ratio %g is not reasonable"
#: ../src/ui/theme.c:337
#: ../src/ui/theme.c:338
#, c-format
msgid "Frame geometry does not specify size of buttons"
msgstr "Frame geometry does not specify size of buttons"
#: ../src/ui/theme.c:1050
#: ../src/ui/theme.c:1051
#, c-format
msgid "Gradients should have at least two colors"
msgstr "Gradients should have at least two colors"
#: ../src/ui/theme.c:1202
#: ../src/ui/theme.c:1203
#, 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 custom color specification must have color name and fallback in parentheses, e.g. gtk:custom(foo,bar); could not parse \"%s\""
#: ../src/ui/theme.c:1218
#: ../src/ui/theme.c:1219
#, c-format
msgid "Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-_ are valid"
msgstr "Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-_ are valid"
#: ../src/ui/theme.c:1232
#: ../src/ui/theme.c:1233
#, c-format
msgid "Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not fit the format"
msgstr "Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not fit the format"
#: ../src/ui/theme.c:1277
#: ../src/ui/theme.c:1278
#, c-format
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 color specification must have the state in brackets, e.g. gtk:fg[NORMAL] where NORMAL is the state; could not parse \"%s\""
#: ../src/ui/theme.c:1291
#: ../src/ui/theme.c:1292
#, c-format
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 color specification must have a close bracket after the state, e.g. gtk:fg[NORMAL] where NORMAL is the state; could not parse \"%s\""
#: ../src/ui/theme.c:1302
#: ../src/ui/theme.c:1303
#, c-format
msgid "Did not understand state \"%s\" in color specification"
msgstr "Did not understand state \"%s\" in color specification"
#: ../src/ui/theme.c:1315
#: ../src/ui/theme.c:1316
#, c-format
msgid "Did not understand color component \"%s\" in color specification"
msgstr "Did not understand color component \"%s\" in color specification"
#: ../src/ui/theme.c:1344
#: ../src/ui/theme.c:1345
#, c-format
msgid "Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the format"
msgstr "Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the format"
#: ../src/ui/theme.c:1355
#: ../src/ui/theme.c:1356
#, c-format
msgid "Could not parse alpha value \"%s\" in blended color"
msgstr "Could not parse alpha value \"%s\" in blended color"
#: ../src/ui/theme.c:1365
#: ../src/ui/theme.c:1366
#, c-format
msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
msgstr "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
#: ../src/ui/theme.c:1412
#: ../src/ui/theme.c:1413
#, c-format
msgid "Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
msgstr "Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
#: ../src/ui/theme.c:1423
#: ../src/ui/theme.c:1424
#, c-format
msgid "Could not parse shade factor \"%s\" in shaded color"
msgstr "Could not parse shade factor \"%s\" in shaded color"
#: ../src/ui/theme.c:1433
#: ../src/ui/theme.c:1434
#, c-format
msgid "Shade factor \"%s\" in shaded color is negative"
msgstr "Shade factor \"%s\" in shaded color is negative"
#: ../src/ui/theme.c:1462
#: ../src/ui/theme.c:1463
#, c-format
msgid "Could not parse color \"%s\""
msgstr "Could not parse color \"%s\""
#: ../src/ui/theme.c:1779
#: ../src/ui/theme.c:1780
#, c-format
msgid "Coordinate expression contains character '%s' which is not allowed"
msgstr "Coordinate expression contains character '%s' which is not allowed"
#: ../src/ui/theme.c:1806
#: ../src/ui/theme.c:1807
#, c-format
msgid "Coordinate expression contains floating point number '%s' which could not be parsed"
msgstr "Coordinate expression contains floating point number '%s' which could not be parsed"
#: ../src/ui/theme.c:1820
#: ../src/ui/theme.c:1821
#, c-format
msgid "Coordinate expression contains integer '%s' which could not be parsed"
msgstr "Coordinate expression contains integer '%s' which could not be parsed"
#: ../src/ui/theme.c:1941
#: ../src/ui/theme.c:1942
#, c-format
msgid "Coordinate expression contained unknown operator at the start of this text: \"%s\""
msgstr "Coordinate expression contained unknown operator at the start of this text: \"%s\""
#: ../src/ui/theme.c:1998
#: ../src/ui/theme.c:1999
#, c-format
msgid "Coordinate expression was empty or not understood"
msgstr "Coordinate expression was empty or not understood"
#: ../src/ui/theme.c:2111
#: ../src/ui/theme.c:2121
#: ../src/ui/theme.c:2155
#: ../src/ui/theme.c:2112
#: ../src/ui/theme.c:2122
#: ../src/ui/theme.c:2156
#, c-format
msgid "Coordinate expression results in division by zero"
msgstr "Coordinate expression results in division by zero"
#: ../src/ui/theme.c:2163
#: ../src/ui/theme.c:2164
#, c-format
msgid "Coordinate expression tries to use mod operator on a floating-point number"
msgstr "Coordinate expression tries to use mod operator on a floating-point number"
#: ../src/ui/theme.c:2219
#: ../src/ui/theme.c:2220
#, c-format
msgid "Coordinate expression has an operator \"%s\" where an operand was expected"
msgstr "Coordinate expression has an operator \"%s\" where an operand was expected"
#: ../src/ui/theme.c:2228
#: ../src/ui/theme.c:2229
#, c-format
msgid "Coordinate expression had an operand where an operator was expected"
msgstr "Coordinate expression had an operand where an operator was expected"
#: ../src/ui/theme.c:2236
#: ../src/ui/theme.c:2237
#, c-format
msgid "Coordinate expression ended with an operator instead of an operand"
msgstr "Coordinate expression ended with an operator instead of an operand"
#: ../src/ui/theme.c:2246
#: ../src/ui/theme.c:2247
#, c-format
msgid "Coordinate expression has operator \"%c\" following operator \"%c\" with no operand in between"
msgstr "Coordinate expression has operator \"%c\" following operator \"%c\" with no operand in between"
#: ../src/ui/theme.c:2397
#: ../src/ui/theme.c:2442
#: ../src/ui/theme.c:2398
#: ../src/ui/theme.c:2443
#, c-format
msgid "Coordinate expression had unknown variable or constant \"%s\""
msgstr "Coordinate expression had unknown variable or constant \"%s\""
#: ../src/ui/theme.c:2496
#: ../src/ui/theme.c:2497
#, c-format
msgid "Coordinate expression parser overflowed its buffer."
msgstr "Coordinate expression parser overflowed its buffer."
#: ../src/ui/theme.c:2525
#: ../src/ui/theme.c:2526
#, c-format
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
msgstr "Coordinate expression had a close parenthesis with no open parenthesis"
#: ../src/ui/theme.c:2589
#: ../src/ui/theme.c:2590
#, c-format
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
msgstr "Coordinate expression had an open parenthesis with no close parenthesis"
#: ../src/ui/theme.c:2600
#: ../src/ui/theme.c:2601
#, c-format
msgid "Coordinate expression doesn't seem to have any operators or operands"
msgstr "Coordinate expression doesn't seem to have any operators or operands"
#: ../src/ui/theme.c:2813
#: ../src/ui/theme.c:2833
#: ../src/ui/theme.c:2853
#: ../src/ui/theme.c:2814
#: ../src/ui/theme.c:2834
#: ../src/ui/theme.c:2854
#, c-format
msgid "Theme contained an expression that resulted in an error: %s\n"
msgstr "Theme contained an expression that resulted in an error: %s\n"
#: ../src/ui/theme.c:4499
#: ../src/ui/theme.c:4500
#, c-format
msgid "<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be specified for this frame style"
msgstr "<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be specified for this frame style"
#: ../src/ui/theme.c:5010
#: ../src/ui/theme.c:5035
#: ../src/ui/theme.c:5011
#: ../src/ui/theme.c:5036
#, c-format
msgid "Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
msgstr "Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
#: ../src/ui/theme.c:5083
#: ../src/ui/theme.c:5084
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Failed to load theme \"%s\": %s\n"
#: ../src/ui/theme.c:5219
#: ../src/ui/theme.c:5226
#: ../src/ui/theme.c:5233
#: ../src/ui/theme.c:5240
#: ../src/ui/theme.c:5247
#: ../src/ui/theme.c:5220
#: ../src/ui/theme.c:5227
#: ../src/ui/theme.c:5234
#: ../src/ui/theme.c:5241
#: ../src/ui/theme.c:5248
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "No <%s> set for theme \"%s\""
#: ../src/ui/theme.c:5255
#: ../src/ui/theme.c:5256
#, c-format
msgid "No frame style set for window type \"%s\" in theme \"%s\", add a <window type=\"%s\" style_set=\"whatever\"/> element"
msgstr "No frame style set for window type \"%s\" in theme \"%s\", add a <window type=\"%s\" style_set=\"whatever\"/> element"
#: ../src/ui/theme.c:5662
#: ../src/ui/theme.c:5724
#: ../src/ui/theme.c:5787
#: ../src/ui/theme.c:5663
#: ../src/ui/theme.c:5725
#: ../src/ui/theme.c:5788
#, c-format
msgid "User-defined constants must begin with a capital letter; \"%s\" does not"
msgstr "User-defined constants must begin with a capital letter; \"%s\" does not"
#: ../src/ui/theme.c:5670
#: ../src/ui/theme.c:5732
#: ../src/ui/theme.c:5795
#: ../src/ui/theme.c:5671
#: ../src/ui/theme.c:5733
#: ../src/ui/theme.c:5796
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "Constant \"%s\" has already been defined"
@ -1423,7 +1428,7 @@ msgstr "מלל לא מורשה בתג <%s>"
msgid "<%s> specified twice for this theme"
msgstr "<%s> צוין פעמיים עבור ערכת נושא זו"
#: ../src/ui/theme-parser.c:4334
#: ../src/ui/theme-parser.c:4336
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "Failed to find a valid file for theme %s\n"

327
po/id.po
View File

@ -11,15 +11,15 @@ msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-03-28 10:28+0000\n"
"PO-Revision-Date: 2013-03-30 11:24+0700\n"
"POT-Creation-Date: 2013-08-18 20:03+0000\n"
"PO-Revision-Date: 2013-09-14 15:44+0700\n"
"Last-Translator: Andika Triwidada <andika@gmail.com>\n"
"Language-Team: Indonesian <gnome@i15n.org>\n"
"Language: id\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Poedit 1.5.5\n"
"X-Generator: Poedit 1.5.7\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: ../src/50-mutter-navigation.xml.in.h:1
@ -212,7 +212,7 @@ msgstr "Tampilan dipisah ke kanan"
#. 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:568
#: ../src/compositor/compositor.c:589
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
@ -220,7 +220,7 @@ msgid ""
msgstr ""
"Manajer komposit lain telah berjalan pada layar %i pada tampilan \"%s\"."
#: ../src/compositor/meta-background.c:1065
#: ../src/compositor/meta-background.c:1076
msgid "background texture could not be created from file"
msgstr "tekstur latar tak bisa dibuat dari berkas"
@ -257,24 +257,24 @@ msgstr "_Tunggu"
msgid "_Force Quit"
msgstr "_Matikan Paksa"
#: ../src/core/display.c:401
#: ../src/core/display.c:421
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Kehilangan ekstensi %s yang diperlukan untuk pengkomposisian"
#: ../src/core/display.c:493
#: ../src/core/display.c:513
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Gagal membuka tampilan X Window System '%s'\n"
#: ../src/core/keybindings.c:935
#: ../src/core/keybindings.c:1136
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
"binding\n"
msgstr "Ada program lain yang menggunakan tombol %s dengan kombinasi %x\n"
#: ../src/core/keybindings.c:1135
#: ../src/core/keybindings.c:1333
#, c-format
msgid "\"%s\" is not a valid accelerator\n"
msgstr "\"%s\" bukan akselerator yang valid\n"
@ -314,6 +314,19 @@ msgid ""
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
msgstr "Tak menemukan tema! Pastikan %s ada dan berisi tema yang biasa.\n"
#: ../src/core/monitor.c:711
msgid "Built-in display"
msgstr "Tampilan bawaan"
#. TRANSLATORS: this is a monitor name (in case we don't know
#. the vendor), it's Unknown followed by a size in inches,
#. like 'Unknown 15"'
#.
#: ../src/core/monitor.c:739
#, c-format
msgid "Unknown %s"
msgstr "%s tidak dikenal"
#: ../src/core/mutter.c:40
#, c-format
msgid ""
@ -338,7 +351,7 @@ msgstr "Cetak versi"
msgid "Mutter plugin to use"
msgstr "Pengaya Mutter yang dipakai"
#: ../src/core/prefs.c:1095
#: ../src/core/prefs.c:1202
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -346,12 +359,12 @@ msgstr ""
"Pencegahan kesalahan bagi aplikasi yang rusak sedang dinonaktifkan. Mungkin "
"nanti ada beberapa aplikasi yang akan bertingkah aneh.\n"
#: ../src/core/prefs.c:1170
#: ../src/core/prefs.c:1277
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Tak dapat mengurai deskripsi fonta \"%s\" dari kunci GSettings %s\n"
#: ../src/core/prefs.c:1236
#: ../src/core/prefs.c:1343
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -360,7 +373,7 @@ msgstr ""
"\"%s\" yang ada pada database konfigurasi bukanlah nilai yang benar untuk "
"tombol mouse.\n"
#: ../src/core/prefs.c:1788
#: ../src/core/prefs.c:1909
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@ -369,17 +382,17 @@ msgstr ""
"\"%s\" yang ada pada database konfigurasi bernilai tidak benar untuk "
"kombinasi tombol \"%s\"\n"
#: ../src/core/prefs.c:1887
#: ../src/core/prefs.c:1999
#, c-format
msgid "Workspace %d"
msgstr "Area kerja %d"
#: ../src/core/screen.c:691
#: ../src/core/screen.c:534
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Layar %d pada tampilan '%s' tidak benar\n"
#: ../src/core/screen.c:707
#: ../src/core/screen.c:550
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@ -388,7 +401,7 @@ msgstr ""
"Layar %d pada tampilan \"%s\" sudah memiliki pengatur jendela. Cobalah "
"gunakan pilihan --replace untuk mengganti pengatur jendela yang aktif.\n"
#: ../src/core/screen.c:734
#: ../src/core/screen.c:577
#, c-format
msgid ""
"Could not acquire window manager selection on screen %d display \"%s\"\n"
@ -396,12 +409,12 @@ msgstr ""
"Tidak dapat mendapatkan pilihan pengatur jendela pada layar %d tampilan \"%s"
"\"\n"
#: ../src/core/screen.c:812
#: ../src/core/screen.c:655
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "Layar %d pada tampilan \"%s\" sudah ada pengatur jendelanya\n"
#: ../src/core/screen.c:998
#: ../src/core/screen.c:846
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Layar %d pada tampilan \"%s\" tidak dapat dilepas\n"
@ -476,8 +489,7 @@ msgstr "Gagal melakukan fdopen pada berkas log %s: %s\n"
msgid "Opened log file %s\n"
msgstr "Berkas log yang dibuka %s\n"
#: ../src/core/util.c:119 ../src/tools/mutter-message.c:149
#, c-format
#: ../src/core/util.c:119
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Muter dikompilasi tanpa dukungan mode riuh\n"
@ -485,20 +497,20 @@ msgstr "Muter dikompilasi tanpa dukungan mode riuh\n"
msgid "Window manager: "
msgstr "Pengatur jendela: "
#: ../src/core/util.c:412
#: ../src/core/util.c:414
msgid "Bug in window manager: "
msgstr "Bug pada pengatur jendela: "
#: ../src/core/util.c:443
#: ../src/core/util.c:445
msgid "Window manager warning: "
msgstr "Peringatan pengatur jendela: "
#: ../src/core/util.c:471
#: ../src/core/util.c:473
msgid "Window manager error: "
msgstr "Eror pengatur jendela: "
#. first time through
#: ../src/core/window.c:7596
#: ../src/core/window.c:7533
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -514,7 +526,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8320
#: ../src/core/window.c:8257
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -524,22 +536,22 @@ msgstr ""
"ukurannya, sedangkan ukuran minimalnya adalah %d x %d dan maksimal %d x %d "
"yang tidak masuk di akal.\n"
#: ../src/core/window-props.c:318
#: ../src/core/window-props.c:347
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "Aplikasi telah membuat _NET_WM_PID %lu bohongan\n"
#: ../src/core/window-props.c:434
#: ../src/core/window-props.c:463
#, c-format
msgid "%s (on %s)"
msgstr "%s (pada %s)"
#: ../src/core/window-props.c:1517
#: ../src/core/window-props.c:1546
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "WM_TRANSIENT_FOR salah jendela 0x%lx ditentukan untuk %s.\n"
#: ../src/core/window-props.c:1528
#: ../src/core/window-props.c:1557
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "Jendela WM_TRANSIENT_FOR 0x%lx untuk %s akan membuat loop.\n"
@ -703,109 +715,104 @@ msgstr "Pilih jendela dari popup tab"
msgid "Cancel tab popup"
msgstr "Batalkan popup tab"
#: ../src/tools/mutter-message.c:123
#, c-format
msgid "Usage: %s\n"
msgstr "Cara pakai: %s\n"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:69
#: ../src/ui/menu.c:67
msgid "Mi_nimize"
msgstr "Kecilka_n"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:71
#: ../src/ui/menu.c:69
msgid "Ma_ximize"
msgstr "Pe_rbesar"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:73
#: ../src/ui/menu.c:71
msgid "Unma_ximize"
msgstr "Kem_balikan"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:75
#: ../src/ui/menu.c:73
msgid "Roll _Up"
msgstr "G_ulung"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:77
#: ../src/ui/menu.c:75
msgid "_Unroll"
msgstr "B_uka"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:79
#: ../src/ui/menu.c:77
msgid "_Move"
msgstr "_Pindahkan"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:81
#: ../src/ui/menu.c:79
msgid "_Resize"
msgstr "Ganti·Uku_ran"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:83
#: ../src/ui/menu.c:81
msgid "Move Titlebar On_screen"
msgstr "Pindahkan Judul Pada _layar"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
msgid "Always on _Top"
msgstr "Selalu di A_tas"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:90
#: ../src/ui/menu.c:88
msgid "_Always on Visible Workspace"
msgstr "T_ampak pada Area Kerja Aktif"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:92
#: ../src/ui/menu.c:90
msgid "_Only on This Workspace"
msgstr "_Tampak pada Area Kerja Ini Saja"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:94
#: ../src/ui/menu.c:92
msgid "Move to Workspace _Left"
msgstr "Pindahkan ke Area Kerja _Kiri"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:96
#: ../src/ui/menu.c:94
msgid "Move to Workspace R_ight"
msgstr "Pindahkan ke A_rea Kerja Kanan"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:98
#: ../src/ui/menu.c:96
msgid "Move to Workspace _Up"
msgstr "Pindahkan ke Area Kerja Ata_s"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:100
#: ../src/ui/menu.c:98
msgid "Move to Workspace _Down"
msgstr "Pindahkan ke Area Kerja _Bawah"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:104
#: ../src/ui/menu.c:102
msgid "_Close"
msgstr "_Tutup"
#: ../src/ui/menu.c:204
#: ../src/ui/menu.c:202
#, c-format
msgid "Workspace %d%n"
msgstr "Area Kerja %d%n"
#: ../src/ui/menu.c:214
#: ../src/ui/menu.c:212
#, c-format
msgid "Workspace 1_0"
msgstr "Area Kerja 1_0"
#: ../src/ui/menu.c:216
#: ../src/ui/menu.c:214
#, c-format
msgid "Workspace %s%d"
msgstr "Area Kerja %s%d"
#: ../src/ui/menu.c:397
#: ../src/ui/menu.c:384
msgid "Move to Another _Workspace"
msgstr "Pindahkan ke Area Kerja _Lain"
@ -1163,18 +1170,18 @@ msgid ""
msgstr ""
"<frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/> tidak ada"
#: ../src/ui/theme.c:5084
#: ../src/ui/theme.c:5082
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Gagal membuka tema \"%s\": %s\n"
#: ../src/ui/theme.c:5220 ../src/ui/theme.c:5227 ../src/ui/theme.c:5234
#: ../src/ui/theme.c:5241 ../src/ui/theme.c:5248
#: ../src/ui/theme.c:5218 ../src/ui/theme.c:5225 ../src/ui/theme.c:5232
#: ../src/ui/theme.c:5239 ../src/ui/theme.c:5246
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "Tidak ada <%s> yang ditentukan untuk tema \"%s\""
#: ../src/ui/theme.c:5256
#: ../src/ui/theme.c:5254
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@ -1183,14 +1190,14 @@ msgstr ""
"Tidak ada gaya frame untuk tipe window \"%s\" pada tema \"%s\". Tambah dulu "
"elemen <window type=\"%s\" style_set=\"whatever\"/>"
#: ../src/ui/theme.c:5663 ../src/ui/theme.c:5725 ../src/ui/theme.c:5788
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
#, c-format
msgid ""
"User-defined constants must begin with a capital letter; \"%s\" does not"
msgstr ""
"Konstanta buatan pengguna harus dimulai dengan huruf besar: \"%s\" tidak"
#: ../src/ui/theme.c:5671 ../src/ui/theme.c:5733 ../src/ui/theme.c:5796
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "Konstanta \"%s\" telah didefinisikan sebelumnya"
@ -1578,201 +1585,3 @@ msgstr "<%s> disebutkan dua kali pada tema ini"
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "Gagal menemukan berkas yang sah untuk tema %s\n"
#: ../src/ui/theme-viewer.c:99
msgid "_Windows"
msgstr "_Jendela"
#: ../src/ui/theme-viewer.c:100
msgid "_Dialog"
msgstr "_Dialog"
#: ../src/ui/theme-viewer.c:101
msgid "_Modal dialog"
msgstr "Dialog _modal"
#: ../src/ui/theme-viewer.c:102
msgid "_Utility"
msgstr "_Utilitas"
#: ../src/ui/theme-viewer.c:103
msgid "_Splashscreen"
msgstr "Layar _pembuka"
#: ../src/ui/theme-viewer.c:104
msgid "_Top dock"
msgstr "Dok a_tas"
#: ../src/ui/theme-viewer.c:105
msgid "_Bottom dock"
msgstr "Dok _bawah"
#: ../src/ui/theme-viewer.c:106
msgid "_Left dock"
msgstr "Dok k_iri"
#: ../src/ui/theme-viewer.c:107
msgid "_Right dock"
msgstr "Dok kana_n"
#: ../src/ui/theme-viewer.c:108
msgid "_All docks"
msgstr "Semu_a dok"
#: ../src/ui/theme-viewer.c:109
msgid "Des_ktop"
msgstr "Des_ktop"
#: ../src/ui/theme-viewer.c:115
msgid "Open another one of these windows"
msgstr "Buka lagi jendela semacam ini"
#: ../src/ui/theme-viewer.c:117
msgid "This is a demo button with an 'open' icon"
msgstr "Ini contoh tombol dengan ikon 'open'"
#: ../src/ui/theme-viewer.c:119
msgid "This is a demo button with a 'quit' icon"
msgstr "Ini contoh tombol dengan ikon 'quit'"
#: ../src/ui/theme-viewer.c:248
msgid "This is a sample message in a sample dialog"
msgstr "Ini contoh pesan pada suatu dialog"
#: ../src/ui/theme-viewer.c:328
#, c-format
msgid "Fake menu item %d\n"
msgstr "Item menu %d\n"
#: ../src/ui/theme-viewer.c:363
msgid "Border-only window"
msgstr "Jendela dengan garis pembatas"
#: ../src/ui/theme-viewer.c:365
msgid "Bar"
msgstr "Kotak"
#: ../src/ui/theme-viewer.c:382
msgid "Normal Application Window"
msgstr "Jendela Aplikasi Normal"
#: ../src/ui/theme-viewer.c:386
msgid "Dialog Box"
msgstr "Kotak Dialog"
#: ../src/ui/theme-viewer.c:390
msgid "Modal Dialog Box"
msgstr "Kotak Dialog Modal"
#: ../src/ui/theme-viewer.c:394
msgid "Utility Palette"
msgstr "Kotak Perkakas"
#: ../src/ui/theme-viewer.c:398
msgid "Torn-off Menu"
msgstr "Menu Dapat Dilepas"
#: ../src/ui/theme-viewer.c:402
msgid "Border"
msgstr "Batas"
#: ../src/ui/theme-viewer.c:406
msgid "Attached Modal Dialog"
msgstr "Dialog Modal yang Dilampirkan"
#: ../src/ui/theme-viewer.c:737
#, c-format
msgid "Button layout test %d"
msgstr "Tes komposisi tombol %d"
#: ../src/ui/theme-viewer.c:766
#, c-format
msgid "%g milliseconds to draw one window frame"
msgstr "lama waktu menggambar satu bingkai jendela %g milidetik"
#: ../src/ui/theme-viewer.c:811
#, c-format
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
msgstr "Cara pakai: metacity-theme-viewer [NAMA TEMA]\n"
#: ../src/ui/theme-viewer.c:818
#, c-format
msgid "Error loading theme: %s\n"
msgstr "Ada error saat membaca tema: %s\n"
#: ../src/ui/theme-viewer.c:824
#, c-format
msgid "Loaded theme \"%s\" in %g seconds\n"
msgstr "Tema \"%s\" dibuka dalam %g detik\n"
#: ../src/ui/theme-viewer.c:869
msgid "Normal Title Font"
msgstr "Judul dengan huruf normal"
#: ../src/ui/theme-viewer.c:875
msgid "Small Title Font"
msgstr "Judul dengan huruf ukuran kecil"
#: ../src/ui/theme-viewer.c:881
msgid "Large Title Font"
msgstr "Judul Raksasa"
#: ../src/ui/theme-viewer.c:886
msgid "Button Layouts"
msgstr "Komposisi Tombol"
#: ../src/ui/theme-viewer.c:891
msgid "Benchmark"
msgstr "Pengukuran"
#: ../src/ui/theme-viewer.c:947
msgid "Window Title Goes Here"
msgstr "Ini tempat judul jendela"
#: ../src/ui/theme-viewer.c:1053
#, c-format
msgid ""
"Drew %d frames in %g client-side seconds (%g milliseconds per frame) and %g "
"seconds wall clock time including X server resources (%g milliseconds per "
"frame)\n"
msgstr ""
"%d frame dibuat dalam %g detik dalam waktu klien (%g milidetik per frame) "
"dan %g detik dalam waktu sebenarnya (%g milidetik per frame)\n"
#: ../src/ui/theme-viewer.c:1273
msgid "position expression test returned TRUE but set error"
msgstr "tes ekspresi posisi berakhir TRUE tapi justru ada error"
#: ../src/ui/theme-viewer.c:1275
msgid "position expression test returned FALSE but didn't set error"
msgstr "tes ekspresi posisi berakhir FALSE tapi tidak ada error"
#: ../src/ui/theme-viewer.c:1279
msgid "Error was expected but none given"
msgstr "Seharusnya ada error, tapi ini kok tidak ada"
#: ../src/ui/theme-viewer.c:1281
#, c-format
msgid "Error %d was expected but %d given"
msgstr "Seharunya ada error %d, tapi yang terjadi %d"
#: ../src/ui/theme-viewer.c:1287
#, c-format
msgid "Error not expected but one was returned: %s"
msgstr "Seharusnya tidak ada error, tapi ini tiba-tiba ada error: %s"
#: ../src/ui/theme-viewer.c:1291
#, c-format
msgid "x value was %d, %d was expected"
msgstr "nilai x sebelumnya %d, padahal seharusnya %d"
#: ../src/ui/theme-viewer.c:1294
#, c-format
msgid "y value was %d, %d was expected"
msgstr "nilai y sebelumnya %d, padahal seharusnya %d"
#: ../src/ui/theme-viewer.c:1359
#, c-format
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
msgstr "ekspresi koordinat %d diambil dalam %g detik (rata-rata %g detik)\n"

View File

@ -12,8 +12,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-03-22 10:02+0000\n"
"PO-Revision-Date: 2013-03-25 17:02+0000\n"
"POT-Creation-Date: 2013-07-30 12:29+0000\n"
"PO-Revision-Date: 2013-07-30 23:01+0900\n"
"Last-Translator: Jiro Matsuzawa <jmatsuzawa@gnome.org>\n"
"Language-Team: Japanese <gnome-translation@gnome.gr.jp>\n"
"Language: ja\n"
@ -133,7 +133,7 @@ msgstr "コマンド実行プロンプトを表示する"
#: ../src/50-mutter-system.xml.in.h:3
msgid "Show the activities overview"
msgstr "アクティビティを表示する"
msgstr "アクティビティ画面を表示する"
#: ../src/50-mutter-windows.xml.in.h:1
msgid "Windows"
@ -213,12 +213,12 @@ msgstr "画面右半分に表示する"
#. 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:568
#: ../src/compositor/compositor.c:589
#, c-format
msgid "Another compositing manager is already running on screen %i on display \"%s\"."
msgstr "既に別の合成マネージャーがディスプレイ \"%2$s\" 上のスクリーン %1$i で起動中です"
#: ../src/compositor/meta-background.c:1191
#: ../src/compositor/meta-background.c:1076
msgid "background texture could not be created from file"
msgstr ""
@ -252,22 +252,22 @@ msgstr "待機する(_W)"
msgid "_Force Quit"
msgstr "強制終了する(_F)"
#: ../src/core/display.c:401
#: ../src/core/display.c:421
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "ウィンドウの合成に必要な %s という拡張モジュールが存在しません"
#: ../src/core/display.c:493
#: ../src/core/display.c:513
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "X Window System のディスプレイ '%s' のオープンに失敗しました\n"
#: ../src/core/keybindings.c:935
#: ../src/core/keybindings.c:1138
#, c-format
msgid "Some other program is already using the key %s with modifiers %x as a binding\n"
msgstr "既にバインディングとして別のプログラムでキー %s (修飾キー %x) を使っています\n"
#: ../src/core/keybindings.c:1135
#: ../src/core/keybindings.c:1335
#, fuzzy, c-format
msgid "\"%s\" is not a valid accelerator\n"
msgstr "\"%s\" はフォーカス属性のためには有効な値ではありません"
@ -328,26 +328,26 @@ msgstr "バージョンを表示する"
msgid "Mutter plugin to use"
msgstr "使用する Mutter のプラグイン"
#: ../src/core/prefs.c:1095
#: ../src/core/prefs.c:1202
msgid "Workarounds for broken applications disabled. Some applications may not behave properly.\n"
msgstr "仕様に準拠していないアプリケーションに対する次善策は無効になっています。一部のアプリケーションは正常に動作しない可能性があります\n"
#: ../src/core/prefs.c:1170
#: ../src/core/prefs.c:1277
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "GSettings の %2$s キーからフォント名 \"%1$s\" を解析できませんでした\n"
#: ../src/core/prefs.c:1236
#: ../src/core/prefs.c:1343
#, c-format
msgid "\"%s\" found in configuration database is not a valid value for mouse button modifier\n"
msgstr "設定データベース中の \"%s\" はマウスボタンの修飾キーとして妥当な値ではありません\n"
#: ../src/core/prefs.c:1788
#: ../src/core/prefs.c:1909
#, c-format
msgid "\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"
msgstr "設定データベース中の \"%s\" はキーバインド \"%s\" に有効な値ではありません\n"
#: ../src/core/prefs.c:1887
#: ../src/core/prefs.c:1999
#, c-format
msgid "Workspace %d"
msgstr "ワークスペース %d"
@ -465,7 +465,7 @@ msgid "Window manager error: "
msgstr "ウィンドウマネージャーのエラー: "
#. first time through
#: ../src/core/window.c:7596
#: ../src/core/window.c:7513
#, c-format
msgid "Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER window as specified in the ICCCM.\n"
msgstr "ウィンドウ %s は ICCCM で指定されていたような WM_CLIENT_LEADER ウィンドウの代わりに自分自身で SM_CLIENT_ID を設定しています\n"
@ -477,7 +477,7 @@ msgstr "ウィンドウ %s は ICCCM で指定されていたような WM_CLIENT
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8320
#: ../src/core/window.c:8237
#, c-format
msgid "Window %s sets an MWM hint indicating it isn't resizable, but sets min size %d x %d and max size %d x %d; this doesn't make much sense.\n"
msgstr "ウィンドウ %s はリサイズ可能ではない MWM ヒント指示を設定していますが、最小サイズ %d x %d と最大サイズ %d x %dも設定しています。これはあまり意味がありません\n"

1477
po/kk.po Normal file

File diff suppressed because it is too large Load Diff

458
po/ko.po
View File

@ -18,8 +18,8 @@ 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-03-01 15:50+0000\n"
"PO-Revision-Date: 2013-03-13 03:52+0900\n"
"POT-Creation-Date: 2013-08-18 20:03+0000\n"
"PO-Revision-Date: 2013-09-09 04:46+0900\n"
"Last-Translator: Changwoo Ryu <cwryu@debian.org>\n"
"Language-Team: GNOME Korea <gnome-kr@googlegroups.com>\n"
"Language: Korean\n"
@ -218,7 +218,7 @@ msgstr "오른쪽 절반 뷰"
#. 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:507
#: ../src/compositor/compositor.c:589
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
@ -227,11 +227,11 @@ msgstr ""
"다른 창 구성 관리 프로그램이 이미 디스플레이 \"%2$s\" 화면 %1$i번에서 실행 중"
"입니다."
#: ../src/compositor/meta-background.c:1111
#: ../src/compositor/meta-background.c:1076
msgid "background texture could not be created from file"
msgstr "파일에서 배경 텍스처를 만들 수 없습니다"
#: ../src/core/bell.c:320
#: ../src/core/bell.c:322
msgid "Bell event"
msgstr "삑소리 이벤트"
@ -263,17 +263,17 @@ msgstr "기다리기(_W)"
msgid "_Force Quit"
msgstr "강제로 끝내기(_F)"
#: ../src/core/display.c:401
#: ../src/core/display.c:421
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "콤포짓에 필요한 %s 확장 기능이 없습니다"
#: ../src/core/display.c:493
#: ../src/core/display.c:513
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "X 윈도 시스템 디스플레이 '%s'을(를) 여는데 실패하였습니다\n"
#: ../src/core/keybindings.c:929
#: ../src/core/keybindings.c:1136
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -282,41 +282,41 @@ msgstr ""
"다른 프로그램에서 이미 단축키로 변경 키 %2$x와(과) 키 %1$s을(를) 사용하고 있"
"습니다\n"
#: ../src/core/keybindings.c:1129
#: ../src/core/keybindings.c:1333
#, c-format
msgid "\"%s\" is not a valid accelerator\n"
msgstr "\"%s\"은(는) 올바른 단축키가 아닙니다\n"
#: ../src/core/main.c:196
#: ../src/core/main.c:197
msgid "Disable connection to session manager"
msgstr "세션 관리자와 연결 하지 않습니다"
#: ../src/core/main.c:202
#: ../src/core/main.c:203
msgid "Replace the running window manager"
msgstr "실행 중인 창 관리자를 바꿉니다"
#: ../src/core/main.c:208
#: ../src/core/main.c:209
msgid "Specify session management ID"
msgstr "세션 관리 ID를 지정합니다"
#: ../src/core/main.c:213
#: ../src/core/main.c:214
msgid "X Display to use"
msgstr "사용할 X 디스플레이"
#: ../src/core/main.c:219
#: ../src/core/main.c:220
msgid "Initialize session from savefile"
msgstr "저장 파일에서 세션을 초기화 합니다"
#: ../src/core/main.c:225
#: ../src/core/main.c:226
msgid "Make X calls synchronous"
msgstr "동기 X 호출을 합니다"
#: ../src/core/main.c:494
#: ../src/core/main.c:534
#, c-format
msgid "Failed to scan themes directory: %s\n"
msgstr "테마 디렉터리를 읽는 데 실패했습니다: %s\n"
#: ../src/core/main.c:510
#: ../src/core/main.c:550
#, c-format
msgid ""
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
@ -324,6 +324,19 @@ msgstr ""
"테마를 찾을 수 없습니다! %s이(가) 있고 올바른 테마가 들어 있는지 확인하십시"
"오.\n"
#: ../src/core/monitor.c:711
msgid "Built-in display"
msgstr "내장 디스플레이"
#. TRANSLATORS: this is a monitor name (in case we don't know
#. the vendor), it's Unknown followed by a size in inches,
#. like 'Unknown 15"'
#.
#: ../src/core/monitor.c:739
#, c-format
msgid "Unknown %s"
msgstr "알 수 없는 %s인치"
#: ../src/core/mutter.c:40
#, c-format
msgid ""
@ -347,18 +360,20 @@ msgstr "버전을 출력합니다"
msgid "Mutter plugin to use"
msgstr "사용할 머터 플러그인"
#: ../src/core/prefs.c:1087
#: ../src/core/prefs.c:1202
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
msgstr "응용 프로그램에 대한 임시 방편을 막았습니다. 몇몇 응용 프로그램이 제대로 동작하지 않을것입니다.\n"
msgstr ""
"응용 프로그램에 대한 임시 방편을 막았습니다. 몇몇 응용 프로그램이 제대로 동작"
"하지 않을것입니다.\n"
#: ../src/core/prefs.c:1162
#: ../src/core/prefs.c:1277
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "GSettings 키 %2$s에서 글꼴 지정 \"%1$s\"을(를) 분석할 수 없습니다\n"
#: ../src/core/prefs.c:1228
#: ../src/core/prefs.c:1343
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -367,7 +382,7 @@ msgstr ""
"설정 데이터베이스에서 찾은 \"%s\"이(가) 마우스 단추 변경 키의 올바른 값이 아"
"닙니다\n"
#: ../src/core/prefs.c:1780
#: ../src/core/prefs.c:1909
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@ -376,17 +391,17 @@ msgstr ""
"설정 데이터베이스에서 찾은 \"%s\"이(가) 단축키 \"%s\"에 대한 올바른 값이 아닙"
"니다\n"
#: ../src/core/prefs.c:1879
#: ../src/core/prefs.c:1999
#, c-format
msgid "Workspace %d"
msgstr "작업 공간 %d"
#: ../src/core/screen.c:673
#: ../src/core/screen.c:534
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "디스플레이 '%2$s'의 화면 %1$d은(는) 잘못되었습니다\n"
#: ../src/core/screen.c:689
#: ../src/core/screen.c:550
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@ -395,19 +410,19 @@ msgstr ""
"디스플레이 \"%2$s\"의 화면 %1$d에 이미 창 관리자가 실행되고 있습니다. 현재 "
"창 관리자를 무시하는 --replace 옵션을 써보십시오.\n"
#: ../src/core/screen.c:716
#: ../src/core/screen.c:577
#, c-format
msgid ""
"Could not acquire window manager selection on screen %d display \"%s\"\n"
msgstr "디스플레이 \"%2$s\"의 화면 %1$d에 창 관리 선택을 가질 수 없습니다\n"
#: ../src/core/screen.c:794
#: ../src/core/screen.c:655
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr ""
"디스플레이 \"%2$s\"의 화면 %1$d은(는) 이미 창 관리자가 실행되고 있습니다\n"
#: ../src/core/screen.c:979
#: ../src/core/screen.c:846
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "디스플레이 \"%2$s\"의 화면 %1$d을(를) 떼어 놓을수 없습니다\n"
@ -467,44 +482,43 @@ msgstr ""
"이 창은 &quot;현재 설정 저장&quot;을 지원하지 않기 때문에 다음 번에 로그인 "
"할 때 수동으로 다시 시작해야 합니다."
#: ../src/core/util.c:80
#: ../src/core/util.c:84
#, c-format
msgid "Failed to open debug log: %s\n"
msgstr "디버그 로그 열기 실패: %s\n"
#: ../src/core/util.c:90
#: ../src/core/util.c:94
#, c-format
msgid "Failed to fdopen() log file %s: %s\n"
msgstr "로그 파일 %s을(를) fdopen()하기 실패: %s\n"
#: ../src/core/util.c:96
#: ../src/core/util.c:100
#, c-format
msgid "Opened log file %s\n"
msgstr "로그 파일 %s을(를) 엽니다\n"
#: ../src/core/util.c:115 ../src/tools/mutter-message.c:149
#, c-format
#: ../src/core/util.c:119
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "머터가 자세한 모드 지원 없이 컴파일 되었습니다\n"
#: ../src/core/util.c:259
#: ../src/core/util.c:264
msgid "Window manager: "
msgstr "창 관리자: "
#: ../src/core/util.c:407
#: ../src/core/util.c:414
msgid "Bug in window manager: "
msgstr "창 관리자의 벌레: "
#: ../src/core/util.c:438
#: ../src/core/util.c:445
msgid "Window manager warning: "
msgstr "창 관리자 주의: "
#: ../src/core/util.c:466
#: ../src/core/util.c:473
msgid "Window manager error: "
msgstr "장 관리자 오류: "
#. first time through
#: ../src/core/window.c:7539
#: ../src/core/window.c:7533
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -520,7 +534,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8263
#: ../src/core/window.c:8257
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -529,23 +543,23 @@ msgstr ""
"%s 창에서 크기 변경이 불가능하다는 MWM 힌트를 설정했지만, 최소 크기 %d x %d "
"및 최대 크기 %d x %d(으)로 설정했습니다. 앞뒤가 맞지 않습니다.\n"
#: ../src/core/window-props.c:318
#: ../src/core/window-props.c:347
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "응용 프로그램이 가짜 _NET_WM_PID %lu을(를) 설정하였습니다\n"
# <창제목> (on <기계>)
#: ../src/core/window-props.c:434
#: ../src/core/window-props.c:463
#, c-format
msgid "%s (on %s)"
msgstr "%s (%s에서)"
#: ../src/core/window-props.c:1517
#: ../src/core/window-props.c:1546
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "%2$s에 대해 WM_TRANSIENT_FOR 0x%1$lx 창이 잘못되었습니다.\n"
#: ../src/core/window-props.c:1528
#: ../src/core/window-props.c:1557
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "%2$s에 대해 WM_TRANSIENT_FOR 0x%1$lx 창은 무한 반복입니다.\n"
@ -574,9 +588,7 @@ msgstr "창 0x%2$lx의 등록 정보 %1$s은(는) 잘못된 UTF-8이 들어 있
#, c-format
msgid ""
"Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n"
msgstr ""
"창 0x%2$lx의 등록 정보 %1$s은(는) 목록안의 항목 %3$d에 잘못된 UTF-8을 포함하"
"고 있습니다\n"
msgstr "창 0x%2$lx의 등록 정보 %1$s은(는) 목록안의 항목 %3$d에 잘못된 UTF-8 문자가 들어 있습니다\n"
#: ../src/mutter.desktop.in.h:1 ../src/mutter-wm.desktop.in.h:1
msgid "Mutter"
@ -705,109 +717,104 @@ msgstr "탭 팝업에서 창 선택"
msgid "Cancel tab popup"
msgstr "탭 팝업 취소"
#: ../src/tools/mutter-message.c:123
#, c-format
msgid "Usage: %s\n"
msgstr "사용법: %s\n"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:69
#: ../src/ui/menu.c:67
msgid "Mi_nimize"
msgstr "최소화(_N)"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:71
#: ../src/ui/menu.c:69
msgid "Ma_ximize"
msgstr "최대화(_X)"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:73
#: ../src/ui/menu.c:71
msgid "Unma_ximize"
msgstr "최대화 취소(_X)"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:75
#: ../src/ui/menu.c:73
msgid "Roll _Up"
msgstr "말아올리기(_U)"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:77
#: ../src/ui/menu.c:75
msgid "_Unroll"
msgstr "펼치기(_U)"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:79
#: ../src/ui/menu.c:77
msgid "_Move"
msgstr "옮기기(_M)"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:81
#: ../src/ui/menu.c:79
msgid "_Resize"
msgstr "크기 조정(_R)"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:83
#: ../src/ui/menu.c:81
msgid "Move Titlebar On_screen"
msgstr "창 제목막대 화면에 표시(_S)"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
msgid "Always on _Top"
msgstr "항상 위(_T)"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:90
#: ../src/ui/menu.c:88
msgid "_Always on Visible Workspace"
msgstr "항상 현재 작업 공간에 놓기(_A)"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:92
#: ../src/ui/menu.c:90
msgid "_Only on This Workspace"
msgstr "이 작업 공간에만 놓기(_O)"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:94
#: ../src/ui/menu.c:92
msgid "Move to Workspace _Left"
msgstr "왼쪽 작업 공간으로 옮기기(_L)"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:96
#: ../src/ui/menu.c:94
msgid "Move to Workspace R_ight"
msgstr "오른쪽 작업 공간으로 옮기기(_I)"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:98
#: ../src/ui/menu.c:96
msgid "Move to Workspace _Up"
msgstr "위쪽 작업 공간으로 옮기기(_U)"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:100
#: ../src/ui/menu.c:98
msgid "Move to Workspace _Down"
msgstr "아래쪽 작업 공간으로 옮기기(_D)"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:104
#: ../src/ui/menu.c:102
msgid "_Close"
msgstr "닫기(_C)"
#: ../src/ui/menu.c:204
#: ../src/ui/menu.c:202
#, c-format
msgid "Workspace %d%n"
msgstr "작업 공간 %d%n"
#: ../src/ui/menu.c:214
#: ../src/ui/menu.c:212
#, c-format
msgid "Workspace 1_0"
msgstr "작업 공간 1_0"
#: ../src/ui/menu.c:216
#: ../src/ui/menu.c:214
#, c-format
msgid "Workspace %s%d"
msgstr "작업 공간 %s%d"
#: ../src/ui/menu.c:397
#: ../src/ui/menu.c:384
msgid "Move to Another _Workspace"
msgstr "다른 작업 공간으로 옮기기(_W)"
@ -909,50 +916,50 @@ msgstr "Mod5"
msgid "%d x %d"
msgstr "%d x %d"
#: ../src/ui/theme.c:235
#: ../src/ui/theme.c:236
msgid "top"
msgstr "맨 위"
#: ../src/ui/theme.c:237
#: ../src/ui/theme.c:238
msgid "bottom"
msgstr "맨 아래"
#: ../src/ui/theme.c:239
#: ../src/ui/theme.c:240
msgid "left"
msgstr "왼쪽"
#: ../src/ui/theme.c:241
#: ../src/ui/theme.c:242
msgid "right"
msgstr "오른쪽"
#: ../src/ui/theme.c:269
#: ../src/ui/theme.c:270
#, c-format
msgid "frame geometry does not specify \"%s\" dimension"
msgstr "프레임 위치가 \"%s\"차원으로 지정되지 않았습니다"
#: ../src/ui/theme.c:288
#: ../src/ui/theme.c:289
#, c-format
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
msgstr ""
"프레임 위치가 가장자리 \"%2$s\" 가장자리의 \"%1$s\"차원으로 지정되지 않았습니"
"다."
#: ../src/ui/theme.c:325
#: ../src/ui/theme.c:326
#, c-format
msgid "Button aspect ratio %g is not reasonable"
msgstr "단추의 가로세로 비 %g이(가) 적당하지 않습니다"
#: ../src/ui/theme.c:337
#: ../src/ui/theme.c:338
#, c-format
msgid "Frame geometry does not specify size of buttons"
msgstr "프레임 위치가 단추의 크기로 지정되지 않았습니다"
#: ../src/ui/theme.c:1050
#: ../src/ui/theme.c:1051
#, c-format
msgid "Gradients should have at least two colors"
msgstr "서서히 변하는 색으로 지정하려면 최소 2색이 필요합니다"
#: ../src/ui/theme.c:1202
#: ../src/ui/theme.c:1203
#, c-format
msgid ""
"GTK custom color specification must have color name and fallback in "
@ -961,7 +968,7 @@ msgstr ""
"GTK 사용자 지정 색상 지정은 색 이름과 대체할 색을 괄호 안에 써야 합니다. 예"
"를 들어: gtk:custom(foo,bar). \"%s\"을(를) 분석할 수 없습니다"
#: ../src/ui/theme.c:1218
#: ../src/ui/theme.c:1219
#, c-format
msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
@ -970,7 +977,7 @@ msgstr ""
"gtk:custom의 color_name 파라미터 안에 잘못된 문자 '%c'. A-Za-z0-9-_ 문자만 허"
"용합니다."
#: ../src/ui/theme.c:1232
#: ../src/ui/theme.c:1233
#, c-format
msgid ""
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
@ -979,7 +986,7 @@ msgstr ""
"gtk:custom 형식은 \"gtk:custom(색이름,대체색)\"입니다, \"%s\"(은)는 형식에 맞"
"지 않습니다"
#: ../src/ui/theme.c:1277
#: ../src/ui/theme.c:1278
#, c-format
msgid ""
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
@ -988,7 +995,7 @@ msgstr ""
"GTK 색상 지정은 중괄호안에 있어야 합니다. 예를 들어: gtk:fg[NORMAL], 여기서 "
"NORMAL이 값입니다. \"%s\"을(를) 분석할 수 없습니다."
#: ../src/ui/theme.c:1291
#: ../src/ui/theme.c:1292
#, c-format
msgid ""
"GTK color specification must have a close bracket after the state, e.g. gtk:"
@ -997,17 +1004,17 @@ msgstr ""
"GTK 색상 지정은 값 뒤에 중괄호로 닫혀 있어야 합니다. 예를 들어: gtk:fg"
"[NORMAL], 여기서 NORMAL은 값입니다. \"%s\"을(를) 분석할 수 없습니다."
#: ../src/ui/theme.c:1302
#: ../src/ui/theme.c:1303
#, c-format
msgid "Did not understand state \"%s\" in color specification"
msgstr "색상 지정의 \"%s\" 값을 이해할 수 없습니다"
#: ../src/ui/theme.c:1315
#: ../src/ui/theme.c:1316
#, c-format
msgid "Did not understand color component \"%s\" in color specification"
msgstr "색상 지정의 색상 구성요소 \"%s\"을(를) 이해할 수 없습니다"
#: ../src/ui/theme.c:1344
#: ../src/ui/theme.c:1345
#, c-format
msgid ""
"Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the "
@ -1016,17 +1023,17 @@ msgstr ""
"섞기 형식은 \"blend/bg_color/fg_color/alpha\"입니다, \"%s\"은(는) 형식에 맞"
"지 않습니다"
#: ../src/ui/theme.c:1355
#: ../src/ui/theme.c:1356
#, c-format
msgid "Could not parse alpha value \"%s\" in blended color"
msgstr "색상 섞기에서 알파 값 \"%s\"을(를) 분석할 수 없습니다"
#: ../src/ui/theme.c:1365
#: ../src/ui/theme.c:1366
#, c-format
msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
msgstr "색상 섞기에서 알파 값 \"%s\"은(는) 0.0 과 1.0사이의 값이 아닙니다"
msgstr "색상 섞기에서 알파 값 \"%s\"은(는) 0.0과 1.0 사이의 값이 아닙니다"
#: ../src/ui/theme.c:1412
#: ../src/ui/theme.c:1413
#, c-format
msgid ""
"Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
@ -1034,79 +1041,78 @@ msgstr ""
"그림자 형식은 \"shade/base_color/format\"입니다, \"%s\"(은)는 형식에 맞지 않"
"습니다"
#: ../src/ui/theme.c:1423
#: ../src/ui/theme.c:1424
#, c-format
msgid "Could not parse shade factor \"%s\" in shaded color"
msgstr "그림자색에서 그림자 인자 \"%s\"(을)를 해석할 수 없습니다"
#: ../src/ui/theme.c:1433
#: ../src/ui/theme.c:1434
#, c-format
msgid "Shade factor \"%s\" in shaded color is negative"
msgstr "그림자색에서 그림자 인자 \"%s\"(은)는 음수입니다"
#: ../src/ui/theme.c:1462
#: ../src/ui/theme.c:1463
#, c-format
msgid "Could not parse color \"%s\""
msgstr "색상 \"%s\"을(를) 해석할 수 없습니다"
#: ../src/ui/theme.c:1779
#: ../src/ui/theme.c:1780
#, c-format
msgid "Coordinate expression contains character '%s' which is not allowed"
msgstr "좌표식에 허용되지 않는 문자 '%s'(이)가 포함되어 있습니다"
msgstr "좌표식에 허용되지 않는 문자 '%s'(이)가 어 있습니다"
#: ../src/ui/theme.c:1806
#: ../src/ui/theme.c:1807
#, c-format
msgid ""
"Coordinate expression contains floating point number '%s' which could not be "
"parsed"
msgstr "좌표식에 분석할 수 없는 부동소수점 숫자 '%s'이(가) 포함되어 있습니다"
#: ../src/ui/theme.c:1820
#: ../src/ui/theme.c:1821
#, c-format
msgid "Coordinate expression contains integer '%s' which could not be parsed"
msgstr "좌표식에 분석할 수 없는 정수 '%s'이(가) 포함되어 있습니다"
#: ../src/ui/theme.c:1941
#: ../src/ui/theme.c:1942
#, c-format
msgid ""
"Coordinate expression contained unknown operator at the start of this text: "
"\"%s\""
msgstr ""
"좌표식에 이 글자 시작부분에 알 수 없는 연산자가 포함되어 있습니다: \"%s\""
msgstr "좌표식에 이 글자 시작부분에 알 수 없는 연산자가 들어 있습니다: \"%s\""
#: ../src/ui/theme.c:1998
#: ../src/ui/theme.c:1999
#, c-format
msgid "Coordinate expression was empty or not understood"
msgstr "좌표식이 비어있거나 이해할 수 없습니다"
#: ../src/ui/theme.c:2111 ../src/ui/theme.c:2121 ../src/ui/theme.c:2155
#: ../src/ui/theme.c:2112 ../src/ui/theme.c:2122 ../src/ui/theme.c:2156
#, c-format
msgid "Coordinate expression results in division by zero"
msgstr "좌표식의 결과 값이 0로 나누었습니다"
#: ../src/ui/theme.c:2163
#: ../src/ui/theme.c:2164
#, c-format
msgid ""
"Coordinate expression tries to use mod operator on a floating-point number"
msgstr "좌표식에서 부동소수점 수에 나머지 연산을 하려 합니다"
#: ../src/ui/theme.c:2219
#: ../src/ui/theme.c:2220
#, c-format
msgid ""
"Coordinate expression has an operator \"%s\" where an operand was expected"
msgstr "좌표식에서 피연산자가 들어갈 곳에 연산자 \"%s\"이(가) 있습니다"
#: ../src/ui/theme.c:2228
#: ../src/ui/theme.c:2229
#, c-format
msgid "Coordinate expression had an operand where an operator was expected"
msgstr "좌표식에서 연산자가 들어갈 곳에 피연산자가 있습니다"
#: ../src/ui/theme.c:2236
#: ../src/ui/theme.c:2237
#, c-format
msgid "Coordinate expression ended with an operator instead of an operand"
msgstr "좌표식에서 피연산자 대신에 연산자로 끝나있습니다"
#: ../src/ui/theme.c:2246
#: ../src/ui/theme.c:2247
#, c-format
msgid ""
"Coordinate expression has operator \"%c\" following operator \"%c\" with no "
@ -1115,37 +1121,37 @@ msgstr ""
"좌표식에서 피연산자가 없는 연산자 \"%2$c\"다음에 연산자 \"%1$c\"이(가) 있습니"
"다"
#: ../src/ui/theme.c:2397 ../src/ui/theme.c:2442
#: ../src/ui/theme.c:2398 ../src/ui/theme.c:2443
#, c-format
msgid "Coordinate expression had unknown variable or constant \"%s\""
msgstr "좌표식에 알 수 없는 변수나 상수 \"%s\"이(가) 있습니다"
#: ../src/ui/theme.c:2496
#: ../src/ui/theme.c:2497
#, c-format
msgid "Coordinate expression parser overflowed its buffer."
msgstr "좌표 계산 파서의 버퍼가 크기를 넘어갔습니다."
#: ../src/ui/theme.c:2525
#: ../src/ui/theme.c:2526
#, c-format
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
msgstr "좌표식에 닫는 괄호는 있지만 여는 괄호가 없습니다"
#: ../src/ui/theme.c:2589
#: ../src/ui/theme.c:2590
#, c-format
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
msgstr "좌표식에 여는 괄호는 있지만 닫는 괄호가 없습니다"
#: ../src/ui/theme.c:2600
#: ../src/ui/theme.c:2601
#, c-format
msgid "Coordinate expression doesn't seem to have any operators or operands"
msgstr "좌표식에 어떠한 연산자나 피연산자가 없습니다"
#: ../src/ui/theme.c:2813 ../src/ui/theme.c:2833 ../src/ui/theme.c:2853
#: ../src/ui/theme.c:2814 ../src/ui/theme.c:2834 ../src/ui/theme.c:2854
#, c-format
msgid "Theme contained an expression that resulted in an error: %s\n"
msgstr "테마가 오류 값을 내는 표현식이 들어 있습니다: %s\n"
#: ../src/ui/theme.c:4499
#: ../src/ui/theme.c:4500
#, c-format
msgid ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
@ -1154,7 +1160,7 @@ msgstr ""
"이 프레임 스타일에는 <button function=\"%s\" style=\"%s\" draw_ops=\"whatever"
"\"/>가 지정되어야 합니다"
#: ../src/ui/theme.c:5010 ../src/ui/theme.c:5035
#: ../src/ui/theme.c:5011 ../src/ui/theme.c:5036
#, c-format
msgid ""
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
@ -1162,18 +1168,18 @@ msgstr ""
"<frame state=\"%s\" resize=\"%s\" focus=\"%s\" state=\"whatever\"/> 가 없습니"
"다"
#: ../src/ui/theme.c:5083
#: ../src/ui/theme.c:5082
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "테마 \"%s\"을(를) 읽을 수 없습니다: %s\n"
#: ../src/ui/theme.c:5219 ../src/ui/theme.c:5226 ../src/ui/theme.c:5233
#: ../src/ui/theme.c:5240 ../src/ui/theme.c:5247
#: ../src/ui/theme.c:5218 ../src/ui/theme.c:5225 ../src/ui/theme.c:5232
#: ../src/ui/theme.c:5239 ../src/ui/theme.c:5246
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "테마 \"%2$s\"의 <%1$s>(이)가 설정되지 않았습니다"
#: ../src/ui/theme.c:5255
#: ../src/ui/theme.c:5254
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@ -1182,14 +1188,14 @@ msgstr ""
"테마 \"%2$s\"의 창 형식 \"%1$s\"에 대한 프레임 스타일이 없습니다,<window "
"type=\"%3$s\" style_set=\"whatever\"/> 엘리먼트를 추가하십시오"
#: ../src/ui/theme.c:5662 ../src/ui/theme.c:5724 ../src/ui/theme.c:5787
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
#, c-format
msgid ""
"User-defined constants must begin with a capital letter; \"%s\" does not"
msgstr ""
"사용자 정의 상수는 대문자로 시작되어야 합니다. \"%s\"은(는) 그렇지 않습니다."
#: ../src/ui/theme.c:5670 ../src/ui/theme.c:5732 ../src/ui/theme.c:5795
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "상수 \"%s\"은(는) 이미 지정되어 있습니다"
@ -1324,9 +1330,7 @@ msgstr "<%s> 엘리먼트는 <%s> 아래에 허용되지 않습니다"
msgid ""
"Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" "
"for buttons"
msgstr ""
"단추의 button_width/button_height 와 \"aspect_ratio\"를 한꺼번에 지정할 수 없"
"습니다"
msgstr "단추의 \"button_width\"/\"button_height\"와 \"aspect_ratio\"를 한꺼번에 지정할 수 없습니다"
#: ../src/ui/theme-parser.c:1450
#, c-format
@ -1387,7 +1391,7 @@ msgstr "\"%s\"라 불리는 <draw_ops>는 정의되지 않았습니다"
#: ../src/ui/theme-parser.c:2706 ../src/ui/theme-parser.c:2802
#, c-format
msgid "Including draw_ops \"%s\" here would create a circular reference"
msgstr "draw_ops를 포함하는 \"%s\"이(가) 자기 자신을 참조하고 있습니다"
msgstr "여기서 draw_ops \"%s\"을(를) 포함하면 순환 참조가 됩니다."
#: ../src/ui/theme-parser.c:2917
#, c-format
@ -1569,205 +1573,7 @@ msgstr "<%s> 엘리먼트 안에 텍스트가 허용되지 않습니다"
msgid "<%s> specified twice for this theme"
msgstr "이 테마에서 <%s> 태그가 두 번 지정되었습니다"
#: ../src/ui/theme-parser.c:4334
#: ../src/ui/theme-parser.c:4336
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "%s 테마의 올바른 파일을 찾는 데 실패했습니다\n"
#: ../src/ui/theme-viewer.c:99
msgid "_Windows"
msgstr "창(_W)"
#: ../src/ui/theme-viewer.c:100
msgid "_Dialog"
msgstr "대화 상자(_D)"
#: ../src/ui/theme-viewer.c:101
msgid "_Modal dialog"
msgstr "모달 대화 상자(_M)"
#: ../src/ui/theme-viewer.c:102
msgid "_Utility"
msgstr "도구(_U)"
#: ../src/ui/theme-viewer.c:103
msgid "_Splashscreen"
msgstr "스플래시 화면(_S)"
#: ../src/ui/theme-viewer.c:104
msgid "_Top dock"
msgstr "위 도크(_T)"
#: ../src/ui/theme-viewer.c:105
msgid "_Bottom dock"
msgstr "아래 도크(_B)"
#: ../src/ui/theme-viewer.c:106
msgid "_Left dock"
msgstr "왼쪽 도크(_L)"
#: ../src/ui/theme-viewer.c:107
msgid "_Right dock"
msgstr "오른쪽 도크(_R)"
#: ../src/ui/theme-viewer.c:108
msgid "_All docks"
msgstr "모든 도크(_A)"
#: ../src/ui/theme-viewer.c:109
msgid "Des_ktop"
msgstr "데스크톱(_K)"
#: ../src/ui/theme-viewer.c:115
msgid "Open another one of these windows"
msgstr "이 창을 하나 더 엽니다"
#: ../src/ui/theme-viewer.c:117
msgid "This is a demo button with an 'open' icon"
msgstr "'열기' 아이콘이 들어 있는 데모 단추입니다"
#: ../src/ui/theme-viewer.c:119
msgid "This is a demo button with a 'quit' icon"
msgstr "'끝내기' 아이콘이 들어 있는 데모 단추입니다"
#: ../src/ui/theme-viewer.c:248
msgid "This is a sample message in a sample dialog"
msgstr "예제 대화 상자의 예제 메시지입니다"
#: ../src/ui/theme-viewer.c:328
#, c-format
msgid "Fake menu item %d\n"
msgstr "가짜 메뉴 항목 %d\n"
#: ../src/ui/theme-viewer.c:363
msgid "Border-only window"
msgstr "테두리만 있는 창"
#: ../src/ui/theme-viewer.c:365
msgid "Bar"
msgstr "모음"
#: ../src/ui/theme-viewer.c:382
msgid "Normal Application Window"
msgstr "보통 프로그램 창"
#: ../src/ui/theme-viewer.c:386
msgid "Dialog Box"
msgstr "대화 상자"
#: ../src/ui/theme-viewer.c:390
msgid "Modal Dialog Box"
msgstr "모달 대화 상자"
#: ../src/ui/theme-viewer.c:394
msgid "Utility Palette"
msgstr "도구 팔레트"
#: ../src/ui/theme-viewer.c:398
msgid "Torn-off Menu"
msgstr "떼어내기 메뉴"
#: ../src/ui/theme-viewer.c:402
msgid "Border"
msgstr "테두리"
#: ../src/ui/theme-viewer.c:406
msgid "Attached Modal Dialog"
msgstr "부착한 모달 대화 상자"
#: ../src/ui/theme-viewer.c:737
#, c-format
msgid "Button layout test %d"
msgstr "단추 배치 테스트 %d"
#: ../src/ui/theme-viewer.c:766
#, c-format
msgid "%g milliseconds to draw one window frame"
msgstr "창 프레임 하나를 그리는 데 %g ms"
#: ../src/ui/theme-viewer.c:811
#, c-format
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
msgstr "사용법: metacity-theme-viewer [테마이름]\n"
#: ../src/ui/theme-viewer.c:818
#, c-format
msgid "Error loading theme: %s\n"
msgstr "테마를 읽어들이는 데 오류가 발생했습니다: %s\n"
#: ../src/ui/theme-viewer.c:824
#, c-format
msgid "Loaded theme \"%s\" in %g seconds\n"
msgstr "\"%s\" 테마를 읽어들이는 데 %g초\n"
#: ../src/ui/theme-viewer.c:869
msgid "Normal Title Font"
msgstr "보통 제목 글꼴"
#: ../src/ui/theme-viewer.c:875
msgid "Small Title Font"
msgstr "작은 제목 글꼴"
#: ../src/ui/theme-viewer.c:881
msgid "Large Title Font"
msgstr "큰 제목 글꼴"
#: ../src/ui/theme-viewer.c:886
msgid "Button Layouts"
msgstr "단추 배치"
#: ../src/ui/theme-viewer.c:891
msgid "Benchmark"
msgstr "벤치마크"
#: ../src/ui/theme-viewer.c:947
msgid "Window Title Goes Here"
msgstr "창 제목이 여기에 들어갑니다"
#: ../src/ui/theme-viewer.c:1053
#, c-format
msgid ""
"Drew %d frames in %g client-side seconds (%g milliseconds per frame) and %g "
"seconds wall clock time including X server resources (%g milliseconds per "
"frame)\n"
msgstr ""
"%d개 프레임을 그리는 데 클라이언트 입장에서 %g초가 걸렸습니다(한 프레임에 %g "
"ms). 그리고 X 서버 리소스까지 포함해 실제 시간으로 %g 초가 걸렸습니다(한 프레"
"임에 %g ms).\n"
#: ../src/ui/theme-viewer.c:1273
msgid "position expression test returned TRUE but set error"
msgstr "위치 표현식 테스트가 참을 리턴했지만 오류가 발생했습니다"
#: ../src/ui/theme-viewer.c:1275
msgid "position expression test returned FALSE but didn't set error"
msgstr "위치 표현식 테스트가 거짓을 리턴했지만 오류가 발생하지 않았습니다"
#: ../src/ui/theme-viewer.c:1279
msgid "Error was expected but none given"
msgstr "오류가 발생해야 하지만 발생하지 않았습니다"
#: ../src/ui/theme-viewer.c:1281
#, c-format
msgid "Error %d was expected but %d given"
msgstr "오류 %d번이 발생해야 하지만 오류 %d번이 발생했습니다"
#: ../src/ui/theme-viewer.c:1287
#, c-format
msgid "Error not expected but one was returned: %s"
msgstr "오류가 발생하면 안 되지만 오류 한 개가 발생했습니다: %s"
#: ../src/ui/theme-viewer.c:1291
#, c-format
msgid "x value was %d, %d was expected"
msgstr "가로값이 %d입니다. 와야 하는 값은 %d입니다"
#: ../src/ui/theme-viewer.c:1294
#, c-format
msgid "y value was %d, %d was expected"
msgstr "세로값이 %d입니다. 와야 하는 값은 %d입니다"
#: ../src/ui/theme-viewer.c:1359
#, c-format
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
msgstr "좌표 표현식 %d개를 %g초에 파싱했습니다(평균 %g초)\n"

498
po/lv.po

File diff suppressed because it is too large Load Diff

176
po/nb.po
View File

@ -4,10 +4,10 @@
#
msgid ""
msgstr ""
"Project-Id-Version: mutter 3.7.x\n"
"Project-Id-Version: mutter 3.9.x\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-04 14:57+0100\n"
"PO-Revision-Date: 2013-03-04 14:57+0100\n"
"POT-Creation-Date: 2013-08-08 22:14+0200\n"
"PO-Revision-Date: 2013-05-28 09:48+0200\n"
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
"Language-Team: Norwegian bokmål <i18n-no@lister.ping.uio.no>\n"
"Language: \n"
@ -205,18 +205,18 @@ msgstr "Visning delt til høyre"
#. 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:509
#: ../src/compositor/compositor.c:589
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
"\"."
msgstr "En annen compositing manager kjører skjerm %i på display «%s»."
#: ../src/compositor/meta-background.c:1180
#: ../src/compositor/meta-background.c:1076
msgid "background texture could not be created from file"
msgstr "bakgrunnstekstur kunne ikke lages fra fil"
#: ../src/core/bell.c:320
#: ../src/core/bell.c:322
msgid "Bell event"
msgstr "Klokkehendelse"
@ -250,17 +250,17 @@ msgstr "_Vent"
msgid "_Force Quit"
msgstr "_Tvungen nedstenging"
#: ../src/core/display.c:401
#: ../src/core/display.c:421
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Mangler utvidelsen %s som kreves for komposittfunksjon"
#: ../src/core/display.c:493
#: ../src/core/display.c:513
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Feil under åpning av X Window System skjerm «%s»\n"
#: ../src/core/keybindings.c:929
#: ../src/core/keybindings.c:1138
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -269,41 +269,41 @@ msgstr ""
"Et annet program bruker allerede nøkkelen %s med modifikatorer %x som "
"binding\n"
#: ../src/core/keybindings.c:1129
#: ../src/core/keybindings.c:1335
#, c-format
msgid "\"%s\" is not a valid accelerator\n"
msgstr "«%s» er ikke en gyldig aksellerator\n"
#: ../src/core/main.c:196
#: ../src/core/main.c:197
msgid "Disable connection to session manager"
msgstr "Deaktiver tilkobling til sesjonshåndtereren"
#: ../src/core/main.c:202
#: ../src/core/main.c:203
msgid "Replace the running window manager"
msgstr "Erstatt kjørende vindushåndterer"
#: ../src/core/main.c:208
#: ../src/core/main.c:209
msgid "Specify session management ID"
msgstr "Oppgi sesjonshåndterings-ID"
#: ../src/core/main.c:213
#: ../src/core/main.c:214
msgid "X Display to use"
msgstr "X-skjerm som skal brukes"
#: ../src/core/main.c:219
#: ../src/core/main.c:220
msgid "Initialize session from savefile"
msgstr "Initier sesjonen fra en lagret fil"
#: ../src/core/main.c:225
#: ../src/core/main.c:226
msgid "Make X calls synchronous"
msgstr "Gjør X-kall synkrone"
#: ../src/core/main.c:533
#: ../src/core/main.c:534
#, c-format
msgid "Failed to scan themes directory: %s\n"
msgstr "Feil under søk i temakatalog: %s\n"
#: ../src/core/main.c:549
#: ../src/core/main.c:550
#, c-format
msgid ""
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
@ -333,7 +333,7 @@ msgstr "Skriv versjonsnummer"
msgid "Mutter plugin to use"
msgstr "Mutter-tillegg som skal brukes"
#: ../src/core/prefs.c:1087
#: ../src/core/prefs.c:1202
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -341,12 +341,12 @@ msgstr ""
"Funksjonalitet for å gå rundt ødelagte programmer er deaktivert. Noen "
"programmer vil kanskje ikke oppføre seg korrekt.\n"
#: ../src/core/prefs.c:1162
#: ../src/core/prefs.c:1277
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Kunne ikke tolke skriftbeskrivelsen «%s» fra GSettings-nøkkel %s\n"
#: ../src/core/prefs.c:1228
#: ../src/core/prefs.c:1343
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -355,7 +355,7 @@ msgstr ""
"«%s» funnet i konfigurasjonsdatabasen er ikke en gyldig verdi for endring av "
"musknapp\n"
#: ../src/core/prefs.c:1780
#: ../src/core/prefs.c:1909
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@ -364,17 +364,17 @@ msgstr ""
"«%s» funnet i konfigurasjonsdatabasen er ikke en gyldig verdi for "
"tastaturbinding «%s»\n"
#: ../src/core/prefs.c:1879
#: ../src/core/prefs.c:1999
#, c-format
msgid "Workspace %d"
msgstr "Arbeidsområde %d"
#: ../src/core/screen.c:673
#: ../src/core/screen.c:691
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Skjerm %d på display «%s» er ugyldig\n"
#: ../src/core/screen.c:689
#: ../src/core/screen.c:707
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@ -383,19 +383,19 @@ msgstr ""
"Skjerm %d på display «%s» har allerede en vindushåndterer; prøv å bruke "
"flagget --replace for å erstatte aktiv vindushåndterer.\n"
#: ../src/core/screen.c:716
#: ../src/core/screen.c:734
#, c-format
msgid ""
"Could not acquire window manager selection on screen %d display \"%s\"\n"
msgstr ""
"Kunne ikke hente utvalg fra vinduhåndterer på skjerm %d, display «%s»\n"
#: ../src/core/screen.c:794
#: ../src/core/screen.c:812
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "Skjerm %d på display «%s» har allerede en vinduhåndterer\n"
#: ../src/core/screen.c:979
#: ../src/core/screen.c:998
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Kunne ikke slippe skjerm %d på display «%s»\n"
@ -455,44 +455,44 @@ msgstr ""
"Disse vinduene støtter ikke &quot;lagre aktiv konfigurasjon&quot;og vil "
"måtte startes på nytt manuelt neste gang du logger inn."
#: ../src/core/util.c:80
#: ../src/core/util.c:84
#, c-format
msgid "Failed to open debug log: %s\n"
msgstr "Feil under åpning av feilsøkingslogg: %s\n"
#: ../src/core/util.c:90
#: ../src/core/util.c:94
#, c-format
msgid "Failed to fdopen() log file %s: %s\n"
msgstr "Feil under fdopen() av loggfil %s: %s\n"
#: ../src/core/util.c:96
#: ../src/core/util.c:100
#, c-format
msgid "Opened log file %s\n"
msgstr "Åpnet loggfil %s\n"
#: ../src/core/util.c:115 ../src/tools/mutter-message.c:149
#: ../src/core/util.c:119 ../src/tools/mutter-message.c:149
#, c-format
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter er kompilert uten støtte for «verbose» modus\n"
#: ../src/core/util.c:259
#: ../src/core/util.c:264
msgid "Window manager: "
msgstr "Vindushåndterer: "
#: ../src/core/util.c:407
#: ../src/core/util.c:412
msgid "Bug in window manager: "
msgstr "Feil i vindushåndterer: "
#: ../src/core/util.c:438
#: ../src/core/util.c:443
msgid "Window manager warning: "
msgstr "Advarsel fra vindushåndterer: "
#: ../src/core/util.c:466
#: ../src/core/util.c:471
msgid "Window manager error: "
msgstr "Feil i vindushåndterer: "
#. first time through
#: ../src/core/window.c:7539
#: ../src/core/window.c:7513
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -508,7 +508,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8263
#: ../src/core/window.c:8237
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -685,6 +685,8 @@ msgid ""
"If enabled, new windows that are initially the size of the monitor "
"automatically get maximized."
msgstr ""
"Nye vinduer som i utgangspunktet er samme størrelse som skjermen vil "
"automatisk bli maksimert hvis denne slås på."
#: ../src/org.gnome.mutter.gschema.xml.in.h:19
msgid "Select window from tab popup"
@ -898,48 +900,48 @@ msgstr "Mod5"
msgid "%d x %d"
msgstr "%d x %d"
#: ../src/ui/theme.c:235
#: ../src/ui/theme.c:236
msgid "top"
msgstr "topp"
#: ../src/ui/theme.c:237
#: ../src/ui/theme.c:238
msgid "bottom"
msgstr "bunn"
#: ../src/ui/theme.c:239
#: ../src/ui/theme.c:240
msgid "left"
msgstr "venstre"
#: ../src/ui/theme.c:241
#: ../src/ui/theme.c:242
msgid "right"
msgstr "høyre"
#: ../src/ui/theme.c:269
#: ../src/ui/theme.c:270
#, c-format
msgid "frame geometry does not specify \"%s\" dimension"
msgstr "rammegeometrien spesifiserer ikke «%s»-dimensjon"
#: ../src/ui/theme.c:288
#: ../src/ui/theme.c:289
#, c-format
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
msgstr "rammegeometri spesifiserer ikke dimensjon «%s» for kant «%s»"
#: ../src/ui/theme.c:325
#: ../src/ui/theme.c:326
#, c-format
msgid "Button aspect ratio %g is not reasonable"
msgstr "Aspektrate %g for knapp er ikke fornuftig"
#: ../src/ui/theme.c:337
#: ../src/ui/theme.c:338
#, c-format
msgid "Frame geometry does not specify size of buttons"
msgstr "Rammegeometrien spesifiserer ikke størrelse på knapper"
#: ../src/ui/theme.c:1050
#: ../src/ui/theme.c:1051
#, c-format
msgid "Gradients should have at least two colors"
msgstr "Gradienter må ha minst to farger"
#: ../src/ui/theme.c:1202
#: ../src/ui/theme.c:1203
#, c-format
msgid ""
"GTK custom color specification must have color name and fallback in "
@ -948,7 +950,7 @@ msgstr ""
"Egendefinert GTK-fargespesifikasjon må ha fargenavn og reserve i parantes, f."
"eks gtk:custom(foo,bar); kunne ikke lese «%s»"
#: ../src/ui/theme.c:1218
#: ../src/ui/theme.c:1219
#, c-format
msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
@ -957,7 +959,7 @@ msgstr ""
"Ugyldig tegn «%c» i parameter color_name for gtk:custom, kun A-Za-z0-9-_ er "
"gyldig"
#: ../src/ui/theme.c:1232
#: ../src/ui/theme.c:1233
#, c-format
msgid ""
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
@ -966,7 +968,7 @@ msgstr ""
"Gtk:custom-format er «gtk:custom(color_name,fallback)», «%s» passer ikke i "
"formatet"
#: ../src/ui/theme.c:1277
#: ../src/ui/theme.c:1278
#, c-format
msgid ""
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
@ -975,7 +977,7 @@ msgstr ""
"GTK-fargespesifikasjon må ha tilstand i klammer, f.eks. gtk:fg[NORMAL], hvor "
"NORMAL er tilstanden; kunne ikke lese «%s»"
#: ../src/ui/theme.c:1291
#: ../src/ui/theme.c:1292
#, c-format
msgid ""
"GTK color specification must have a close bracket after the state, e.g. gtk:"
@ -984,17 +986,17 @@ msgstr ""
"GTK-fargespesifikasjon må ha en avsluttende klamme etter tilstanden, f.eks. "
"gtk:fg[NORMAL], hvor NORMAL er tilstanden; kunne ikke lese «%s»"
#: ../src/ui/theme.c:1302
#: ../src/ui/theme.c:1303
#, c-format
msgid "Did not understand state \"%s\" in color specification"
msgstr "Forsto ikke tilstand «%s» i fargespesifikasjonen"
#: ../src/ui/theme.c:1315
#: ../src/ui/theme.c:1316
#, c-format
msgid "Did not understand color component \"%s\" in color specification"
msgstr "Forsto ikke fargekomponent «%s» i fargespesifikasjonen"
#: ../src/ui/theme.c:1344
#: ../src/ui/theme.c:1345
#, c-format
msgid ""
"Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the "
@ -1003,56 +1005,56 @@ msgstr ""
"Blandingsformat er «blend/bg_color/fg_color/alpha», «%s» passer ikke i "
"formatet"
#: ../src/ui/theme.c:1355
#: ../src/ui/theme.c:1356
#, c-format
msgid "Could not parse alpha value \"%s\" in blended color"
msgstr "Kunne ikke lese alpha-verdi «%s» i blandet farge"
#: ../src/ui/theme.c:1365
#: ../src/ui/theme.c:1366
#, c-format
msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
msgstr "Alpha-verdi «%s» i blandet farge er ikke mellom 0.0 og 1.0"
#: ../src/ui/theme.c:1412
#: ../src/ui/theme.c:1413
#, c-format
msgid ""
"Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
msgstr ""
"Skyggeformatet er «shade/base_color/factor», «%s» passer ikke i formatet"
#: ../src/ui/theme.c:1423
#: ../src/ui/theme.c:1424
#, c-format
msgid "Could not parse shade factor \"%s\" in shaded color"
msgstr "Kunne ikke lese skyggefaktor «%s» i skyggelagt farge"
#: ../src/ui/theme.c:1433
#: ../src/ui/theme.c:1434
#, c-format
msgid "Shade factor \"%s\" in shaded color is negative"
msgstr "Skyggefaktor «%s» i skyggelagt farge er negativ"
#: ../src/ui/theme.c:1462
#: ../src/ui/theme.c:1463
#, c-format
msgid "Could not parse color \"%s\""
msgstr "Kunne ikke lese farge «%s»"
#: ../src/ui/theme.c:1779
#: ../src/ui/theme.c:1780
#, c-format
msgid "Coordinate expression contains character '%s' which is not allowed"
msgstr "Koordinatuttrykk inneholder tegn «%s» som ikke er tillatt"
#: ../src/ui/theme.c:1806
#: ../src/ui/theme.c:1807
#, c-format
msgid ""
"Coordinate expression contains floating point number '%s' which could not be "
"parsed"
msgstr "Koordinatuttrykk inneholder flyttall «%s» som ikke kunne tolkes"
#: ../src/ui/theme.c:1820
#: ../src/ui/theme.c:1821
#, c-format
msgid "Coordinate expression contains integer '%s' which could not be parsed"
msgstr "Koordinatuttrykk inneholder heltall «%s» som ikke kunne tolkes"
#: ../src/ui/theme.c:1941
#: ../src/ui/theme.c:1942
#, c-format
msgid ""
"Coordinate expression contained unknown operator at the start of this text: "
@ -1061,39 +1063,39 @@ msgstr ""
"Koordinatuttrykket inneholdt en ukjent operator ved begynnelsen av denne "
"teksten: «%s»"
#: ../src/ui/theme.c:1998
#: ../src/ui/theme.c:1999
#, c-format
msgid "Coordinate expression was empty or not understood"
msgstr "Koordinatuttrykket var tomt eller ble ikke forstått"
#: ../src/ui/theme.c:2111 ../src/ui/theme.c:2121 ../src/ui/theme.c:2155
#: ../src/ui/theme.c:2112 ../src/ui/theme.c:2122 ../src/ui/theme.c:2156
#, c-format
msgid "Coordinate expression results in division by zero"
msgstr "Koordinatuttrykket resulterer i divisjon med null"
#: ../src/ui/theme.c:2163
#: ../src/ui/theme.c:2164
#, c-format
msgid ""
"Coordinate expression tries to use mod operator on a floating-point number"
msgstr "Koordinatuttrykket prøver å bruke mod-operator på et flyttall"
#: ../src/ui/theme.c:2219
#: ../src/ui/theme.c:2220
#, c-format
msgid ""
"Coordinate expression has an operator \"%s\" where an operand was expected"
msgstr "Koordinatuttrykket har en operator «%s» hvor en operand var ventet"
#: ../src/ui/theme.c:2228
#: ../src/ui/theme.c:2229
#, c-format
msgid "Coordinate expression had an operand where an operator was expected"
msgstr "Koordinatuttrykket hadde en operand hvor en operator var ventet"
#: ../src/ui/theme.c:2236
#: ../src/ui/theme.c:2237
#, c-format
msgid "Coordinate expression ended with an operator instead of an operand"
msgstr "Koordinatuttrykket sluttet med en operator i stedet for en operand"
#: ../src/ui/theme.c:2246
#: ../src/ui/theme.c:2247
#, c-format
msgid ""
"Coordinate expression has operator \"%c\" following operator \"%c\" with no "
@ -1102,38 +1104,38 @@ msgstr ""
"Koordinatuttrykket har en operator «%c» etter en operator «%c» og ingen "
"operand mellom dem."
#: ../src/ui/theme.c:2397 ../src/ui/theme.c:2442
#: ../src/ui/theme.c:2398 ../src/ui/theme.c:2443
#, c-format
msgid "Coordinate expression had unknown variable or constant \"%s\""
msgstr "Koordinatuttrykket haddeen ukjent variabel eller konstant «%s»"
#: ../src/ui/theme.c:2496
#: ../src/ui/theme.c:2497
#, c-format
msgid "Coordinate expression parser overflowed its buffer."
msgstr "Tolkeren for koordinatuttrykk oversteg buffergrensen."
#: ../src/ui/theme.c:2525
#: ../src/ui/theme.c:2526
#, c-format
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
msgstr "Koordinatuttrykket hadde en parantes slutt uten parantes start"
#: ../src/ui/theme.c:2589
#: ../src/ui/theme.c:2590
#, c-format
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
msgstr "Koordinatuttrykket hadde en åpen parantes uten en avsluttende parantes"
#: ../src/ui/theme.c:2600
#: ../src/ui/theme.c:2601
#, c-format
msgid "Coordinate expression doesn't seem to have any operators or operands"
msgstr ""
"Koordinatuttrykket ser ikke ut til å ha noen operatorer eller operander"
#: ../src/ui/theme.c:2813 ../src/ui/theme.c:2833 ../src/ui/theme.c:2853
#: ../src/ui/theme.c:2814 ../src/ui/theme.c:2834 ../src/ui/theme.c:2854
#, c-format
msgid "Theme contained an expression that resulted in an error: %s\n"
msgstr "Tema inneholdt et uttrykk som resulterte i en feil: %s\n"
#: ../src/ui/theme.c:4499
#: ../src/ui/theme.c:4500
#, c-format
msgid ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
@ -1142,25 +1144,25 @@ msgstr ""
"<button function=«%s» state=«%s» draw_ops=«ett-eller-annet»/> må "
"spesifiseres for denne rammestilen"
#: ../src/ui/theme.c:5010 ../src/ui/theme.c:5035
#: ../src/ui/theme.c:5011 ../src/ui/theme.c:5036
#, c-format
msgid ""
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
msgstr ""
"Mangler <frame state=«%s» resize=«%s» focus=«%s» stil=«ett-eller-annet»/>"
#: ../src/ui/theme.c:5083
#: ../src/ui/theme.c:5084
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Klarte ikke å laste tema «%s»: %s\n"
#: ../src/ui/theme.c:5219 ../src/ui/theme.c:5226 ../src/ui/theme.c:5233
#: ../src/ui/theme.c:5240 ../src/ui/theme.c:5247
#: ../src/ui/theme.c:5220 ../src/ui/theme.c:5227 ../src/ui/theme.c:5234
#: ../src/ui/theme.c:5241 ../src/ui/theme.c:5248
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "<%s> er ikke satt for tema «%s»"
#: ../src/ui/theme.c:5255
#: ../src/ui/theme.c:5256
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@ -1169,14 +1171,14 @@ msgstr ""
"Ingen rammestil satt for vindutype «%s» i tema «%s», legg til et <window "
"type=«%s» style_set=«ett-eller-annet»/>-element"
#: ../src/ui/theme.c:5662 ../src/ui/theme.c:5724 ../src/ui/theme.c:5787
#: ../src/ui/theme.c:5663 ../src/ui/theme.c:5725 ../src/ui/theme.c:5788
#, c-format
msgid ""
"User-defined constants must begin with a capital letter; \"%s\" does not"
msgstr ""
"Brukerdefinerte konstanter må begynne med stor bokstav; «%s» gjør ikke det"
#: ../src/ui/theme.c:5670 ../src/ui/theme.c:5732 ../src/ui/theme.c:5795
#: ../src/ui/theme.c:5671 ../src/ui/theme.c:5733 ../src/ui/theme.c:5796
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "Konstant «%s» er allerede definert"
@ -1557,7 +1559,7 @@ msgstr "Ingen tekst er tillatt inne i element <%s>"
msgid "<%s> specified twice for this theme"
msgstr "<%s> spesifisert to ganger for dette temaet"
#: ../src/ui/theme-parser.c:4334
#: ../src/ui/theme-parser.c:4336
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "Fant ikke en gyldig fil for tema %s\n"

493
po/pa.po

File diff suppressed because it is too large Load Diff

921
po/ru.po

File diff suppressed because it is too large Load Diff

480
po/sk.po

File diff suppressed because it is too large Load Diff

View File

@ -10,8 +10,8 @@ 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-03-01 15:50+0000\n"
"PO-Revision-Date: 2013-03-11 11:40+0200\n"
"POT-Creation-Date: 2013-08-18 20:03+0000\n"
"PO-Revision-Date: 2013-09-06 09:19+0200\n"
"Last-Translator: Мирослав Николић <miroslavnikolic@rocketmail.com>\n"
"Language-Team: Serbian <gnom@prevod.org>\n"
"Language: sr\n"
@ -320,6 +320,20 @@ msgstr ""
"Не могу да пронађем тему! Проверите да „%s“ постоји и да садржи уобичајене "
"теме.\n"
#: ../src/core/monitor.c:711
msgid "Built-in display"
msgstr "Уграђени дисплеј"
#. TRANSLATORS: this is a monitor name (in case we don't know
#. the vendor), it's Unknown followed by a size in inches,
#. like 'Unknown 15"'
#.
#: ../src/core/monitor.c:739
#, c-format
#| msgid "Unknown element %s"
msgid "Unknown %s"
msgstr "Непознат %s"
#: ../src/core/mutter.c:40
#, c-format
msgid ""

View File

@ -10,8 +10,8 @@ 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-03-01 15:50+0000\n"
"PO-Revision-Date: 2013-03-11 11:40+0200\n"
"POT-Creation-Date: 2013-08-18 20:03+0000\n"
"PO-Revision-Date: 2013-09-06 09:19+0200\n"
"Last-Translator: Miroslav Nikolić <miroslavnikolic@rocketmail.com>\n"
"Language-Team: Serbian <gnom@prevod.org>\n"
"Language: sr\n"
@ -320,6 +320,20 @@ msgstr ""
"Ne mogu da pronađem temu! Proverite da „%s“ postoji i da sadrži uobičajene "
"teme.\n"
#: ../src/core/monitor.c:711
msgid "Built-in display"
msgstr "Ugrađeni displej"
#. TRANSLATORS: this is a monitor name (in case we don't know
#. the vendor), it's Unknown followed by a size in inches,
#. like 'Unknown 15"'
#.
#: ../src/core/monitor.c:739
#, c-format
#| msgid "Unknown element %s"
msgid "Unknown %s"
msgstr "Nepoznat %s"
#: ../src/core/mutter.c:40
#, c-format
msgid ""

186
po/ug.po
View File

@ -9,8 +9,8 @@ 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-02-20 15:50+0000\n"
"PO-Revision-Date: 2013-02-25 18:42+0900\n"
"POT-Creation-Date: 2013-03-31 13:47+0000\n"
"PO-Revision-Date: 2013-04-06 18:40+0900\n"
"Last-Translator: Gheyret Kenji <gheyret@gmail.com>\n"
"Language-Team: Uyghur Computer Science Association <UKIJ@yahoogroups.com>\n"
"Language: \n"
@ -208,18 +208,18 @@ msgstr "كۆزنەكنىڭ ئوڭ تەرىپىدە كۆرسەتسۇن"
#. 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:507
#: ../src/compositor/compositor.c:568
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
"\"."
msgstr "كۆرسەتكۈچ «%2$s» نىڭدىكى ئېكران %1$i دا بۆلەك باشقۇرغۇچ ئىجرا قىلىنىۋاتىدۇ."
#: ../src/compositor/meta-background.c:1116
#: ../src/compositor/meta-background.c:1064
msgid "background texture could not be created from file"
msgstr "ھۆججەتتىن تەگلىك texture نى قۇرغىلى بولمايدۇ"
#: ../src/core/bell.c:320
#: ../src/core/bell.c:322
msgid "Bell event"
msgstr "قوڭغۇراق ھادىسىسى"
@ -251,53 +251,59 @@ msgstr "كۈت(_W)"
msgid "_Force Quit"
msgstr "مەجبۇرى ئاخىرلاشتۇر(_F)"
#: ../src/core/display.c:392
#: ../src/core/display.c:401
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "بىرىكتۈرۈش ئۈچۈن زۆرۈر بولغان كېڭەيتىلمە %s يوق"
#: ../src/core/display.c:485
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "X كۆزنەك سىستېمىسى كۆرسەتكۈچى %s نى ئېچىش مەغلۇپ بولدى\n"
#: ../src/core/keybindings.c:876
#: ../src/core/keybindings.c:935
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
"binding\n"
msgstr "باشقا پروگرامما %s كۇنۇپكىسى بىلەن سۈپەتلىگۈچى كۇنۇپكا %x نىڭ بىرىكمىسىنى ئىشلىتىۋاتىدۇ\n"
#: ../src/core/main.c:196
#: ../src/core/keybindings.c:1135
#, c-format
#| msgid "\"%s\" is not a valid value for focus attribute"
msgid "\"%s\" is not a valid accelerator\n"
msgstr "«%s» ئىناۋەتلىك تېزلەتكۈچ ئەمەس\n"
#: ../src/core/main.c:197
msgid "Disable connection to session manager"
msgstr "ئەڭگىمە باشقۇرغۇچقا باغلىنىشنى ئىناۋەتسىز قىل"
#: ../src/core/main.c:202
#: ../src/core/main.c:203
msgid "Replace the running window manager"
msgstr "ئىجرا قىلىنىۋاتقان كۆزنەك باشقۇرغۇچنى ئالماشتۇر"
#: ../src/core/main.c:208
#: ../src/core/main.c:209
msgid "Specify session management ID"
msgstr "ئەڭگىمە باشقۇرغۇ ID سېنى بەلگىلە"
#: ../src/core/main.c:213
#: ../src/core/main.c:214
msgid "X Display to use"
msgstr "ئىشلىتىدىغان X كۆرسەتكۈچى"
#: ../src/core/main.c:219
#: ../src/core/main.c:220
msgid "Initialize session from savefile"
msgstr "ساقلانغان ھۆججەتتىن ئەڭگىمەنى دەسلەپلەشتۈرۈش"
#: ../src/core/main.c:225
#: ../src/core/main.c:226
msgid "Make X calls synchronous"
msgstr "X نى قەدەمداش قىلىپ ئىشلەت"
#: ../src/core/main.c:494
#: ../src/core/main.c:534
#, c-format
msgid "Failed to scan themes directory: %s\n"
msgstr "ئۆرنەكلەر مۇندەرىجىسىنى ئىزدەش مەغلۇپ بولدى: %s\n"
#: ../src/core/main.c:510
#: ../src/core/main.c:550
#, c-format
msgid ""
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
@ -324,60 +330,60 @@ msgstr "نەشرىنى باس"
msgid "Mutter plugin to use"
msgstr "ئىشلىتىدىغان Mutter قىستۇرمىسى"
#: ../src/core/prefs.c:1087
#: ../src/core/prefs.c:1095
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
msgstr "بۇزۇلغان پروگراممىلارنى تۈزىتىش-ياخشىلاش ئىناۋەتسىز قىلىنغان. بەزى پروگراممىلار نورمال ئىشلىمەسلىكى مۇمكىن.\n"
#: ../src/core/prefs.c:1162
#: ../src/core/prefs.c:1170
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "GSettings ئاچقۇچى %s نىڭ تەركىبىدىكى فونت چۈشەندۈرۈشى «%s»نى تەھلىل قىلغىنى بولمىدى\n"
#: ../src/core/prefs.c:1228
#: ../src/core/prefs.c:1236
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
"modifier\n"
msgstr "سەپلىمە سانداندىن تېپىلغان «%s» چاشقىنەك توپچىسىنىڭ سۈپەتلىگۈچىسى ئۈچۈن ئىناۋەتسىز\n"
#: ../src/core/prefs.c:1780
#: ../src/core/prefs.c:1788
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
"\"%s\"\n"
msgstr "سەپلىمە ساندىنىدىن تېپىلغان «%s»، «%s» كۇنۇپكا باغلانمىسىنىڭ ئىناۋەتلىك قىممىتى ئەمەس\n"
#: ../src/core/prefs.c:1879
#: ../src/core/prefs.c:1887
#, c-format
msgid "Workspace %d"
msgstr "خىزمەت بوشلۇقى %d"
#: ../src/core/screen.c:673
#: ../src/core/screen.c:691
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "كۆرسەتكۈچ %2$s دىكى ئېكران %1$d ئىناۋەتسىز\n"
#: ../src/core/screen.c:689
#: ../src/core/screen.c:707
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
"replace option to replace the current window manager.\n"
msgstr "كۆرسەتكۈچ «%2$s» دىكى ئېكران %1$d نىڭ كۆزنەك باشقۇرغۇسى بار؛ ھازىرقى كۆزنەك باشقۇرغۇنى ئالماشتۇرۇش ئۈچۈن --replace تاللانمىسىنى ئىشلىتىپ كۆرۈپ بېقىڭ.\n"
#: ../src/core/screen.c:716
#: ../src/core/screen.c:734
#, c-format
msgid ""
"Could not acquire window manager selection on screen %d display \"%s\"\n"
msgstr "كۆرسەتكۈچ «%2$s» نىڭدىكى ئېكران %1$d دا كۆزنەك باشقۇرغۇنىڭ تاللانمىسىنى ئالغىلى بولمىدى\n"
#: ../src/core/screen.c:794
#: ../src/core/screen.c:812
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "«%2$s» دىكى %1$d ئېكراندا بىر كۆزنەك باشقۇرغۇ بار\n"
#: ../src/core/screen.c:979
#: ../src/core/screen.c:998
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "«%2$s» دىكى %1$d ئېكراننى بوشاتقىلى بولمىدى\n"
@ -435,49 +441,49 @@ msgid ""
"be restarted manually next time you log in."
msgstr "بۇ كۆزنەكلەردە «ھازىرقى تەڭشەكنى ساقلاش» ئىقتىدارىنى ئىشلەتكىلى بولمايدۇ. كېيىن كىرگەندە يەنە قوزغىتىڭ."
#: ../src/core/util.c:80
#: ../src/core/util.c:84
#, c-format
msgid "Failed to open debug log: %s\n"
msgstr "سازلاش خاتىرىسىنى ئېچىش مەغلۇپ بولدى:%s\n"
#: ../src/core/util.c:90
#: ../src/core/util.c:94
#, c-format
msgid "Failed to fdopen() log file %s: %s\n"
msgstr "خاتىرە ھۆججىتى %s غا fdopen() مەشغۇلاتى قىلغىلى بولمىدى:%s\n"
#: ../src/core/util.c:96
#: ../src/core/util.c:100
#, c-format
msgid "Opened log file %s\n"
msgstr "ئاچقان خاتىرە ھۆججەت %s\n"
#: ../src/core/util.c:115 ../src/tools/mutter-message.c:149
#: ../src/core/util.c:119 ../src/tools/mutter-message.c:149
#, c-format
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter تەرجىمە-تەھرىرلىگەندە تەپسىلات قوللاش ھالىتى قوشۇلمىغان\n"
#: ../src/core/util.c:259
#: ../src/core/util.c:264
msgid "Window manager: "
msgstr "كۆزنەك باشقۇرغۇ: "
#: ../src/core/util.c:407
#: ../src/core/util.c:412
msgid "Bug in window manager: "
msgstr "كۆزنەك باشقۇرغۇدىكى كەمتۈك: "
#: ../src/core/util.c:438
#: ../src/core/util.c:443
msgid "Window manager warning: "
msgstr "كۆزنەك باشقۇرغۇ ئاگاھلاندۇرۇشى: "
#: ../src/core/util.c:466
#: ../src/core/util.c:471
msgid "Window manager error: "
msgstr "كۆزنەك باشقۇرغۇ خاتالىقى: "
#. first time through
#: ../src/core/window.c:7503
#: ../src/core/window.c:7596
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
"window as specified in the ICCCM.\n"
msgstr "كۆزنەك %s بەلگىلىمە ICCCM دا بەلگىلەنگەن WM_CLIENT_LEADER كۆزنەكنى ئەمەس SM_CLIENT_ID نى ئۆزى بەلگىلىۋېپتۇ.\n"
msgstr "كۆزنەك %s بەلگىلىمە ICCCM دا بەلگىلەنگەن WM_CLIENT_LEADER كۆزنەكنى ئەمەس SM_CLIENT_ID نى ئۆزى بەلگىلىۋېلىپتۇ.\n"
#. We ignore mwm_has_resize_func because WM_NORMAL_HINTS is the
#. * authoritative source for that info. Some apps such as mplayer or
@ -486,29 +492,29 @@ msgstr "كۆزنەك %s بەلگىلىمە ICCCM دا بەلگىلەنگەن WM
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8227
#: ../src/core/window.c:8320
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
"%d x %d and max size %d x %d; this doesn't make much sense.\n"
msgstr "كۆزنەك %s نىڭدا MWM بەلگىلەنگەن بولۇپ، بۇ كۆزنەك چوڭلۇقىنى ئۆزگەرتكىلى بولمايدۇ دېگەن مەنىدە. بىراق ئەڭ كىچىك چوڭلۇقى%d x %d، ۋە ئەڭ كىچىك چوڭلۇقى %d x %d قىلىپ بەلگىلىنىپتۇ. بۇنىڭ ھېچقانداق ئەھمىيىتى يوق.\n"
#: ../src/core/window-props.c:304
#: ../src/core/window-props.c:318
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "پروگرامما بىر ساختا _NET_WM_PID نى بەلگىلىدى%lu\n"
#: ../src/core/window-props.c:423
#: ../src/core/window-props.c:434
#, c-format
msgid "%s (on %s)"
msgstr "%s (ھازىر %s نىڭ ئۈستىدە)"
#: ../src/core/window-props.c:1506
#: ../src/core/window-props.c:1517
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "%2$s گە بەلگىلەنگەن ئۈنۈمسىز WM_TRANSIENT_FOR كۆزنەك 0x%1$lx بولىدۇ.\n"
#: ../src/core/window-props.c:1517
#: ../src/core/window-props.c:1528
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "%2$s نىڭ WM_TRANSIENT_FOR كۆزنەك0x%1$lx دەۋرىيلىك قۇرۇشى مۇمكىن.\n"
@ -850,261 +856,261 @@ msgstr "Mod5"
msgid "%d x %d"
msgstr "%d x %d"
#: ../src/ui/theme.c:235
#: ../src/ui/theme.c:236
msgid "top"
msgstr "چوققا"
#: ../src/ui/theme.c:237
#: ../src/ui/theme.c:238
msgid "bottom"
msgstr "ئاستى"
#: ../src/ui/theme.c:239
#: ../src/ui/theme.c:240
msgid "left"
msgstr "سول"
#: ../src/ui/theme.c:241
#: ../src/ui/theme.c:242
msgid "right"
msgstr "ئوڭ"
#: ../src/ui/theme.c:269
#: ../src/ui/theme.c:270
#, c-format
msgid "frame geometry does not specify \"%s\" dimension"
msgstr "كاندۇكنىڭ گېئومېتىرىيىلىك شەكلى «%s» ئۆلچەمنى ئىپادىلىمەيدۇ"
#: ../src/ui/theme.c:288
#: ../src/ui/theme.c:289
#, c-format
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
msgstr "كاندۇكنىڭ گېئومېتىرىيىلىك شەكلى گىرۋەك «%2$s» نىڭ ئۆلچىمى «%1$s» ئىپادىلىمەيدۇ"
#: ../src/ui/theme.c:325
#: ../src/ui/theme.c:326
#, c-format
msgid "Button aspect ratio %g is not reasonable"
msgstr "توپچىنىڭ ئېگىزلىك ۋە كەڭلىك نىسبىتى %g مۇۋاپىق ئەمەس"
#: ../src/ui/theme.c:337
#: ../src/ui/theme.c:338
#, c-format
msgid "Frame geometry does not specify size of buttons"
msgstr "كاندۇكنىڭ گېئومېتىرىيىلىك شەكلى توپچىلارنىڭ چوڭلۇقىنى ئىپادىلىمەيدۇ"
#: ../src/ui/theme.c:1050
#: ../src/ui/theme.c:1051
#, c-format
msgid "Gradients should have at least two colors"
msgstr "تەدرىجىي ئۆزگىرىشتە ئاز دېگەندە ئىككى خىل رەڭ بولۇش كېرەك"
#: ../src/ui/theme.c:1202
#: ../src/ui/theme.c:1203
#, 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 رەڭ ئۆلچىمىدە ھالەتتىن كېيىن چوقۇم رەڭ ئاتى ۋە زاپاس بولۇشى لازىم، مەسىلەن، gtk:custom(foo,bar) ھالەت؛ «%s» نى تەھلىل قىلالمايدۇ"
#: ../src/ui/theme.c:1218
#: ../src/ui/theme.c:1219
#, c-format
msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
"_ are valid"
msgstr "gtk:custom نىڭ color_name پارامېتىرىدىكى ئىناۋەتسىز ھەرپ '%c'، پەقەت A-Za-z0-9-_ نىلا ئىشلەتكىلى بولىدۇ"
#: ../src/ui/theme.c:1232
#: ../src/ui/theme.c:1233
#, c-format
msgid ""
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
"fit the format"
msgstr "Gtk:custom نىڭ پىچىمى \"gtk:custom(color_name,fallback)\" بولۇپ، «%s» پىچىمغا توغرا كەلمەيدۇ"
#: ../src/ui/theme.c:1277
#: ../src/ui/theme.c:1278
#, c-format
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 رەڭ بەلگىلىمىسىنىڭ ھالىتى چوقۇم gtk:fg[NORMAL] نىڭدەك تىرناق ئىچىگە ئېلىنىشى كېرەك؛ «%s» نى تەھلىل قىلغىلى بولمىدى."
#: ../src/ui/theme.c:1291
#: ../src/ui/theme.c:1292
#, c-format
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 رەڭ بەلگىلىمىسىنىڭ ھالىتىنىڭ ئارقىسىغا سول تىرناق يېزىلىشى كېرەك. مەسىلەن gtk:fg[NORMAL] نىڭدەك بۇ يەردىكى «NORMAL» ھالەتنى بىلدۈرىدۇ؛ «%s» نى تەھلىل قىلغىلى بولمىدى."
#: ../src/ui/theme.c:1302
#: ../src/ui/theme.c:1303
#, c-format
msgid "Did not understand state \"%s\" in color specification"
msgstr "رەڭ بەلگىلىمىسىدىكى «%s» ھالەتنى چۈشەنگىلى بولمىدى"
#: ../src/ui/theme.c:1315
#: ../src/ui/theme.c:1316
#, c-format
msgid "Did not understand color component \"%s\" in color specification"
msgstr "رەڭ بەلگىلىمىسىدىكى «%s» رەڭ بۆلىكىنى چۈشەنگىلى بولمىدى"
#: ../src/ui/theme.c:1344
#: ../src/ui/theme.c:1345
#, c-format
msgid ""
"Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the "
"format"
msgstr "بىرىكمە رەڭنىڭ فورماتى \"blend/bg_color/fg_color/alpha\"، «%s» بۇ پىچىمغا ماس كەلمىدى"
#: ../src/ui/theme.c:1355
#: ../src/ui/theme.c:1356
#, c-format
msgid "Could not parse alpha value \"%s\" in blended color"
msgstr "بىرىكمە رەڭدىكى ئالفا قىممىتى «%s» نى تەھلىل قىلغىلى بولمىدى"
#: ../src/ui/theme.c:1365
#: ../src/ui/theme.c:1366
#, c-format
msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
msgstr "بىرىكمە رەڭنىڭ ئالفا قىممىتى «%s» نىڭ دائىرىسى 0.0 ~1.0 ئىچىدە ئەمەس"
#: ../src/ui/theme.c:1412
#: ../src/ui/theme.c:1413
#, c-format
msgid ""
"Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
msgstr "سايە پىچىمى «shade/base_color/factor»، «%s» بۇ پىچىمغا ماسلاشمىدى"
#: ../src/ui/theme.c:1423
#: ../src/ui/theme.c:1424
#, c-format
msgid "Could not parse shade factor \"%s\" in shaded color"
msgstr "سايە رەڭگىدىكى سايە فاكتور «%s» نى تەھلىل قىلغىلى بولمىدى"
#: ../src/ui/theme.c:1433
#: ../src/ui/theme.c:1434
#, c-format
msgid "Shade factor \"%s\" in shaded color is negative"
msgstr "سايە رەڭگىدىكى سايە فاكتورى «%s» مەنپىي سان"
#: ../src/ui/theme.c:1462
#: ../src/ui/theme.c:1463
#, c-format
msgid "Could not parse color \"%s\""
msgstr "رەڭ «%s» نى ئانالىز قىلغىلى بولمىدى"
#: ../src/ui/theme.c:1779
#: ../src/ui/theme.c:1780
#, c-format
msgid "Coordinate expression contains character '%s' which is not allowed"
msgstr "كوئوردېنات ئىپادىسىنىڭ تەركىبىدە رۇخسەت قىلىنمىغان ھەرپ '%s بار"
#: ../src/ui/theme.c:1806
#: ../src/ui/theme.c:1807
#, c-format
msgid ""
"Coordinate expression contains floating point number '%s' which could not be "
"parsed"
msgstr "كوئوردېنات ئىپادىسىنىڭ تەركىبىدە تەھلىل قىلغىلى بولمايدىغان كەسىر سان %s بار"
#: ../src/ui/theme.c:1820
#: ../src/ui/theme.c:1821
#, c-format
msgid "Coordinate expression contains integer '%s' which could not be parsed"
msgstr "كوئوردېنات ئىپادىسىنىڭ تەركىبىدە تەھلىل قىلغىلى بولمايدىغان پۈتۈن سان %s بار"
#: ../src/ui/theme.c:1941
#: ../src/ui/theme.c:1942
#, c-format
msgid ""
"Coordinate expression contained unknown operator at the start of this text: "
"\"%s\""
msgstr "كوئوردېنات ئىپادىسىنىڭ بېشىدا نامەلۇم ئەمەل بار: «%s»"
#: ../src/ui/theme.c:1998
#: ../src/ui/theme.c:1999
#, c-format
msgid "Coordinate expression was empty or not understood"
msgstr "كوئوردېنات ئىپادىسى قۇرۇق ياكى چۈشىنىكسىز"
#: ../src/ui/theme.c:2111 ../src/ui/theme.c:2121 ../src/ui/theme.c:2155
#: ../src/ui/theme.c:2112 ../src/ui/theme.c:2122 ../src/ui/theme.c:2156
#, c-format
msgid "Coordinate expression results in division by zero"
msgstr "كوئوردېنات ئىپادىسى 0 نى بۆلگۈچى قىلغان"
#: ../src/ui/theme.c:2163
#: ../src/ui/theme.c:2164
#, c-format
msgid ""
"Coordinate expression tries to use mod operator on a floating-point number"
msgstr "كوئوردېنات ئىپادىسى كەسىر سانغا mod ئەمىلىنى ئىشلەتمەكچى"
#: ../src/ui/theme.c:2219
#: ../src/ui/theme.c:2220
#, c-format
msgid ""
"Coordinate expression has an operator \"%s\" where an operand was expected"
msgstr "كوئوردېنات ئىپادىسىنىڭ تەركىبىدە سان كېلىدىغان يەردە ئەمەل «%s» بار ئىكەن"
#: ../src/ui/theme.c:2228
#: ../src/ui/theme.c:2229
#, c-format
msgid "Coordinate expression had an operand where an operator was expected"
msgstr "كوئوردېنات ئىپادىسىنىڭ تەركىبىدە ئەمەل كېلىدىغان يەردە سان بار ئىكەن"
#: ../src/ui/theme.c:2236
#: ../src/ui/theme.c:2237
#, c-format
msgid "Coordinate expression ended with an operator instead of an operand"
msgstr "كوئوردېنات ئىپادىسى سان بىلەن ئاياغلاشماي ئەمەل بىلەن ئاياغلاشقان"
#: ../src/ui/theme.c:2246
#: ../src/ui/theme.c:2247
#, c-format
msgid ""
"Coordinate expression has operator \"%c\" following operator \"%c\" with no "
"operand in between"
msgstr "كوئوردېنات ئىپادىسىنىڭ تەركىبىدە ئەمەل «%2$c» نىڭ ئارقىسىدىن ئەمەل «%1$c» كېلىپتۇ، ئارىلىقتا سان يوق ئىكەن"
#: ../src/ui/theme.c:2397 ../src/ui/theme.c:2442
#: ../src/ui/theme.c:2398 ../src/ui/theme.c:2443
#, c-format
msgid "Coordinate expression had unknown variable or constant \"%s\""
msgstr "كوئوردېنات ئىپادىسىنىڭ تەركىبىدە نامەلۇم ئۆزگەرگۈچى ياكى تۇراقلىق سان «%s» بار ئىكەن"
#: ../src/ui/theme.c:2496
#: ../src/ui/theme.c:2497
#, c-format
msgid "Coordinate expression parser overflowed its buffer."
msgstr "كوئوردېنات ئىپادىسىنى تەھلىل قىلىۋاتقاندا يىغلەك تېشىپ كەتتى."
#: ../src/ui/theme.c:2525
#: ../src/ui/theme.c:2526
#, c-format
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
msgstr "كوئوردېنات ئىپادىسىنىڭ تەركىبىدىكى يېپىلغان تىرناققا ماس كېلىدىغان ئېچىلغان تىرناق يوق"
#: ../src/ui/theme.c:2589
#: ../src/ui/theme.c:2590
#, c-format
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
msgstr "كوئوردېنات ئىپادىسىنىڭ تەركىبىدىكى ئېچىلغان تىرناققا ماس كېلىدىغان يېپىلغان تىرناق يوق"
#: ../src/ui/theme.c:2600
#: ../src/ui/theme.c:2601
#, c-format
msgid "Coordinate expression doesn't seem to have any operators or operands"
msgstr "كوئوردېنات ئىپادىسىنىڭ تەركىبىدە ئەمەل(قوشۇش، ئېلىش...) ياكى سان يوق"
#: ../src/ui/theme.c:2813 ../src/ui/theme.c:2833 ../src/ui/theme.c:2853
#: ../src/ui/theme.c:2814 ../src/ui/theme.c:2834 ../src/ui/theme.c:2854
#, c-format
msgid "Theme contained an expression that resulted in an error: %s\n"
msgstr "ئۆرنەك تەركىبىدە خاتالىق چىقىرىدىغان ئىپادە بار: %s\n"
#: ../src/ui/theme.c:4499
#: ../src/ui/theme.c:4500
#, c-format
msgid ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
"specified for this frame style"
msgstr "<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/>بۇ كۆزنەكنىڭ ئۇسلۇبى ئۈچۈن بەلگىلىنىشى زۆرۈر"
#: ../src/ui/theme.c:5010 ../src/ui/theme.c:5035
#: ../src/ui/theme.c:5011 ../src/ui/theme.c:5036
#, c-format
msgid ""
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
msgstr "<frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/> يوق"
#: ../src/ui/theme.c:5083
#: ../src/ui/theme.c:5084
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "ئۆرنەك «%s» نى ئوقۇش مەغلۇپ بولدى: %s\n"
#: ../src/ui/theme.c:5219 ../src/ui/theme.c:5226 ../src/ui/theme.c:5233
#: ../src/ui/theme.c:5240 ../src/ui/theme.c:5247
#: ../src/ui/theme.c:5220 ../src/ui/theme.c:5227 ../src/ui/theme.c:5234
#: ../src/ui/theme.c:5241 ../src/ui/theme.c:5248
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "ئۆرنەك «%2$s» نىڭ <%1$s> ئى بەلگىلەنمىگەن"
#: ../src/ui/theme.c:5255
#: ../src/ui/theme.c:5256
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
"type=\"%s\" style_set=\"whatever\"/> element"
msgstr "ئۆرنەك «%2$s» نىڭ ئىچىدىكى كۆزنەك تىپى <%1$s> نىڭ كاندۇك ئۇسلۇبى بەلگىلەنمىگەن. بىر <window type=\"%3$s\" style_set=\"whatever\"/> ئېلېمېنتى قوشۇڭ"
#: ../src/ui/theme.c:5662 ../src/ui/theme.c:5724 ../src/ui/theme.c:5787
#: ../src/ui/theme.c:5663 ../src/ui/theme.c:5725 ../src/ui/theme.c:5788
#, c-format
msgid ""
"User-defined constants must begin with a capital letter; \"%s\" does not"
msgstr "ئىشلەتكۈچى بەلگىلىگەن تۇراقلىق مىقدار چوقۇم چوڭ ھەرپ بىلەن باشلانسۇن؛ «%s» بولمايدۇ"
#: ../src/ui/theme.c:5670 ../src/ui/theme.c:5732 ../src/ui/theme.c:5795
#: ../src/ui/theme.c:5671 ../src/ui/theme.c:5733 ../src/ui/theme.c:5796
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "تۇراقلىق سان «%s» غا ئېنىقلىما بېرىلگەن"
@ -1464,7 +1470,7 @@ msgstr "ئېلېمېنت <%s> نىڭ ئىچىدە تېكىست بولسا بول
msgid "<%s> specified twice for this theme"
msgstr "بۇ ئۆرنەك ئۈچۈن <%s> ئىككى قېتىم بەلگىلەنگەن"
#: ../src/ui/theme-parser.c:4334
#: ../src/ui/theme-parser.c:4336
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "ئۆرنەك %s ئۈچۈن ئىناۋەتلىك ھۆججەتنى تېپىش مەغلۇپ بولدى\n"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1
protocol/Makefile.am Normal file
View File

@ -0,0 +1 @@
EXTRA_DIST = xserver.xml

30
protocol/gtk-shell.xml Normal file
View File

@ -0,0 +1,30 @@
<protocol name="gtk">
<interface name="gtk_shell" version="1">
<enum name="capability">
<entry name="global_app_menu" value="1"/>
<entry name="global_menu_bar" value="2"/>
</enum>
<event name="capabilities">
<arg name="capabilities" type="uint"/>
</event>
<request name="get_gtk_surface">
<arg name="gtk_surface" type="new_id" interface="gtk_surface"/>
<arg name="surface" type="object" interface="wl_surface"/>
</request>
</interface>
<interface name="gtk_surface" version="1">
<request name="set_dbus_properties">
<arg name="application_id" type="string" allow-null="true"/>
<arg name="app_menu_path" type="string" allow-null="true"/>
<arg name="menubar_path" type="string" allow-null="true"/>
<arg name="window_object_path" type="string" allow-null="true"/>
<arg name="application_object_path" type="string" allow-null="true"/>
<arg name="unique_bus_name" type="string" allow-null="true"/>
</request>
</interface>
</protocol>

18
protocol/xserver.xml Normal file
View File

@ -0,0 +1,18 @@
<protocol name="xserver">
<interface name="xserver" version="1">
<request name="set_window_id">
<arg name="surface" type="object" interface="wl_surface"/>
<arg name="id" type="uint"/>
</request>
<event name="client">
<arg name="fd" type="fd"/>
</event>
<event name="listen_socket">
<arg name="fd" type="fd"/>
</event>
</interface>
</protocol>

View File

@ -1,15 +1,16 @@
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
.AUTOPARALLEL:
lib_LTLIBRARIES = libmutter.la
lib_LTLIBRARIES = libmutter-wayland.la
SUBDIRS=wm-tester tools compositor/plugins
SUBDIRS=compositor/plugins
INCLUDES= \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
$(MUTTER_CFLAGS) \
-I$(top_builddir) \
-I$(srcdir) \
-I$(srcdir)/core \
-I$(srcdir)/ui \
@ -29,11 +30,24 @@ INCLUDES= \
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
mutter_built_sources = \
mutter-enum-types.h \
mutter-enum-types.c
INCLUDES += \
-I$(srcdir)/wayland \
-I$(builddir)/wayland \
-DXWAYLAND_PATH='"@XWAYLAND_PATH@"'
libmutter_la_SOURCES = \
mutter_built_sources = \
$(dbus_idle_built_sources) \
$(dbus_xrandr_built_sources) \
mutter-enum-types.h \
mutter-enum-types.c \
wayland/gtk-shell-protocol.c \
wayland/gtk-shell-server-protocol.h \
wayland/gtk-shell-client-protocol.h \
wayland/xserver-protocol.c \
wayland/xserver-server-protocol.h \
wayland/xserver-client-protocol.h
libmutter_wayland_la_SOURCES = \
core/async-getprop.c \
core/async-getprop.h \
core/barrier.c \
@ -62,6 +76,7 @@ libmutter_la_SOURCES = \
compositor/meta-shadow-factory.c \
compositor/meta-shadow-factory-private.h \
compositor/meta-shaped-texture.c \
compositor/meta-shaped-texture-private.h \
compositor/meta-texture-rectangle.c \
compositor/meta-texture-rectangle.h \
compositor/meta-texture-tower.c \
@ -94,6 +109,8 @@ libmutter_la_SOURCES = \
ui/draw-workspace.h \
core/edge-resistance.c \
core/edge-resistance.h \
core/edid-parse.c \
core/edid.h \
core/errors.c \
meta/errors.h \
core/frame.c \
@ -110,6 +127,16 @@ libmutter_la_SOURCES = \
core/keybindings.c \
core/keybindings-private.h \
core/main.c \
core/meta-cursor-tracker.c \
core/meta-cursor-tracker-private.h \
core/meta-idle-monitor.c \
core/meta-idle-monitor-private.h \
core/meta-xrandr-shared.h \
core/monitor.c \
core/monitor-config.c \
core/monitor-kms.c \
core/monitor-private.h \
core/monitor-xrandr.c \
core/mutter-Xatomtype.h \
core/place.c \
core/place.h \
@ -127,6 +154,7 @@ libmutter_la_SOURCES = \
core/stack-tracker.h \
core/util.c \
meta/util.h \
core/util-private.h \
core/window-props.c \
core/window-props.h \
core/window.c \
@ -139,7 +167,6 @@ libmutter_la_SOURCES = \
meta/common.h \
core/core.h \
ui/ui.h \
inlinepixbufs.h \
ui/frames.c \
ui/frames.h \
ui/menu.c \
@ -157,12 +184,32 @@ libmutter_la_SOURCES = \
meta/theme.h \
ui/theme-private.h \
ui/ui.c \
meta/preview-widget.h \
ui/preview-widget.c \
$(mutter_built_sources)
libmutter_la_LDFLAGS = -no-undefined
libmutter_la_LIBADD = $(MUTTER_LIBS)
libmutter_wayland_la_SOURCES += \
wayland/meta-wayland.c \
wayland/meta-wayland-private.h \
wayland/meta-xwayland-private.h \
wayland/meta-xwayland.c \
wayland/meta-wayland-data-device.c \
wayland/meta-wayland-data-device.h \
wayland/meta-wayland-keyboard.c \
wayland/meta-wayland-keyboard.h \
wayland/meta-wayland-pointer.c \
wayland/meta-wayland-pointer.h \
wayland/meta-wayland-seat.c \
wayland/meta-wayland-seat.h \
wayland/meta-wayland-stage.h \
wayland/meta-wayland-stage.c \
wayland/meta-wayland-surface.c \
wayland/meta-wayland-surface.h \
wayland/meta-wayland-types.h \
wayland/meta-wayland-versions.h \
wayland/meta-weston-launch.c \
wayland/meta-weston-launch.h
libmutter_wayland_la_LDFLAGS = -no-undefined
libmutter_wayland_la_LIBADD = $(MUTTER_LIBS)
# Headers installed for plugins; introspected information will
# be extracted into Mutter-<version>.gir
@ -181,6 +228,8 @@ libmutterinclude_base_headers = \
meta/meta-background-actor.h \
meta/meta-background-group.h \
meta/meta-background.h \
meta/meta-cursor-tracker.h \
meta/meta-idle-monitor.h \
meta/meta-plugin.h \
meta/meta-shaped-texture.h \
meta/meta-shadow-factory.h \
@ -196,22 +245,29 @@ libmutterinclude_base_headers = \
# Excluded from scanning for introspection but installed
# atomnames.h: macros cause problems for scanning process
libmutterinclude_extra_headers = \
meta/preview-widget.h \
meta/atomnames.h
libmutterincludedir = $(includedir)/mutter/meta
libmutterincludedir = $(includedir)/mutter-wayland/meta
libmutterinclude_HEADERS = \
$(libmutterinclude_base_headers) \
$(libmutterinclude_extra_headers)
mutter_theme_viewer_SOURCES= \
ui/theme-viewer.c
bin_PROGRAMS=mutter-wayland
bin_PROGRAMS=mutter mutter-theme-viewer
mutter_wayland_SOURCES = core/mutter.c
mutter_wayland_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
mutter_SOURCES = core/mutter.c
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
bin_PROGRAMS+=mutter-launch
mutter_launch_SOURCES = wayland/weston-launch.c wayland/weston-launch.h
mutter_launch_CFLAGS = $(MUTTER_LAUNCH_CFLAGS) -DLIBDIR=\"$(libdir)\"
mutter_launch_LDFLAGS = $(MUTTER_LAUNCH_LIBS) -lpam
install-exec-hook:
-chown root $(DESTDIR)$(bindir)/mutter-launch
-chmod u+s $(DESTDIR)$(bindir)/mutter-launch
if HAVE_INTROSPECTION
include $(INTROSPECTION_MAKEFILE)
@ -233,43 +289,36 @@ typelib_DATA = Meta-$(api_version).typelib
INTROSPECTION_GIRS = Meta-$(api_version).gir
Meta-$(api_version).gir: libmutter.la
Meta-$(api_version).gir: libmutter-wayland.la
@META_GIR@_INCLUDES = GObject-2.0 GDesktopEnums-3.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0 Cogl-1.0
@META_GIR@_EXPORT_PACKAGES = libmutter
@META_GIR@_EXPORT_PACKAGES = libmutter-wayland
@META_GIR@_CFLAGS = $(INCLUDES)
@META_GIR@_LIBS = libmutter.la
@META_GIR@_LIBS = libmutter-wayland.la
@META_GIR@_FILES = \
mutter-enum-types.h \
$(libmutterinclude_base_headers) \
$(filter %.c,$(libmutter_la_SOURCES))
$(filter %.c,$(libmutter_wayland_la_SOURCES))
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
endif
mutter_theme_viewer_LDADD= $(MUTTER_LIBS) libmutter.la
testboxes_SOURCES = core/testboxes.c
testgradient_SOURCES = ui/testgradient.c
testasyncgetprop_SOURCES = core/testasyncgetprop.c
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
testboxes_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
testgradient_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter-wayland.la
@INTLTOOL_DESKTOP_RULE@
desktopfilesdir=$(datadir)/applications
desktopfiles_in_files=mutter.desktop.in
desktopfiles_in_files=mutter-wayland.desktop.in
desktopfiles_files=$(desktopfiles_in_files:.desktop.in=.desktop)
desktopfiles_DATA = $(desktopfiles_files)
wmpropertiesdir=$(datadir)/gnome/wm-properties
wmproperties_in_files=mutter-wm.desktop.in
wmproperties_files=$(wmproperties_in_files:.desktop.in=.desktop)
wmproperties_DATA = $(wmproperties_files)
xmldir = @GNOME_KEYBINDINGS_KEYSDIR@
xml_in_files = \
50-mutter-navigation.xml.in \
@ -277,35 +326,28 @@ xml_in_files = \
50-mutter-windows.xml.in
xml_DATA = $(xml_in_files:.xml.in=.xml)
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
gsettings_SCHEMAS = org.gnome.mutter.gschema.xml org.gnome.mutter.wayland.gschema.xml
@INTLTOOL_XML_NOMERGE_RULE@
@GSETTINGS_RULES@
convertdir = $(datadir)/GConf/gsettings
convert_DATA = mutter-schemas.convert
IMAGES=stock_maximize.png stock_minimize.png stock_delete.png
VARIABLES=stock_maximize_data $(srcdir)/stock_maximize.png \
stock_minimize_data $(srcdir)/stock_minimize.png \
stock_delete_data $(srcdir)/stock_delete.png
BUILT_SOURCES = inlinepixbufs.h
CLEANFILES = \
inlinepixbufs.h \
mutter.desktop \
mutter-wayland.desktop \
mutter-wm.desktop \
org.gnome.mutter.gschema.xml \
org.gnome.mutter.wayland.gschema.xml \
$(xml_DATA) \
$(mutter_built_sources) \
$(typelib_DATA) \
$(gir_DATA)
inlinepixbufs.h: $(IMAGES)
$(GDK_PIXBUF_CSOURCE) --raw --build-list $(VARIABLES) >$(srcdir)/inlinepixbufs.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmutter.pc mutter-plugins.pc
pkgconfig_DATA = libmutter-wayland.pc
EXTRA_DIST=$(desktopfiles_files) \
$(wmproperties_files) \
@ -314,13 +356,14 @@ EXTRA_DIST=$(desktopfiles_files) \
$(wmproperties_in_files) \
$(xml_in_files) \
org.gnome.mutter.gschema.xml.in \
org.gnome.mutter.wayland.gschema.xml.in \
mutter-schemas.convert \
libmutter.pc.in \
mutter-plugins.pc.in \
libmutter-wayland.pc.in \
mutter-enum-types.h.in \
mutter-enum-types.c.in
mutter-enum-types.c.in \
xrandr.xml idle-monitor.xml
BUILT_SOURCES += $(mutter_built_sources)
BUILT_SOURCES = $(mutter_built_sources)
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
CLEANFILES += $(MUTTER_STAMP_FILES)
@ -342,3 +385,32 @@ mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
$(libmutterinclude_base_headers) ) >> xgen-tetc && \
cp xgen-tetc mutter-enum-types.c && \
rm -f xgen-tetc
dbus_xrandr_built_sources = meta-dbus-xrandr.c meta-dbus-xrandr.h
$(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
$(AM_V_GEN)gdbus-codegen \
--interface-prefix org.gnome.Mutter \
--c-namespace MetaDBus \
--generate-c-code meta-dbus-xrandr \
$(srcdir)/xrandr.xml
dbus_idle_built_sources = meta-dbus-idle-monitor.c meta-dbus-idle-monitor.h
$(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
$(AM_V_GEN)gdbus-codegen \
--interface-prefix org.gnome.Mutter \
--c-namespace MetaDBus \
--generate-c-code meta-dbus-idle-monitor \
--c-generate-object-manager \
$(srcdir)/idle-monitor.xml
wayland/%-protocol.c : $(top_builddir)/protocol/%.xml
mkdir -p wayland
$(AM_V_GEN)$(WAYLAND_SCANNER) code < $< > $@
wayland/%-server-protocol.h : $(top_builddir)/protocol/%.xml
mkdir -p wayland
$(AM_V_GEN)$(WAYLAND_SCANNER) server-header < $< > $@
wayland/%-client-protocol.h : $(top_builddir)/protocol/%.xml
mkdir -p wayland
$(AM_V_GEN)$(WAYLAND_SCANNER) client-header < $< > $@

View File

@ -50,7 +50,7 @@ meta_create_color_texture_4ub (guint8 red,
CoglColor color;
guint8 pixel[4];
cogl_color_set_from_4ub (&color, red, green, blue, alpha);
cogl_color_init_from_4ub (&color, red, green, blue, alpha);
cogl_color_premultiply (&color);
pixel[0] = cogl_color_get_red_byte (&color);
@ -73,10 +73,8 @@ meta_create_color_texture_4ub (guint8 red,
* @src_texture: (allow-none): texture to use initially for the layer
*
* Creates a pipeline with a single layer. Using a common template
* allows sharing a shader for different uses in Mutter. To share the same
* shader with all other pipelines that are just texture plus opacity
* would require Cogl fixes.
* (See http://bugzilla.clutter-project.org/show_bug.cgi?id=2425)
* makes it easier for Cogl to share a shader for different uses in
* Mutter.
*
* Return value: (transfer full): a newly created #CoglPipeline
*/
@ -86,22 +84,21 @@ meta_create_texture_pipeline (CoglTexture *src_texture)
static CoglPipeline *texture_pipeline_template = NULL;
CoglPipeline *pipeline;
/* We use a pipeline that has a dummy texture as a base for all
texture pipelines. The idea is that only the Cogl texture object
would be different in the children so it is likely that Cogl will
be able to share GL programs between all the textures. */
/* The only state used in the pipeline that would affect the shader
generation is the texture type on the layer. Therefore we create
a template pipeline which sets this state and all texture
pipelines are created as a copy of this. That way Cogl can find
the shader state for the pipeline more quickly by looking at the
pipeline ancestry instead of resorting to the shader cache. */
if (G_UNLIKELY (texture_pipeline_template == NULL))
{
CoglTexture *dummy_texture;
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
dummy_texture = meta_create_color_texture_4ub (0xff, 0xff, 0xff, 0xff,
COGL_TEXTURE_NONE);
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
texture_pipeline_template = cogl_pipeline_new (ctx);
cogl_pipeline_set_layer_texture (texture_pipeline_template, 0, dummy_texture);
cogl_object_unref (dummy_texture);
cogl_pipeline_set_layer_null_texture (texture_pipeline_template,
0, /* layer */
COGL_TEXTURE_TYPE_2D);
}
pipeline = cogl_pipeline_copy (texture_pipeline_template);

View File

@ -66,8 +66,6 @@ void meta_switch_workspace_completed (MetaScreen *screen);
gboolean meta_begin_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp);
void meta_end_modal_for_plugin (MetaScreen *screen,

View File

@ -53,17 +53,15 @@
*
* # Containers #
*
* There's three containers in the stage that can be used to place actors, here
* There's two containers in the stage that are used to place window actors, here
* are listed in the order in which they are painted:
*
* - window group, accessible with meta_get_window_group_for_screen()
* - top window group, accessible with meta_get_top_window_group_for_screen()
* - overlay group, accessible with meta_get_overlay_group_for_screen()
*
* Mutter will place actors representing windows in the window group, except for
* override-redirect windows (ie. popups and menus) which will be placed in the
* top window group. Mutter won't put any actors in the overlay group, but it's
* intended for compositors to place there panel, dashes, status bars, etc.
* top window group.
*/
#include <config.h>
@ -86,6 +84,10 @@
#include "meta-window-group.h"
#include "window-private.h" /* to check window->hidden */
#include "display-private.h" /* for meta_display_lookup_x_window() */
#include "util-private.h"
#include "meta-wayland-private.h"
#include "meta-wayland-pointer.h"
#include "meta-wayland-keyboard.h"
#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
@ -174,7 +176,7 @@ process_damage (MetaCompositor *compositor,
if (window_actor == NULL)
return;
meta_window_actor_process_damage (window_actor, event);
meta_window_actor_process_x11_damage (window_actor, event);
}
static void
@ -255,23 +257,6 @@ meta_get_stage_for_screen (MetaScreen *screen)
return info->stage;
}
/**
* meta_get_overlay_group_for_screen:
* @screen: a #MetaScreen
*
* Returns: (transfer none): The overlay group corresponding to @screen
*/
ClutterActor *
meta_get_overlay_group_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info)
return NULL;
return info->overlay_group;
}
/**
* meta_get_window_group_for_screen:
* @screen: a #MetaScreen
@ -346,29 +331,37 @@ void
meta_set_stage_input_region (MetaScreen *screen,
XserverRegion region)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
/* As a wayland compositor we can simply ignore all this trickery
* for setting an input region on the stage for capturing events in
* clutter since all input comes to us first and we get to choose
* who else sees them.
*/
if (!meta_is_wayland_compositor ())
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
if (info->stage && info->output)
{
do_set_stage_input_region (screen, region);
if (info->stage && info->output)
{
do_set_stage_input_region (screen, region);
}
else
{
/* Reset info->pending_input_region if one existed before and set the new
* one to use it later. */
if (info->pending_input_region)
{
XFixesDestroyRegion (xdpy, info->pending_input_region);
info->pending_input_region = None;
}
if (region != None)
{
info->pending_input_region = XFixesCreateRegion (xdpy, NULL, 0);
XFixesCopyRegion (xdpy, info->pending_input_region, region);
}
}
}
else
{
/* Reset info->pending_input_region if one existed before and set the new
* one to use it later. */
if (info->pending_input_region)
{
XFixesDestroyRegion (xdpy, info->pending_input_region);
info->pending_input_region = None;
}
if (region != None)
{
info->pending_input_region = XFixesCreateRegion (xdpy, NULL, 0);
XFixesCopyRegion (xdpy, info->pending_input_region, region);
}
}
}
void
@ -388,28 +381,67 @@ meta_empty_stage_input_region (MetaScreen *screen)
meta_set_stage_input_region (screen, region);
}
gboolean
meta_begin_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp)
void
meta_focus_stage_window (MetaScreen *screen,
guint32 timestamp)
{
/* To some extent this duplicates code in meta_display_begin_grab_op(), but there
* are significant differences in how we handle grabs that make it difficult to
* merge the two.
*/
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
MetaCompositor *compositor = display->compositor;
gboolean pointer_grabbed = FALSE;
gboolean keyboard_grabbed = FALSE;
int result;
ClutterStage *stage;
Window window;
if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
if (!stage)
return;
if (!meta_is_wayland_compositor ())
{
window = clutter_x11_get_stage_window (stage);
if (window == None)
return;
meta_display_set_input_focus_xwindow (screen->display,
screen,
META_FOCUS_STAGE,
window,
timestamp);
}
else
{
meta_display_set_input_focus_xwindow (screen->display,
screen,
META_FOCUS_STAGE,
None,
timestamp);
}
}
gboolean
meta_stage_is_focused (MetaScreen *screen)
{
ClutterStage *stage;
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
if (!stage)
return FALSE;
return (screen->display->focus_type == META_FOCUS_STAGE);
}
static gboolean
begin_modal_x11 (MetaScreen *screen,
MetaPlugin *plugin,
MetaModalOptions options,
guint32 timestamp)
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
Window grab_window = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
Cursor cursor = None;
int result;
gboolean pointer_grabbed = FALSE;
gboolean keyboard_grabbed = FALSE;
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
{
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
@ -458,14 +490,6 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
keyboard_grabbed = TRUE;
}
display->grab_op = META_GRAB_OP_COMPOSITOR;
display->grab_window = NULL;
display->grab_screen = screen;
display->grab_have_pointer = TRUE;
display->grab_have_keyboard = TRUE;
compositor->modal_plugin = plugin;
return TRUE;
fail:
@ -477,6 +501,80 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
return FALSE;
}
static gboolean
begin_modal_wayland (MetaScreen *screen,
MetaPlugin *plugin,
MetaModalOptions options,
guint32 timestamp)
{
MetaWaylandCompositor *compositor;
gboolean pointer_grabbed = FALSE;
gboolean keyboard_grabbed = FALSE;
compositor = meta_wayland_compositor_get_default ();
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
{
if (!meta_wayland_pointer_begin_modal (&compositor->seat->pointer))
goto fail;
pointer_grabbed = TRUE;
}
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
{
if (!meta_wayland_keyboard_begin_modal (&compositor->seat->keyboard,
timestamp))
goto fail;
keyboard_grabbed = TRUE;
}
return TRUE;
fail:
if (pointer_grabbed)
meta_wayland_pointer_end_modal (&compositor->seat->pointer);
if (keyboard_grabbed)
meta_wayland_keyboard_end_modal (&compositor->seat->keyboard, timestamp);
return FALSE;
}
gboolean
meta_begin_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
MetaModalOptions options,
guint32 timestamp)
{
/* To some extent this duplicates code in meta_display_begin_grab_op(), but there
* are significant differences in how we handle grabs that make it difficult to
* merge the two.
*/
MetaDisplay *display = meta_screen_get_display (screen);
MetaCompositor *compositor = display->compositor;
gboolean ok;
if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
return FALSE;
if (meta_is_wayland_compositor ())
ok = begin_modal_wayland (screen, plugin, options, timestamp);
else
ok = begin_modal_x11 (screen, plugin, options, timestamp);
if (!ok)
return FALSE;
display->grab_op = META_GRAB_OP_COMPOSITOR;
display->grab_window = NULL;
display->grab_screen = screen;
display->grab_have_pointer = TRUE;
display->grab_have_keyboard = TRUE;
compositor->modal_plugin = plugin;
return TRUE;
}
void
meta_end_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
@ -488,8 +586,19 @@ meta_end_modal_for_plugin (MetaScreen *screen,
g_return_if_fail (compositor->modal_plugin == plugin);
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
if (meta_is_wayland_compositor ())
{
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
meta_wayland_pointer_end_modal (&compositor->seat->pointer);
meta_wayland_keyboard_end_modal (&compositor->seat->keyboard,
timestamp);
}
else
{
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_POINTER_ID, timestamp);
XIUngrabDevice (xdpy, META_VIRTUAL_CORE_KEYBOARD_ID, timestamp);
}
display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL;
@ -514,20 +623,20 @@ meta_check_end_modal (MetaScreen *screen)
{
meta_end_modal_for_plugin (screen,
compositor->modal_plugin,
CurrentTime);
CurrentTime);
}
}
static gboolean
after_stage_paint (gpointer data)
static void
after_stage_paint (ClutterStage *stage,
gpointer data)
{
MetaCompScreen *info = (MetaCompScreen*) data;
GList *l;
for (l = info->windows; l; l = l->next)
meta_window_actor_post_paint (l->data);
return TRUE;
}
static void
@ -541,6 +650,11 @@ redirect_windows (MetaCompositor *compositor,
guint n_retries;
guint max_retries;
/* If we're running with wayland, connected to a headless xwayland
* server then all the windows are implicitly redirected offscreen
* already and it would generate an error to try and explicitly
* redirect them via XCompositeRedirectSubwindows() */
if (meta_get_replace_current_wm ())
max_retries = 5;
else
@ -581,8 +695,9 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
MetaCompScreen *info;
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window xwin;
Window xwin = None;
gint width, height;
MetaWaylandCompositor *wayland_compositor;
/* Check if the screen is already managed */
if (meta_screen_get_compositor_data (screen))
@ -595,7 +710,14 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
* We have to initialize info->pending_input_region to an empty region explicitly,
* because None value is used to mean that the whole screen is an input region.
*/
info->pending_input_region = XFixesCreateRegion (xdisplay, NULL, 0);
if (!meta_is_wayland_compositor ())
info->pending_input_region = XFixesCreateRegion (xdisplay, NULL, 0);
else
{
/* Stage input region trickery isn't needed when we're running as a
* wayland compositor. */
info->pending_input_region = None;
}
info->screen = screen;
@ -606,106 +728,132 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
meta_screen_set_cm_selection (screen);
info->stage = clutter_stage_new ();
/* We will have already created a stage if running as a wayland
* compositor... */
if (meta_is_wayland_compositor ())
{
wayland_compositor = meta_wayland_compositor_get_default ();
info->stage = wayland_compositor->stage;
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
after_stage_paint,
info, NULL);
meta_screen_get_size (screen, &width, &height);
clutter_actor_set_size (info->stage, width, height);
}
else
{
info->stage = clutter_stage_new ();
meta_screen_get_size (screen, &width, &height);
clutter_actor_realize (info->stage);
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
XResizeWindow (xdisplay, xwin, width, height);
{
long event_mask;
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XWindowAttributes attr;
meta_core_add_old_event_mask (xdisplay, xwin, &mask);
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
XIClearMask (mask.mask, XI_TouchBegin);
XIClearMask (mask.mask, XI_TouchEnd);
XIClearMask (mask.mask, XI_TouchUpdate);
XISelectEvents (xdisplay, xwin, &mask, 1);
event_mask = ExposureMask | PropertyChangeMask | StructureNotifyMask;
if (XGetWindowAttributes (xdisplay, xwin, &attr))
event_mask |= attr.your_event_mask;
XSelectInput (xdisplay, xwin, event_mask);
}
}
clutter_stage_set_paint_callback (CLUTTER_STAGE (info->stage),
after_stage_paint,
info,
NULL);
clutter_stage_set_sync_delay (CLUTTER_STAGE (info->stage), META_SYNC_DELAY);
meta_screen_get_size (screen, &width, &height);
clutter_actor_realize (info->stage);
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
XResizeWindow (xdisplay, xwin, width, height);
{
long event_mask;
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
XWindowAttributes attr;
meta_core_add_old_event_mask (xdisplay, xwin, &mask);
XISetMask (mask.mask, XI_KeyPress);
XISetMask (mask.mask, XI_KeyRelease);
XISetMask (mask.mask, XI_ButtonPress);
XISetMask (mask.mask, XI_ButtonRelease);
XISetMask (mask.mask, XI_Enter);
XISetMask (mask.mask, XI_Leave);
XISetMask (mask.mask, XI_FocusIn);
XISetMask (mask.mask, XI_FocusOut);
XISetMask (mask.mask, XI_Motion);
XISelectEvents (xdisplay, xwin, &mask, 1);
event_mask = ExposureMask | PropertyChangeMask | StructureNotifyMask;
if (XGetWindowAttributes (xdisplay, xwin, &attr))
event_mask |= attr.your_event_mask;
XSelectInput (xdisplay, xwin, event_mask);
}
info->window_group = meta_window_group_new (screen);
info->top_window_group = meta_window_group_new (screen);
info->overlay_group = clutter_actor_new ();
clutter_actor_add_child (info->stage, info->window_group);
clutter_actor_add_child (info->stage, info->top_window_group);
clutter_actor_add_child (info->stage, info->overlay_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);
/* Make sure there isn't any left-over output shape on the
* overlay window by setting the whole screen to be an
* output region.
*
* Note: there doesn't seem to be any real chance of that
* because the X server will destroy the overlay window
* when the last client using it exits.
*/
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
do_set_stage_input_region (screen, info->pending_input_region);
if (info->pending_input_region != None)
if (meta_is_wayland_compositor ())
{
XFixesDestroyRegion (xdisplay, info->pending_input_region);
info->pending_input_region = None;
/* NB: When running as a wayland compositor we don't need an X
* composite overlay window, and we don't need to play any input
* region tricks to redirect events into clutter. */
info->output = None;
}
else
{
/*
* 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);
clutter_actor_show (info->overlay_group);
/* Make sure there isn't any left-over output shape on the
* overlay window by setting the whole screen to be an
* output region.
*
* Note: there doesn't seem to be any real chance of that
* because the X server will destroy the overlay window
* when the last client using it exits.
*/
XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
/* Map overlay window before redirecting windows offscreen so we catch their
* contents until we show the stage.
*/
XMapWindow (xdisplay, info->output);
do_set_stage_input_region (screen, info->pending_input_region);
if (info->pending_input_region != None)
{
XFixesDestroyRegion (xdisplay, info->pending_input_region);
info->pending_input_region = None;
}
redirect_windows (compositor, screen);
/* Map overlay window before redirecting windows offscreen so we catch their
* contents until we show the stage.
*/
XMapWindow (xdisplay, info->output);
redirect_windows (compositor, screen);
}
}
void
meta_compositor_unmanage_screen (MetaCompositor *compositor,
MetaScreen *screen)
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window xroot = meta_screen_get_xroot (screen);
if (!meta_is_wayland_compositor ())
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window xroot = meta_screen_get_xroot (screen);
/* This is the most important part of cleanup - we have to do this
* before giving up the window manager selection or the next
* window manager won't be able to redirect subwindows */
XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
/* This is the most important part of cleanup - we have to do this
* before giving up the window manager selection or the next
* window manager won't be able to redirect subwindows */
XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
}
}
/*
@ -777,15 +925,18 @@ meta_compositor_remove_window (MetaCompositor *compositor,
if (!window_actor)
return;
screen = meta_window_get_screen (window);
info = meta_screen_get_compositor_data (screen);
if (window_actor == info->unredirected_window)
if (!meta_is_wayland_compositor ())
{
meta_window_actor_set_redirected (window_actor, TRUE);
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (info->unredirected_window)),
NULL);
info->unredirected_window = NULL;
screen = meta_window_get_screen (window);
info = meta_screen_get_compositor_data (screen);
if (window_actor == info->unredirected_window)
{
meta_window_actor_set_redirected (window_actor, TRUE);
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (info->unredirected_window)),
NULL);
info->unredirected_window = NULL;
}
}
meta_window_actor_destroy (window_actor);
@ -916,10 +1067,7 @@ meta_compositor_process_event (MetaCompositor *compositor,
{
if (compositor->modal_plugin && is_grabbed_event (compositor->display, event))
{
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (compositor->modal_plugin);
if (klass->xevent_filter)
klass->xevent_filter (compositor->modal_plugin, event);
_meta_plugin_xevent_filter (compositor->modal_plugin, event);
/* We always consume events even if the plugin says it didn't handle them;
* exclusive is exclusive */
@ -972,7 +1120,8 @@ meta_compositor_process_event (MetaCompositor *compositor,
break;
default:
if (event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
if (!meta_is_wayland_compositor () &&
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
@ -991,7 +1140,7 @@ meta_compositor_process_event (MetaCompositor *compositor,
/* Clutter needs to know about MapNotify events otherwise it will
think the stage is invisible */
if (event->type == MapNotify)
if (!meta_is_wayland_compositor () && event->type == MapNotify)
clutter_x11_handle_event (event);
/* The above handling is basically just "observing" the events, so we return
@ -1124,6 +1273,7 @@ sync_actor_stacking (MetaCompScreen *info)
* we go ahead and do it */
children = clutter_actor_get_children (info->window_group);
has_windows = FALSE;
reordered = FALSE;
/* We allow for actors in the window group other than the actors we
@ -1335,20 +1485,38 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
{
MetaDisplay *display = meta_screen_get_display (screen);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
Display *xdisplay;
Window xwin;
DEBUG_TRACE ("meta_compositor_sync_screen_size\n");
g_return_if_fail (info);
if (meta_is_wayland_compositor ())
{
/* FIXME: when we support a sliced stage, this is the place to do it
But! This is not the place to apply KMS config, here we only
notify Clutter/Cogl/GL that the framebuffer sizes changed.
xdisplay = meta_display_get_xdisplay (display);
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
And because for now clutter does not do sliced, we use one
framebuffer the size of the whole screen, and when running on
bare metal MetaMonitorManager will do the necessary tricks to
show the right portions on the right screens.
*/
XResizeWindow (xdisplay, xwin, width, height);
clutter_actor_set_size (info->stage, width, height);
}
else
{
Display *xdisplay;
Window xwin;
DEBUG_TRACE ("meta_compositor_sync_screen_size\n");
g_return_if_fail (info);
xdisplay = meta_display_get_xdisplay (display);
xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));
XResizeWindow (xdisplay, xwin, width, height);
}
meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
meta_screen_get_screen_number (screen),
width, height);
meta_screen_get_screen_number (screen),
width, height);
}
static void
@ -1412,29 +1580,32 @@ pre_paint_windows (MetaCompScreen *info)
if (info->windows == NULL)
return;
top_window = g_list_last (info->windows)->data;
if (meta_window_actor_should_unredirect (top_window) &&
info->disable_unredirect_count == 0)
expected_unredirected_window = top_window;
if (info->unredirected_window != expected_unredirected_window)
if (!meta_is_wayland_compositor ())
{
if (info->unredirected_window != NULL)
{
meta_window_actor_set_redirected (info->unredirected_window, TRUE);
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (info->unredirected_window)),
NULL);
}
top_window = g_list_last (info->windows)->data;
if (expected_unredirected_window != NULL)
{
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (top_window)),
meta_window_actor_get_meta_window (top_window));
meta_window_actor_set_redirected (top_window, FALSE);
}
if (meta_window_actor_should_unredirect (top_window) &&
info->disable_unredirect_count == 0)
expected_unredirected_window = top_window;
info->unredirected_window = expected_unredirected_window;
if (info->unredirected_window != expected_unredirected_window)
{
if (info->unredirected_window != NULL)
{
meta_window_actor_set_redirected (info->unredirected_window, TRUE);
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (info->unredirected_window)),
NULL);
}
if (expected_unredirected_window != NULL)
{
meta_shape_cow_for_window (meta_window_get_screen (meta_window_actor_get_meta_window (top_window)),
meta_window_actor_get_meta_window (top_window));
meta_window_actor_set_redirected (top_window, FALSE);
}
info->unredirected_window = expected_unredirected_window;
}
}
for (l = info->windows; l; l = l->next)
@ -1566,8 +1737,10 @@ void
meta_enable_unredirect_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (info != NULL)
info->disable_unredirect_count = MAX(0, info->disable_unredirect_count - 1);
if (info != NULL && info->disable_unredirect_count == 0)
g_warning ("Called enable_unredirect_for_screen while unredirection is enabled.");
if (info != NULL && info->disable_unredirect_count > 0)
info->disable_unredirect_count = info->disable_unredirect_count - 1;
}
#define FLASH_TIME_MS 50

View File

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

View File

@ -44,7 +44,7 @@
struct _MetaBackgroundActorPrivate
{
cairo_region_t *visible_region;
cairo_region_t *clip_region;
};
G_DEFINE_TYPE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR);
@ -54,7 +54,7 @@ meta_background_actor_dispose (GObject *object)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
meta_background_actor_set_visible_region (self, NULL);
meta_background_actor_set_clip_region (self, NULL);
G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object);
}
@ -167,17 +167,17 @@ meta_background_actor_new (void)
}
/**
* meta_background_actor_set_visible_region:
* meta_background_actor_set_clip_region:
* @self: a #MetaBackgroundActor
* @visible_region: (allow-none): the area of the actor (in allocate-relative
* @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_visible_region (MetaBackgroundActor *self,
cairo_region_t *visible_region)
meta_background_actor_set_clip_region (MetaBackgroundActor *self,
cairo_region_t *clip_region)
{
MetaBackgroundActorPrivate *priv;
@ -185,16 +185,16 @@ meta_background_actor_set_visible_region (MetaBackgroundActor *self,
priv = self->priv;
g_clear_pointer (&priv->visible_region,
g_clear_pointer (&priv->clip_region,
(GDestroyNotify)
cairo_region_destroy);
if (visible_region)
priv->visible_region = cairo_region_copy (visible_region);
if (clip_region)
priv->clip_region = cairo_region_copy (clip_region);
}
/**
* meta_background_actor_get_visible_region:
* meta_background_actor_get_clip_region:
* @self: a #MetaBackgroundActor
*
* Return value (transfer full): a #cairo_region_t that represents the part of
@ -202,16 +202,16 @@ meta_background_actor_set_visible_region (MetaBackgroundActor *self,
* #MetaWindowActor objects.
*/
cairo_region_t *
meta_background_actor_get_visible_region (MetaBackgroundActor *self)
meta_background_actor_get_clip_region (MetaBackgroundActor *self)
{
MetaBackgroundActorPrivate *priv = self->priv;
ClutterActorBox content_box;
cairo_rectangle_int_t content_area = { 0 };
cairo_region_t *visible_region;
cairo_region_t *clip_region;
g_return_val_if_fail (META_IS_BACKGROUND_ACTOR (self), NULL);
if (!priv->visible_region)
if (!priv->clip_region)
return NULL;
clutter_actor_get_content_box (CLUTTER_ACTOR (self), &content_box);
@ -221,8 +221,8 @@ meta_background_actor_get_visible_region (MetaBackgroundActor *self)
content_area.width = content_box.x2 - content_box.x1;
content_area.height = content_box.y2 - content_box.y1;
visible_region = cairo_region_create_rectangle (&content_area);
cairo_region_intersect (visible_region, priv->visible_region);
clip_region = cairo_region_create_rectangle (&content_area);
cairo_region_intersect (clip_region, priv->clip_region);
return visible_region;
return clip_region;
}

View File

@ -6,6 +6,6 @@
#include <meta/screen.h>
#include <meta/meta-background-group.h>
void meta_background_group_set_visible_region (MetaBackgroundGroup *self,
cairo_region_t *visible_region);
void meta_background_group_set_clip_region (MetaBackgroundGroup *self,
cairo_region_t *visible_region);
#endif /* META_BACKGROUND_GROUP_PRIVATE_H */

View File

@ -62,16 +62,16 @@ meta_background_group_init (MetaBackgroundGroup *self)
}
/**
* meta_background_group_set_visible_region:
* meta_background_group_set_clip_region:
* @self: a #MetaBackgroundGroup
* @visible_region: (allow-none): the parts of the background to paint
* @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_visible_region (MetaBackgroundGroup *self,
cairo_region_t *region)
meta_background_group_set_clip_region (MetaBackgroundGroup *self,
cairo_region_t *region)
{
GList *children, *l;
@ -82,7 +82,7 @@ meta_background_group_set_visible_region (MetaBackgroundGroup *self,
if (META_IS_BACKGROUND_ACTOR (actor))
{
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (actor), region);
meta_background_actor_set_clip_region (META_BACKGROUND_ACTOR (actor), region);
}
else if (META_IS_BACKGROUND_GROUP (actor))
{
@ -92,7 +92,7 @@ meta_background_group_set_visible_region (MetaBackgroundGroup *self,
continue;
cairo_region_translate (region, -x, -y);
meta_background_group_set_visible_region (META_BACKGROUND_GROUP (actor), region);
meta_background_group_set_clip_region (META_BACKGROUND_GROUP (actor), region);
cairo_region_translate (region, x, y);
}
}

View File

@ -37,6 +37,7 @@
#include "mutter-enum-types.h"
#include <meta/errors.h>
#include <meta/meta-background.h>
#include "util-private.h"
#include "meta-background-actor-private.h"
#define FRAGMENT_SHADER_DECLARATIONS \
@ -412,13 +413,13 @@ meta_background_paint_content (ClutterContent *content,
*/
if (META_IS_BACKGROUND_ACTOR (actor))
{
cairo_region_t *visible_region;
visible_region = meta_background_actor_get_visible_region (META_BACKGROUND_ACTOR (actor));
cairo_region_t *clip_region;
clip_region = meta_background_actor_get_clip_region (META_BACKGROUND_ACTOR (actor));
if (visible_region != NULL)
if (clip_region != NULL)
{
cairo_region_intersect (paintable_region, visible_region);
cairo_region_destroy (visible_region);
cairo_region_intersect (paintable_region, clip_region);
cairo_region_destroy (clip_region);
}
}
@ -472,6 +473,17 @@ meta_background_dispose (GObject *object)
G_OBJECT_CLASS (meta_background_parent_class)->dispose (object);
}
static void
meta_background_finalize (GObject *object)
{
MetaBackground *self = META_BACKGROUND (object);
MetaBackgroundPrivate *priv = self->priv;
g_free (priv->filename);
G_OBJECT_CLASS (meta_background_parent_class)->finalize (object);
}
static void
ensure_pipeline (MetaBackground *self)
{
@ -643,6 +655,7 @@ meta_background_class_init (MetaBackgroundClass *klass)
g_type_class_add_private (klass, sizeof (MetaBackgroundPrivate));
object_class->dispose = meta_background_dispose;
object_class->finalize = meta_background_finalize;
object_class->set_property = meta_background_set_property;
object_class->get_property = meta_background_get_property;
@ -1019,7 +1032,6 @@ meta_background_load_file_finish (MetaBackground *self,
GAsyncResult *result,
GError **error)
{
static CoglUserDataKey key;
GTask *task;
LoadFileTaskData *task_data;
CoglTexture *texture;
@ -1048,7 +1060,7 @@ meta_background_load_file_finish (MetaBackground *self,
texture = cogl_texture_new_from_data (width,
height,
COGL_TEXTURE_NO_SLICING,
COGL_TEXTURE_NO_ATLAS,
has_alpha ?
COGL_PIXEL_FORMAT_RGBA_8888 :
COGL_PIXEL_FORMAT_RGB_888,
@ -1065,12 +1077,6 @@ meta_background_load_file_finish (MetaBackground *self,
goto out;
}
cogl_object_set_user_data (COGL_OBJECT (texture),
&key,
g_object_ref (pixbuf),
(CoglUserDataDestroyCallback)
g_object_unref);
ensure_pipeline (self);
unset_texture (self);
set_style (self, task_data->style);

View File

@ -192,10 +192,7 @@ meta_module_class_init (MetaModuleClass *klass)
static void
meta_module_init (MetaModule *self)
{
MetaModulePrivate *priv;
self->priv = priv = META_MODULE_GET_PRIVATE (self);
self->priv = META_MODULE_GET_PRIVATE (self);
}
GType

View File

@ -85,12 +85,20 @@ meta_plugin_manager_load (const gchar *plugin_name)
g_free (path);
}
static void
on_confirm_display_change (MetaMonitorManager *monitors,
MetaPluginManager *plugin_mgr)
{
meta_plugin_manager_confirm_display_change (plugin_mgr);
}
MetaPluginManager *
meta_plugin_manager_new (MetaScreen *screen)
{
MetaPluginManager *plugin_mgr;
MetaPluginClass *klass;
MetaPlugin *plugin;
MetaMonitorManager *monitors;
plugin_mgr = g_new0 (MetaPluginManager, 1);
plugin_mgr->screen = screen;
@ -101,6 +109,10 @@ meta_plugin_manager_new (MetaScreen *screen)
if (klass->start)
klass->start (plugin);
monitors = meta_monitor_manager_get ();
g_signal_connect (monitors, "confirm-display-change",
G_CALLBACK (on_confirm_display_change), plugin_mgr);
return plugin_mgr;
}
@ -294,29 +306,23 @@ meta_plugin_manager_filter_keybinding (MetaPluginManager *plugin_mgr,
return FALSE;
}
/*
* The public method that the compositor hooks into for desktop switching.
*
* Returns TRUE if the plugin handled the event type (i.e.,
* if the return value is FALSE, there will be no subsequent call to the
* manager completed() callback, and the compositor must ensure that any
* appropriate post-effect cleanup is carried out.
*/
gboolean
meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
XEvent *xev)
{
MetaPlugin *plugin = plugin_mgr->plugin;
return _meta_plugin_xevent_filter (plugin, xev);
}
void
meta_plugin_manager_confirm_display_change (MetaPluginManager *plugin_mgr)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
/* We need to make sure that clutter gets certain events, like
* ConfigureNotify on the stage window. If there is a plugin that
* provides an xevent_filter function, then it's the responsibility
* of that plugin to pass events to Clutter. Otherwise, we send the
* event directly to Clutter ourselves.
*/
if (klass->xevent_filter)
return klass->xevent_filter (plugin, xev);
if (klass->confirm_display_change)
return klass->confirm_display_change (plugin);
else
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
return meta_plugin_complete_display_change (plugin, TRUE);
}

View File

@ -72,5 +72,9 @@ gboolean meta_plugin_manager_filter_keybinding (MetaPluginManager *mgr,
gboolean meta_plugin_manager_xevent_filter (MetaPluginManager *mgr,
XEvent *xev);
gboolean _meta_plugin_xevent_filter (MetaPlugin *plugin,
XEvent *xev);
void meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr);
#endif

View File

@ -41,6 +41,7 @@
#include "compositor-private.h"
#include "meta-window-actor-private.h"
#include "monitor-private.h"
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
@ -137,9 +138,7 @@ meta_plugin_class_init (MetaPluginClass *klass)
static void
meta_plugin_init (MetaPlugin *self)
{
MetaPluginPrivate *priv;
self->priv = priv = META_PLUGIN_GET_PRIVATE (self);
self->priv = META_PLUGIN_GET_PRIVATE (self);
}
gboolean
@ -184,6 +183,28 @@ _meta_plugin_effect_started (MetaPlugin *plugin)
priv->running++;
}
gboolean
_meta_plugin_xevent_filter (MetaPlugin *plugin,
XEvent *xev)
{
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
/* When mutter is running as a wayland compositor, things like input
* events just come directly from clutter so it won't have disabled
* clutter's event retrieval and won't need to forward it events (if
* it did it would lead to recursion). Also when running as a
* wayland compositor we shouldn't be assuming that we're running
* with the clutter x11 backend.
*/
if (klass->xevent_filter && klass->xevent_filter (plugin, xev))
return TRUE;
else if (!meta_is_wayland_compositor ())
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
else
return FALSE;
}
void
meta_plugin_switch_workspace_completed (MetaPlugin *plugin)
{
@ -266,10 +287,6 @@ meta_plugin_destroy_completed (MetaPlugin *plugin,
/**
* meta_plugin_begin_modal:
* @plugin: a #MetaPlugin
* @grab_window: the X window to grab the keyboard and mouse on
* @cursor: the cursor to use for the pointer grab, or None,
* to use the normal cursor for the grab window and
* its descendants.
* @options: flags that modify the behavior of the modal grab
* @timestamp: the timestamp used for establishing grabs
*
@ -290,15 +307,13 @@ meta_plugin_destroy_completed (MetaPlugin *plugin,
*/
gboolean
meta_plugin_begin_modal (MetaPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return meta_begin_modal_for_plugin (priv->screen, plugin,
grab_window, cursor, options, timestamp);
options, timestamp);
}
/**
@ -338,3 +353,13 @@ meta_plugin_get_screen (MetaPlugin *plugin)
return priv->screen;
}
void
meta_plugin_complete_display_change (MetaPlugin *plugin,
gboolean ok)
{
MetaMonitorManager *manager;
manager = meta_monitor_manager_get ();
meta_monitor_manager_confirm_configuration (manager, ok);
}

View File

@ -123,12 +123,12 @@ static guint signals[LAST_SIGNAL] = { 0 };
/* The first element in this array also defines the default parameters
* for newly created classes */
MetaShadowClassInfo default_shadow_classes[] = {
{ "normal", { 6, -1, 0, 3, 255 }, { 3, -1, 0, 3, 128 } },
{ "dialog", { 6, -1, 0, 3, 255 }, { 3, -1, 0, 3, 128 } },
{ "modal_dialog", { 6, -1, 0, 1, 255 }, { 3, -1, 0, 3, 128 } },
{ "utility", { 3, -1, 0, 1, 255 }, { 3, -1, 0, 1, 128 } },
{ "border", { 6, -1, 0, 3, 255 }, { 3, -1, 0, 3, 128 } },
{ "menu", { 6, -1, 0, 3, 255 }, { 3, -1, 0, 0, 128 } },
{ "normal", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "dialog", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "modal_dialog", { 6, -1, 0, 1, 128 }, { 3, -1, 0, 3, 32 } },
{ "utility", { 3, -1, 0, 1, 128 }, { 3, -1, 0, 1, 32 } },
{ "border", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 3, 32 } },
{ "menu", { 6, -1, 0, 3, 128 }, { 3, -1, 0, 0, 32 } },
{ "popup-menu", { 1, -1, 0, 1, 128 }, { 1, -1, 0, 1, 128 } },

View File

@ -0,0 +1,44 @@
/*
* shaped texture
*
* An actor to draw a texture clipped to a list of rectangles
*
* Authored By Neil Roberts <neil@linux.intel.com>
*
* Copyright (C) 2008 Intel Corporation
* 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_SHAPED_TEXTURE_PRIVATE_H__
#define __META_SHAPED_TEXTURE_PRIVATE_H__
#include <meta/meta-shaped-texture.h>
#include "meta-wayland-private.h"
ClutterActor *meta_shaped_texture_new_with_xwindow (Window xwindow);
ClutterActor *meta_shaped_texture_new_with_wayland_surface (MetaWaylandSurface *surface);
void meta_shaped_texture_set_wayland_surface (MetaShapedTexture *stex,
MetaWaylandSurface *surface);
MetaWaylandSurface *meta_shaped_texture_get_wayland_surface (MetaShapedTexture *stex);
void meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
Pixmap pixmap);
void meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
MetaWaylandBuffer *buffer);
#endif

View File

@ -30,8 +30,13 @@
#include <config.h>
#include <meta/meta-shaped-texture.h>
#include <meta/util.h>
#include "meta-texture-tower.h"
#include "meta-shaped-texture-private.h"
#include "meta-wayland-private.h"
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h>
#include <cogl/cogl.h>
#include <cogl/cogl-texture-pixmap-x11.h>
@ -55,6 +60,13 @@ static void meta_shaped_texture_get_preferred_height (ClutterActor *self,
static gboolean meta_shaped_texture_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume);
typedef enum _MetaShapedTextureType
{
META_SHAPED_TEXTURE_TYPE_X11_PIXMAP,
META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE,
} MetaShapedTextureType;
G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
CLUTTER_TYPE_ACTOR);
@ -65,13 +77,24 @@ G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
struct _MetaShapedTexturePrivate
{
MetaTextureTower *paint_tower;
Pixmap pixmap;
CoglTexturePixmapX11 *texture;
MetaShapedTextureType type;
union {
struct {
Pixmap pixmap;
} x11;
struct {
MetaWaylandSurface *surface;
} wayland;
};
CoglTexture *texture;
CoglTexture *mask_texture;
CoglPipeline *pipeline;
CoglPipeline *pipeline_unshaped;
cairo_region_t *clip_region;
cairo_region_t *input_shape_region;
cairo_region_t *opaque_region;
guint tex_width, tex_height;
@ -103,7 +126,10 @@ meta_shaped_texture_init (MetaShapedTexture *self)
priv = self->priv = META_SHAPED_TEXTURE_GET_PRIVATE (self);
priv->paint_tower = meta_texture_tower_new ();
priv->type = META_SHAPED_TEXTURE_TYPE_X11_PIXMAP;
priv->texture = NULL;
priv->mask_texture = NULL;
priv->create_mipmaps = TRUE;
}
@ -118,9 +144,8 @@ meta_shaped_texture_dispose (GObject *object)
meta_texture_tower_free (priv->paint_tower);
priv->paint_tower = NULL;
g_clear_pointer (&priv->pipeline, cogl_object_unref);
g_clear_pointer (&priv->pipeline_unshaped, cogl_object_unref);
g_clear_pointer (&priv->texture, cogl_object_unref);
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
meta_shaped_texture_set_mask_texture (self, NULL);
meta_shaped_texture_set_clip_region (self, NULL);
@ -128,19 +153,133 @@ meta_shaped_texture_dispose (GObject *object)
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
}
static CoglPipeline *
get_unmasked_pipeline (CoglContext *ctx)
{
return cogl_pipeline_new (ctx);
}
static CoglPipeline *
get_masked_pipeline (CoglContext *ctx)
{
static CoglPipeline *template = NULL;
if (G_UNLIKELY (template == NULL))
{
template = cogl_pipeline_new (ctx);
cogl_pipeline_set_layer_combine (template, 1,
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
NULL);
}
return cogl_pipeline_copy (template);
}
static CoglPipeline *
get_unblended_pipeline (CoglContext *ctx)
{
static CoglPipeline *template = NULL;
if (G_UNLIKELY (template == NULL))
{
CoglColor color;
template = cogl_pipeline_new (ctx);
cogl_color_init_from_4ub (&color, 255, 255, 255, 255);
cogl_pipeline_set_blend (template,
"RGBA = ADD (SRC_COLOR, 0)",
NULL);
cogl_pipeline_set_color (template, &color);
}
return cogl_pipeline_copy (template);
}
static void
paint_clipped_rectangle (CoglFramebuffer *fb,
CoglPipeline *pipeline,
cairo_rectangle_int_t *rect,
ClutterActorBox *alloc)
{
float coords[8];
float x1, y1, x2, y2;
x1 = rect->x;
y1 = rect->y;
x2 = rect->x + rect->width;
y2 = rect->y + rect->height;
coords[0] = rect->x / (alloc->x2 - alloc->x1);
coords[1] = rect->y / (alloc->y2 - alloc->y1);
coords[2] = (rect->x + rect->width) / (alloc->x2 - alloc->x1);
coords[3] = (rect->y + rect->height) / (alloc->y2 - alloc->y1);
coords[4] = coords[0];
coords[5] = coords[1];
coords[6] = coords[2];
coords[7] = coords[3];
cogl_framebuffer_draw_multitextured_rectangle (fb, pipeline,
x1, y1, x2, y2,
&coords[0], 8);
}
static void
set_cogl_texture (MetaShapedTexture *stex,
CoglTexture *cogl_tex)
{
MetaShapedTexturePrivate *priv;
guint width, height;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
if (priv->texture)
cogl_object_unref (priv->texture);
priv->texture = cogl_object_ref (cogl_tex);
if (cogl_tex != NULL)
{
width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex));
if (width != priv->tex_width ||
height != priv->tex_height)
{
priv->tex_width = width;
priv->tex_height = height;
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
}
}
else
{
/* size changed to 0 going to an invalid handle */
priv->tex_width = 0;
priv->tex_height = 0;
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
}
/* NB: We don't queue a redraw of the actor here because we don't
* know how much of the buffer has changed with respect to the
* previous buffer. We only queue a redraw in response to surface
* damage. */
}
static void
meta_shaped_texture_paint (ClutterActor *actor)
{
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
MetaShapedTexturePrivate *priv = stex->priv;
CoglTexture *paint_tex;
guint tex_width, tex_height;
guchar opacity;
CoglContext *ctx;
CoglFramebuffer *fb;
CoglPipeline *pipeline = NULL;
CoglTexture *paint_tex;
ClutterActorBox alloc;
static CoglPipeline *pipeline_template = NULL;
static CoglPipeline *pipeline_unshaped_template = NULL;
CoglPipeline *pipeline;
cairo_region_t *blended_region = NULL;
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
return;
@ -177,38 +316,74 @@ meta_shaped_texture_paint (ClutterActor *actor)
if (tex_width == 0 || tex_height == 0) /* no contents yet */
return;
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
fb = cogl_get_draw_framebuffer ();
opacity = clutter_actor_get_paint_opacity (actor);
clutter_actor_get_allocation_box (actor, &alloc);
if (priv->opaque_region != NULL && opacity == 255)
{
CoglPipeline *opaque_pipeline;
cairo_region_t *region;
int n_rects;
int i;
if (priv->clip_region != NULL)
{
region = cairo_region_copy (priv->clip_region);
cairo_region_intersect (region, priv->opaque_region);
}
else
{
region = cairo_region_reference (priv->opaque_region);
}
if (cairo_region_is_empty (region))
goto paint_blended;
opaque_pipeline = get_unblended_pipeline (ctx);
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
n_rects = cairo_region_num_rectangles (region);
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
paint_clipped_rectangle (fb, opaque_pipeline, &rect, &alloc);
}
cogl_object_unref (opaque_pipeline);
if (priv->clip_region != NULL)
{
blended_region = cairo_region_copy (priv->clip_region);
}
else
{
cairo_rectangle_int_t rect = { 0, 0, tex_width, tex_height };
blended_region = cairo_region_create_rectangle (&rect);
}
cairo_region_subtract (blended_region, priv->opaque_region);
paint_blended:
cairo_region_destroy (region);
}
if (blended_region == NULL && priv->clip_region != NULL)
blended_region = cairo_region_reference (priv->clip_region);
if (blended_region != NULL && cairo_region_is_empty (blended_region))
goto out;
if (priv->mask_texture == NULL)
{
/* Use a single-layer texture if we don't have a mask. */
if (priv->pipeline_unshaped == NULL)
{
if (G_UNLIKELY (pipeline_unshaped_template == NULL))
{
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
pipeline_unshaped_template = cogl_pipeline_new (ctx);
}
priv->pipeline_unshaped = cogl_pipeline_copy (pipeline_unshaped_template);
}
pipeline = priv->pipeline_unshaped;
pipeline = get_unmasked_pipeline (ctx);
}
else
{
if (priv->pipeline == NULL)
{
if (G_UNLIKELY (pipeline_template == NULL))
{
CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
pipeline_template = cogl_pipeline_new (ctx);
cogl_pipeline_set_layer_combine (pipeline_template, 1,
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
NULL);
}
priv->pipeline = cogl_pipeline_copy (pipeline_template);
}
pipeline = priv->pipeline;
pipeline = get_masked_pipeline (ctx);
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
}
@ -216,66 +391,50 @@ meta_shaped_texture_paint (ClutterActor *actor)
{
CoglColor color;
guchar opacity = clutter_actor_get_paint_opacity (actor);
cogl_color_set_from_4ub (&color, opacity, opacity, opacity, opacity);
cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity);
cogl_pipeline_set_color (pipeline, &color);
}
cogl_set_source (pipeline);
clutter_actor_get_allocation_box (actor, &alloc);
if (priv->clip_region)
if (blended_region != NULL)
{
int n_rects;
int i;
cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
/* Limit to how many separate rectangles we'll draw; beyond this just
* fall back and draw the whole thing */
# define MAX_RECTS 16
n_rects = cairo_region_num_rectangles (priv->clip_region);
n_rects = cairo_region_num_rectangles (blended_region);
if (n_rects <= MAX_RECTS)
{
float coords[8];
float x1, y1, x2, y2;
int i;
cairo_rectangle_int_t tex_rect = { 0, 0, tex_width, tex_height };
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (priv->clip_region, i, &rect);
cairo_region_get_rectangle (blended_region, i, &rect);
if (!gdk_rectangle_intersect (&tex_rect, &rect, &rect))
continue;
x1 = rect.x;
y1 = rect.y;
x2 = rect.x + rect.width;
y2 = rect.y + rect.height;
coords[0] = rect.x / (alloc.x2 - alloc.x1);
coords[1] = rect.y / (alloc.y2 - alloc.y1);
coords[2] = (rect.x + rect.width) / (alloc.x2 - alloc.x1);
coords[3] = (rect.y + rect.height) / (alloc.y2 - alloc.y1);
coords[4] = coords[0];
coords[5] = coords[1];
coords[6] = coords[2];
coords[7] = coords[3];
cogl_rectangle_with_multitexture_coords (x1, y1, x2, y2,
&coords[0], 8);
paint_clipped_rectangle (fb, pipeline, &rect, &alloc);
}
return;
goto out;
}
}
cogl_rectangle (0, 0,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1);
cogl_framebuffer_draw_rectangle (fb, pipeline,
0, 0,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1);
out:
if (pipeline != NULL)
cogl_object_unref (pipeline);
if (blended_region != NULL)
cairo_region_destroy (blended_region);
}
static void
@ -285,38 +444,61 @@ 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)
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)
->pick (actor, color);
else if (clutter_actor_should_pick_paint (actor))
if (priv->input_shape_region == NULL)
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)->pick (actor, color);
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);
cogl_set_source_color4ub (color->red, color->green, color->blue,
color->alpha);
rectangles[pos] = rect.x;
rectangles[pos + 1] = rect.y;
rectangles[pos + 2] = rect.x + rect.width;
rectangles[pos + 3] = rect.y + rect.height;
}
clutter_actor_get_allocation_box (actor, &alloc);
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
fb = cogl_get_draw_framebuffer ();
/* Paint the mask rectangle in the given color */
cogl_set_source_texture (priv->mask_texture);
cogl_rectangle_with_texture_coords (0, 0,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1,
0, 0, 1, 1);
cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
pipeline = cogl_pipeline_new (ctx);
cogl_pipeline_set_color (pipeline, &cogl_color);
cogl_framebuffer_draw_rectangles (fb, pipeline,
rectangles, n_rects);
cogl_object_unref (pipeline);
}
}
@ -366,11 +548,45 @@ meta_shaped_texture_get_paint_volume (ClutterActor *self,
}
ClutterActor *
meta_shaped_texture_new (void)
meta_shaped_texture_new_with_wayland_surface (MetaWaylandSurface *surface)
{
ClutterActor *self = g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
ClutterActor *actor = g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
MetaShapedTexturePrivate *priv = META_SHAPED_TEXTURE (actor)->priv;
return self;
/* XXX: it could probably be better to have a "type" construct-only
* property or create wayland/x11 subclasses */
priv->type = META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE;
meta_shaped_texture_set_wayland_surface (META_SHAPED_TEXTURE (actor),
surface);
return actor;
}
void
meta_shaped_texture_set_wayland_surface (MetaShapedTexture *stex,
MetaWaylandSurface *surface)
{
MetaShapedTexturePrivate *priv = stex->priv;
priv->wayland.surface = surface;
if (surface && surface->buffer_ref.buffer)
meta_shaped_texture_attach_wayland_buffer (stex,
surface->buffer_ref.buffer);
}
MetaWaylandSurface *
meta_shaped_texture_get_wayland_surface (MetaShapedTexture *stex)
{
MetaShapedTexturePrivate *priv = stex->priv;
return priv->wayland.surface;
}
ClutterActor *
meta_shaped_texture_new_with_xwindow (Window xwindow)
{
return g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
}
void
@ -389,8 +605,7 @@ meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
{
CoglTexture *base_texture;
priv->create_mipmaps = create_mipmaps;
base_texture = create_mipmaps ?
COGL_TEXTURE (priv->texture) : NULL;
base_texture = create_mipmaps ? priv->texture : NULL;
meta_texture_tower_set_base_texture (priv->paint_tower, base_texture);
}
}
@ -416,74 +631,194 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
void
static void
wayland_surface_update_area (MetaShapedTexture *stex,
int x,
int y,
int width,
int height)
{
MetaShapedTexturePrivate *priv;
MetaWaylandBuffer *buffer;
priv = stex->priv;
g_return_if_fail (priv->type == META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE);
g_return_if_fail (priv->texture != NULL);
buffer = priv->wayland.surface->buffer_ref.buffer;
if (buffer)
{
struct wl_resource *resource = buffer->resource;
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (resource);
if (shm_buffer)
{
CoglPixelFormat format;
switch (wl_shm_buffer_get_format (shm_buffer))
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
break;
case WL_SHM_FORMAT_XRGB8888:
format = COGL_PIXEL_FORMAT_ARGB_8888;
break;
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
break;
case WL_SHM_FORMAT_XRGB8888:
format = COGL_PIXEL_FORMAT_BGRA_8888;
break;
#endif
default:
g_warn_if_reached ();
format = COGL_PIXEL_FORMAT_ARGB_8888;
}
cogl_texture_set_region (priv->texture,
x, y,
x, y,
width, height,
width, height,
format,
wl_shm_buffer_get_stride (shm_buffer),
wl_shm_buffer_get_data (shm_buffer));
}
}
}
static gboolean
get_clip (MetaShapedTexture *stex,
int x,
int y,
int width,
int height,
cairo_rectangle_int_t *clip)
{
ClutterActor *self = CLUTTER_ACTOR (stex);
MetaShapedTexturePrivate *priv;
ClutterActorBox allocation;
float scale_x;
float scale_y;
/* NB: clutter_actor_queue_redraw_with_clip expects a box in the actor's
* coordinate space so we need to convert from surface coordinates to
* actor coordinates...
*/
/* Calling clutter_actor_get_allocation_box() is enormously expensive
* if the actor has an out-of-date allocation, since it triggers
* a full redraw. clutter_actor_queue_redraw_with_clip() would redraw
* the whole stage anyways in that case, so just go ahead and do
* it here.
*/
if (!clutter_actor_has_allocation (self))
return FALSE;
priv = stex->priv;
if (priv->tex_width == 0 || priv->tex_height == 0)
return FALSE;
clutter_actor_get_allocation_box (self, &allocation);
scale_x = (allocation.x2 - allocation.x1) / priv->tex_width;
scale_y = (allocation.y2 - allocation.y1) / priv->tex_height;
clip->x = x * scale_x;
clip->y = y * scale_y;
clip->width = width * scale_x;
clip->height = height * scale_y;
return TRUE;
}
/**
* meta_shaped_texture_update_area:
* @stex: #MetaShapedTexture
* @x: the x coordinate of the damaged area
* @y: the y coordinate of the damaged area
* @width: the width of the damaged area
* @height: the height of the damaged area
* @unobscured_region: The unobscured region of the window or %NULL if
* there is no valid one (like when the actor is transformed or
* has a mapped clone)
*
* Repairs the damaged area indicated by @x, @y, @width and @height
* and queues a redraw for the intersection @visibible_region and
* the damage area. If @visibible_region is %NULL a redraw will always
* get queued.
*
* Return value: Whether a redraw have been queued or not
*/
gboolean
meta_shaped_texture_update_area (MetaShapedTexture *stex,
int x,
int y,
int width,
int height)
int height,
cairo_region_t *unobscured_region)
{
MetaShapedTexturePrivate *priv;
const cairo_rectangle_int_t clip = { x, y, width, height };
cairo_rectangle_int_t clip;
gboolean has_clip;
priv = stex->priv;
if (priv->texture == NULL)
return;
return FALSE;
cogl_texture_pixmap_x11_update_area (priv->texture,
x, y, width, height);
switch (priv->type)
{
case META_SHAPED_TEXTURE_TYPE_X11_PIXMAP:
cogl_texture_pixmap_x11_update_area (COGL_TEXTURE_PIXMAP_X11 (priv->texture),
x, y, width, height);
break;
case META_SHAPED_TEXTURE_TYPE_WAYLAND_SURFACE:
wayland_surface_update_area (stex, x, y, width, height);
break;
}
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
}
has_clip = get_clip (stex, x, y, width, height, &clip);
static void
set_cogl_texture (MetaShapedTexture *stex,
CoglTexturePixmapX11 *cogl_tex)
{
MetaShapedTexturePrivate *priv;
guint width, height;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
if (priv->texture != NULL)
cogl_object_unref (priv->texture);
priv->texture = cogl_tex;
if (priv->pipeline != NULL)
cogl_pipeline_set_layer_texture (priv->pipeline, 0, COGL_TEXTURE (cogl_tex));
if (priv->pipeline_unshaped != NULL)
cogl_pipeline_set_layer_texture (priv->pipeline_unshaped, 0, COGL_TEXTURE (cogl_tex));
if (cogl_tex != NULL)
if (unobscured_region)
{
width = cogl_texture_get_width (COGL_TEXTURE (cogl_tex));
height = cogl_texture_get_height (COGL_TEXTURE (cogl_tex));
cairo_region_t *intersection;
if (width != priv->tex_width ||
height != priv->tex_height)
if (cairo_region_is_empty (unobscured_region))
return FALSE;
intersection = cairo_region_copy (unobscured_region);
if (has_clip)
cairo_region_intersect_rectangle (intersection, &clip);
if (!cairo_region_is_empty (intersection))
{
priv->tex_width = width;
priv->tex_height = height;
cairo_rectangle_int_t damage_rect;
cairo_region_get_extents (intersection, &damage_rect);
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &damage_rect);
cairo_region_destroy (intersection);
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
return TRUE;
}
}
else
{
/* size changed to 0 going to an inavlid texture */
priv->tex_width = 0;
priv->tex_height = 0;
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
cairo_region_destroy (intersection);
return FALSE;
}
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
if (has_clip)
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
else
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
return TRUE;
}
/**
@ -501,16 +836,18 @@ meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
priv = stex->priv;
if (priv->pixmap == pixmap)
if (priv->x11.pixmap == pixmap)
return;
priv->pixmap = pixmap;
priv->x11.pixmap = pixmap;
if (pixmap != None)
{
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
set_cogl_texture (stex, cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, NULL));
CoglTexture *texture =
COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, NULL));
set_cogl_texture (stex, texture);
}
else
set_cogl_texture (stex, NULL);
@ -520,6 +857,33 @@ meta_shaped_texture_set_pixmap (MetaShapedTexture *stex,
COGL_TEXTURE (priv->texture));
}
void
meta_shaped_texture_attach_wayland_buffer (MetaShapedTexture *stex,
MetaWaylandBuffer *buffer)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
/* TODO: we should change this api to be something like
* meta_shaped_texture_notify_buffer_attach() since we now maintain
* a reference to the MetaWaylandSurface where we can access the
* buffer without it being explicitly passed as an argument.
*/
g_return_if_fail (priv->wayland.surface->buffer_ref.buffer == buffer);
if (buffer)
set_cogl_texture (stex, buffer->texture);
else
set_cogl_texture (stex, NULL);
if (priv->create_mipmaps)
meta_texture_tower_set_base_texture (priv->paint_tower,
COGL_TEXTURE (priv->texture));
}
/**
* meta_shaped_texture_get_texture:
* @stex: The #MetaShapedTexture
@ -533,11 +897,46 @@ 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
* @clip_region: (transfer full): the region of the texture that
* is visible and should be painted.
* @clip_region: the region of the texture that is visible and
* should be painted.
*
* Provides a hint to the texture about what areas of the texture
* are not completely obscured and thus need to be painted. This
@ -558,10 +957,7 @@ meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
priv = stex->priv;
if (priv->clip_region)
{
cairo_region_destroy (priv->clip_region);
priv->clip_region = NULL;
}
cairo_region_destroy (priv->clip_region);
if (clip_region)
priv->clip_region = cairo_region_copy (clip_region);
@ -569,6 +965,36 @@ meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
priv->clip_region = NULL;
}
/**
* meta_shaped_texture_set_opaque_region:
* @stex: a #MetaShapedTexture
* @opaque_region: (transfer full): the region of the texture that
* can have blending turned off.
*
* As most windows have a large portion that does not require blending,
* we can easily turn off blending if we know the areas that do not
* require blending. This sets the region where we will not blend for
* optimization purposes.
*/
void
meta_shaped_texture_set_opaque_region (MetaShapedTexture *stex,
cairo_region_t *opaque_region)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
if (priv->opaque_region)
cairo_region_destroy (priv->opaque_region);
if (opaque_region)
priv->opaque_region = cairo_region_reference (opaque_region);
else
priv->opaque_region = NULL;
}
/**
* meta_shaped_texture_get_image:
* @stex: A #MetaShapedTexture

View File

@ -5,6 +5,9 @@
#include <config.h>
#include <wayland-server.h>
#include <meta-wayland-private.h>
#include <X11/extensions/Xdamage.h>
#include <meta/compositor-mutter.h>
@ -24,8 +27,18 @@ void meta_window_actor_unmaximize (MetaWindowActor *self,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
void meta_window_actor_process_damage (MetaWindowActor *self,
XDamageNotifyEvent *event);
void meta_window_actor_process_x11_damage (MetaWindowActor *self,
XDamageNotifyEvent *event);
void meta_window_actor_process_wayland_damage (MetaWindowActor *self,
int x,
int y,
int width,
int height);
void meta_window_actor_set_wayland_surface (MetaWindowActor *self,
MetaWaylandSurface *surface);
void meta_window_actor_attach_wayland_buffer (MetaWindowActor *self,
MetaWaylandBuffer *buffer);
void meta_window_actor_pre_paint (MetaWindowActor *self);
void meta_window_actor_post_paint (MetaWindowActor *self);
@ -57,11 +70,14 @@ void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
cairo_region_t *meta_window_actor_get_obscured_region (MetaWindowActor *self);
void meta_window_actor_set_visible_region (MetaWindowActor *self,
cairo_region_t *visible_region);
void meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
cairo_region_t *beneath_region);
void meta_window_actor_reset_visible_regions (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);
void meta_window_actor_effect_completed (MetaWindowActor *actor,
gulong event);

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@
#include "meta-window-group.h"
#include "meta-background-actor-private.h"
#include "meta-background-group-private.h"
#include "window-private.h"
struct _MetaWindowGroupClass
{
@ -89,16 +90,30 @@ painting_untransformed (MetaWindowGroup *window_group,
static void
meta_window_group_paint (ClutterActor *actor)
{
cairo_region_t *visible_region;
ClutterActor *stage;
cairo_rectangle_int_t visible_rect;
GList *children, *l;
cairo_region_t *clip_region;
cairo_region_t *unobscured_region;
ClutterActorIter iter;
ClutterActor *child;
cairo_rectangle_int_t visible_rect, clip_rect;
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);
/* Start off by treating all windows as completely unobscured, so damage anywhere
* in a window queues redraws, but confine it more below. */
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_set_unobscured_region (window_actor, NULL);
}
}
/* Normally we expect an actor to be drawn at it's position on the screen.
* However, if we're inside the paint of a ClutterClone, that won't be the
@ -123,12 +138,11 @@ meta_window_group_paint (ClutterActor *actor)
paint_x_offset = paint_x_origin - actor_x_origin;
paint_y_offset = paint_y_origin - actor_y_origin;
/* 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.
*/
children = clutter_actor_get_children (actor);
children = g_list_reverse (children);
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));
unobscured_region = cairo_region_create_rectangle (&visible_rect);
/* Get the clipped redraw bounds from Clutter so that we can avoid
* painting shadows on windows that don't need to be painted in this
@ -136,27 +150,38 @@ meta_window_group_paint (ClutterActor *actor)
* sizes, we could intersect this with an accurate union of the
* monitors to avoid painting shadows that are visible only in the
* holes. */
stage = clutter_actor_get_stage (actor);
clutter_stage_get_redraw_clip_bounds (CLUTTER_STAGE (stage),
&visible_rect);
&clip_rect);
visible_region = cairo_region_create_rectangle (&visible_rect);
clip_region = cairo_region_create_rectangle (&clip_rect);
if (info->unredirected_window != NULL)
if (!meta_is_wayland_compositor ())
{
cairo_rectangle_int_t unredirected_rect;
MetaWindow *window = meta_window_actor_get_meta_window (info->unredirected_window);
info = meta_screen_get_compositor_data (window_group->screen);
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);
cairo_region_subtract_rectangle (visible_region, &unredirected_rect);
meta_window_get_outer_rect (window, (MetaRectangle *)&unredirected_rect);
cairo_region_subtract_rectangle (unobscured_region, &unredirected_rect);
cairo_region_subtract_rectangle (clip_region, &unredirected_rect);
}
}
for (l = children; l; l = l->next)
/* 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 (l->data))
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
continue;
if (l->data == info->unredirected_window)
if (!meta_is_wayland_compositor () &&
info->unredirected_window != NULL &&
child == CLUTTER_ACTOR (info->unredirected_window))
continue;
/* If an actor has effects applied, then that can change the area
@ -175,12 +200,12 @@ meta_window_group_paint (ClutterActor *actor)
* as well for the same reason, but omitted for simplicity in the
* hopes that no-one will do that.
*/
if (clutter_actor_has_effects (l->data))
if (clutter_actor_has_effects (child))
continue;
if (META_IS_WINDOW_ACTOR (l->data))
if (META_IS_WINDOW_ACTOR (child))
{
MetaWindowActor *window_actor = l->data;
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
int x, y;
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
@ -189,65 +214,72 @@ meta_window_group_paint (ClutterActor *actor)
x += paint_x_offset;
y += paint_y_offset;
/* Temporarily move to the coordinate system of the actor */
cairo_region_translate (visible_region, - x, - y);
meta_window_actor_set_visible_region (window_actor, visible_region);
/* 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 (visible_region, obscured_region);
{
cairo_region_subtract (unobscured_region, obscured_region);
cairo_region_subtract (clip_region, obscured_region);
}
}
meta_window_actor_set_visible_region_beneath (window_actor, visible_region);
cairo_region_translate (visible_region, x, y);
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 (l->data) ||
META_IS_BACKGROUND_GROUP (l->data))
else if (META_IS_BACKGROUND_ACTOR (child) ||
META_IS_BACKGROUND_GROUP (child))
{
ClutterActor *background_actor = l->data;
int x, y;
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (background_actor), &x, &y))
if (!meta_actor_is_untransformed (child, &x, &y))
continue;
x += paint_x_offset;
y += paint_y_offset;
cairo_region_translate (visible_region, - x, - y);
cairo_region_translate (clip_region, - x, - y);
if (META_IS_BACKGROUND_GROUP (background_actor))
meta_background_group_set_visible_region (META_BACKGROUND_GROUP (background_actor), visible_region);
if (META_IS_BACKGROUND_GROUP (child))
meta_background_group_set_clip_region (META_BACKGROUND_GROUP (child), clip_region);
else
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (background_actor), visible_region);
cairo_region_translate (visible_region, x, y);
meta_background_actor_set_clip_region (META_BACKGROUND_ACTOR (child), clip_region);
cairo_region_translate (clip_region, x, y);
}
}
cairo_region_destroy (visible_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)
*/
for (l = children; l; l = l->next)
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
{
if (META_IS_WINDOW_ACTOR (l->data))
if (META_IS_WINDOW_ACTOR (child))
{
MetaWindowActor *window_actor = l->data;
meta_window_actor_reset_visible_regions (window_actor);
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
meta_window_actor_reset_clip_regions (window_actor);
}
else if (META_IS_BACKGROUND_ACTOR (l->data))
else if (META_IS_BACKGROUND_ACTOR (child))
{
MetaBackgroundActor *background_actor = l->data;
meta_background_actor_set_visible_region (background_actor, NULL);
MetaBackgroundActor *background_actor = META_BACKGROUND_ACTOR (child);
meta_background_actor_set_clip_region (background_actor, NULL);
}
}
g_list_free (children);
}
static gboolean

View File

@ -21,13 +21,14 @@
* 02111-1307, USA.
*/
#include <config.h>
#include <meta/meta-plugin.h>
#include <meta/window.h>
#include <meta/meta-background-group.h>
#include <meta/meta-background-actor.h>
#include <meta/util.h>
#include <libintl.h>
#define _(x) dgettext (GETTEXT_PACKAGE, x)
#define N_(x) x
#include <glib/gi18n-lib.h>
#include <clutter/clutter.h>
#include <gmodule.h>
@ -98,6 +99,8 @@ static void kill_window_effects (MetaPlugin *plugin,
MetaWindowActor *actor);
static void kill_switch_workspace (MetaPlugin *plugin);
static void confirm_display_change (MetaPlugin *plugin);
static const MetaPluginInfo * plugin_info (MetaPlugin *plugin);
META_PLUGIN_DECLARE(MetaDefaultPlugin, meta_default_plugin);
@ -113,6 +116,8 @@ struct _MetaDefaultPluginPrivate
ClutterActor *desktop1;
ClutterActor *desktop2;
ClutterActor *background_group;
MetaPluginInfo info;
};
@ -203,6 +208,7 @@ meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
plugin_class->plugin_info = plugin_info;
plugin_class->kill_window_effects = kill_window_effects;
plugin_class->kill_switch_workspace = kill_switch_workspace;
plugin_class->confirm_display_change = confirm_display_change;
g_type_class_add_private (gobject_class, sizeof (MetaDefaultPluginPrivate));
}
@ -299,9 +305,58 @@ show_stage (MetaPlugin *plugin)
return FALSE;
}
static void
on_monitors_changed (MetaScreen *screen,
MetaPlugin *plugin)
{
MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
int i, n;
clutter_actor_destroy_all_children (self->priv->background_group);
n = meta_screen_get_n_monitors (screen);
for (i = 0; i < n; i++)
{
MetaRectangle rect;
ClutterActor *background;
ClutterColor color;
meta_screen_get_monitor_geometry (screen, i, &rect);
background = meta_background_actor_new ();
clutter_actor_set_position (background, rect.x, rect.y);
clutter_actor_set_size (background, rect.width, rect.height);
/* Don't use rand() here, mesa calls srand() internally when
parsing the driconf XML, but it's nice if the colors are
reproducible.
*/
clutter_color_init (&color,
g_random_int () % 255,
g_random_int () % 255,
g_random_int () % 255,
255);
clutter_actor_set_background_color (background, &color);
clutter_actor_add_child (self->priv->background_group, background);
}
}
static void
start (MetaPlugin *plugin)
{
MetaDefaultPlugin *self = META_DEFAULT_PLUGIN (plugin);
MetaScreen *screen = meta_plugin_get_screen (plugin);
self->priv->background_group = meta_background_group_new ();
clutter_actor_insert_child_below (meta_get_window_group_for_screen (screen),
self->priv->background_group, NULL);
g_signal_connect (screen, "monitors-changed",
G_CALLBACK (on_monitors_changed), plugin);
on_monitors_changed (screen, plugin);
meta_later_add (META_LATER_BEFORE_REDRAW,
(GSourceFunc) show_stage,
plugin,
@ -782,3 +837,33 @@ plugin_info (MetaPlugin *plugin)
return &priv->info;
}
static void
on_dialog_closed (GPid pid,
gint status,
gpointer user_data)
{
MetaPlugin *plugin = user_data;
gboolean ok;
ok = g_spawn_check_exit_status (status, NULL);
meta_plugin_complete_display_change (plugin, ok);
}
static void
confirm_display_change (MetaPlugin *plugin)
{
GPid pid;
pid = meta_show_dialog ("--question",
"Does the display look OK?",
"20",
NULL,
"_Keep This Configuration",
"_Restore Previous Configuration",
"preferences-desktop-display",
0,
NULL, NULL);
g_child_watch_add (pid, on_dialog_closed, plugin);
}

View File

@ -59,6 +59,8 @@ struct _MetaBarrierPrivate
PointerBarrier xbarrier;
};
static void meta_barrier_event_unref (MetaBarrierEvent *event);
static void
meta_barrier_get_property (GObject *object,
guint prop_id,
@ -359,6 +361,8 @@ meta_barrier_fire_event (MetaBarrier *barrier,
default:
g_assert_not_reached ();
}
meta_barrier_event_unref (event);
}
gboolean

View File

@ -53,6 +53,7 @@
#include "bell.h"
#include "screen-private.h"
#include "window-private.h"
#include "util-private.h"
#include <meta/prefs.h>
#include <meta/compositor.h>
#ifdef HAVE_LIBCANBERRA

View File

@ -35,7 +35,8 @@ typedef enum
META_DO_GRAVITY_ADJUST = 1 << 1,
META_IS_USER_ACTION = 1 << 2,
META_IS_MOVE_ACTION = 1 << 3,
META_IS_RESIZE_ACTION = 1 << 4
META_IS_RESIZE_ACTION = 1 << 4,
META_IS_WAYLAND_RESIZE = 1 << 5
} MetaMoveResizeFlags;
void meta_window_constrain (MetaWindow *window,

View File

@ -29,6 +29,7 @@
#include "workspace-private.h"
#include <meta/prefs.h>
#include <meta/errors.h>
#include "util-private.h"
/* Looks up the MetaWindow representing the frame of the given X window.
* Used as a helper function by a bunch of the functions below.
@ -89,7 +90,7 @@ meta_core_get (Display *xdisplay,
if (request != META_CORE_WINDOW_HAS_FRAME &&
(window == NULL || window->frame == NULL)) {
meta_bug ("No such frame window 0x%lx!\n", xwindow);
return;
goto out;
}
while (request != META_CORE_GET_END) {
@ -99,7 +100,7 @@ meta_core_get (Display *xdisplay,
switch (request) {
case META_CORE_WINDOW_HAS_FRAME:
*((gboolean*)answer) = window != NULL && window->frame != NULL;
if (!*((gboolean*)answer)) return; /* see above */
if (!*((gboolean*)answer)) goto out; /* see above */
break;
case META_CORE_GET_CLIENT_WIDTH:
*((gint*)answer) = window->rect.width;
@ -154,12 +155,13 @@ meta_core_get (Display *xdisplay,
break;
default:
meta_warning(_("Unknown window information request: %d"), request);
meta_warning("Unknown window information request: %d\n", request);
}
request = va_arg (args, MetaCoreGetType);
}
out:
va_end (args);
}
@ -269,6 +271,8 @@ meta_core_lower_beneath_grab_window (Display *xdisplay,
MetaDisplay *display;
MetaScreen *screen;
MetaWindow *grab_window;
MetaStackWindow stack_window;
MetaStackWindow stack_sibling;
display = meta_display_for_x_display (xdisplay);
screen = meta_display_screen_for_xwindow (display, xwindow);
@ -281,9 +285,13 @@ meta_core_lower_beneath_grab_window (Display *xdisplay,
changes.sibling = grab_window->frame ? grab_window->frame->xwindow
: grab_window->xwindow;
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = xwindow;
stack_sibling.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_sibling.x11.xwindow = changes.sibling;
meta_stack_tracker_record_lower_below (screen->stack_tracker,
xwindow,
changes.sibling,
&stack_window,
&stack_sibling,
XNextRequest (screen->display->xdisplay));
meta_error_trap_push (display);

View File

@ -25,7 +25,7 @@
#define _XOPEN_SOURCE /* for kill() */
#include <config.h>
#include <meta/util.h>
#include "util-private.h"
#include "window-private.h"
#include <meta/errors.h>
#include <meta/workspace.h>

View File

@ -86,6 +86,14 @@ typedef enum {
META_TILE_MAXIMIZED
} MetaTileMode;
typedef enum {
META_FOCUS_NONE = 0,
META_FOCUS_X_CLIENT = 1,
META_FOCUS_WAYLAND_CLIENT = 2,
META_FOCUS_NO_FOCUS_WINDOW = 3,
META_FOCUS_STAGE = 4
} MetaFocusType;
struct _MetaDisplay
{
GObject parent_instance;
@ -103,19 +111,21 @@ struct _MetaDisplay
#include <meta/atomnames.h>
#undef item
/* This is the actual window from focus events,
* not the one we last set
/* The window and serial of the most recent FocusIn event. */
Window server_focus_window;
gulong server_focus_serial;
/* Our best guess as to the "currently" focused window (that is, the
* window that we expect will be focused at the point when the X
* server processes our next request), and the serial of the request
* or event that caused this.
*/
MetaWindow *focus_window;
/* window we are expecting a FocusIn event for or the current focus
* window if we are not expecting any FocusIn/FocusOut events; not
* perfect because applications can call XSetInputFocus directly.
* (It could also be messed up if a timestamp later than current
* time is sent to meta_display_set_input_focus_window, though that
* would be a programming error). See bug 154598 for more info.
*/
MetaWindow *expected_focus_window;
/* For windows we've focused that don't necessarily have an X window,
* like the no_focus_window or the stage X window. */
Window focus_xwindow;
gulong focus_serial;
MetaFocusType focus_type;
/* last timestamp passed to XSetInputFocus */
guint32 last_focus_time;
@ -144,6 +154,7 @@ struct _MetaDisplay
GSList *screens;
MetaScreen *active_screen;
GHashTable *xids;
GHashTable *wayland_windows;
int error_traps;
int (* error_trap_handler) (Display *display,
XErrorEvent *error);
@ -239,6 +250,8 @@ struct _MetaDisplay
unsigned int meta_mask;
MetaKeyCombo overlay_key_combo;
gboolean overlay_key_only_pressed;
MetaKeyCombo *iso_next_group_combos;
int n_iso_next_group_combos;
/* Monitor cache */
unsigned int monitor_cache_invalidated : 1;
@ -368,6 +381,11 @@ void meta_display_register_x_window (MetaDisplay *display,
void meta_display_unregister_x_window (MetaDisplay *display,
Window xwindow);
void meta_display_register_wayland_window (MetaDisplay *display,
MetaWindow *window);
void meta_display_unregister_wayland_window (MetaDisplay *display,
MetaWindow *window);
#ifdef HAVE_XSYNC
MetaWindow* meta_display_lookup_sync_alarm (MetaDisplay *display,
XSyncAlarm alarm);
@ -457,14 +475,25 @@ void meta_display_remove_autoraise_callback (MetaDisplay *display);
void meta_display_overlay_key_activate (MetaDisplay *display);
void meta_display_accelerator_activate (MetaDisplay *display,
guint action,
guint deviceid);
guint deviceid,
guint timestamp);
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
/* In above-tab-keycode.c */
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
gboolean meta_display_handle_event (MetaDisplay *display,
XEvent *event);
#ifdef HAVE_XI23
gboolean meta_display_process_barrier_event (MetaDisplay *display,
XIBarrierEvent *event);
#endif /* HAVE_XI23 */
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
MetaScreen *screen,
MetaFocusType type,
Window window,
guint32 timestamp);
#endif

File diff suppressed because it is too large Load Diff

539
src/core/edid-parse.c Normal file
View File

@ -0,0 +1,539 @@
/*
* Copyright 2007 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* Author: Soren Sandmann <sandmann@redhat.com> */
#include "edid.h"
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <glib.h>
static int
get_bit (int in, int bit)
{
return (in & (1 << bit)) >> bit;
}
static int
get_bits (int in, int begin, int end)
{
int mask = (1 << (end - begin + 1)) - 1;
return (in >> begin) & mask;
}
static int
decode_header (const uchar *edid)
{
if (memcmp (edid, "\x00\xff\xff\xff\xff\xff\xff\x00", 8) == 0)
return TRUE;
return FALSE;
}
static int
decode_vendor_and_product_identification (const uchar *edid, MonitorInfo *info)
{
int is_model_year;
/* Manufacturer Code */
info->manufacturer_code[0] = get_bits (edid[0x08], 2, 6);
info->manufacturer_code[1] = get_bits (edid[0x08], 0, 1) << 3;
info->manufacturer_code[1] |= get_bits (edid[0x09], 5, 7);
info->manufacturer_code[2] = get_bits (edid[0x09], 0, 4);
info->manufacturer_code[3] = '\0';
info->manufacturer_code[0] += 'A' - 1;
info->manufacturer_code[1] += 'A' - 1;
info->manufacturer_code[2] += 'A' - 1;
/* Product Code */
info->product_code = edid[0x0b] << 8 | edid[0x0a];
/* Serial Number */
info->serial_number =
edid[0x0c] | edid[0x0d] << 8 | edid[0x0e] << 16 | edid[0x0f] << 24;
/* Week and Year */
is_model_year = FALSE;
switch (edid[0x10])
{
case 0x00:
info->production_week = -1;
break;
case 0xff:
info->production_week = -1;
is_model_year = TRUE;
break;
default:
info->production_week = edid[0x10];
break;
}
if (is_model_year)
{
info->production_year = -1;
info->model_year = 1990 + edid[0x11];
}
else
{
info->production_year = 1990 + edid[0x11];
info->model_year = -1;
}
return TRUE;
}
static int
decode_edid_version (const uchar *edid, MonitorInfo *info)
{
info->major_version = edid[0x12];
info->minor_version = edid[0x13];
return TRUE;
}
static int
decode_display_parameters (const uchar *edid, MonitorInfo *info)
{
/* Digital vs Analog */
info->is_digital = get_bit (edid[0x14], 7);
if (info->is_digital)
{
int bits;
static const int bit_depth[8] =
{
-1, 6, 8, 10, 12, 14, 16, -1
};
static const Interface interfaces[6] =
{
UNDEFINED, DVI, HDMI_A, HDMI_B, MDDI, DISPLAY_PORT
};
bits = get_bits (edid[0x14], 4, 6);
info->connector.digital.bits_per_primary = bit_depth[bits];
bits = get_bits (edid[0x14], 0, 3);
if (bits <= 5)
info->connector.digital.interface = interfaces[bits];
else
info->connector.digital.interface = UNDEFINED;
}
else
{
int bits = get_bits (edid[0x14], 5, 6);
static const double levels[][3] =
{
{ 0.7, 0.3, 1.0 },
{ 0.714, 0.286, 1.0 },
{ 1.0, 0.4, 1.4 },
{ 0.7, 0.0, 0.7 },
};
info->connector.analog.video_signal_level = levels[bits][0];
info->connector.analog.sync_signal_level = levels[bits][1];
info->connector.analog.total_signal_level = levels[bits][2];
info->connector.analog.blank_to_black = get_bit (edid[0x14], 4);
info->connector.analog.separate_hv_sync = get_bit (edid[0x14], 3);
info->connector.analog.composite_sync_on_h = get_bit (edid[0x14], 2);
info->connector.analog.composite_sync_on_green = get_bit (edid[0x14], 1);
info->connector.analog.serration_on_vsync = get_bit (edid[0x14], 0);
}
/* Screen Size / Aspect Ratio */
if (edid[0x15] == 0 && edid[0x16] == 0)
{
info->width_mm = -1;
info->height_mm = -1;
info->aspect_ratio = -1.0;
}
else if (edid[0x16] == 0)
{
info->width_mm = -1;
info->height_mm = -1;
info->aspect_ratio = 100.0 / (edid[0x15] + 99);
}
else if (edid[0x15] == 0)
{
info->width_mm = -1;
info->height_mm = -1;
info->aspect_ratio = 100.0 / (edid[0x16] + 99);
info->aspect_ratio = 1/info->aspect_ratio; /* portrait */
}
else
{
info->width_mm = 10 * edid[0x15];
info->height_mm = 10 * edid[0x16];
}
/* Gamma */
if (edid[0x17] == 0xFF)
info->gamma = -1.0;
else
info->gamma = (edid[0x17] + 100.0) / 100.0;
/* Features */
info->standby = get_bit (edid[0x18], 7);
info->suspend = get_bit (edid[0x18], 6);
info->active_off = get_bit (edid[0x18], 5);
if (info->is_digital)
{
info->connector.digital.rgb444 = TRUE;
if (get_bit (edid[0x18], 3))
info->connector.digital.ycrcb444 = 1;
if (get_bit (edid[0x18], 4))
info->connector.digital.ycrcb422 = 1;
}
else
{
int bits = get_bits (edid[0x18], 3, 4);
ColorType color_type[4] =
{
MONOCHROME, RGB, OTHER_COLOR, UNDEFINED_COLOR
};
info->connector.analog.color_type = color_type[bits];
}
info->srgb_is_standard = get_bit (edid[0x18], 2);
/* In 1.3 this is called "has preferred timing" */
info->preferred_timing_includes_native = get_bit (edid[0x18], 1);
/* FIXME: In 1.3 this indicates whether the monitor accepts GTF */
info->continuous_frequency = get_bit (edid[0x18], 0);
return TRUE;
}
static double
decode_fraction (int high, int low)
{
double result = 0.0;
int i;
high = (high << 2) | low;
for (i = 0; i < 10; ++i)
result += get_bit (high, i) * pow (2, i - 10);
return result;
}
static int
decode_color_characteristics (const uchar *edid, MonitorInfo *info)
{
info->red_x = decode_fraction (edid[0x1b], get_bits (edid[0x19], 6, 7));
info->red_y = decode_fraction (edid[0x1c], get_bits (edid[0x19], 5, 4));
info->green_x = decode_fraction (edid[0x1d], get_bits (edid[0x19], 2, 3));
info->green_y = decode_fraction (edid[0x1e], get_bits (edid[0x19], 0, 1));
info->blue_x = decode_fraction (edid[0x1f], get_bits (edid[0x1a], 6, 7));
info->blue_y = decode_fraction (edid[0x20], get_bits (edid[0x1a], 4, 5));
info->white_x = decode_fraction (edid[0x21], get_bits (edid[0x1a], 2, 3));
info->white_y = decode_fraction (edid[0x22], get_bits (edid[0x1a], 0, 1));
return TRUE;
}
static int
decode_established_timings (const uchar *edid, MonitorInfo *info)
{
static const Timing established[][8] =
{
{
{ 800, 600, 60 },
{ 800, 600, 56 },
{ 640, 480, 75 },
{ 640, 480, 72 },
{ 640, 480, 67 },
{ 640, 480, 60 },
{ 720, 400, 88 },
{ 720, 400, 70 }
},
{
{ 1280, 1024, 75 },
{ 1024, 768, 75 },
{ 1024, 768, 70 },
{ 1024, 768, 60 },
{ 1024, 768, 87 },
{ 832, 624, 75 },
{ 800, 600, 75 },
{ 800, 600, 72 }
},
{
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 0, 0, 0 },
{ 1152, 870, 75 }
},
};
int i, j, idx;
idx = 0;
for (i = 0; i < 3; ++i)
{
for (j = 0; j < 8; ++j)
{
int byte = edid[0x23 + i];
if (get_bit (byte, j) && established[i][j].frequency != 0)
info->established[idx++] = established[i][j];
}
}
return TRUE;
}
static int
decode_standard_timings (const uchar *edid, MonitorInfo *info)
{
int i;
for (i = 0; i < 8; i++)
{
int first = edid[0x26 + 2 * i];
int second = edid[0x27 + 2 * i];
if (first != 0x01 && second != 0x01)
{
int w = 8 * (first + 31);
int h = 0;
switch (get_bits (second, 6, 7))
{
case 0x00: h = (w / 16) * 10; break;
case 0x01: h = (w / 4) * 3; break;
case 0x02: h = (w / 5) * 4; break;
case 0x03: h = (w / 16) * 9; break;
}
info->standard[i].width = w;
info->standard[i].height = h;
info->standard[i].frequency = get_bits (second, 0, 5) + 60;
}
}
return TRUE;
}
static void
decode_lf_string (const uchar *s, int n_chars, char *result)
{
int i;
for (i = 0; i < n_chars; ++i)
{
if (s[i] == 0x0a)
{
*result++ = '\0';
break;
}
else if (s[i] == 0x00)
{
/* Convert embedded 0's to spaces */
*result++ = ' ';
}
else
{
*result++ = s[i];
}
}
}
static void
decode_display_descriptor (const uchar *desc,
MonitorInfo *info)
{
switch (desc[0x03])
{
case 0xFC:
decode_lf_string (desc + 5, 13, info->dsc_product_name);
break;
case 0xFF:
decode_lf_string (desc + 5, 13, info->dsc_serial_number);
break;
case 0xFE:
decode_lf_string (desc + 5, 13, info->dsc_string);
break;
case 0xFD:
/* Range Limits */
break;
case 0xFB:
/* Color Point */
break;
case 0xFA:
/* Timing Identifications */
break;
case 0xF9:
/* Color Management */
break;
case 0xF8:
/* Timing Codes */
break;
case 0xF7:
/* Established Timings */
break;
case 0x10:
break;
}
}
static void
decode_detailed_timing (const uchar *timing,
DetailedTiming *detailed)
{
int bits;
StereoType stereo[] =
{
NO_STEREO, NO_STEREO, FIELD_RIGHT, FIELD_LEFT,
TWO_WAY_RIGHT_ON_EVEN, TWO_WAY_LEFT_ON_EVEN,
FOUR_WAY_INTERLEAVED, SIDE_BY_SIDE
};
detailed->pixel_clock = (timing[0x00] | timing[0x01] << 8) * 10000;
detailed->h_addr = timing[0x02] | ((timing[0x04] & 0xf0) << 4);
detailed->h_blank = timing[0x03] | ((timing[0x04] & 0x0f) << 8);
detailed->v_addr = timing[0x05] | ((timing[0x07] & 0xf0) << 4);
detailed->v_blank = timing[0x06] | ((timing[0x07] & 0x0f) << 8);
detailed->h_front_porch = timing[0x08] | get_bits (timing[0x0b], 6, 7) << 8;
detailed->h_sync = timing[0x09] | get_bits (timing[0x0b], 4, 5) << 8;
detailed->v_front_porch =
get_bits (timing[0x0a], 4, 7) | get_bits (timing[0x0b], 2, 3) << 4;
detailed->v_sync =
get_bits (timing[0x0a], 0, 3) | get_bits (timing[0x0b], 0, 1) << 4;
detailed->width_mm = timing[0x0c] | get_bits (timing[0x0e], 4, 7) << 8;
detailed->height_mm = timing[0x0d] | get_bits (timing[0x0e], 0, 3) << 8;
detailed->right_border = timing[0x0f];
detailed->top_border = timing[0x10];
detailed->interlaced = get_bit (timing[0x11], 7);
/* Stereo */
bits = get_bits (timing[0x11], 5, 6) << 1 | get_bit (timing[0x11], 0);
detailed->stereo = stereo[bits];
/* Sync */
bits = timing[0x11];
detailed->digital_sync = get_bit (bits, 4);
if (detailed->digital_sync)
{
detailed->connector.digital.composite = !get_bit (bits, 3);
if (detailed->connector.digital.composite)
{
detailed->connector.digital.serrations = get_bit (bits, 2);
detailed->connector.digital.negative_vsync = FALSE;
}
else
{
detailed->connector.digital.serrations = FALSE;
detailed->connector.digital.negative_vsync = !get_bit (bits, 2);
}
detailed->connector.digital.negative_hsync = !get_bit (bits, 0);
}
else
{
detailed->connector.analog.bipolar = get_bit (bits, 3);
detailed->connector.analog.serrations = get_bit (bits, 2);
detailed->connector.analog.sync_on_green = !get_bit (bits, 1);
}
}
static int
decode_descriptors (const uchar *edid, MonitorInfo *info)
{
int i;
int timing_idx;
timing_idx = 0;
for (i = 0; i < 4; ++i)
{
int index = 0x36 + i * 18;
if (edid[index + 0] == 0x00 && edid[index + 1] == 0x00)
{
decode_display_descriptor (edid + index, info);
}
else
{
decode_detailed_timing (edid + index, &(info->detailed_timings[timing_idx++]));
}
}
info->n_detailed_timings = timing_idx;
return TRUE;
}
static void
decode_check_sum (const uchar *edid,
MonitorInfo *info)
{
int i;
uchar check = 0;
for (i = 0; i < 128; ++i)
check += edid[i];
info->checksum = check;
}
MonitorInfo *
decode_edid (const uchar *edid)
{
MonitorInfo *info = g_new0 (MonitorInfo, 1);
decode_check_sum (edid, info);
if (decode_header (edid)
&& decode_vendor_and_product_identification (edid, info)
&& decode_edid_version (edid, info)
&& decode_display_parameters (edid, info)
&& decode_color_characteristics (edid, info)
&& decode_established_timings (edid, info)
&& decode_standard_timings (edid, info)
&& decode_descriptors (edid, info))
{
return info;
}
else
{
g_free (info);
return NULL;
}
}

195
src/core/edid.h Normal file
View File

@ -0,0 +1,195 @@
/* edid.h
*
* Copyright 2007, 2008, Red Hat, Inc.
*
* This file is part of the Gnome Library.
*
* The Gnome Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* The Gnome Library 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with the Gnome Library; see the file COPYING.LIB. If not,
* write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*
* Author: Soren Sandmann <sandmann@redhat.com>
*/
#ifndef EDID_H
#define EDID_H
typedef unsigned char uchar;
typedef struct MonitorInfo MonitorInfo;
typedef struct Timing Timing;
typedef struct DetailedTiming DetailedTiming;
typedef enum
{
UNDEFINED,
DVI,
HDMI_A,
HDMI_B,
MDDI,
DISPLAY_PORT
} Interface;
typedef enum
{
UNDEFINED_COLOR,
MONOCHROME,
RGB,
OTHER_COLOR
} ColorType;
typedef enum
{
NO_STEREO,
FIELD_RIGHT,
FIELD_LEFT,
TWO_WAY_RIGHT_ON_EVEN,
TWO_WAY_LEFT_ON_EVEN,
FOUR_WAY_INTERLEAVED,
SIDE_BY_SIDE
} StereoType;
struct Timing
{
int width;
int height;
int frequency;
};
struct DetailedTiming
{
int pixel_clock;
int h_addr;
int h_blank;
int h_sync;
int h_front_porch;
int v_addr;
int v_blank;
int v_sync;
int v_front_porch;
int width_mm;
int height_mm;
int right_border;
int top_border;
int interlaced;
StereoType stereo;
int digital_sync;
union
{
struct
{
int bipolar;
int serrations;
int sync_on_green;
} analog;
struct
{
int composite;
int serrations;
int negative_vsync;
int negative_hsync;
} digital;
} connector;
};
struct MonitorInfo
{
int checksum;
char manufacturer_code[4];
int product_code;
unsigned int serial_number;
int production_week; /* -1 if not specified */
int production_year; /* -1 if not specified */
int model_year; /* -1 if not specified */
int major_version;
int minor_version;
int is_digital;
union
{
struct
{
int bits_per_primary;
Interface interface;
int rgb444;
int ycrcb444;
int ycrcb422;
} digital;
struct
{
double video_signal_level;
double sync_signal_level;
double total_signal_level;
int blank_to_black;
int separate_hv_sync;
int composite_sync_on_h;
int composite_sync_on_green;
int serration_on_vsync;
ColorType color_type;
} analog;
} connector;
int width_mm; /* -1 if not specified */
int height_mm; /* -1 if not specified */
double aspect_ratio; /* -1.0 if not specififed */
double gamma; /* -1.0 if not specified */
int standby;
int suspend;
int active_off;
int srgb_is_standard;
int preferred_timing_includes_native;
int continuous_frequency;
double red_x;
double red_y;
double green_x;
double green_y;
double blue_x;
double blue_y;
double white_x;
double white_y;
Timing established[24]; /* Terminated by 0x0x0 */
Timing standard[8];
int n_detailed_timings;
DetailedTiming detailed_timings[4]; /* If monitor has a preferred
* mode, it is the first one
* (whether it has, is
* determined by the
* preferred_timing_includes
* bit.
*/
/* Optional product description */
char dsc_serial_number[14];
char dsc_product_name[14];
char dsc_string[14]; /* Unspecified ASCII data */
};
MonitorInfo *decode_edid (const uchar *data);
char *make_display_name (const MonitorInfo *info);
char *make_display_size_string (int width_mm, int height_mm);
#endif

View File

@ -47,6 +47,7 @@ meta_window_ensure_frame (MetaWindow *window)
XSetWindowAttributes attrs;
Visual *visual;
gulong create_serial;
MetaStackWindow stack_window;
if (window->frame)
return;
@ -105,8 +106,10 @@ meta_window_ensure_frame (MetaWindow *window)
frame->rect.height,
frame->window->screen->number,
&create_serial);
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = frame->xwindow;
meta_stack_tracker_record_add (window->screen->stack_tracker,
frame->xwindow,
&stack_window,
create_serial);
meta_verbose ("Frame for %s is 0x%lx\n", frame->window->desc, frame->xwindow);
@ -138,8 +141,9 @@ meta_window_ensure_frame (MetaWindow *window)
window->rect.x = 0;
window->rect.y = 0;
stack_window.x11.xwindow = window->xwindow;
meta_stack_tracker_record_remove (window->screen->stack_tracker,
window->xwindow,
&stack_window,
XNextRequest (window->display->xdisplay));
XReparentWindow (window->display->xdisplay,
window->xwindow,
@ -174,6 +178,7 @@ meta_window_destroy_frame (MetaWindow *window)
{
MetaFrame *frame;
MetaFrameBorders borders;
MetaStackWindow stack_window;
if (window->frame == NULL)
return;
@ -200,8 +205,10 @@ meta_window_destroy_frame (MetaWindow *window)
"Incrementing unmaps_pending on %s for reparent back to root\n", window->desc);
window->unmaps_pending += 1;
}
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = window->xwindow;
meta_stack_tracker_record_add (window->screen->stack_tracker,
window->xwindow,
&stack_window,
XNextRequest (window->display->xdisplay));
XReparentWindow (window->display->xdisplay,
window->xwindow,
@ -332,19 +339,6 @@ meta_frame_calc_borders (MetaFrame *frame,
borders);
}
void
meta_frame_get_corner_radiuses (MetaFrame *frame,
float *top_left,
float *top_right,
float *bottom_left,
float *bottom_right)
{
meta_ui_get_corner_radiuses (frame->window->screen->ui,
frame->xwindow,
top_left, top_right,
bottom_left, bottom_right);
}
gboolean
meta_frame_sync_to_window (MetaFrame *frame,
int resize_gravity,
@ -400,6 +394,14 @@ meta_frame_get_frame_bounds (MetaFrame *frame)
frame->rect.height);
}
void
meta_frame_get_mask (MetaFrame *frame,
cairo_t *cr)
{
meta_ui_get_frame_mask (frame->window->screen->ui, frame->xwindow,
frame->rect.width, frame->rect.height, cr);
}
void
meta_frame_queue_draw (MetaFrame *frame)
{

View File

@ -63,12 +63,6 @@ Window meta_frame_get_xwindow (MetaFrame *frame);
void meta_frame_calc_borders (MetaFrame *frame,
MetaFrameBorders *borders);
void meta_frame_get_corner_radiuses (MetaFrame *frame,
float *top_left,
float *top_right,
float *bottom_left,
float *bottom_right);
gboolean meta_frame_sync_to_window (MetaFrame *frame,
int gravity,
gboolean need_move,
@ -76,6 +70,9 @@ gboolean meta_frame_sync_to_window (MetaFrame *frame,
cairo_region_t *meta_frame_get_frame_bounds (MetaFrame *frame);
void meta_frame_get_mask (MetaFrame *frame,
cairo_t *cr);
void meta_frame_set_screen_cursor (MetaFrame *frame,
MetaCursor cursor);

View File

@ -69,7 +69,6 @@ void meta_window_ungrab_all_keys (MetaWindow *window,
gboolean meta_display_process_key_event (MetaDisplay *display,
MetaWindow *window,
XIDeviceEvent *event);
void meta_set_keybindings_disabled (gboolean setting);
void meta_display_process_mapping_event (MetaDisplay *display,
XEvent *event);

View File

@ -42,7 +42,7 @@
#include "frame.h"
#include "place.h"
#include <meta/prefs.h>
#include <meta/util.h>
#include "util-private.h"
#include <X11/keysym.h>
#include <string.h>
@ -53,10 +53,13 @@
#include <X11/XKBlib.h>
#endif
#ifdef HAVE_WAYLAND
#include "meta-wayland-private.h"
#endif
#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
static gboolean all_bindings_disabled = FALSE;
#define SCHEMA_MUTTER_WAYLAND_KEYBINDINGS "org.gnome.mutter.wayland.keybindings"
static gboolean add_builtin_keybinding (MetaDisplay *display,
const char *name,
@ -147,7 +150,8 @@ static gboolean process_workspace_switch_grab (MetaDisplay *display,
XIDeviceEvent *event,
KeySym keysym);
static void regrab_key_bindings (MetaDisplay *display);
static void grab_key_bindings (MetaDisplay *display);
static void ungrab_key_bindings (MetaDisplay *display);
static GHashTable *key_handlers;
@ -301,6 +305,172 @@ reload_modmap (MetaDisplay *display)
display->meta_mask);
}
/* Original code from gdk_x11_keymap_get_entries_for_keyval() in
* gdkkeys-x11.c */
static int
get_keycodes_for_keysym (MetaDisplay *display,
int keysym,
int **keycodes)
{
GArray *retval;
int n_keycodes;
int keycode;
retval = g_array_new (FALSE, FALSE, sizeof (int));
keycode = display->min_keycode;
while (keycode <= display->max_keycode)
{
const KeySym *syms = display->keymap + (keycode - display->min_keycode) * display->keysyms_per_keycode;
int i = 0;
while (i < display->keysyms_per_keycode)
{
if (syms[i] == (unsigned int)keysym)
g_array_append_val (retval, keycode);
++i;
}
++keycode;
}
n_keycodes = retval->len;
*keycodes = (int*) g_array_free (retval, n_keycodes == 0 ? TRUE : FALSE);
return n_keycodes;
}
static void
reload_iso_next_group_combos (MetaDisplay *display)
{
const char *iso_next_group_option;
MetaKeyCombo *combos;
int *keycodes;
int n_keycodes;
int n_combos;
int i;
g_clear_pointer (&display->iso_next_group_combos, g_free);
display->n_iso_next_group_combos = 0;
iso_next_group_option = meta_prefs_get_iso_next_group_option ();
if (iso_next_group_option == NULL)
return;
n_keycodes = get_keycodes_for_keysym (display, XK_ISO_Next_Group, &keycodes);
if (g_str_equal (iso_next_group_option, "toggle") ||
g_str_equal (iso_next_group_option, "lalt_toggle") ||
g_str_equal (iso_next_group_option, "lwin_toggle") ||
g_str_equal (iso_next_group_option, "rwin_toggle") ||
g_str_equal (iso_next_group_option, "lshift_toggle") ||
g_str_equal (iso_next_group_option, "rshift_toggle") ||
g_str_equal (iso_next_group_option, "lctrl_toggle") ||
g_str_equal (iso_next_group_option, "rctrl_toggle") ||
g_str_equal (iso_next_group_option, "sclk_toggle") ||
g_str_equal (iso_next_group_option, "menu_toggle") ||
g_str_equal (iso_next_group_option, "caps_toggle"))
{
n_combos = n_keycodes;
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XK_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].modifiers = 0;
}
}
else if (g_str_equal (iso_next_group_option, "shift_caps_toggle") ||
g_str_equal (iso_next_group_option, "shifts_toggle"))
{
n_combos = n_keycodes;
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XK_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].modifiers = ShiftMask;
}
}
else if (g_str_equal (iso_next_group_option, "alt_caps_toggle") ||
g_str_equal (iso_next_group_option, "alt_space_toggle"))
{
n_combos = n_keycodes;
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XK_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].modifiers = Mod1Mask;
}
}
else if (g_str_equal (iso_next_group_option, "ctrl_shift_toggle") ||
g_str_equal (iso_next_group_option, "lctrl_lshift_toggle") ||
g_str_equal (iso_next_group_option, "rctrl_rshift_toggle"))
{
n_combos = n_keycodes * 2;
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XK_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].modifiers = ShiftMask;
combos[i + n_keycodes].keysym = XK_ISO_Next_Group;
combos[i + n_keycodes].keycode = keycodes[i];
combos[i + n_keycodes].modifiers = ControlMask;
}
}
else if (g_str_equal (iso_next_group_option, "ctrl_alt_toggle"))
{
n_combos = n_keycodes * 2;
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XK_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].modifiers = Mod1Mask;
combos[i + n_keycodes].keysym = XK_ISO_Next_Group;
combos[i + n_keycodes].keycode = keycodes[i];
combos[i + n_keycodes].modifiers = ControlMask;
}
}
else if (g_str_equal (iso_next_group_option, "alt_shift_toggle") ||
g_str_equal (iso_next_group_option, "lalt_lshift_toggle"))
{
n_combos = n_keycodes * 2;
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XK_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].modifiers = Mod1Mask;
combos[i + n_keycodes].keysym = XK_ISO_Next_Group;
combos[i + n_keycodes].keycode = keycodes[i];
combos[i + n_keycodes].modifiers = ShiftMask;
}
}
else
{
n_combos = 0;
combos = NULL;
}
g_free (keycodes);
display->n_iso_next_group_combos = n_combos;
display->iso_next_group_combos = combos;
}
static guint
keysym_to_keycode (MetaDisplay *display,
guint keysym)
@ -327,6 +497,8 @@ reload_keycodes (MetaDisplay *display)
display->overlay_key_combo.keycode = 0;
}
reload_iso_next_group_combos (display);
if (display->key_bindings)
{
int i;
@ -531,7 +703,7 @@ rebuild_special_bindings (MetaDisplay *display)
}
static void
regrab_key_bindings (MetaDisplay *display)
ungrab_key_bindings (MetaDisplay *display)
{
GSList *tmp;
GSList *windows;
@ -544,7 +716,6 @@ regrab_key_bindings (MetaDisplay *display)
MetaScreen *screen = tmp->data;
meta_screen_ungrab_keys (screen);
meta_screen_grab_keys (screen);
tmp = tmp->next;
}
@ -556,6 +727,38 @@ regrab_key_bindings (MetaDisplay *display)
MetaWindow *w = tmp->data;
meta_window_ungrab_keys (w);
tmp = tmp->next;
}
meta_error_trap_pop (display);
g_slist_free (windows);
}
static void
grab_key_bindings (MetaDisplay *display)
{
GSList *tmp;
GSList *windows;
meta_error_trap_push (display); /* for efficiency push outer trap */
tmp = display->screens;
while (tmp != NULL)
{
MetaScreen *screen = tmp->data;
meta_screen_grab_keys (screen);
tmp = tmp->next;
}
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
tmp = windows;
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
meta_window_grab_keys (w);
tmp = tmp->next;
@ -796,6 +999,8 @@ meta_display_process_mapping_event (MetaDisplay *display,
if (keymap_changed || modmap_changed)
{
ungrab_key_bindings (display);
if (keymap_changed)
reload_keymap (display);
@ -809,7 +1014,7 @@ meta_display_process_mapping_event (MetaDisplay *display,
reload_modifiers (display);
regrab_key_bindings (display);
grab_key_bindings (display);
}
}
@ -824,11 +1029,12 @@ bindings_changed_callback (MetaPreference pref,
switch (pref)
{
case META_PREF_KEYBINDINGS:
ungrab_key_bindings (display);
rebuild_key_binding_table (display);
rebuild_special_bindings (display);
reload_keycodes (display);
reload_modifiers (display);
regrab_key_bindings (display);
grab_key_bindings (display);
break;
default:
break;
@ -932,7 +1138,7 @@ meta_change_keygrab (MetaDisplay *display,
if (grab && result != Success)
{
if (result == BadAccess)
meta_warning (_("Some other program is already using the key %s with modifiers %x as a binding\n"), keysym_name (keysym), modmask | ignored_mask);
meta_warning ("Some other program is already using the key %s with modifiers %x as a binding\n", keysym_name (keysym), modmask | ignored_mask);
else
meta_topic (META_DEBUG_KEYBINDINGS,
"Failed to grab key %s with modifiers %x\n",
@ -947,21 +1153,12 @@ meta_change_keygrab (MetaDisplay *display,
}
static void
meta_grab_key (MetaDisplay *display,
Window xwindow,
int keysym,
unsigned int keycode,
int modmask)
{
meta_change_keygrab (display, xwindow, TRUE, keysym, keycode, modmask);
}
static void
grab_keys (MetaKeyBinding *bindings,
int n_bindings,
MetaDisplay *display,
Window xwindow,
gboolean binding_per_window)
change_binding_keygrabs (MetaKeyBinding *bindings,
int n_bindings,
MetaDisplay *display,
Window xwindow,
gboolean binding_per_window,
gboolean grab)
{
int i;
@ -976,10 +1173,10 @@ grab_keys (MetaKeyBinding *bindings,
!!(bindings[i].handler->flags & META_KEY_BINDING_PER_WINDOW) &&
bindings[i].keycode != 0)
{
meta_grab_key (display, xwindow,
bindings[i].keysym,
bindings[i].keycode,
bindings[i].mask);
meta_change_keygrab (display, xwindow, grab,
bindings[i].keysym,
bindings[i].keycode,
bindings[i].mask);
}
++i;
@ -989,51 +1186,49 @@ grab_keys (MetaKeyBinding *bindings,
}
static void
ungrab_all_keys (MetaDisplay *display,
Window xwindow)
meta_screen_change_keygrabs (MetaScreen *screen,
gboolean grab)
{
if (meta_is_debugging ())
meta_error_trap_push_with_return (display);
else
meta_error_trap_push (display);
MetaDisplay *display = screen->display;
XUngrabKey (display->xdisplay, AnyKey, AnyModifier,
xwindow);
if (display->overlay_key_combo.keycode != 0)
meta_change_keygrab (display, screen->xroot, grab,
display->overlay_key_combo.keysym,
display->overlay_key_combo.keycode,
display->overlay_key_combo.modifiers);
if (meta_is_debugging ())
if (display->iso_next_group_combos)
{
int result;
result = meta_error_trap_pop_with_return (display);
if (result != Success)
meta_topic (META_DEBUG_KEYBINDINGS,
"Ungrabbing all keys on 0x%lx failed\n", xwindow);
int i = 0;
while (i < display->n_iso_next_group_combos)
{
if (display->iso_next_group_combos[i].keycode != 0)
{
meta_change_keygrab (display, screen->xroot, grab,
display->iso_next_group_combos[i].keysym,
display->iso_next_group_combos[i].keycode,
display->iso_next_group_combos[i].modifiers);
}
++i;
}
}
else
meta_error_trap_pop (display);
change_binding_keygrabs (screen->display->key_bindings,
screen->display->n_key_bindings,
screen->display, screen->xroot,
FALSE, grab);
}
void
meta_screen_grab_keys (MetaScreen *screen)
{
MetaDisplay *display = screen->display;
if (screen->all_keys_grabbed)
return;
if (screen->keys_grabbed)
return;
if (display->overlay_key_combo.keycode != 0)
meta_grab_key (display, screen->xroot,
display->overlay_key_combo.keysym,
display->overlay_key_combo.keycode,
display->overlay_key_combo.modifiers);
grab_keys (screen->display->key_bindings,
screen->display->n_key_bindings,
screen->display, screen->xroot,
FALSE);
meta_screen_change_keygrabs (screen, TRUE);
screen->keys_grabbed = TRUE;
}
@ -1041,11 +1236,23 @@ meta_screen_grab_keys (MetaScreen *screen)
void
meta_screen_ungrab_keys (MetaScreen *screen)
{
if (screen->keys_grabbed)
{
ungrab_all_keys (screen->display, screen->xroot);
screen->keys_grabbed = FALSE;
}
if (!screen->keys_grabbed)
return;
meta_screen_change_keygrabs (screen, FALSE);
screen->keys_grabbed = FALSE;
}
static void
meta_window_change_keygrabs (MetaWindow *window,
Window xwindow,
gboolean grab)
{
change_binding_keygrabs (window->display->key_bindings,
window->display->n_key_bindings,
window->display, xwindow,
TRUE, grab);
}
void
@ -1058,7 +1265,7 @@ meta_window_grab_keys (MetaWindow *window)
|| window->override_redirect)
{
if (window->keys_grabbed)
ungrab_all_keys (window->display, window->xwindow);
meta_window_change_keygrabs (window, window->xwindow, FALSE);
window->keys_grabbed = FALSE;
return;
}
@ -1066,7 +1273,7 @@ meta_window_grab_keys (MetaWindow *window)
if (window->keys_grabbed)
{
if (window->frame && !window->grab_on_frame)
ungrab_all_keys (window->display, window->xwindow);
meta_window_change_keygrabs (window, window->xwindow, FALSE);
else if (window->frame == NULL &&
window->grab_on_frame)
; /* continue to regrab on client window */
@ -1074,11 +1281,9 @@ meta_window_grab_keys (MetaWindow *window)
return; /* already all good */
}
grab_keys (window->display->key_bindings,
window->display->n_key_bindings,
window->display,
window->frame ? window->frame->xwindow : window->xwindow,
TRUE);
meta_window_change_keygrabs (window,
window->frame ? window->frame->xwindow : window->xwindow,
TRUE);
window->keys_grabbed = TRUE;
window->grab_on_frame = window->frame != NULL;
@ -1091,11 +1296,9 @@ meta_window_ungrab_keys (MetaWindow *window)
{
if (window->grab_on_frame &&
window->frame != NULL)
ungrab_all_keys (window->display,
window->frame->xwindow);
meta_window_change_keygrabs (window, window->frame->xwindow, FALSE);
else if (!window->grab_on_frame)
ungrab_all_keys (window->display,
window->xwindow);
meta_window_change_keygrabs (window, window->xwindow, FALSE);
window->keys_grabbed = FALSE;
}
@ -1112,7 +1315,7 @@ handle_external_grab (MetaDisplay *display,
guint action = meta_display_get_keybinding_action (display,
binding->keycode,
binding->mask);
meta_display_accelerator_activate (display, action, event->deviceid);
meta_display_accelerator_activate (display, action, event->deviceid, event->time);
}
@ -1132,7 +1335,7 @@ meta_display_grab_accelerator (MetaDisplay *display,
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Failed to parse accelerator\n");
meta_warning (_("\"%s\" is not a valid accelerator\n"), accelerator);
meta_warning ("\"%s\" is not a valid accelerator\n", accelerator);
return META_KEYBINDING_ACTION_NONE;
}
@ -1151,7 +1354,7 @@ meta_display_grab_accelerator (MetaDisplay *display,
for (l = display->screens; l; l = l->next)
{
MetaScreen *screen = l->data;
meta_grab_key (display, screen->xroot, keysym, keycode, mask);
meta_change_keygrab (display, screen->xroot, TRUE, keysym, keycode, mask);
}
grab = g_new0 (MetaKeyGrab, 1);
@ -1248,7 +1451,8 @@ grab_status_to_string (int status)
static gboolean
grab_keyboard (MetaDisplay *display,
Window xwindow,
guint32 timestamp)
guint32 timestamp,
int grab_mode)
{
int result;
int grab_status;
@ -1264,13 +1468,22 @@ grab_keyboard (MetaDisplay *display,
*/
meta_error_trap_push_with_return (display);
/* Strictly, we only need to set grab_mode on the keyboard device
* while the pointer should always be XIGrabModeAsync. Unfortunately
* there is a bug in the X server, only fixed (link below) in 1.15,
* which swaps these arguments for keyboard devices. As such, we set
* both the device and the paired device mode which works around
* that bug and also works on fixed X servers.
*
* http://cgit.freedesktop.org/xorg/xserver/commit/?id=9003399708936481083424b4ff8f18a16b88b7b3
*/
grab_status = XIGrabDevice (display->xdisplay,
META_VIRTUAL_CORE_KEYBOARD_ID,
xwindow,
timestamp,
None,
XIGrabModeAsync, XIGrabModeAsync,
True, /* owner_events */
grab_mode, grab_mode,
False, /* owner_events */
&mask);
if (grab_status != Success)
@ -1323,7 +1536,7 @@ meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp)
meta_topic (META_DEBUG_KEYBINDINGS,
"Grabbing all keys on RootWindow\n");
retval = grab_keyboard (screen->display, screen->xroot, timestamp);
retval = grab_keyboard (screen->display, screen->xroot, timestamp, XIGrabModeAsync);
if (retval)
{
screen->all_keys_grabbed = TRUE;
@ -1376,7 +1589,7 @@ meta_window_grab_all_keys (MetaWindow *window,
meta_topic (META_DEBUG_KEYBINDINGS,
"Grabbing all keys on window %s\n", window->desc);
retval = grab_keyboard (window->display, grabwindow, timestamp);
retval = grab_keyboard (window->display, grabwindow, timestamp, XIGrabModeAsync);
if (retval)
{
window->keys_grabbed = FALSE;
@ -1403,6 +1616,32 @@ meta_window_ungrab_all_keys (MetaWindow *window, guint32 timestamp)
}
}
void
meta_display_freeze_keyboard (MetaDisplay *display, Window window, guint32 timestamp)
{
grab_keyboard (display, window, timestamp, XIGrabModeSync);
}
void
meta_display_ungrab_keyboard (MetaDisplay *display, guint32 timestamp)
{
ungrab_keyboard (display, timestamp);
}
void
meta_display_unfreeze_keyboard (MetaDisplay *display, guint32 timestamp)
{
meta_error_trap_push (display);
XIAllowEvents (display->xdisplay, META_VIRTUAL_CORE_KEYBOARD_ID,
XIAsyncDevice, timestamp);
/* We shouldn't need to unfreeze the pointer device here, however we
* have to, due to the workaround we do in grab_keyboard().
*/
XIAllowEvents (display->xdisplay, META_VIRTUAL_CORE_POINTER_ID,
XIAsyncDevice, timestamp);
meta_error_trap_pop (display);
}
static gboolean
is_modifier (MetaDisplay *display,
unsigned int keycode)
@ -1731,6 +1970,23 @@ process_overlay_key (MetaDisplay *display,
return TRUE;
meta_display_overlay_key_activate (display);
}
else
{
/* In some rare race condition, mutter might not receive the Super_L
* KeyRelease event because:
* - the compositor might end the modal mode and call XIUngrabDevice
* while the key is still down
* - passive grabs are only activated on KeyPress and not KeyRelease.
*
* In this case, display->overlay_key_only_pressed might be wrong.
* Mutter still ought to acknowledge events, otherwise the X server
* will not send the next events.
*
* https://bugzilla.gnome.org/show_bug.cgi?id=666101
*/
XIAllowEvents (display->xdisplay, event->deviceid,
XIAsyncDevice, event->time);
}
return TRUE;
}
@ -1749,6 +2005,41 @@ process_overlay_key (MetaDisplay *display,
return FALSE;
}
static gboolean
process_iso_next_group (MetaDisplay *display,
MetaScreen *screen,
XIDeviceEvent *event,
KeySym keysym)
{
gboolean activate;
unsigned int mods;
int i;
if (event->evtype != XI_KeyPress)
return FALSE;
activate = FALSE;
mods = (event->mods.effective & 0xff & ~(display->ignored_modifier_mask));
for (i = 0; i < display->n_iso_next_group_combos; ++i)
{
if (event->detail == (int)display->iso_next_group_combos[i].keycode &&
mods == display->iso_next_group_combos[i].modifiers)
{
/* If the signal handler returns TRUE the keyboard will
remain frozen. It's the signal handler's responsibility
to unfreeze it. */
if (!meta_display_modifiers_accelerator_activate (display))
XIAllowEvents (display->xdisplay, event->deviceid,
XIAsyncDevice, event->time);
activate = TRUE;
break;
}
}
return activate;
}
/* Handle a key event. May be called recursively: some key events cause
* grabs to be ended and then need to be processed again in their own
* right. This cannot cause infinite recursion because we never call
@ -1775,21 +2066,6 @@ meta_display_process_key_event (MetaDisplay *display,
const char *str;
MetaScreen *screen;
if (all_bindings_disabled)
{
/* In this mode, we try to pretend we don't have grabs, so we
* immediately replay events and drop the grab. (This still
* messes up global passive grabs from other clients.) The
* FALSE return here is a little suspect, but we don't really
* know if we'll see the event again or not, and it's pretty
* poorly defined how this mode is supposed to interact with
* plugins.
*/
XIAllowEvents (display->xdisplay, event->deviceid,
XIReplayDevice, event->time);
return FALSE;
}
/* if key event was on root window, we have a shortcut */
screen = meta_display_screen_for_root (display, event->event);
@ -1823,6 +2099,10 @@ meta_display_process_key_event (MetaDisplay *display,
handled = process_overlay_key (display, screen, event, keysym);
if (handled)
return TRUE;
handled = process_iso_next_group (display, screen, event, keysym);
if (handled)
return TRUE;
}
XIAllowEvents (display->xdisplay, event->deviceid,
@ -3823,13 +4103,39 @@ handle_set_spew_mark (MetaDisplay *display,
meta_verbose ("-- MARK MARK MARK MARK --\n");
}
void
meta_set_keybindings_disabled (gboolean setting)
#ifdef HAVE_WAYLAND
static void
handle_switch_vt (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
XIDeviceEvent *event,
MetaKeyBinding *binding,
gpointer dummy)
{
all_bindings_disabled = setting;
meta_topic (META_DEBUG_KEYBINDINGS,
"Keybindings %s\n", all_bindings_disabled ? "disabled" : "enabled");
gint vt = binding->handler->data;
MetaWaylandCompositor *compositor;
MetaLauncher *launcher;
compositor = meta_wayland_compositor_get_default ();
launcher = meta_wayland_compositor_get_launcher (compositor);
if (launcher)
{
GError *error;
error = NULL;
if (!meta_launcher_activate_vt (launcher, vt, &error))
{
g_warning ("Failed to switch VT: %s", error->message);
g_error_free (error);
}
}
else
{
g_debug ("Ignoring VT switch keybinding, not running as VT manager");
}
}
#endif
/**
* meta_keybindings_set_custom_handler:
@ -3894,6 +4200,7 @@ init_builtin_key_bindings (MetaDisplay *display)
META_KEY_BINDING_IS_REVERSED)
GSettings *common_keybindings = g_settings_new (SCHEMA_COMMON_KEYBINDINGS);
GSettings *mutter_keybindings = g_settings_new (SCHEMA_MUTTER_KEYBINDINGS);
GSettings *mutter_wayland_keybindings = g_settings_new (SCHEMA_MUTTER_WAYLAND_KEYBINDINGS);
add_builtin_keybinding (display,
"switch-to-workspace-1",
@ -4155,6 +4462,60 @@ init_builtin_key_bindings (MetaDisplay *display)
META_KEYBINDING_ACTION_SET_SPEW_MARK,
handle_set_spew_mark, 0);
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor ())
{
add_builtin_keybinding (display,
"switch-to-session-1",
mutter_wayland_keybindings,
META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 1);
add_builtin_keybinding (display,
"switch-to-session-2",
mutter_wayland_keybindings,
META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 2);
add_builtin_keybinding (display,
"switch-to-session-3",
mutter_wayland_keybindings,
META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 3);
add_builtin_keybinding (display,
"switch-to-session-4",
mutter_wayland_keybindings,
META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 4);
add_builtin_keybinding (display,
"switch-to-session-5",
mutter_wayland_keybindings,
META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 5);
add_builtin_keybinding (display,
"switch-to-session-6",
mutter_wayland_keybindings,
META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 6);
add_builtin_keybinding (display,
"switch-to-session-7",
mutter_wayland_keybindings,
META_KEY_BINDING_NONE,
META_KEYBINDING_ACTION_NONE,
handle_switch_vt, 7);
}
#endif
#undef REVERSES_AND_REVERSED
/************************ PER WINDOW BINDINGS ************************/
@ -4516,6 +4877,12 @@ meta_display_init_keys (MetaDisplay *display)
g_hash_table_insert (key_handlers, g_strdup ("overlay-key"), handler);
handler = g_new0 (MetaKeyHandler, 1);
handler->name = g_strdup ("iso-next-group");
handler->flags = META_KEY_BINDING_BUILTIN;
g_hash_table_insert (key_handlers, g_strdup ("iso-next-group"), handler);
handler = g_new0 (MetaKeyHandler, 1);
handler->name = g_strdup ("external-grab");
handler->func = handle_external_grab;

View File

@ -48,15 +48,17 @@
#include <config.h>
#include <meta/main.h>
#include <meta/util.h>
#include "util-private.h"
#include "display-private.h"
#include <meta/errors.h>
#include "ui.h"
#include "session.h"
#include <meta/prefs.h>
#include <meta/compositor.h>
#include "meta-wayland-private.h"
#include <glib-object.h>
#include <glib-unix.h>
#include <gdk/gdkx.h>
#include <stdlib.h>
@ -189,6 +191,7 @@ static gchar *opt_client_id;
static gboolean opt_replace_wm;
static gboolean opt_disable_sm;
static gboolean opt_sync;
static gboolean opt_wayland;
static GOptionEntry meta_options[] = {
{
@ -226,6 +229,12 @@ static GOptionEntry meta_options[] = {
N_("Make X calls synchronous"),
NULL
},
{
"wayland", 0, 0, G_OPTION_ARG_NONE,
&opt_wayland,
N_("Run as a wayland compositor"),
NULL
},
{NULL}
};
@ -247,6 +256,14 @@ meta_get_option_context (void)
bindtextdomain (GETTEXT_PACKAGE, MUTTER_LOCALEDIR);
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
/* We must set the windowing backend here, because Clutter creates the backend
object when the first call is made.
We consider running from mutter-launch equivalent to running from bare metal.
*/
if (getenv ("WESTON_LAUNCHER_SOCK"))
clutter_set_windowing_backend (CLUTTER_WINDOWING_EGL);
ctx = g_option_context_new (NULL);
g_option_context_add_main_entries (ctx, meta_options, GETTEXT_PACKAGE);
g_option_context_add_group (ctx, clutter_get_option_group_without_init ());
@ -346,28 +363,17 @@ meta_finalize (void)
if (display)
meta_display_close (display,
CurrentTime); /* I doubt correct timestamps matter here */
}
static int sigterm_pipe_fds[2] = { -1, -1 };
static void
sigterm_handler (int signum)
{
if (sigterm_pipe_fds[1] >= 0)
{
int G_GNUC_UNUSED dummy;
dummy = write (sigterm_pipe_fds[1], "", 1);
close (sigterm_pipe_fds[1]);
sigterm_pipe_fds[1] = -1;
}
if (meta_is_wayland_compositor ())
meta_wayland_finalize ();
}
static gboolean
on_sigterm (void)
on_sigterm (gpointer user_data)
{
meta_quit (META_EXIT_SUCCESS);
return FALSE;
meta_quit (EXIT_SUCCESS);
return G_SOURCE_REMOVE;
}
/**
@ -381,7 +387,6 @@ meta_init (void)
{
struct sigaction act;
sigset_t empty_mask;
GIOChannel *channel;
sigemptyset (&empty_mask);
act.sa_handler = SIG_IGN;
@ -396,26 +401,15 @@ meta_init (void)
g_strerror (errno));
#endif
if (pipe (sigterm_pipe_fds) != 0)
g_printerr ("Failed to create SIGTERM pipe: %s\n",
g_strerror (errno));
channel = g_io_channel_unix_new (sigterm_pipe_fds[0]);
g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
g_io_add_watch (channel, G_IO_IN, (GIOFunc) on_sigterm, NULL);
g_io_channel_set_close_on_unref (channel, TRUE);
g_io_channel_unref (channel);
act.sa_handler = &sigterm_handler;
if (sigaction (SIGTERM, &act, NULL) < 0)
g_printerr ("Failed to register SIGTERM handler: %s\n",
g_strerror (errno));
g_unix_signal_add (SIGTERM, on_sigterm, NULL);
if (g_getenv ("MUTTER_VERBOSE"))
meta_set_verbose (TRUE);
if (g_getenv ("MUTTER_DEBUG"))
meta_set_debugging (TRUE);
meta_set_is_wayland_compositor (opt_wayland);
if (g_get_home_dir ())
if (chdir (g_get_home_dir ()) < 0)
meta_warning ("Could not change to home directory %s.\n",
@ -427,9 +421,16 @@ meta_init (void)
g_irepository_prepend_search_path (MUTTER_PKGLIBDIR);
#endif
meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL));
if (meta_is_wayland_compositor ())
{
/* NB: When running as a hybrid wayland compositor we run our own headless X
* server so the user can't control the X display to connect too. */
meta_wayland_init ();
}
else
meta_select_display (opt_display_name);
meta_select_display (opt_display_name);
meta_set_syncing (opt_sync || (g_getenv ("MUTTER_SYNC") != NULL));
if (opt_replace_wm)
meta_set_replace_current_wm (TRUE);
@ -441,10 +442,17 @@ meta_init (void)
meta_ui_init ();
/*
* Clutter can only be initialized after the UI.
*/
meta_clutter_init ();
/* If we are running with wayland then we don't wait until we have
* an X connection before initializing clutter we instead initialize
* it earlier since we need to initialize the GL driver so the driver
* can register any needed wayland extensions. */
if (!meta_is_wayland_compositor ())
{
/*
* Clutter can only be initialized after the UI.
*/
meta_clutter_init ();
}
}
/**
@ -514,14 +522,14 @@ meta_run (void)
if (g_getenv ("MUTTER_G_FATAL_WARNINGS") != NULL)
g_log_set_always_fatal (G_LOG_LEVEL_MASK);
meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE);
meta_ui_set_current_theme (meta_prefs_get_theme ());
/* Try to find some theme that'll work if the theme preference
* doesn't exist. First try Simple (the default theme) then just
* try anything in the themes directory.
*/
if (!meta_ui_have_a_theme ())
meta_ui_set_current_theme ("Simple", FALSE);
meta_ui_set_current_theme ("Simple");
if (!meta_ui_have_a_theme ())
{
@ -539,7 +547,7 @@ meta_run (void)
while (((dir_entry = g_dir_read_name (themes_dir)) != NULL) &&
(!meta_ui_have_a_theme ()))
{
meta_ui_set_current_theme (dir_entry, FALSE);
meta_ui_set_current_theme (dir_entry);
}
g_dir_close (themes_dir);
@ -598,7 +606,7 @@ prefs_changed_callback (MetaPreference pref,
{
case META_PREF_THEME:
case META_PREF_DRAGGABLE_BORDER_WIDTH:
meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE);
meta_ui_set_current_theme (meta_prefs_get_theme ());
meta_display_retheme_all ();
break;

View File

@ -0,0 +1,48 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#ifndef META_CURSOR_TRACKER_PRIVATE_H
#define META_CURSOR_TRACKER_PRIVATE_H
#include <meta/meta-cursor-tracker.h>
#include <wayland-server.h>
#include <clutter/clutter.h>
gboolean meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
XEvent *xevent);
void meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
MetaCursor cursor);
void meta_cursor_tracker_revert_root (MetaCursorTracker *tracker);
void meta_cursor_tracker_set_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y);
void meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y);
void meta_cursor_tracker_paint (MetaCursorTracker *tracker);
void meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker,
ClutterActor *stage);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,31 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
#include <meta/meta-idle-monitor.h>
void meta_idle_monitor_handle_xevent_all (XEvent *xevent);
void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor);
void meta_idle_monitor_init_dbus (void);

View File

@ -0,0 +1,992 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright 2013 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Adapted from gnome-session/gnome-session/gs-idle-monitor.c and
* from gnome-desktop/libgnome-desktop/gnome-idle-monitor.c
*/
/**
* SECTION:idle-monitor
* @title: MetaIdleMonitor
* @short_description: Mutter idle counter (similar to X's IDLETIME)
*/
#include "config.h"
#include <string.h>
#include <clutter/clutter.h>
#include <X11/Xlib.h>
#include <X11/extensions/sync.h>
#include <meta/util.h>
#include <meta/main.h>
#include <meta/meta-idle-monitor.h>
#include "display-private.h"
#include "meta-idle-monitor-private.h"
#include "meta-dbus-idle-monitor.h"
G_STATIC_ASSERT(sizeof(unsigned long) == sizeof(gpointer));
struct _MetaIdleMonitor
{
GObject parent_instance;
GHashTable *watches;
GHashTable *alarms;
int device_id;
/* X11 implementation */
Display *display;
int sync_event_base;
XSyncCounter counter;
XSyncAlarm user_active_alarm;
/* Wayland implementation */
guint64 last_event_time;
};
struct _MetaIdleMonitorClass
{
GObjectClass parent_class;
};
typedef struct
{
MetaIdleMonitor *monitor;
guint id;
MetaIdleMonitorWatchFunc callback;
gpointer user_data;
GDestroyNotify notify;
guint64 timeout_msec;
/* x11 */
XSyncAlarm xalarm;
int idle_source_id;
/* wayland */
GSource *timeout_source;
} MetaIdleMonitorWatch;
enum
{
PROP_0,
PROP_DEVICE_ID,
PROP_LAST,
};
static GParamSpec *obj_props[PROP_LAST];
G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT)
static MetaIdleMonitor *device_monitors[256];
static int device_id_max;
static gint64
_xsyncvalue_to_int64 (XSyncValue value)
{
return ((guint64) XSyncValueHigh32 (value)) << 32
| (guint64) XSyncValueLow32 (value);
}
#define GUINT64_TO_XSYNCVALUE(value, ret) XSyncIntsToValue (ret, (value) & 0xFFFFFFFF, ((guint64)(value)) >> 32)
static void
fire_watch (MetaIdleMonitorWatch *watch)
{
MetaIdleMonitor *monitor;
guint id;
gboolean is_user_active_watch;
monitor = watch->monitor;
g_object_ref (monitor);
if (watch->idle_source_id)
{
g_source_remove (watch->idle_source_id);
watch->idle_source_id = 0;
}
id = watch->id;
is_user_active_watch = (watch->timeout_msec == 0);
if (watch->callback)
watch->callback (monitor, id, watch->user_data);
if (is_user_active_watch)
meta_idle_monitor_remove_watch (monitor, id);
g_object_unref (monitor);
}
static XSyncAlarm
_xsync_alarm_set (MetaIdleMonitor *monitor,
XSyncTestType test_type,
guint64 interval,
gboolean want_events)
{
XSyncAlarmAttributes attr;
XSyncValue delta;
guint flags;
flags = XSyncCACounter | XSyncCAValueType | XSyncCATestType |
XSyncCAValue | XSyncCADelta | XSyncCAEvents;
XSyncIntToValue (&delta, 0);
attr.trigger.counter = monitor->counter;
attr.trigger.value_type = XSyncAbsolute;
attr.delta = delta;
attr.events = want_events;
GUINT64_TO_XSYNCVALUE (interval, &attr.trigger.wait_value);
attr.trigger.test_type = test_type;
return XSyncCreateAlarm (monitor->display, flags, &attr);
}
static void
ensure_alarm_rescheduled (Display *dpy,
XSyncAlarm alarm)
{
XSyncAlarmAttributes attr;
/* Some versions of Xorg have an issue where alarms aren't
* always rescheduled. Calling XSyncChangeAlarm, even
* without any attributes, will reschedule the alarm. */
XSyncChangeAlarm (dpy, alarm, 0, &attr);
}
static void
set_alarm_enabled (Display *dpy,
XSyncAlarm alarm,
gboolean enabled)
{
XSyncAlarmAttributes attr;
attr.events = enabled;
XSyncChangeAlarm (dpy, alarm, XSyncCAEvents, &attr);
}
static void
check_x11_watch (gpointer data,
gpointer user_data)
{
MetaIdleMonitorWatch *watch = data;
XSyncAlarm alarm = (XSyncAlarm) user_data;
if (watch->xalarm != alarm)
return;
fire_watch (watch);
}
static void
meta_idle_monitor_handle_xevent (MetaIdleMonitor *monitor,
XSyncAlarmNotifyEvent *alarm_event)
{
XSyncAlarm alarm;
GList *watches;
gboolean has_alarm;
if (alarm_event->state != XSyncAlarmActive)
return;
alarm = alarm_event->alarm;
has_alarm = FALSE;
if (alarm == monitor->user_active_alarm)
{
set_alarm_enabled (monitor->display,
alarm,
FALSE);
has_alarm = TRUE;
}
else if (g_hash_table_contains (monitor->alarms, (gpointer) alarm))
{
ensure_alarm_rescheduled (monitor->display,
alarm);
has_alarm = TRUE;
}
if (has_alarm)
{
watches = g_hash_table_get_values (monitor->watches);
g_list_foreach (watches, check_x11_watch, (gpointer) alarm);
g_list_free (watches);
}
}
void
meta_idle_monitor_handle_xevent_all (XEvent *xevent)
{
int i;
for (i = 0; i <= device_id_max; i++)
if (device_monitors[i])
meta_idle_monitor_handle_xevent (device_monitors[i], (XSyncAlarmNotifyEvent*)xevent);
}
static char *
counter_name_for_device (int device_id)
{
if (device_id > 0)
return g_strdup_printf ("DEVICEIDLETIME %d", device_id);
return g_strdup ("IDLETIME");
}
static XSyncCounter
find_idletime_counter (MetaIdleMonitor *monitor)
{
int i;
int ncounters;
XSyncSystemCounter *counters;
XSyncCounter counter = None;
char *counter_name;
counter_name = counter_name_for_device (monitor->device_id);
counters = XSyncListSystemCounters (monitor->display, &ncounters);
for (i = 0; i < ncounters; i++)
{
if (counters[i].name != NULL && strcmp (counters[i].name, counter_name) == 0)
{
counter = counters[i].counter;
break;
}
}
XSyncFreeSystemCounterList (counters);
g_free (counter_name);
return counter;
}
static guint32
get_next_watch_serial (void)
{
static guint32 serial = 0;
g_atomic_int_inc (&serial);
return serial;
}
static void
idle_monitor_watch_free (MetaIdleMonitorWatch *watch)
{
MetaIdleMonitor *monitor;
if (watch == NULL)
return;
monitor = watch->monitor;
if (watch->idle_source_id)
{
g_source_remove (watch->idle_source_id);
watch->idle_source_id = 0;
}
if (watch->notify != NULL)
watch->notify (watch->user_data);
if (watch->xalarm != monitor->user_active_alarm &&
watch->xalarm != None)
{
XSyncDestroyAlarm (monitor->display, watch->xalarm);
g_hash_table_remove (monitor->alarms, (gpointer) watch->xalarm);
}
if (watch->timeout_source != NULL)
g_source_destroy (watch->timeout_source);
g_slice_free (MetaIdleMonitorWatch, watch);
}
static void
init_xsync (MetaIdleMonitor *monitor)
{
monitor->counter = find_idletime_counter (monitor);
/* IDLETIME counter not found? */
if (monitor->counter == None)
{
meta_warning ("IDLETIME counter not found\n");
return;
}
monitor->user_active_alarm = _xsync_alarm_set (monitor, XSyncNegativeTransition, 1, FALSE);
}
static void
meta_idle_monitor_dispose (GObject *object)
{
MetaIdleMonitor *monitor;
monitor = META_IDLE_MONITOR (object);
g_clear_pointer (&monitor->watches, g_hash_table_destroy);
g_clear_pointer (&monitor->alarms, g_hash_table_destroy);
if (monitor->user_active_alarm != None)
{
XSyncDestroyAlarm (monitor->display, monitor->user_active_alarm);
monitor->user_active_alarm = None;
}
G_OBJECT_CLASS (meta_idle_monitor_parent_class)->dispose (object);
}
static void
meta_idle_monitor_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
switch (prop_id)
{
case PROP_DEVICE_ID:
g_value_set_int (value, monitor->device_id);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_idle_monitor_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
switch (prop_id)
{
case PROP_DEVICE_ID:
monitor->device_id = g_value_get_int (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_idle_monitor_constructed (GObject *object)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
if (!meta_is_wayland_compositor ())
{
monitor->display = meta_get_display ()->xdisplay;
init_xsync (monitor);
}
}
static void
meta_idle_monitor_class_init (MetaIdleMonitorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = meta_idle_monitor_dispose;
object_class->constructed = meta_idle_monitor_constructed;
object_class->get_property = meta_idle_monitor_get_property;
object_class->set_property = meta_idle_monitor_set_property;
/**
* MetaIdleMonitor:device_id:
*
* The device to listen to idletime on.
*/
obj_props[PROP_DEVICE_ID] =
g_param_spec_int ("device-id",
"Device ID",
"The device to listen to idletime on",
0, 255, 0,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
g_object_class_install_property (object_class, PROP_DEVICE_ID, obj_props[PROP_DEVICE_ID]);
}
static void
meta_idle_monitor_init (MetaIdleMonitor *monitor)
{
monitor->watches = g_hash_table_new_full (NULL,
NULL,
NULL,
(GDestroyNotify)idle_monitor_watch_free);
monitor->alarms = g_hash_table_new (NULL, NULL);
}
static void
ensure_device_monitor (int device_id)
{
if (device_monitors[device_id])
return;
device_monitors[device_id] = g_object_new (META_TYPE_IDLE_MONITOR, "device-id", device_id, NULL);
device_id_max = MAX (device_id_max, device_id);
}
/**
* meta_idle_monitor_get_core:
*
* Returns: (transfer none): the #MetaIdleMonitor that tracks the server-global
* idletime for all devices. To track device-specific idletime,
* use meta_idle_monitor_get_for_device().
*/
MetaIdleMonitor *
meta_idle_monitor_get_core (void)
{
ensure_device_monitor (0);
return device_monitors[0];
}
/**
* meta_idle_monitor_get_for_device:
* @device_id: the device to get the idle time for.
*
* Returns: (transfer none): a new #MetaIdleMonitor that tracks the
* device-specific idletime for @device. To track server-global idletime
* for all devices, use meta_idle_monitor_get_core().
*/
MetaIdleMonitor *
meta_idle_monitor_get_for_device (int device_id)
{
g_return_val_if_fail (device_id > 0 && device_id < 256, NULL);
ensure_device_monitor (device_id);
return device_monitors[device_id];
}
static gboolean
wayland_dispatch_timeout (GSource *source,
GSourceFunc callback,
gpointer user_data)
{
MetaIdleMonitorWatch *watch = user_data;
fire_watch (watch);
g_source_set_ready_time (watch->timeout_source, -1);
return TRUE;
}
static GSourceFuncs wayland_source_funcs = {
NULL, /* prepare */
NULL, /* check */
wayland_dispatch_timeout,
NULL, /* finalize */
};
static gboolean
fire_watch_idle (gpointer data)
{
MetaIdleMonitorWatch *watch = data;
watch->idle_source_id = 0;
fire_watch (watch);
return FALSE;
}
static MetaIdleMonitorWatch *
make_watch (MetaIdleMonitor *monitor,
guint64 timeout_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
watch = g_slice_new0 (MetaIdleMonitorWatch);
watch->monitor = monitor;
watch->id = get_next_watch_serial ();
watch->callback = callback;
watch->user_data = user_data;
watch->notify = notify;
watch->timeout_msec = timeout_msec;
if (meta_is_wayland_compositor ())
{
if (timeout_msec != 0)
{
GSource *source = g_source_new (&wayland_source_funcs, sizeof (GSource));
g_source_set_callback (source, NULL, watch, NULL);
g_source_set_ready_time (source, monitor->last_event_time + timeout_msec * 1000);
g_source_attach (source, NULL);
g_source_unref (source);
watch->timeout_source = source;
}
}
else
{
if (timeout_msec != 0)
{
watch->xalarm = _xsync_alarm_set (monitor, XSyncPositiveTransition, timeout_msec, TRUE);
g_hash_table_add (monitor->alarms, (gpointer) watch->xalarm);
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
}
else
{
watch->xalarm = monitor->user_active_alarm;
set_alarm_enabled (monitor->display, monitor->user_active_alarm, TRUE);
}
}
g_hash_table_insert (monitor->watches,
GUINT_TO_POINTER (watch->id),
watch);
return watch;
}
/**
* meta_idle_monitor_add_idle_watch:
* @monitor: A #MetaIdleMonitor
* @interval_msec: The idletime interval, in milliseconds
* @callback: (allow-none): The callback to call when the user has
* accumulated @interval_msec milliseconds of idle time.
* @user_data: (allow-none): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id
*
* Adds a watch for a specific idle time. The callback will be called
* when the user has accumulated @interval_msec milliseconds of idle time.
* This function will return an ID that can either be passed to
* meta_idle_monitor_remove_watch(), or can be used to tell idle time
* watches apart if you have more than one.
*
* Also note that this function will only care about positive transitions
* (user's idle time exceeding a certain time). If you want to know about
* when the user has become active, use
* meta_idle_monitor_add_user_active_watch().
*/
guint
meta_idle_monitor_add_idle_watch (MetaIdleMonitor *monitor,
guint64 interval_msec,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
g_return_val_if_fail (interval_msec > 0, 0);
watch = make_watch (monitor,
interval_msec,
callback,
user_data,
notify);
return watch->id;
}
/**
* meta_idle_monitor_add_user_active_watch:
* @monitor: A #MetaIdleMonitor
* @callback: (allow-none): The callback to call when the user is
* active again.
* @user_data: (allow-none): The user data to pass to the callback
* @notify: A #GDestroyNotify
*
* Returns: a watch id
*
* Add a one-time watch to know when the user is active again.
* Note that this watch is one-time and will de-activate after the
* function is called, for efficiency purposes. It's most convenient
* to call this when an idle watch, as added by
* meta_idle_monitor_add_idle_watch(), has triggered.
*/
guint
meta_idle_monitor_add_user_active_watch (MetaIdleMonitor *monitor,
MetaIdleMonitorWatchFunc callback,
gpointer user_data,
GDestroyNotify notify)
{
MetaIdleMonitorWatch *watch;
g_return_val_if_fail (META_IS_IDLE_MONITOR (monitor), 0);
watch = make_watch (monitor,
0,
callback,
user_data,
notify);
return watch->id;
}
/**
* meta_idle_monitor_remove_watch:
* @monitor: A #MetaIdleMonitor
* @id: A watch ID
*
* Removes an idle time watcher, previously added by
* meta_idle_monitor_add_idle_watch() or
* meta_idle_monitor_add_user_active_watch().
*/
void
meta_idle_monitor_remove_watch (MetaIdleMonitor *monitor,
guint id)
{
g_return_if_fail (META_IS_IDLE_MONITOR (monitor));
g_hash_table_remove (monitor->watches,
GUINT_TO_POINTER (id));
}
/**
* meta_idle_monitor_get_idletime:
* @monitor: A #MetaIdleMonitor
*
* Returns: The current idle time, in milliseconds, or -1 for not supported
*/
gint64
meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
{
XSyncValue value;
if (meta_is_wayland_compositor ())
{
return (g_get_monotonic_time () - monitor->last_event_time) / 1000;
}
else
{
if (!XSyncQueryCounter (monitor->display, monitor->counter, &value))
return -1;
return _xsyncvalue_to_int64 (value);
}
}
typedef struct {
MetaIdleMonitor *monitor;
GList *fired_watches;
} CheckWaylandClosure;
static gboolean
check_wayland_watch (gpointer key,
gpointer value,
gpointer user_data)
{
MetaIdleMonitorWatch *watch = value;
CheckWaylandClosure *closure = user_data;
gboolean steal;
if (watch->timeout_msec == 0)
{
closure->fired_watches = g_list_prepend (closure->fired_watches, watch);
steal = TRUE;
}
else
{
g_source_set_ready_time (watch->timeout_source,
closure->monitor->last_event_time +
watch->timeout_msec * 1000);
steal = FALSE;
}
return steal;
}
static void
fire_wayland_watch (gpointer watch,
gpointer data)
{
fire_watch (watch);
}
void
meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor)
{
CheckWaylandClosure closure;
monitor->last_event_time = g_get_monotonic_time ();
closure.monitor = monitor;
closure.fired_watches = NULL;
g_hash_table_foreach_steal (monitor->watches, check_wayland_watch, &closure);
g_list_foreach (closure.fired_watches, fire_wayland_watch, NULL);
g_list_free (closure.fired_watches);
}
static gboolean
handle_get_idletime (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
guint64 idletime;
idletime = meta_idle_monitor_get_idletime (monitor);
meta_dbus_idle_monitor_complete_get_idletime (skeleton, invocation, idletime);
return TRUE;
}
typedef struct {
MetaDBusIdleMonitor *dbus_monitor;
MetaIdleMonitor *monitor;
char *dbus_name;
guint watch_id;
guint name_watcher_id;
} DBusWatch;
static void
destroy_dbus_watch (gpointer data)
{
DBusWatch *watch = data;
g_object_unref (watch->dbus_monitor);
g_object_unref (watch->monitor);
g_free (watch->dbus_name);
g_bus_unwatch_name (watch->name_watcher_id);
g_slice_free (DBusWatch, watch);
}
static void
dbus_idle_callback (MetaIdleMonitor *monitor,
guint watch_id,
gpointer user_data)
{
DBusWatch *watch = user_data;
GDBusInterfaceSkeleton *skeleton = G_DBUS_INTERFACE_SKELETON (watch->dbus_monitor);
g_dbus_connection_emit_signal (g_dbus_interface_skeleton_get_connection (skeleton),
watch->dbus_name,
g_dbus_interface_skeleton_get_object_path (skeleton),
"org.gnome.Mutter.IdleMonitor",
"WatchFired",
g_variant_new ("(u)", watch_id),
NULL);
}
static void
name_vanished_callback (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
DBusWatch *watch = user_data;
meta_idle_monitor_remove_watch (watch->monitor, watch->watch_id);
}
static DBusWatch *
make_dbus_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = g_slice_new (DBusWatch);
watch->dbus_monitor = g_object_ref (skeleton);
watch->monitor = g_object_ref (monitor);
watch->dbus_name = g_strdup (g_dbus_method_invocation_get_sender (invocation));
watch->name_watcher_id = g_bus_watch_name_on_connection (g_dbus_method_invocation_get_connection (invocation),
watch->dbus_name,
G_BUS_NAME_WATCHER_FLAGS_NONE,
NULL, /* appeared */
name_vanished_callback,
watch, NULL);
return watch;
}
static gboolean
handle_add_idle_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
guint64 interval,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = make_dbus_watch (skeleton, invocation, monitor);
watch->watch_id = meta_idle_monitor_add_idle_watch (monitor, interval,
dbus_idle_callback, watch, destroy_dbus_watch);
meta_dbus_idle_monitor_complete_add_idle_watch (skeleton, invocation, watch->watch_id);
return TRUE;
}
static gboolean
handle_add_user_active_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
MetaIdleMonitor *monitor)
{
DBusWatch *watch;
watch = make_dbus_watch (skeleton, invocation, monitor);
watch->watch_id = meta_idle_monitor_add_user_active_watch (monitor,
dbus_idle_callback, watch,
destroy_dbus_watch);
meta_dbus_idle_monitor_complete_add_user_active_watch (skeleton, invocation, watch->watch_id);
return TRUE;
}
static gboolean
handle_remove_watch (MetaDBusIdleMonitor *skeleton,
GDBusMethodInvocation *invocation,
guint id,
MetaIdleMonitor *monitor)
{
meta_idle_monitor_remove_watch (monitor, id);
meta_dbus_idle_monitor_complete_remove_watch (skeleton, invocation);
return TRUE;
}
static void
create_monitor_skeleton (GDBusObjectManagerServer *manager,
MetaIdleMonitor *monitor,
const char *path)
{
MetaDBusIdleMonitor *skeleton;
MetaDBusObjectSkeleton *object;
skeleton = meta_dbus_idle_monitor_skeleton_new ();
g_signal_connect_object (skeleton, "handle-add-idle-watch",
G_CALLBACK (handle_add_idle_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-add-user-active-watch",
G_CALLBACK (handle_add_user_active_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-remove-watch",
G_CALLBACK (handle_remove_watch), monitor, 0);
g_signal_connect_object (skeleton, "handle-get-idletime",
G_CALLBACK (handle_get_idletime), monitor, 0);
object = meta_dbus_object_skeleton_new (path);
meta_dbus_object_skeleton_set_idle_monitor (object, skeleton);
g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (object));
}
static void
on_device_added (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
GDBusObjectManagerServer *manager)
{
MetaIdleMonitor *monitor;
int device_id;
char *path;
device_id = clutter_input_device_get_device_id (device);
monitor = meta_idle_monitor_get_for_device (device_id);
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
create_monitor_skeleton (manager, monitor, path);
g_free (path);
}
static void
on_device_removed (ClutterDeviceManager *device_manager,
ClutterInputDevice *device,
GDBusObjectManagerServer *manager)
{
int device_id;
char *path;
device_id = clutter_input_device_get_device_id (device);
path = g_strdup_printf ("/org/gnome/Mutter/IdleMonitor/Device%d", device_id);
g_dbus_object_manager_server_unexport (manager, path);
g_free (path);
g_clear_object (&device_monitors[device_id]);
if (device_id == device_id_max)
device_id_max--;
}
static void
on_bus_acquired (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
GDBusObjectManagerServer *manager;
ClutterDeviceManager *device_manager;
MetaIdleMonitor *monitor;
GSList *devices, *iter;
char *path;
manager = g_dbus_object_manager_server_new ("/org/gnome/Mutter/IdleMonitor");
/* We never clear the core monitor, as that's supposed to cumulate idle times from
all devices */
monitor = meta_idle_monitor_get_core ();
path = g_strdup ("/org/gnome/Mutter/IdleMonitor/Core");
create_monitor_skeleton (manager, monitor, path);
g_free (path);
device_manager = clutter_device_manager_get_default ();
devices = clutter_device_manager_list_devices (device_manager);
for (iter = devices; iter; iter = iter->next)
on_device_added (device_manager, iter->data, manager);
g_signal_connect_object (device_manager, "device-added",
G_CALLBACK (on_device_added), manager, 0);
g_signal_connect_object (device_manager, "device-removed",
G_CALLBACK (on_device_removed), manager, 0);
g_dbus_object_manager_server_set_connection (manager, connection);
}
static void
on_name_acquired (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
meta_verbose ("Acquired name %s\n", name);
}
static void
on_name_lost (GDBusConnection *connection,
const char *name,
gpointer user_data)
{
meta_verbose ("Lost or failed to acquire name %s\n", name);
}
void
meta_idle_monitor_init_dbus (void)
{
static int dbus_name_id;
if (dbus_name_id > 0)
return;
dbus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION,
"org.gnome.Mutter.IdleMonitor",
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
(meta_get_replace_current_wm () ?
G_BUS_NAME_OWNER_FLAGS_REPLACE : 0),
on_bus_acquired,
on_name_acquired,
on_name_lost,
NULL, NULL);
}

View File

@ -0,0 +1,40 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
/* This file is shared between mutter (src/core/meta-xrandr-shared.h)
and gnome-desktop (libgnome-desktop/meta-xrandr-shared.h).
The canonical place for all changes is mutter.
There should be no includes in this file.
*/
#ifndef META_XRANDR_SHARED_H
#define META_XRANDR_SHARED_H
typedef enum {
META_POWER_SAVE_UNSUPPORTED = -1,
META_POWER_SAVE_ON = 0,
META_POWER_SAVE_STANDBY,
META_POWER_SAVE_SUSPEND,
META_POWER_SAVE_OFF,
} MetaPowerSave;
#endif

1827
src/core/monitor-config.c Normal file

File diff suppressed because it is too large Load Diff

939
src/core/monitor-kms.c Normal file
View File

@ -0,0 +1,939 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Giovanni Campagna <gcampagn@redhat.com>
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <clutter/clutter.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <meta/main.h>
#include <meta/errors.h>
#include "monitor-private.h"
#include "edid.h"
#define ALL_WL_TRANSFORMS ((1 << (WL_OUTPUT_TRANSFORM_FLIPPED_270 + 1)) - 1)
typedef struct {
drmModeConnector *connector;
unsigned n_encoders;
drmModeEncoderPtr *encoders;
drmModeEncoderPtr current_encoder;
/* bitmasks of encoder position in the resources array */
uint32_t encoder_mask;
uint32_t enc_clone_mask;
uint32_t dpms_prop_id;
uint32_t edid_blob_id;
} MetaOutputKms;
struct _MetaMonitorManagerKms
{
MetaMonitorManager parent_instance;
int fd;
drmModeConnector **connectors;
unsigned int n_connectors;
drmModeEncoder **encoders;
unsigned int n_encoders;
drmModeEncoder *current_encoder;
};
struct _MetaMonitorManagerKmsClass
{
MetaMonitorManagerClass parent_class;
};
G_DEFINE_TYPE (MetaMonitorManagerKms, meta_monitor_manager_kms, META_TYPE_MONITOR_MANAGER);
static void
free_resources (MetaMonitorManagerKms *manager_kms)
{
unsigned i;
for (i = 0; i < manager_kms->n_encoders; i++)
drmModeFreeEncoder (manager_kms->encoders[i]);
for (i = 0; i < manager_kms->n_connectors; i++)
drmModeFreeConnector (manager_kms->connectors[i]);
g_free (manager_kms->encoders);
g_free (manager_kms->connectors);
}
static int
compare_outputs (const void *one,
const void *two)
{
const MetaOutput *o_one = one, *o_two = two;
return strcmp (o_one->name, o_two->name);
}
static char *
make_output_name (drmModeConnector *connector)
{
static const char * const connector_type_names[] = {
"unknown", "VGA", "DVII", "DVID", "DVID", "Composite",
"SVIDEO", "LVDS", "Component", "9PinDIN", "DisplayPort",
"HDMIA", "HDMIB", "TV", "eDP"
};
const char *connector_type_name;
if (connector->connector_type >= 0 &&
connector->connector_type < G_N_ELEMENTS (connector_type_names))
connector_type_name = connector_type_names[connector->connector_type];
else
connector_type_name = "unknown";
return g_strdup_printf ("%s%d", connector_type_name, connector->connector_id);
}
static void
meta_output_destroy_notify (MetaOutput *output)
{
MetaOutputKms *output_kms;
unsigned i;
output_kms = output->driver_private;
for (i = 0; i < output_kms->n_encoders; i++)
drmModeFreeEncoder (output_kms->encoders[i]);
g_free (output_kms->encoders);
g_slice_free (MetaOutputKms, output_kms);
}
static void
meta_monitor_mode_destroy_notify (MetaMonitorMode *output)
{
g_slice_free (drmModeModeInfo, output->driver_private);
}
static gboolean
drm_mode_equal (gconstpointer one,
gconstpointer two)
{
const drmModeModeInfo *m_one = one;
const drmModeModeInfo *m_two = two;
return m_one->clock == m_two->clock &&
m_one->hdisplay == m_two->hdisplay &&
m_one->hsync_start == m_two->hsync_start &&
m_one->hsync_end == m_two->hsync_end &&
m_one->htotal == m_two->htotal &&
m_one->hskew == m_two->hskew &&
m_one->vdisplay == m_two->vdisplay &&
m_one->vsync_start == m_two->vsync_start &&
m_one->vsync_end == m_two->vsync_end &&
m_one->vtotal == m_two->vtotal &&
m_one->vscan == m_two->vscan &&
m_one->vrefresh == m_two->vrefresh &&
m_one->flags == m_two->flags &&
m_one->type == m_two->type &&
strncmp (m_one->name, m_two->name, DRM_DISPLAY_MODE_LEN) == 0;
}
static guint
drm_mode_hash (gconstpointer ptr)
{
const drmModeModeInfo *mode = ptr;
guint hash = 0;
/* We don't include the name in the hash because it's generally
derived from the other fields (hdisplay, vdisplay and flags)
*/
hash ^= mode->clock;
hash ^= mode->hdisplay ^ mode->hsync_start ^ mode->hsync_end;
hash ^= mode->vdisplay ^ mode->vsync_start ^ mode->vsync_end;
hash ^= mode->vrefresh;
hash ^= mode->flags ^ mode->type;
return hash;
}
static void
find_properties (MetaMonitorManagerKms *manager_kms,
MetaOutputKms *output_kms)
{
drmModePropertyPtr prop;
int i;
for (i = 0; i < output_kms->connector->count_props; i++)
{
prop = drmModeGetProperty (manager_kms->fd, output_kms->connector->props[i]);
if (!prop)
continue;
if ((prop->flags & DRM_MODE_PROP_ENUM) &&
strcmp(prop->name, "DPMS") == 0)
output_kms->dpms_prop_id = prop->prop_id;
else if ((prop->flags & DRM_MODE_PROP_BLOB) &&
strcmp (prop->name, "EDID") == 0)
output_kms->edid_blob_id = output_kms->connector->prop_values[i];
drmModeFreeProperty(prop);
}
}
static GBytes *
read_output_edid (MetaMonitorManagerKms *manager_kms,
MetaOutput *output)
{
MetaOutputKms *output_kms = output->driver_private;
drmModePropertyBlobPtr edid_blob = NULL;
if (output_kms->edid_blob_id == 0)
return NULL;
edid_blob = drmModeGetPropertyBlob (manager_kms->fd, output_kms->edid_blob_id);
if (!edid_blob)
{
meta_warning ("Failed to read EDID of output %s: %s\n", output->name, strerror(errno));
return NULL;
}
if (edid_blob->length > 0)
return g_bytes_new_with_free_func (edid_blob->data, edid_blob->length,
(GDestroyNotify)drmModeFreePropertyBlob, edid_blob);
else
{
drmModeFreePropertyBlob (edid_blob);
return NULL;
}
}
static MetaMonitorMode *
find_meta_mode (MetaMonitorManager *manager,
const drmModeModeInfo *drm_mode)
{
unsigned k;
for (k = 0; k < manager->n_modes; k++)
{
if (drm_mode_equal (drm_mode, manager->modes[k].driver_private))
return &manager->modes[k];
}
g_assert_not_reached ();
return NULL;
}
static MetaOutput *
find_output_by_id (MetaOutput *outputs,
unsigned n_outputs,
glong id)
{
unsigned i;
for (i = 0; i < n_outputs; i++)
if (outputs[i].output_id == id)
return &outputs[i];
return NULL;
}
static void
meta_monitor_manager_kms_read_current (MetaMonitorManager *manager)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
drmModeRes *resources;
GHashTable *modes;
GHashTableIter iter;
drmModeModeInfo *mode;
unsigned int i, j, k;
unsigned int n_actual_outputs;
int width, height;
MetaOutput *old_outputs;
unsigned int n_old_outputs;
resources = drmModeGetResources(manager_kms->fd);
modes = g_hash_table_new (drm_mode_hash, drm_mode_equal);
manager->max_screen_width = resources->max_width;
manager->max_screen_height = resources->max_height;
manager->power_save_mode = META_POWER_SAVE_ON;
old_outputs = manager->outputs;
n_old_outputs = manager->n_outputs;
/* Note: we must not free the public structures (output, crtc, monitor
mode and monitor info) here, they must be kept alive until the API
users are done with them after we emit monitors-changed, and thus
are freed by the platform-independent layer. */
free_resources (manager_kms);
manager_kms->n_connectors = resources->count_connectors;
manager_kms->connectors = g_new (drmModeConnector *, manager_kms->n_connectors);
for (i = 0; i < manager_kms->n_connectors; i++)
{
drmModeConnector *connector;
connector = drmModeGetConnector (manager_kms->fd, resources->connectors[i]);
manager_kms->connectors[i] = connector;
if (connector->connection == DRM_MODE_CONNECTED)
{
/* Collect all modes for this connector */
for (j = 0; j < (unsigned)connector->count_modes; j++)
g_hash_table_add (modes, &connector->modes[j]);
}
}
manager_kms->n_encoders = resources->count_encoders;
manager_kms->encoders = g_new (drmModeEncoder *, manager_kms->n_encoders);
for (i = 0; i < manager_kms->n_encoders; i++)
{
manager_kms->encoders[i] = drmModeGetEncoder (manager_kms->fd,
resources->encoders[i]);
}
manager->n_modes = g_hash_table_size (modes);
manager->modes = g_new0 (MetaMonitorMode, manager->n_modes);
g_hash_table_iter_init (&iter, modes);
i = 0;
while (g_hash_table_iter_next (&iter, NULL, (gpointer)&mode))
{
MetaMonitorMode *meta_mode;
meta_mode = &manager->modes[i];
meta_mode->mode_id = i;
meta_mode->name = g_strndup (mode->name, DRM_DISPLAY_MODE_LEN);
meta_mode->width = mode->hdisplay;
meta_mode->height = mode->vdisplay;
meta_mode->refresh_rate = (1000 * mode->clock /
((float)mode->htotal * mode->vtotal));
meta_mode->driver_private = g_slice_dup (drmModeModeInfo, mode);
meta_mode->driver_notify = (GDestroyNotify)meta_monitor_mode_destroy_notify;
i++;
}
g_hash_table_destroy (modes);
manager->n_crtcs = resources->count_crtcs;
manager->crtcs = g_new0 (MetaCRTC, manager->n_crtcs);
width = 0; height = 0;
for (i = 0; i < (unsigned)resources->count_crtcs; i++)
{
drmModeCrtc *crtc;
MetaCRTC *meta_crtc;
crtc = drmModeGetCrtc (manager_kms->fd, resources->crtcs[i]);
meta_crtc = &manager->crtcs[i];
meta_crtc->crtc_id = crtc->crtc_id;
meta_crtc->rect.x = crtc->x;
meta_crtc->rect.y = crtc->y;
meta_crtc->rect.width = crtc->width;
meta_crtc->rect.height = crtc->height;
meta_crtc->is_dirty = FALSE;
meta_crtc->transform = WL_OUTPUT_TRANSFORM_NORMAL;
/* FIXME: implement! */
meta_crtc->all_transforms = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
if (crtc->mode_valid)
{
for (j = 0; j < manager->n_modes; j++)
{
if (drm_mode_equal (&crtc->mode, manager->modes[j].driver_private))
{
meta_crtc->current_mode = &manager->modes[j];
break;
}
}
width = MAX (width, meta_crtc->rect.x + meta_crtc->rect.width);
height = MAX (height, meta_crtc->rect.y + meta_crtc->rect.height);
}
drmModeFreeCrtc (crtc);
}
manager->screen_width = width;
manager->screen_height = height;
manager->outputs = g_new0 (MetaOutput, manager_kms->n_connectors);
n_actual_outputs = 0;
for (i = 0; i < manager_kms->n_connectors; i++)
{
MetaOutput *meta_output, *old_output;
MetaOutputKms *output_kms;
drmModeConnector *connector;
GArray *crtcs;
unsigned int crtc_mask;
GBytes *edid;
connector = manager_kms->connectors[i];
meta_output = &manager->outputs[n_actual_outputs];
if (connector->connection == DRM_MODE_CONNECTED)
{
meta_output->driver_private = output_kms = g_slice_new0 (MetaOutputKms);
meta_output->driver_notify = (GDestroyNotify)meta_output_destroy_notify;
meta_output->output_id = connector->connector_id;
meta_output->name = make_output_name (connector);
meta_output->width_mm = connector->mmWidth;
meta_output->height_mm = connector->mmHeight;
switch (connector->subpixel)
{
case DRM_MODE_SUBPIXEL_NONE:
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_NONE;
break;
case DRM_MODE_SUBPIXEL_HORIZONTAL_RGB:
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_RGB;
break;
case DRM_MODE_SUBPIXEL_HORIZONTAL_BGR:
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_HORIZONTAL_BGR;
break;
case DRM_MODE_SUBPIXEL_VERTICAL_RGB:
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_RGB;
break;
case DRM_MODE_SUBPIXEL_VERTICAL_BGR:
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_VERTICAL_BGR;
break;
case DRM_MODE_SUBPIXEL_UNKNOWN:
default:
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
break;
}
meta_output->n_modes = connector->count_modes;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
for (j = 0; j < meta_output->n_modes; j++)
meta_output->modes[j] = find_meta_mode (manager, &connector->modes[j]);
meta_output->preferred_mode = meta_output->modes[0];
output_kms->connector = connector;
output_kms->n_encoders = connector->count_encoders;
output_kms->encoders = g_new0 (drmModeEncoderPtr, output_kms->n_encoders);
crtc_mask = ~(unsigned int)0;
for (j = 0; j < output_kms->n_encoders; j++)
{
output_kms->encoders[j] = drmModeGetEncoder (manager_kms->fd, connector->encoders[j]);
/* We only list CRTCs as supported if they are supported by all encoders
for this connectors.
This is what xf86-video-modesetting does (see drmmode_output_init())
*/
crtc_mask &= output_kms->encoders[j]->possible_crtcs;
if (output_kms->encoders[j]->encoder_id == connector->encoder_id)
output_kms->current_encoder = output_kms->encoders[j];
}
crtcs = g_array_new (FALSE, FALSE, sizeof (MetaCRTC*));
for (j = 0; j < manager->n_crtcs; j++)
{
if (crtc_mask & (1 << j))
{
MetaCRTC *crtc = &manager->crtcs[j];
g_array_append_val (crtcs, crtc);
}
}
meta_output->n_possible_crtcs = crtcs->len;
meta_output->possible_crtcs = (void*)g_array_free (crtcs, FALSE);
if (output_kms->current_encoder && output_kms->current_encoder->crtc_id != 0)
{
for (j = 0; j < manager->n_crtcs; j++)
{
if (manager->crtcs[j].crtc_id == output_kms->current_encoder->crtc_id)
{
meta_output->crtc = &manager->crtcs[j];
break;
}
}
}
else
meta_output->crtc = NULL;
old_output = find_output_by_id (old_outputs, n_old_outputs,
meta_output->output_id);
if (old_output)
{
meta_output->is_primary = old_output->is_primary;
meta_output->is_presentation = old_output->is_presentation;
}
else
{
meta_output->is_primary = FALSE;
meta_output->is_presentation = FALSE;
}
find_properties (manager_kms, output_kms);
edid = read_output_edid (manager_kms, meta_output);
if (edid)
{
MonitorInfo *parsed_edid;
gsize len;
parsed_edid = decode_edid (g_bytes_get_data (edid, &len));
if (parsed_edid)
{
meta_output->vendor = g_strndup (parsed_edid->manufacturer_code, 4);
meta_output->product = g_strndup (parsed_edid->dsc_product_name, 14);
meta_output->serial = g_strndup (parsed_edid->dsc_serial_number, 14);
g_free (parsed_edid);
}
g_bytes_unref (edid);
}
if (!meta_output->vendor)
{
meta_output->vendor = g_strdup ("unknown");
meta_output->product = g_strdup ("unknown");
meta_output->serial = g_strdup ("unknown");
}
/* FIXME: backlight is a very driver specific thing unfortunately,
every DDX does its own thing, and the dumb KMS API does not include it.
For example, xf86-video-intel has a list of paths to probe in /sys/class/backlight
(one for each major HW maker, and then some).
We can't do the same because we're not root.
It might be best to leave backlight out of the story and rely on the setuid
helper in gnome-settings-daemon.
*/
meta_output->backlight_min = 0;
meta_output->backlight_max = 0;
meta_output->backlight = -1;
n_actual_outputs++;
}
}
manager->n_outputs = n_actual_outputs;
manager->outputs = g_renew (MetaOutput, manager->outputs, manager->n_outputs);
/* Sort the outputs for easier handling in MetaMonitorConfig */
qsort (manager->outputs, manager->n_outputs, sizeof (MetaOutput), compare_outputs);
/* Now fix the clones.
Code mostly inspired by xf86-video-modesetting. */
/* XXX: intel hardware doesn't usually have clones, but I only have laptops with
intel cards, so this code was never tested! */
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *meta_output;
MetaOutputKms *output_kms;
meta_output = &manager->outputs[i];
output_kms = meta_output->driver_private;
output_kms->enc_clone_mask = 0xff;
output_kms->encoder_mask = 0;
for (j = 0; j < output_kms->n_encoders; j++)
{
for (k = 0; k < manager_kms->n_encoders; k++)
{
if (output_kms->encoders[j]->encoder_id == manager_kms->encoders[k]->encoder_id)
{
output_kms->encoder_mask |= (1 << k);
break;
}
}
output_kms->enc_clone_mask &= output_kms->encoders[j]->possible_clones;
}
}
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *meta_output;
MetaOutputKms *output_kms;
meta_output = &manager->outputs[i];
output_kms = meta_output->driver_private;
if (output_kms->enc_clone_mask == 0)
continue;
for (j = 0; j < manager->n_outputs; j++)
{
MetaOutput *meta_clone;
MetaOutputKms *clone_kms;
meta_clone = &manager->outputs[i];
clone_kms = meta_clone->driver_private;
if (meta_clone == meta_output)
continue;
if (clone_kms->encoder_mask == 0)
continue;
if (clone_kms->encoder_mask == output_kms->enc_clone_mask)
{
meta_output->n_possible_clones++;
meta_output->possible_clones = g_renew (MetaOutput *,
meta_output->possible_clones,
meta_output->n_possible_clones);
meta_output->possible_clones[meta_output->n_possible_clones - 1] = meta_clone;
}
}
}
drmModeFreeResources (resources);
}
static GBytes *
meta_monitor_manager_kms_read_edid (MetaMonitorManager *manager,
MetaOutput *output)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
return read_output_edid (manager_kms, output);
}
static void
meta_monitor_manager_kms_set_power_save_mode (MetaMonitorManager *manager,
MetaPowerSave mode)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
uint64_t state;
unsigned i;
switch (mode) {
case META_POWER_SAVE_ON:
state = DRM_MODE_DPMS_ON;
break;
case META_POWER_SAVE_STANDBY:
state = DRM_MODE_DPMS_STANDBY;
break;
case META_POWER_SAVE_SUSPEND:
state = DRM_MODE_DPMS_SUSPEND;
break;
case META_POWER_SAVE_OFF:
state = DRM_MODE_DPMS_SUSPEND;
break;
default:
return;
}
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *meta_output;
MetaOutputKms *output_kms;
meta_output = &manager->outputs[i];
output_kms = meta_output->driver_private;
if (output_kms->dpms_prop_id != 0)
{
int ok = drmModeConnectorSetProperty(manager_kms->fd, meta_output->output_id,
output_kms->dpms_prop_id, state);
if (ok < 0)
meta_warning ("Failed to set power save mode for output %s: %s\n",
meta_output->name, strerror (errno));
}
}
}
static void
crtc_free (CoglKmsCrtc *crtc)
{
g_free (crtc->connectors);
g_slice_free (CoglKmsCrtc, crtc);
}
static void
meta_monitor_manager_kms_apply_configuration (MetaMonitorManager *manager,
MetaCRTCInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs)
{
ClutterBackend *backend;
CoglContext *cogl_context;
CoglDisplay *cogl_display;
unsigned i;
GPtrArray *cogl_crtcs;
int screen_width, screen_height;
gboolean ok;
GError *error;
cogl_crtcs = g_ptr_array_new_full (manager->n_crtcs, (GDestroyNotify)crtc_free);
screen_width = 0; screen_height = 0;
for (i = 0; i < n_crtcs; i++)
{
MetaCRTCInfo *crtc_info = crtcs[i];
MetaCRTC *crtc = crtc_info->crtc;
CoglKmsCrtc *cogl_crtc;
crtc->is_dirty = TRUE;
cogl_crtc = g_slice_new0 (CoglKmsCrtc);
g_ptr_array_add (cogl_crtcs, cogl_crtc);
if (crtc_info->mode == NULL)
{
cogl_crtc->id = crtc->crtc_id;
cogl_crtc->x = 0;
cogl_crtc->y = 0;
cogl_crtc->count = 0;
memset (&cogl_crtc->mode, 0, sizeof (drmModeModeInfo));
cogl_crtc->connectors = NULL;
cogl_crtc->count = 0;
crtc->rect.x = 0;
crtc->rect.y = 0;
crtc->rect.width = 0;
crtc->rect.height = 0;
crtc->current_mode = NULL;
}
else
{
MetaMonitorMode *mode;
uint32_t *connectors;
unsigned int j, n_connectors;
int width, height;
mode = crtc_info->mode;
cogl_crtc->id = crtc->crtc_id;
cogl_crtc->x = crtc_info->x;
cogl_crtc->y = crtc_info->y;
cogl_crtc->count = n_connectors = crtc_info->outputs->len;
cogl_crtc->connectors = connectors = g_new (uint32_t, n_connectors);
for (j = 0; j < n_connectors; j++)
{
MetaOutput *output = g_ptr_array_index (crtc_info->outputs, j);
connectors[j] = output->output_id;
output->is_dirty = TRUE;
output->crtc = crtc;
}
memcpy (&cogl_crtc->mode, crtc_info->mode->driver_private,
sizeof (drmModeModeInfo));
if (meta_monitor_transform_is_rotated (crtc_info->transform))
{
width = mode->height;
height = mode->width;
}
else
{
width = mode->width;
height = mode->height;
}
screen_width = MAX (screen_width, crtc_info->x + width);
screen_height = MAX (screen_height, crtc_info->y + height);
crtc->rect.x = crtc_info->x;
crtc->rect.y = crtc_info->y;
crtc->rect.width = width;
crtc->rect.height = height;
crtc->current_mode = mode;
crtc->transform = crtc_info->transform;
}
}
/* Disable CRTCs not mentioned in the list (they have is_dirty == FALSE,
because they weren't seen in the first loop) */
for (i = 0; i < manager->n_crtcs; i++)
{
MetaCRTC *crtc = &manager->crtcs[i];
CoglKmsCrtc *cogl_crtc;
crtc->logical_monitor = NULL;
if (crtc->is_dirty)
{
crtc->is_dirty = FALSE;
continue;
}
cogl_crtc = g_slice_new0 (CoglKmsCrtc);
g_ptr_array_add (cogl_crtcs, cogl_crtc);
cogl_crtc->id = crtc->crtc_id;
cogl_crtc->x = 0;
cogl_crtc->y = 0;
cogl_crtc->count = 0;
memset (&cogl_crtc->mode, 0, sizeof (drmModeModeInfo));
cogl_crtc->connectors = NULL;
cogl_crtc->count = 0;
crtc->rect.x = 0;
crtc->rect.y = 0;
crtc->rect.width = 0;
crtc->rect.height = 0;
crtc->current_mode = NULL;
}
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
cogl_display = cogl_context_get_display (cogl_context);
error = NULL;
ok = cogl_kms_display_set_layout (cogl_display, screen_width, screen_height,
(CoglKmsCrtc**)cogl_crtcs->pdata, cogl_crtcs->len, &error);
g_ptr_array_unref (cogl_crtcs);
if (!ok)
{
meta_warning ("Applying display configuration failed: %s\n", error->message);
g_error_free (error);
return;
}
for (i = 0; i < n_outputs; i++)
{
MetaOutputInfo *output_info = outputs[i];
MetaOutput *output = output_info->output;
output->is_primary = output_info->is_primary;
output->is_presentation = output_info->is_presentation;
}
/* Disable outputs not mentioned in the list */
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *output = &manager->outputs[i];
if (output->is_dirty)
{
output->is_dirty = FALSE;
continue;
}
output->crtc = NULL;
output->is_primary = FALSE;
}
manager->screen_width = screen_width;
manager->screen_height = screen_height;
meta_monitor_manager_rebuild_derived (manager);
}
static void
meta_monitor_manager_kms_get_crtc_gamma (MetaMonitorManager *manager,
MetaCRTC *crtc,
gsize *size,
unsigned short **red,
unsigned short **green,
unsigned short **blue)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
drmModeCrtc *kms_crtc;
kms_crtc = drmModeGetCrtc (manager_kms->fd, crtc->crtc_id);
*size = kms_crtc->gamma_size;
*red = g_new (unsigned short, *size);
*green = g_new (unsigned short, *size);
*blue = g_new (unsigned short, *size);
drmModeCrtcGetGamma (manager_kms->fd, crtc->crtc_id, *size, *red, *green, *blue);
drmModeFreeCrtc (kms_crtc);
}
static void
meta_monitor_manager_kms_set_crtc_gamma (MetaMonitorManager *manager,
MetaCRTC *crtc,
gsize size,
unsigned short *red,
unsigned short *green,
unsigned short *blue)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (manager);
drmModeCrtcSetGamma (manager_kms->fd, crtc->crtc_id, size, red, green, blue);
}
static void
meta_monitor_manager_kms_init (MetaMonitorManagerKms *manager_kms)
{
ClutterBackend *backend;
CoglContext *cogl_context;
CoglDisplay *cogl_display;
CoglRenderer *cogl_renderer;
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
cogl_display = cogl_context_get_display (cogl_context);
cogl_renderer = cogl_display_get_renderer (cogl_display);
manager_kms->fd = cogl_kms_renderer_get_kms_fd (cogl_renderer);
}
static void
meta_monitor_manager_kms_finalize (GObject *object)
{
MetaMonitorManagerKms *manager_kms = META_MONITOR_MANAGER_KMS (object);
free_resources (manager_kms);
G_OBJECT_CLASS (meta_monitor_manager_kms_parent_class)->finalize (object);
}
static void
meta_monitor_manager_kms_class_init (MetaMonitorManagerKmsClass *klass)
{
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_monitor_manager_kms_finalize;
manager_class->read_current = meta_monitor_manager_kms_read_current;
manager_class->read_edid = meta_monitor_manager_kms_read_edid;
manager_class->apply_configuration = meta_monitor_manager_kms_apply_configuration;
manager_class->set_power_save_mode = meta_monitor_manager_kms_set_power_save_mode;
manager_class->get_crtc_gamma = meta_monitor_manager_kms_get_crtc_gamma;
manager_class->set_crtc_gamma = meta_monitor_manager_kms_set_crtc_gamma;
}

419
src/core/monitor-private.h Normal file
View File

@ -0,0 +1,419 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* \file screen-private.h Handling of monitor configuration
*
* Managing multiple monitors
* This file contains structures and functions that handle
* multiple monitors, including reading the current configuration
* and available hardware, and applying it.
*
* This interface is private to mutter, API users should look
* at MetaScreen instead.
*/
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_MONITOR_PRIVATE_H
#define META_MONITOR_PRIVATE_H
#include <cogl/cogl.h>
#include <libgnome-desktop/gnome-pnp-ids.h>
#include "display-private.h"
#include <meta/screen.h>
#include "stack-tracker.h"
#include "ui.h"
#ifdef HAVE_WAYLAND
#include <wayland-server.h>
#endif
#include "meta-xrandr-shared.h"
#include "meta-dbus-xrandr.h"
typedef struct _MetaMonitorManagerClass MetaMonitorManagerClass;
typedef struct _MetaMonitorManager MetaMonitorManager;
typedef struct _MetaMonitorConfigClass MetaMonitorConfigClass;
typedef struct _MetaMonitorConfig MetaMonitorConfig;
#ifndef HAVE_WAYLAND
enum wl_output_transform {
WL_OUTPUT_TRANSFORM_NORMAL,
WL_OUTPUT_TRANSFORM_90,
WL_OUTPUT_TRANSFORM_180,
WL_OUTPUT_TRANSFORM_270,
WL_OUTPUT_TRANSFORM_FLIPPED,
WL_OUTPUT_TRANSFORM_FLIPPED_90,
WL_OUTPUT_TRANSFORM_FLIPPED_180,
WL_OUTPUT_TRANSFORM_FLIPPED_270
};
#endif
typedef struct _MetaOutput MetaOutput;
typedef struct _MetaCRTC MetaCRTC;
typedef struct _MetaMonitorMode MetaMonitorMode;
typedef struct _MetaMonitorInfo MetaMonitorInfo;
typedef struct _MetaCRTCInfo MetaCRTCInfo;
typedef struct _MetaOutputInfo MetaOutputInfo;
struct _MetaOutput
{
/* The CRTC driving this output, NULL if the output is not enabled */
MetaCRTC *crtc;
/* The low-level ID of this output, used to apply back configuration */
glong output_id;
char *name;
char *vendor;
char *product;
char *serial;
int width_mm;
int height_mm;
CoglSubpixelOrder subpixel_order;
MetaMonitorMode *preferred_mode;
MetaMonitorMode **modes;
unsigned int n_modes;
MetaCRTC **possible_crtcs;
unsigned int n_possible_crtcs;
MetaOutput **possible_clones;
unsigned int n_possible_clones;
int backlight;
int backlight_min;
int backlight_max;
/* Used when changing configuration */
gboolean is_dirty;
/* The low-level bits used to build the high-level info
in MetaMonitorInfo
XXX: flags maybe?
There is a lot of code that uses MonitorInfo->is_primary,
but nobody uses MetaOutput yet
*/
gboolean is_primary;
gboolean is_presentation;
gpointer driver_private;
GDestroyNotify driver_notify;
};
struct _MetaCRTC
{
glong crtc_id;
MetaRectangle rect;
MetaMonitorMode *current_mode;
enum wl_output_transform transform;
unsigned int all_transforms;
/* Only used to build the logical configuration
from the HW one
*/
MetaMonitorInfo *logical_monitor;
/* Used when changing configuration */
gboolean is_dirty;
/* Updated by MetaCursorTracker */
gboolean has_hw_cursor;
};
struct _MetaMonitorMode
{
/* The low-level ID of this mode, used to apply back configuration */
glong mode_id;
char *name;
int width;
int height;
float refresh_rate;
gpointer driver_private;
GDestroyNotify driver_notify;
};
/**
* MetaMonitorInfo:
*
* A structure with high-level information about monitors.
* This corresponds to a subset of the compositor coordinate space.
* Clones are only reported once, irrespective of the way
* they're implemented (two CRTCs configured for the same
* coordinates or one CRTCs driving two outputs). Inactive CRTCs
* are ignored, and so are disabled outputs.
*/
struct _MetaMonitorInfo
{
int number;
int xinerama_index;
MetaRectangle rect;
gboolean is_primary;
gboolean is_presentation; /* XXX: not yet used */
gboolean in_fullscreen;
/* The primary or first output for this monitor, 0 if we can't figure out.
It can be matched to an output_id of a MetaOutput.
This is used as an opaque token on reconfiguration when switching from
clone to extened, to decide on what output the windows should go next
(it's an attempt to keep windows on the same monitor, and preferably on
the primary one).
*/
glong output_id;
};
/*
* MetaCRTCInfo:
* This represents the writable part of a CRTC, as deserialized from DBus
* or built by MetaMonitorConfig
*
* Note: differently from the other structures in this file, MetaCRTCInfo
* is handled by pointer. This is to accomodate the usage in MetaMonitorConfig
*/
struct _MetaCRTCInfo {
MetaCRTC *crtc;
MetaMonitorMode *mode;
int x;
int y;
enum wl_output_transform transform;
GPtrArray *outputs;
};
/*
* MetaOutputInfo:
* this is the same as MetaOutputInfo, but for CRTCs
*/
struct _MetaOutputInfo {
MetaOutput *output;
gboolean is_primary;
gboolean is_presentation;
};
#define META_TYPE_MONITOR_MANAGER (meta_monitor_manager_get_type ())
#define META_MONITOR_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER, MetaMonitorManager))
#define META_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass))
#define META_IS_MONITOR_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER))
#define META_IS_MONITOR_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER))
#define META_MONITOR_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER, MetaMonitorManagerClass))
struct _MetaMonitorManager
{
MetaDBusDisplayConfigSkeleton parent_instance;
/* XXX: this structure is very badly
packed, but I like the logical organization
of fields */
gboolean in_init;
unsigned int serial;
MetaPowerSave power_save_mode;
int max_screen_width;
int max_screen_height;
int screen_width;
int screen_height;
/* Outputs refer to physical screens,
CRTCs refer to stuff that can drive outputs
(like encoders, but less tied to the HW),
while monitor_infos refer to logical ones.
See also the comment in monitor-private.h
*/
MetaOutput *outputs;
unsigned int n_outputs;
MetaMonitorMode *modes;
unsigned int n_modes;
MetaCRTC *crtcs;
unsigned int n_crtcs;
MetaMonitorInfo *monitor_infos;
unsigned int n_monitor_infos;
int primary_monitor_index;
int dbus_name_id;
int persistent_timeout_id;
MetaMonitorConfig *config;
GnomePnpIds *pnp_ids;
};
struct _MetaMonitorManagerClass
{
MetaDBusDisplayConfigSkeletonClass parent_class;
void (*read_current) (MetaMonitorManager *);
char* (*get_edid_file) (MetaMonitorManager *,
MetaOutput *);
GBytes* (*read_edid) (MetaMonitorManager *,
MetaOutput *);
void (*apply_configuration) (MetaMonitorManager *,
MetaCRTCInfo **,
unsigned int ,
MetaOutputInfo **,
unsigned int);
void (*set_power_save_mode) (MetaMonitorManager *,
MetaPowerSave);
void (*change_backlight) (MetaMonitorManager *,
MetaOutput *,
int);
void (*get_crtc_gamma) (MetaMonitorManager *,
MetaCRTC *,
gsize *,
unsigned short **,
unsigned short **,
unsigned short **);
void (*set_crtc_gamma) (MetaMonitorManager *,
MetaCRTC *,
gsize ,
unsigned short *,
unsigned short *,
unsigned short *);
gboolean (*handle_xevent) (MetaMonitorManager *,
XEvent *);
};
GType meta_monitor_manager_get_type (void);
void meta_monitor_manager_initialize (void);
MetaMonitorManager *meta_monitor_manager_get (void);
void meta_monitor_manager_rebuild_derived (MetaMonitorManager *manager);
MetaMonitorInfo *meta_monitor_manager_get_monitor_infos (MetaMonitorManager *manager,
unsigned int *n_infos);
MetaOutput *meta_monitor_manager_get_outputs (MetaMonitorManager *manager,
unsigned int *n_outputs);
void meta_monitor_manager_get_resources (MetaMonitorManager *manager,
MetaMonitorMode **modes,
unsigned int *n_modes,
MetaCRTC **crtcs,
unsigned int *n_crtcs,
MetaOutput **outputs,
unsigned int *n_outputs);
int meta_monitor_manager_get_primary_index (MetaMonitorManager *manager);
gboolean meta_monitor_manager_handle_xevent (MetaMonitorManager *manager,
XEvent *event);
void meta_monitor_manager_get_screen_size (MetaMonitorManager *manager,
int *width,
int *height);
void meta_monitor_manager_get_screen_limits (MetaMonitorManager *manager,
int *width,
int *height);
void meta_monitor_manager_apply_configuration (MetaMonitorManager *manager,
MetaCRTCInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs);
void meta_monitor_manager_confirm_configuration (MetaMonitorManager *manager,
gboolean ok);
#define META_TYPE_MONITOR_MANAGER_XRANDR (meta_monitor_manager_xrandr_get_type ())
#define META_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandr))
#define META_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
#define META_IS_MONITOR_MANAGER_XRANDR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_XRANDR))
#define META_IS_MONITOR_MANAGER_XRANDR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_XRANDR))
#define META_MONITOR_MANAGER_XRANDR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_XRANDR, MetaMonitorManagerXrandrClass))
typedef struct _MetaMonitorManagerXrandrClass MetaMonitorManagerXrandrClass;
typedef struct _MetaMonitorManagerXrandr MetaMonitorManagerXrandr;
GType meta_monitor_manager_xrandr_get_type (void);
#define META_TYPE_MONITOR_MANAGER_KMS (meta_monitor_manager_kms_get_type ())
#define META_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKms))
#define META_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
#define META_IS_MONITOR_MANAGER_KMS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_MANAGER_KMS))
#define META_IS_MONITOR_MANAGER_KMS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_MANAGER_KMS))
#define META_MONITOR_MANAGER_KMS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_MANAGER_KMS, MetaMonitorManagerKmsClass))
typedef struct _MetaMonitorManagerKmsClass MetaMonitorManagerKmsClass;
typedef struct _MetaMonitorManagerKms MetaMonitorManagerKms;
GType meta_monitor_manager_kms_get_type (void);
#define META_TYPE_MONITOR_CONFIG (meta_monitor_config_get_type ())
#define META_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfig))
#define META_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
#define META_IS_MONITOR_CONFIG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_MONITOR_CONFIG))
#define META_IS_MONITOR_CONFIG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MONITOR_CONFIG))
#define META_MONITOR_CONFIG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MONITOR_CONFIG, MetaMonitorConfigClass))
GType meta_monitor_config_get_type (void) G_GNUC_CONST;
MetaMonitorConfig *meta_monitor_config_new (void);
gboolean meta_monitor_config_match_current (MetaMonitorConfig *config,
MetaMonitorManager *manager);
gboolean meta_monitor_config_apply_stored (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_make_default (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_update_current (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_monitor_config_make_persistent (MetaMonitorConfig *config);
void meta_monitor_config_restore_previous (MetaMonitorConfig *config,
MetaMonitorManager *manager);
void meta_crtc_info_free (MetaCRTCInfo *info);
void meta_output_info_free (MetaOutputInfo *info);
void meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
int n_old_outputs);
void meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
int n_old_modes);
/* Returns true if transform causes width and height to be inverted
This is true for the odd transforms in the enum */
static inline gboolean
meta_monitor_transform_is_rotated (enum wl_output_transform transform)
{
return (transform % 2);
}
#endif

1086
src/core/monitor-xrandr.c Normal file

File diff suppressed because it is too large Load Diff

1434
src/core/monitor.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,7 @@
#include <meta/main.h>
#include <meta/util.h>
#include <glib/gi18n-lib.h>
#include "meta-plugin-manager.h"
#include <glib.h>

View File

@ -31,7 +31,7 @@
#include <config.h>
#include <meta/prefs.h>
#include "ui.h"
#include <meta/util.h>
#include "util-private.h"
#include "meta-plugin-manager.h"
#include <glib.h>
#include <gio/gio.h>
@ -55,6 +55,7 @@
#define KEY_GNOME_ANIMATIONS "enable-animations"
#define KEY_GNOME_CURSOR_THEME "cursor-theme"
#define KEY_GNOME_CURSOR_SIZE "cursor-size"
#define KEY_XKB_OPTIONS "xkb-options"
#define KEY_OVERLAY_KEY "overlay-key"
#define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary"
@ -65,6 +66,7 @@
#define SCHEMA_GENERAL "org.gnome.desktop.wm.preferences"
#define SCHEMA_MUTTER "org.gnome.mutter"
#define SCHEMA_INTERFACE "org.gnome.desktop.interface"
#define SCHEMA_INPUT_SOURCES "org.gnome.desktop.input-sources"
#define SETTINGS(s) g_hash_table_lookup (settings_schemas, (s))
@ -87,7 +89,6 @@ static GDesktopTitlebarAction action_double_click_titlebar = G_DESKTOP_TITLEBAR_
static GDesktopTitlebarAction action_middle_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_LOWER;
static GDesktopTitlebarAction action_right_click_titlebar = G_DESKTOP_TITLEBAR_ACTION_MENU;
static gboolean dynamic_workspaces = FALSE;
static gboolean application_based = FALSE;
static gboolean disable_workarounds = FALSE;
static gboolean auto_raise = FALSE;
static gboolean auto_raise_delay = 500;
@ -115,6 +116,7 @@ static gboolean workspaces_only_on_primary = FALSE;
static gboolean no_tab_popup = FALSE;
static char *iso_next_group_option = NULL;
static void handle_preference_update_enum (GSettings *settings,
gchar *key);
@ -122,7 +124,6 @@ static gboolean update_binding (MetaKeyPref *binding,
gchar **strokes);
static gboolean update_key_binding (const char *key,
gchar **strokes);
static gboolean update_workspace_names (void);
static void settings_changed (GSettings *settings,
gchar *key,
@ -140,11 +141,11 @@ static gboolean theme_name_handler (GVariant*, gpointer*, gpointer);
static gboolean mouse_button_mods_handler (GVariant*, gpointer*, gpointer);
static gboolean button_layout_handler (GVariant*, gpointer*, gpointer);
static gboolean overlay_key_handler (GVariant*, gpointer*, gpointer);
static gboolean iso_next_group_handler (GVariant*, gpointer*, gpointer);
static void do_override (char *key, char *schema);
static void init_bindings (void);
static void init_workspace_names (void);
typedef struct
@ -198,6 +199,13 @@ typedef struct
gchar **target;
} MetaStringPreference;
typedef struct
{
MetaBasePreference base;
GSettingsGetMapping handler;
gchar ***target;
} MetaStringArrayPreference;
typedef struct
{
MetaBasePreference base;
@ -289,13 +297,6 @@ static MetaBoolPreference preferences_bool[] =
},
&dynamic_workspaces,
},
{
{ "application-based",
SCHEMA_GENERAL,
META_PREF_APPLICATION_BASED,
},
NULL, /* feature is known but disabled */
},
{
{ "disable-workarounds",
SCHEMA_GENERAL,
@ -436,6 +437,27 @@ static MetaStringPreference preferences_string[] =
{ { NULL, 0, 0 }, NULL },
};
static MetaStringArrayPreference preferences_string_array[] =
{
{
{ KEY_WORKSPACE_NAMES,
SCHEMA_GENERAL,
META_PREF_KEYBINDINGS,
},
NULL,
&workspace_names,
},
{
{ KEY_XKB_OPTIONS,
SCHEMA_INPUT_SOURCES,
META_PREF_KEYBINDINGS,
},
iso_next_group_handler,
NULL,
},
{ { NULL, 0, 0 }, NULL },
};
static MetaIntPreference preferences_int[] =
{
{
@ -555,6 +577,42 @@ handle_preference_init_string (void)
}
}
static void
handle_preference_init_string_array (void)
{
MetaStringArrayPreference *cursor = preferences_string_array;
while (cursor->base.key != NULL)
{
char **value;
/* Complex keys have a mapping function to check validity */
if (cursor->handler)
{
if (cursor->target)
meta_bug ("%s has both a target and a handler\n", cursor->base.key);
g_settings_get_mapped (SETTINGS (cursor->base.schema),
cursor->base.key, cursor->handler, NULL);
}
else
{
if (!cursor->target)
meta_bug ("%s must have handler or target\n", cursor->base.key);
if (*(cursor->target))
g_strfreev (*(cursor->target));
value = g_settings_get_strv (SETTINGS (cursor->base.schema),
cursor->base.key);
*(cursor->target) = value;
}
++cursor;
}
}
static void
handle_preference_init_int (void)
{
@ -673,6 +731,56 @@ handle_preference_update_string (GSettings *settings,
queue_changed (cursor->base.pref);
}
static void
handle_preference_update_string_array (GSettings *settings,
gchar *key)
{
MetaStringArrayPreference *cursor = preferences_string_array;
gboolean inform_listeners = FALSE;
while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0)
++cursor;
if (cursor->base.key==NULL)
/* Didn't recognise that key. */
return;
/* Complex keys have a mapping function to check validity */
if (cursor->handler)
{
if (cursor->target)
meta_bug ("%s has both a target and a handler\n", cursor->base.key);
g_settings_get_mapped (SETTINGS (cursor->base.schema),
cursor->base.key, cursor->handler, NULL);
}
else
{
char **values, **previous;
int n_values, n_previous, i;
if (!cursor->target)
meta_bug ("%s must have handler or target\n", cursor->base.key);
values = g_settings_get_strv (SETTINGS (cursor->base.schema),
cursor->base.key);
n_values = g_strv_length (values);
previous = *(cursor->target);
n_previous = previous ? g_strv_length (previous) : 0;
inform_listeners = n_previous != n_values;
for (i = 0; i < n_values && !inform_listeners; i++)
inform_listeners = g_strcmp0 (values[i], previous[i]) != 0;
if (*(cursor->target))
g_strfreev (*(cursor->target));
*(cursor->target) = values;
}
if (inform_listeners)
queue_changed (cursor->base.pref);
}
static void
handle_preference_update_int (GSettings *settings,
gchar *key)
@ -857,6 +965,11 @@ meta_prefs_init (void)
G_CALLBACK (settings_changed), NULL);
g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_INTERFACE), settings);
settings = g_settings_new (SCHEMA_INPUT_SOURCES);
g_signal_connect (settings, "changed::" KEY_XKB_OPTIONS,
G_CALLBACK (settings_changed), NULL);
g_hash_table_insert (settings_schemas, g_strdup (SCHEMA_INPUT_SOURCES), settings);
for (tmp = overridden_keys; tmp; tmp = tmp->next)
{
@ -869,10 +982,10 @@ meta_prefs_init (void)
handle_preference_init_enum ();
handle_preference_init_bool ();
handle_preference_init_string ();
handle_preference_init_string_array ();
handle_preference_init_int ();
init_bindings ();
init_workspace_names ();
}
static gboolean
@ -1020,14 +1133,6 @@ settings_changed (GSettings *settings,
MetaEnumPreference *cursor;
gboolean found_enum;
/* String array, handled separately */
if (strcmp (key, KEY_WORKSPACE_NAMES) == 0)
{
if (update_workspace_names ())
queue_changed (META_PREF_WORKSPACE_NAMES);
return;
}
value = g_settings_get_value (settings, key);
type = g_variant_get_type (value);
@ -1035,6 +1140,8 @@ settings_changed (GSettings *settings,
handle_preference_update_bool (settings, key);
else if (g_variant_type_equal (type, G_VARIANT_TYPE_INT32))
handle_preference_update_int (settings, key);
else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING_ARRAY))
handle_preference_update_string_array (settings, key);
else if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING))
{
cursor = preferences_enum;
@ -1092,8 +1199,8 @@ maybe_give_disable_workarounds_warning (void)
{
first_disable = FALSE;
meta_warning (_("Workarounds for broken applications disabled. "
"Some applications may not behave properly.\n"));
meta_warning ("Workarounds for broken applications disabled. "
"Some applications may not behave properly.\n");
}
}
@ -1167,8 +1274,8 @@ titlebar_handler (GVariant *value,
if (desc == NULL)
{
meta_warning (_("Could not parse font description "
"\"%s\" from GSettings key %s\n"),
meta_warning ("Could not parse font description "
"\"%s\" from GSettings key %s\n",
string_value ? string_value : "(null)",
KEY_TITLEBAR_FONT);
return FALSE;
@ -1233,8 +1340,8 @@ mouse_button_mods_handler (GVariant *value,
meta_topic (META_DEBUG_KEYBINDINGS,
"Failed to parse new GSettings value\n");
meta_warning (_("\"%s\" found in configuration database is "
"not a valid value for mouse button modifier\n"),
meta_warning ("\"%s\" found in configuration database is "
"not a valid value for mouse button modifier\n",
string_value);
return FALSE;
@ -1554,6 +1661,39 @@ overlay_key_handler (GVariant *value,
return TRUE;
}
static gboolean
iso_next_group_handler (GVariant *value,
gpointer *result,
gpointer data)
{
const char **xkb_options, **p;
const char *option = NULL;
gboolean changed = FALSE;
*result = NULL; /* ignored */
xkb_options = g_variant_get_strv (value, NULL);
for (p = xkb_options; p && *p; ++p)
if (g_str_has_prefix (*p, "grp:"))
{
option = (*p + 4);
break;
}
changed = (g_strcmp0 (option, iso_next_group_option) != 0);
if (changed)
{
g_free (iso_next_group_option);
iso_next_group_option = g_strdup (option);
queue_changed (META_PREF_KEYBINDINGS);
}
g_free (xkb_options);
return TRUE;
}
const PangoFontDescription*
meta_prefs_get_titlebar_font (void)
{
@ -1575,14 +1715,6 @@ meta_prefs_get_dynamic_workspaces (void)
return dynamic_workspaces;
}
gboolean
meta_prefs_get_application_based (void)
{
return FALSE; /* For now, we never want this to do anything */
return application_based;
}
gboolean
meta_prefs_get_disable_workarounds (void)
{
@ -1620,9 +1752,6 @@ meta_preference_to_string (MetaPreference pref)
case META_PREF_NUM_WORKSPACES:
return "NUM_WORKSPACES";
case META_PREF_APPLICATION_BASED:
return "APPLICATION_BASED";
case META_PREF_KEYBINDINGS:
return "KEYBINDINGS";
@ -1708,12 +1837,13 @@ meta_prefs_set_num_workspaces (int n_workspaces)
{
MetaBasePreference *pref;
find_pref (preferences_int, sizeof(MetaIntPreference),
KEY_NUM_WORKSPACES, &pref);
g_settings_set_int (SETTINGS (pref->schema),
KEY_NUM_WORKSPACES,
n_workspaces);
if (find_pref (preferences_int, sizeof(MetaIntPreference),
KEY_NUM_WORKSPACES, &pref))
{
g_settings_set_int (SETTINGS (pref->schema),
KEY_NUM_WORKSPACES,
n_workspaces);
}
}
static GHashTable *key_bindings;
@ -1747,20 +1877,15 @@ init_bindings (void)
g_hash_table_insert (key_bindings, g_strdup ("overlay-key"), pref);
}
static void
init_workspace_names (void)
{
update_workspace_names ();
}
static gboolean
update_binding (MetaKeyPref *binding,
gchar **strokes)
{
GSList *old_bindings, *a, *b;
gboolean changed;
unsigned int keysym;
unsigned int keycode;
MetaVirtualModifier mods;
gboolean changed = FALSE;
MetaKeyCombo *combo;
int i;
@ -1768,13 +1893,9 @@ update_binding (MetaKeyPref *binding,
"Binding \"%s\" has new GSettings value\n",
binding->name);
/* Okay, so, we're about to provide a new list of key combos for this
* action. Delete any pre-existing list.
*/
g_slist_foreach (binding->bindings, (GFunc) g_free, NULL);
g_slist_free (binding->bindings);
old_bindings = binding->bindings;
binding->bindings = NULL;
for (i = 0; strokes && strokes[i]; i++)
{
keysym = 0;
@ -1785,7 +1906,7 @@ update_binding (MetaKeyPref *binding,
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Failed to parse new GSettings value\n");
meta_warning (_("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n"),
meta_warning ("\"%s\" found in configuration database is not a valid value for keybinding \"%s\"\n",
strokes[i], binding->name);
/* Value is kept and will thus be removed next time we save the key.
@ -1809,8 +1930,6 @@ update_binding (MetaKeyPref *binding,
* Changing the key in response to a modification could lead to cyclic calls. */
continue;
}
changed = TRUE;
combo = g_malloc0 (sizeof (MetaKeyCombo));
combo->keysym = keysym;
@ -1825,6 +1944,34 @@ update_binding (MetaKeyPref *binding,
binding->bindings = g_slist_reverse (binding->bindings);
a = old_bindings;
b = binding->bindings;
while (TRUE)
{
if ((!a && b) || (a && !b))
{
changed = TRUE;
break;
}
else if (!a && !b)
{
changed = FALSE;
break;
}
else if (memcmp (a->data, b->data, sizeof (MetaKeyCombo)) != 0)
{
changed = TRUE;
break;
}
else
{
a = a->next;
b = b->next;
}
}
g_slist_free_full (old_bindings, g_free);
return changed;
}
@ -1840,41 +1987,6 @@ update_key_binding (const char *key,
return FALSE;
}
static gboolean
update_workspace_names (void)
{
int i;
char **names;
int n_workspace_names, n_names;
gboolean changed = FALSE;
names = g_settings_get_strv (SETTINGS (SCHEMA_GENERAL), KEY_WORKSPACE_NAMES);
n_names = g_strv_length (names);
n_workspace_names = workspace_names ? g_strv_length (workspace_names) : 0;
for (i = 0; i < n_names; i++)
if (n_workspace_names < i + 1 || !workspace_names[i] ||
g_strcmp0 (names[i], workspace_names[i]) != 0)
{
changed = TRUE;
break;
}
if (n_workspace_names != n_names)
changed = TRUE;
if (changed)
{
if (workspace_names)
g_strfreev (workspace_names);
workspace_names = names;
}
else
g_strfreev (names);
return changed;
}
const char*
meta_prefs_get_workspace_name (int i)
{
@ -2074,6 +2186,12 @@ meta_prefs_get_overlay_binding (MetaKeyCombo *combo)
*combo = overlay_key_combo;
}
const char *
meta_prefs_get_iso_next_group_option (void)
{
return iso_next_group_option;
}
GDesktopTitlebarAction
meta_prefs_get_action_double_click_titlebar (void)
{
@ -2216,9 +2334,11 @@ meta_prefs_set_no_tab_popup (gboolean whether)
{
MetaBasePreference *pref;
find_pref (preferences_bool, sizeof(MetaBoolPreference),
KEY_NO_TAB_POPUP, &pref);
g_settings_set_boolean (SETTINGS (pref->schema), KEY_NO_TAB_POPUP, whether);
if (find_pref (preferences_bool, sizeof(MetaBoolPreference),
KEY_NO_TAB_POPUP, &pref))
{
g_settings_set_boolean (SETTINGS (pref->schema), KEY_NO_TAB_POPUP, whether);
}
}
int

View File

@ -38,17 +38,7 @@
#include <X11/Xutil.h>
#include "stack-tracker.h"
#include "ui.h"
typedef struct _MetaMonitorInfo MetaMonitorInfo;
struct _MetaMonitorInfo
{
int number;
MetaRectangle rect;
gboolean is_primary;
gboolean in_fullscreen;
XID output; /* The primary or first output for this crtc, None if no xrandr */
};
#include "monitor-private.h"
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
gpointer user_data);
@ -93,6 +83,7 @@ struct _MetaScreen
MetaStack *stack;
MetaStackTracker *stack_tracker;
MetaCursorTracker *cursor_tracker;
MetaCursor current_cursor;
Window flash_window;
@ -100,10 +91,11 @@ struct _MetaScreen
Window wm_sn_selection_window;
Atom wm_sn_atom;
guint32 wm_sn_timestamp;
MetaMonitorInfo *monitor_infos;
int primary_monitor_index;
int n_monitor_infos;
int primary_monitor_index;
gboolean has_xinerama_indices;
/* Cache the current monitor */
int last_monitor_index;
@ -159,8 +151,6 @@ void meta_screen_foreach_window (MetaScreen *scree
MetaScreenWindowFunc func,
gpointer data);
void meta_screen_set_cursor (MetaScreen *screen,
MetaCursor cursor);
void meta_screen_update_cursor (MetaScreen *screen);
void meta_screen_tab_popup_create (MetaScreen *screen,
@ -187,6 +177,9 @@ MetaWindow* meta_screen_get_mouse_window (MetaScreen *scre
MetaWindow *not_this_one);
const MetaMonitorInfo* meta_screen_get_current_monitor_info (MetaScreen *screen);
const MetaMonitorInfo* meta_screen_get_current_monitor_info_for_pos (MetaScreen *screen,
int x,
int y);
const MetaMonitorInfo* meta_screen_get_monitor_for_rect (MetaScreen *screen,
MetaRectangle *rect);
const MetaMonitorInfo* meta_screen_get_monitor_for_window (MetaScreen *screen,
@ -228,10 +221,6 @@ void meta_screen_calc_workspace_layout (MetaScreen *screen,
MetaWorkspaceLayout *layout);
void meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout);
void meta_screen_resize (MetaScreen *screen,
int width,
int height);
void meta_screen_minimize_all_on_active_workspace_except (MetaScreen *screen,
MetaWindow *keep);
@ -254,4 +243,14 @@ void meta_screen_workspace_switched (MetaScreen *screen,
void meta_screen_set_active_workspace_hint (MetaScreen *screen);
Window meta_screen_create_guard_window (Display *xdisplay, MetaScreen *screen);
gboolean meta_screen_handle_xevent (MetaScreen *screen,
XEvent *xevent);
int meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
int index);
int meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
int index);
#endif

View File

@ -33,7 +33,7 @@
#include <config.h>
#include "screen-private.h"
#include <meta/main.h>
#include <meta/util.h>
#include "util-private.h"
#include <meta/errors.h>
#include "window-private.h"
#include "frame.h"
@ -45,13 +45,11 @@
#include <meta/compositor.h>
#include "mutter-enum-types.h"
#include "core.h"
#include "meta-wayland-private.h"
#include "meta-cursor-tracker-private.h"
#include <X11/extensions/Xinerama.h>
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
#endif
#include <X11/Xatom.h>
#include <locale.h>
#include <string.h>
@ -76,6 +74,9 @@ static void meta_screen_sn_event (SnMonitorEvent *event,
void *user_data);
#endif
static void on_monitors_changed (MetaMonitorManager *manager,
MetaScreen *screen);
enum
{
PROP_N_WORKSPACES = 1,
@ -350,250 +351,93 @@ set_wm_icon_size_hint (MetaScreen *screen)
#undef N_VALS
}
/* The list of monitors reported by the windowing system might include
* mirrored monitors with identical bounds. Since mirrored monitors
* shouldn't be treated as separate monitors for most purposes, we
* filter them out here. (We ignore the possibility of partially
* overlapping monitors because they are rare and it's hard to come
* up with any sensible interpretation.)
*/
static void
filter_mirrored_monitors (MetaScreen *screen)
meta_screen_ensure_xinerama_indices (MetaScreen *screen)
{
int i, j;
XineramaScreenInfo *infos;
int n_infos, i, j;
/* Currently always true and simplifies things */
g_assert (screen->primary_monitor_index == 0);
if (screen->has_xinerama_indices)
return;
for (i = 1; i < screen->n_monitor_infos; i++)
screen->has_xinerama_indices = TRUE;
if (!XineramaIsActive (screen->display->xdisplay))
return;
infos = XineramaQueryScreens (screen->display->xdisplay, &n_infos);
if (n_infos <= 0 || infos == NULL)
{
/* In case we've filtered previous monitors */
screen->monitor_infos[i].number = i;
meta_XFree (infos);
return;
}
for (j = 0; j < i; j++)
for (i = 0; i < screen->n_monitor_infos; ++i)
{
for (j = 0; j < n_infos; ++j)
{
if (meta_rectangle_equal (&screen->monitor_infos[i].rect,
&screen->monitor_infos[j].rect))
{
memmove (&screen->monitor_infos[i],
&screen->monitor_infos[i + 1],
(screen->n_monitor_infos - i - 1) * sizeof (MetaMonitorInfo));
screen->n_monitor_infos--;
i--;
continue;
}
if (screen->monitor_infos[i].rect.x == infos[j].x_org &&
screen->monitor_infos[i].rect.y == infos[j].y_org &&
screen->monitor_infos[i].rect.width == infos[j].width &&
screen->monitor_infos[i].rect.height == infos[j].height)
screen->monitor_infos[i].xinerama_index = j;
}
}
meta_XFree (infos);
}
#ifdef HAVE_RANDR
static MetaMonitorInfo *
find_monitor_with_rect (MetaScreen *screen, int x, int y, int w, int h)
int
meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
int index)
{
meta_screen_ensure_xinerama_indices (screen);
return screen->monitor_infos[index].xinerama_index;
}
int
meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
int index)
{
MetaMonitorInfo *info;
int i;
meta_screen_ensure_xinerama_indices (screen);
for (i = 0; i < screen->n_monitor_infos; i++)
{
info = &screen->monitor_infos[i];
if (x == info->rect.x &&
y == info->rect.y &&
w == info->rect.width &&
h == info->rect.height)
return info;
}
return NULL;
if (screen->monitor_infos[i].xinerama_index == index)
return i;
return -1;
}
/* In the case of multiple outputs of a single crtc (mirroring), we consider one of the
* outputs the "main". This is the one we consider "owning" the windows, so if
* the mirroring is changed to a dual monitor setup then the windows are moved to the
* crtc that now has that main output. If one of the outputs is the primary that is
* always the main, otherwise we just use the first.
*/
static XID
find_main_output_for_crtc (MetaScreen *screen, XRRScreenResources *resources, XRRCrtcInfo *crtc)
{
XRROutputInfo *output;
RROutput primary_output;
int i;
XID res;
primary_output = XRRGetOutputPrimary (screen->display->xdisplay, screen->xroot);
res = None;
for (i = 0; i < crtc->noutput; i++)
{
output = XRRGetOutputInfo (screen->display->xdisplay, resources, crtc->outputs[i]);
if (output->connection != RR_Disconnected &&
(res == None || crtc->outputs[i] == primary_output))
res = crtc->outputs[i];
XRRFreeOutputInfo (output);
}
return res;
}
#endif
static void
reload_monitor_infos (MetaScreen *screen)
{
MetaDisplay *display;
GList *tmp;
MetaMonitorManager *manager;
{
GList *tmp;
tmp = screen->workspaces;
while (tmp != NULL)
{
MetaWorkspace *space = tmp->data;
tmp = screen->workspaces;
while (tmp != NULL)
{
MetaWorkspace *space = tmp->data;
meta_workspace_invalidate_work_area (space);
tmp = tmp->next;
}
meta_workspace_invalidate_work_area (space);
tmp = tmp->next;
}
}
/* Any previous screen->monitor_infos or screen->outputs is freed by the caller */
display = screen->display;
/* Any previous screen->monitor_infos is freed by the caller */
screen->monitor_infos = NULL;
screen->n_monitor_infos = 0;
screen->last_monitor_index = 0;
/* Xinerama doesn't have a concept of primary monitor, however XRandR
* does. However, the XRandR xinerama compat code always sorts the
* primary output first, so we rely on that here. We could use the
* native XRandR calls instead of xinerama, but that would be
* slightly problematic for _NET_WM_FULLSCREEN_MONITORS support, as
* that is defined in terms of xinerama monitor indexes.
* So, since we don't need anything in xrandr except the primary
* we can keep using xinerama and use the first monitor as the
* primary.
*/
screen->primary_monitor_index = 0;
screen->has_xinerama_indices = FALSE;
screen->display->monitor_cache_invalidated = TRUE;
if (g_getenv ("MUTTER_DEBUG_XINERAMA"))
{
meta_topic (META_DEBUG_XINERAMA,
"Pretending a single monitor has two Xinerama screens\n");
manager = meta_monitor_manager_get ();
screen->monitor_infos = g_new0 (MetaMonitorInfo, 2);
screen->n_monitor_infos = 2;
screen->monitor_infos[0].number = 0;
screen->monitor_infos[0].rect = screen->rect;
screen->monitor_infos[0].rect.width = screen->rect.width / 2;
screen->monitor_infos[0].in_fullscreen = -1;
screen->monitor_infos[1].number = 1;
screen->monitor_infos[1].rect = screen->rect;
screen->monitor_infos[1].rect.x = screen->rect.width / 2;
screen->monitor_infos[1].rect.width = screen->rect.width / 2;
screen->monitor_infos[0].in_fullscreen = -1;
}
if (screen->n_monitor_infos == 0 &&
XineramaIsActive (display->xdisplay))
{
XineramaScreenInfo *infos;
int n_infos;
int i;
n_infos = 0;
infos = XineramaQueryScreens (display->xdisplay, &n_infos);
meta_topic (META_DEBUG_XINERAMA,
"Found %d Xinerama screens on display %s\n",
n_infos, display->name);
if (n_infos > 0)
{
screen->monitor_infos = g_new0 (MetaMonitorInfo, n_infos);
screen->n_monitor_infos = n_infos;
i = 0;
while (i < n_infos)
{
screen->monitor_infos[i].number = infos[i].screen_number;
screen->monitor_infos[i].rect.x = infos[i].x_org;
screen->monitor_infos[i].rect.y = infos[i].y_org;
screen->monitor_infos[i].rect.width = infos[i].width;
screen->monitor_infos[i].rect.height = infos[i].height;
screen->monitor_infos[i].in_fullscreen = -1;
meta_topic (META_DEBUG_XINERAMA,
"Monitor %d is %d,%d %d x %d\n",
screen->monitor_infos[i].number,
screen->monitor_infos[i].rect.x,
screen->monitor_infos[i].rect.y,
screen->monitor_infos[i].rect.width,
screen->monitor_infos[i].rect.height);
++i;
}
}
meta_XFree (infos);
#ifdef HAVE_RANDR
{
XRRScreenResources *resources;
resources = XRRGetScreenResourcesCurrent (display->xdisplay, screen->xroot);
if (resources)
{
for (i = 0; i < resources->ncrtc; i++)
{
XRRCrtcInfo *crtc;
MetaMonitorInfo *info;
crtc = XRRGetCrtcInfo (display->xdisplay, resources, resources->crtcs[i]);
info = find_monitor_with_rect (screen, crtc->x, crtc->y, (int)crtc->width, (int)crtc->height);
if (info)
info->output = find_main_output_for_crtc (screen, resources, crtc);
XRRFreeCrtcInfo (crtc);
}
XRRFreeScreenResources (resources);
}
}
#endif
}
else if (screen->n_monitor_infos > 0)
{
meta_topic (META_DEBUG_XINERAMA,
"No Xinerama extension or Xinerama inactive on display %s\n",
display->name);
}
/* If no Xinerama, fill in the single screen info so
* we can use the field unconditionally
*/
if (screen->n_monitor_infos == 0)
{
meta_topic (META_DEBUG_XINERAMA,
"No Xinerama screens, using default screen info\n");
screen->monitor_infos = g_new0 (MetaMonitorInfo, 1);
screen->n_monitor_infos = 1;
screen->monitor_infos[0].number = 0;
screen->monitor_infos[0].rect = screen->rect;
screen->monitor_infos[0].in_fullscreen = -1;
}
filter_mirrored_monitors (screen);
screen->monitor_infos[screen->primary_monitor_index].is_primary = TRUE;
g_assert (screen->n_monitor_infos > 0);
g_assert (screen->monitor_infos != NULL);
screen->monitor_infos = meta_monitor_manager_get_monitor_infos (manager,
(unsigned*)&screen->n_monitor_infos);
screen->primary_monitor_index = meta_monitor_manager_get_primary_index (manager);
}
/* The guard window allows us to leave minimized windows mapped so
@ -603,12 +447,13 @@ reload_monitor_infos (MetaScreen *screen)
* should effectively be forwarded to events on the background actor,
* providing that the scene graph is set up correctly.
*/
static Window
create_guard_window (Display *xdisplay, MetaScreen *screen)
Window
meta_screen_create_guard_window (Display *xdisplay, MetaScreen *screen)
{
XSetWindowAttributes attributes;
Window guard_window;
gulong create_serial;
MetaStackWindow stack_window;
attributes.event_mask = NoEventMask;
attributes.override_redirect = True;
@ -641,12 +486,14 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
XISelectEvents (xdisplay, guard_window, &mask, 1);
}
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = guard_window;
meta_stack_tracker_record_add (screen->stack_tracker,
guard_window,
&stack_window,
create_serial);
meta_stack_tracker_record_lower (screen->stack_tracker,
guard_window,
&stack_window,
XNextRequest (xdisplay));
XLowerWindow (xdisplay, guard_window);
XMapWindow (xdisplay, guard_window);
@ -668,6 +515,7 @@ meta_screen_new (MetaDisplay *display,
char buf[128];
guint32 manager_timestamp;
gulong current_workspace;
MetaMonitorManager *manager;
replace_current_wm = meta_get_replace_current_wm ();
@ -731,7 +579,7 @@ meta_screen_new (MetaDisplay *display,
if (XGetSelectionOwner (xdisplay, wm_sn_atom) != new_wm_sn_owner)
{
meta_warning (_("Could not acquire window manager selection on screen %d display \"%s\"\n"),
meta_warning ("Could not acquire window manager selection on screen %d display \"%s\"\n",
number, display->name);
XDestroyWindow (xdisplay, new_wm_sn_owner);
@ -826,8 +674,18 @@ meta_screen_new (MetaDisplay *display,
screen->xscreen = ScreenOfDisplay (xdisplay, number);
screen->xroot = xroot;
screen->rect.x = screen->rect.y = 0;
screen->rect.width = WidthOfScreen (screen->xscreen);
screen->rect.height = HeightOfScreen (screen->xscreen);
if (!meta_is_wayland_compositor ())
meta_monitor_manager_initialize ();
manager = meta_monitor_manager_get ();
g_signal_connect (manager, "monitors-changed",
G_CALLBACK (on_monitors_changed), screen);
meta_monitor_manager_get_screen_size (manager,
&screen->rect.width,
&screen->rect.height);
screen->current_cursor = -1; /* invalid/unset */
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
@ -852,12 +710,9 @@ meta_screen_new (MetaDisplay *display,
screen->compositor_data = NULL;
screen->guard_window = None;
screen->monitor_infos = NULL;
screen->n_monitor_infos = 0;
screen->last_monitor_index = 0;
reload_monitor_infos (screen);
meta_cursor_tracker_get_for_screen (screen);
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
/* Handle creating a no_focus_window for this screen */
@ -941,7 +796,7 @@ meta_screen_new (MetaDisplay *display,
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
screen->number, screen->screen_name, screen->xroot);
return screen;
}
@ -995,7 +850,7 @@ meta_screen_free (MetaScreen *screen,
meta_error_trap_push_with_return (screen->display);
XSelectInput (screen->display->xdisplay, screen->xroot, 0);
if (meta_error_trap_pop_with_return (screen->display) != Success)
meta_warning (_("Could not release screen %d on display \"%s\"\n"),
meta_warning ("Could not release screen %d on display \"%s\"\n",
screen->number, screen->display->name);
unset_wm_check_hint (screen);
@ -1082,8 +937,8 @@ meta_screen_manage_all_windows (MetaScreen *screen)
meta_display_grab (screen->display);
if (screen->guard_window == None)
screen->guard_window = create_guard_window (screen->display->xdisplay,
screen);
screen->guard_window =
meta_screen_create_guard_window (screen->display->xdisplay, screen);
windows = list_windows (screen);
@ -1613,29 +1468,18 @@ void
meta_screen_set_cursor (MetaScreen *screen,
MetaCursor cursor)
{
Cursor xcursor;
if (cursor == screen->current_cursor)
return;
screen->current_cursor = cursor;
xcursor = meta_display_create_x_cursor (screen->display, cursor);
XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor);
XFlush (screen->display->xdisplay);
XFreeCursor (screen->display->xdisplay, xcursor);
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker, cursor);
}
void
meta_screen_update_cursor (MetaScreen *screen)
{
Cursor xcursor;
xcursor = meta_display_create_x_cursor (screen->display,
screen->current_cursor);
XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor);
XFlush (screen->display->xdisplay);
XFreeCursor (screen->display->xdisplay, xcursor);
meta_cursor_tracker_set_root_cursor (screen->cursor_tracker,
screen->current_cursor);
}
void
@ -1898,12 +1742,15 @@ meta_screen_tile_preview_update_timeout (gpointer data)
{
Window xwindow;
gulong create_serial;
MetaStackWindow stack_window;
screen->tile_preview = meta_tile_preview_new (screen->number);
xwindow = meta_tile_preview_get_xwindow (screen->tile_preview,
&create_serial);
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = xwindow;
meta_stack_tracker_record_add (screen->stack_tracker,
xwindow,
&stack_window,
create_serial);
}
@ -2216,6 +2063,65 @@ meta_screen_get_current_monitor_info (MetaScreen *screen)
return &screen->monitor_infos[monitor_index];
}
const MetaMonitorInfo*
meta_screen_get_current_monitor_info_for_pos (MetaScreen *screen,
int x,
int y)
{
int monitor_index;
monitor_index = meta_screen_get_current_monitor_for_pos (screen, x, y);
return &screen->monitor_infos[monitor_index];
}
/**
* meta_screen_get_current_monitor_for_pos:
* @screen: a #MetaScreen
* @x: The x coordinate
* @y: The y coordinate
*
* Gets the index of the monitor that contains the passed coordinates.
*
* Return value: a monitor index
*/
int
meta_screen_get_current_monitor_for_pos (MetaScreen *screen,
int x,
int y)
{
if (screen->n_monitor_infos == 1)
return 0;
else if (screen->display->monitor_cache_invalidated)
{
int i;
MetaRectangle pointer_position;
pointer_position.x = x;
pointer_position.y = y;
pointer_position.width = pointer_position.height = 1;
screen->display->monitor_cache_invalidated = FALSE;
screen->last_monitor_index = 0;
for (i = 0; i < screen->n_monitor_infos; i++)
{
if (meta_rectangle_contains_rect (&screen->monitor_infos[i].rect,
&pointer_position))
{
screen->last_monitor_index = i;
break;
}
}
meta_topic (META_DEBUG_XINERAMA,
"Rechecked current monitor, now %d\n",
screen->last_monitor_index);
}
return screen->last_monitor_index;
}
/**
* meta_screen_get_current_monitor:
* @screen: a #MetaScreen
@ -2241,11 +2147,7 @@ meta_screen_get_current_monitor (MetaScreen *screen)
XIButtonState buttons;
XIModifierState mods;
XIGroupState group;
int i;
MetaRectangle pointer_position;
screen->display->monitor_cache_invalidated = FALSE;
XIQueryPointer (screen->display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
screen->xroot,
@ -2260,24 +2162,7 @@ meta_screen_get_current_monitor (MetaScreen *screen)
&group);
free (buttons.mask);
pointer_position.x = root_x_return;
pointer_position.y = root_y_return;
pointer_position.width = pointer_position.height = 1;
screen->last_monitor_index = 0;
for (i = 0; i < screen->n_monitor_infos; i++)
{
if (meta_rectangle_contains_rect (&screen->monitor_infos[i].rect,
&pointer_position))
{
screen->last_monitor_index = i;
break;
}
}
meta_topic (META_DEBUG_XINERAMA,
"Rechecked current monitor, now %d\n",
screen->last_monitor_index);
meta_screen_get_current_monitor_for_pos (screen, root_x_return, root_y_return);
}
return screen->last_monitor_index;
@ -2959,19 +2844,15 @@ meta_screen_resize_func (MetaScreen *screen,
meta_window_recalc_features (window);
}
void
meta_screen_resize (MetaScreen *screen,
int width,
int height)
static void
on_monitors_changed (MetaMonitorManager *manager,
MetaScreen *screen)
{
GSList *windows, *tmp;
MetaMonitorInfo *old_monitor_infos;
GSList *tmp, *windows;
screen->rect.width = width;
screen->rect.height = height;
/* Save the old monitor infos, so they stay valid during the update */
old_monitor_infos = screen->monitor_infos;
meta_monitor_manager_get_screen_size (manager,
&screen->rect.width,
&screen->rect.height);
reload_monitor_infos (screen);
set_desktop_geometry_hint (screen);
@ -2983,8 +2864,8 @@ meta_screen_resize (MetaScreen *screen,
changes.x = 0;
changes.y = 0;
changes.width = width;
changes.height = height;
changes.width = screen->rect.width;
changes.height = screen->rect.height;
XConfigureWindow(screen->display->xdisplay,
screen->guard_window,
@ -2994,14 +2875,15 @@ meta_screen_resize (MetaScreen *screen,
if (screen->display->compositor)
meta_compositor_sync_screen_size (screen->display->compositor,
screen, width, height);
screen,
screen->rect.width, screen->rect.height);
/* Queue a resize on all the windows */
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
/* Fix up monitor for all windows on this screen */
windows = meta_display_list_windows (screen->display,
META_LIST_DEFAULT);
META_LIST_INCLUDE_OVERRIDE_REDIRECT);
for (tmp = windows; tmp != NULL; tmp = tmp->next)
{
MetaWindow *window = tmp->data;
@ -3010,7 +2892,6 @@ meta_screen_resize (MetaScreen *screen,
meta_window_update_for_monitors_changed (window);
}
g_free (old_monitor_infos);
g_slist_free (windows);
meta_screen_queue_check_fullscreen (screen);
@ -3806,3 +3687,13 @@ meta_screen_get_monitor_in_fullscreen (MetaScreen *screen,
/* We use -1 as a flag to mean "not known yet" for notification purposes */
return screen->monitor_infos[monitor].in_fullscreen == TRUE;
}
gboolean
meta_screen_handle_xevent (MetaScreen *screen,
XEvent *xevent)
{
if (meta_cursor_tracker_handle_xevent (screen->cursor_tracker, xevent))
return TRUE;
return FALSE;
}

View File

@ -25,6 +25,8 @@
#include <config.h>
#include "util-private.h"
#include <meta/main.h>
#include "session.h"
#include <X11/Xatom.h>
@ -531,6 +533,12 @@ die_callback (SmcConn smc_conn, SmPointer client_data)
* Anything that wants us to go away outside of session management
* can use kill().
*/
/* All of that is true - unless we're a wayland compositor. In which
* case the X server won't go down until we do, so we must die first.
*/
if (meta_is_wayland_compositor ())
meta_quit (0);
}
static void
@ -840,14 +848,14 @@ save_state (void)
if (mkdir (mutter_dir, 0700) < 0 &&
errno != EEXIST)
{
meta_warning (_("Could not create directory '%s': %s\n"),
meta_warning ("Could not create directory '%s': %s\n",
mutter_dir, g_strerror (errno));
}
if (mkdir (session_dir, 0700) < 0 &&
errno != EEXIST)
{
meta_warning (_("Could not create directory '%s': %s\n"),
meta_warning ("Could not create directory '%s': %s\n",
session_dir, g_strerror (errno));
}
@ -857,7 +865,7 @@ save_state (void)
if (outfile == NULL)
{
meta_warning (_("Could not open session file '%s' for writing: %s\n"),
meta_warning ("Could not open session file '%s' for writing: %s\n",
full_save_file (), g_strerror (errno));
goto out;
}
@ -998,12 +1006,12 @@ save_state (void)
/* FIXME need a dialog for this */
if (ferror (outfile))
{
meta_warning (_("Error writing session file '%s': %s\n"),
meta_warning ("Error writing session file '%s': %s\n",
full_save_file (), g_strerror (errno));
}
if (fclose (outfile))
{
meta_warning (_("Error closing session file '%s': %s\n"),
meta_warning ("Error closing session file '%s': %s\n",
full_save_file (), g_strerror (errno));
}
}
@ -1133,7 +1141,7 @@ load_state (const char *previous_save_file)
error:
meta_warning (_("Failed to parse saved session file: %s\n"),
meta_warning ("Failed to parse saved session file: %s\n",
error->message);
g_error_free (error);
@ -1182,7 +1190,7 @@ start_element_handler (GMarkupParseContext *context,
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_PARSE,
_("<mutter_session> attribute seen but we already have the session ID"));
"<mutter_session> attribute seen but we already have the session ID");
return;
}
@ -1195,7 +1203,7 @@ start_element_handler (GMarkupParseContext *context,
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
_("Unknown attribute %s on <%s> element"),
"Unknown attribute %s on <%s> element",
name, "mutter_session");
return;
}
@ -1212,7 +1220,7 @@ start_element_handler (GMarkupParseContext *context,
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_PARSE,
_("nested <window> tag"));
"nested <window> tag");
return;
}
@ -1270,7 +1278,7 @@ start_element_handler (GMarkupParseContext *context,
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
_("Unknown attribute %s on <%s> element"),
"Unknown attribute %s on <%s> element",
name, "window");
session_info_free (pd->info);
pd->info = NULL;
@ -1302,7 +1310,7 @@ start_element_handler (GMarkupParseContext *context,
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
_("Unknown attribute %s on <%s> element"),
"Unknown attribute %s on <%s> element",
name, "window");
session_info_free (pd->info);
pd->info = NULL;
@ -1374,7 +1382,7 @@ start_element_handler (GMarkupParseContext *context,
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
_("Unknown attribute %s on <%s> element"),
"Unknown attribute %s on <%s> element",
name, "maximized");
return;
}
@ -1434,7 +1442,7 @@ start_element_handler (GMarkupParseContext *context,
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE,
_("Unknown attribute %s on <%s> element"),
"Unknown attribute %s on <%s> element",
name, "geometry");
return;
}
@ -1454,7 +1462,7 @@ start_element_handler (GMarkupParseContext *context,
g_set_error (error,
G_MARKUP_ERROR,
G_MARKUP_ERROR_UNKNOWN_ELEMENT,
_("Unknown element %s"),
"Unknown element %s",
element_name);
return;
}

File diff suppressed because it is too large Load Diff

View File

@ -37,36 +37,55 @@
#define META_STACK_TRACKER_H
#include <meta/screen.h>
#include <meta/window.h>
typedef struct _MetaStackTracker MetaStackTracker;
typedef union _MetaStackWindow
{
struct {
MetaWindowClientType type;
} any;
struct {
MetaWindowClientType type;
Window xwindow;
} x11;
struct {
MetaWindowClientType type;
MetaWindow *meta_window;
} wayland;
} MetaStackWindow;
gboolean meta_stack_window_equal (const MetaStackWindow *a,
const MetaStackWindow *b);
MetaStackTracker *meta_stack_tracker_new (MetaScreen *screen);
void meta_stack_tracker_free (MetaStackTracker *tracker);
/* These functions are called when we make an X call that changes the
* stacking order; this allows MetaStackTracker to predict stacking
* order before it receives events back from the X server */
void meta_stack_tracker_record_add (MetaStackTracker *tracker,
Window window,
gulong serial);
void meta_stack_tracker_record_remove (MetaStackTracker *tracker,
Window window,
gulong serial);
void meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker,
Window *windows,
int n_windows,
gulong serial);
void meta_stack_tracker_record_raise_above (MetaStackTracker *tracker,
Window window,
Window sibling,
gulong serial);
void meta_stack_tracker_record_lower_below (MetaStackTracker *tracker,
Window window,
Window sibling,
gulong serial);
void meta_stack_tracker_record_lower (MetaStackTracker *tracker,
Window window,
gulong serial);
void meta_stack_tracker_record_add (MetaStackTracker *tracker,
const MetaStackWindow *window,
gulong serial);
void meta_stack_tracker_record_remove (MetaStackTracker *tracker,
const MetaStackWindow *window,
gulong serial);
void meta_stack_tracker_record_restack_windows (MetaStackTracker *tracker,
const MetaStackWindow *windows,
int n_windows,
gulong serial);
void meta_stack_tracker_record_raise_above (MetaStackTracker *tracker,
const MetaStackWindow *window,
const MetaStackWindow *sibling,
gulong serial);
void meta_stack_tracker_record_lower_below (MetaStackTracker *tracker,
const MetaStackWindow *window,
const MetaStackWindow *sibling,
gulong serial);
void meta_stack_tracker_record_lower (MetaStackTracker *tracker,
const MetaStackWindow *window,
gulong serial);
/* These functions are used to update the stack when we get events
* reflecting changes to the stacking order */
@ -79,9 +98,9 @@ void meta_stack_tracker_reparent_event (MetaStackTracker *tracker,
void meta_stack_tracker_configure_event (MetaStackTracker *tracker,
XConfigureEvent *event);
void meta_stack_tracker_get_stack (MetaStackTracker *tracker,
Window **windows,
int *n_windows);
void meta_stack_tracker_get_stack (MetaStackTracker *tracker,
MetaStackWindow **windows,
int *n_entries);
void meta_stack_tracker_sync_stack (MetaStackTracker *tracker);
void meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker);

View File

@ -52,7 +52,7 @@
#define WINDOW_IN_STACK(w) (w->stack_position >= 0)
static void stack_sync_to_server (MetaStack *stack);
static void stack_sync_to_xserver (MetaStack *stack);
static void meta_window_set_stack_position_no_sync (MetaWindow *window,
int position);
static void stack_do_window_deletions (MetaStack *stack);
@ -71,14 +71,14 @@ meta_stack_new (MetaScreen *screen)
stack = g_new (MetaStack, 1);
stack->screen = screen;
stack->windows = g_array_new (FALSE, FALSE, sizeof (Window));
stack->xwindows = g_array_new (FALSE, FALSE, sizeof (Window));
stack->sorted = NULL;
stack->added = NULL;
stack->removed = NULL;
stack->freeze_count = 0;
stack->last_root_children_stacked = NULL;
stack->last_all_root_children_stacked = NULL;
stack->n_positions = 0;
@ -89,17 +89,34 @@ meta_stack_new (MetaScreen *screen)
return stack;
}
static void
free_last_all_root_children_stacked_cache (MetaStack *stack)
{
unsigned int i;
for (i = 0; i < stack->last_all_root_children_stacked->len; i++)
{
MetaStackWindow *window = &g_array_index (stack->last_all_root_children_stacked, MetaStackWindow, i);
if (window->any.type == META_WINDOW_CLIENT_TYPE_WAYLAND)
g_object_remove_weak_pointer (G_OBJECT (window->wayland.meta_window),
(gpointer *)&window->wayland.meta_window);
}
g_array_free (stack->last_all_root_children_stacked, TRUE);
stack->last_all_root_children_stacked = NULL;
}
void
meta_stack_free (MetaStack *stack)
{
g_array_free (stack->windows, TRUE);
g_array_free (stack->xwindows, TRUE);
g_list_free (stack->sorted);
g_list_free (stack->added);
g_list_free (stack->removed);
if (stack->last_root_children_stacked)
g_array_free (stack->last_root_children_stacked, TRUE);
if (stack->last_all_root_children_stacked)
free_last_all_root_children_stacked_cache (stack);
g_free (stack);
}
@ -121,7 +138,7 @@ meta_stack_add (MetaStack *stack,
"Window %s has stack_position initialized to %d\n",
window->desc, window->stack_position);
stack_sync_to_server (stack);
stack_sync_to_xserver (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
@ -157,7 +174,7 @@ meta_stack_remove (MetaStack *stack,
stack->removed = g_list_prepend (stack->removed,
GUINT_TO_POINTER (window->frame->xwindow));
stack_sync_to_server (stack);
stack_sync_to_xserver (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
@ -167,7 +184,7 @@ meta_stack_update_layer (MetaStack *stack,
{
stack->need_relayer = TRUE;
stack_sync_to_server (stack);
stack_sync_to_xserver (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
@ -177,7 +194,7 @@ meta_stack_update_transient (MetaStack *stack,
{
stack->need_constrain = TRUE;
stack_sync_to_server (stack);
stack_sync_to_xserver (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
@ -206,7 +223,7 @@ meta_stack_raise (MetaStack *stack,
meta_window_set_stack_position_no_sync (window, max_stack_position);
stack_sync_to_server (stack);
stack_sync_to_xserver (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
@ -234,7 +251,7 @@ meta_stack_lower (MetaStack *stack,
meta_window_set_stack_position_no_sync (window, min_stack_position);
stack_sync_to_server (stack);
stack_sync_to_xserver (stack);
meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
@ -250,7 +267,7 @@ meta_stack_thaw (MetaStack *stack)
g_return_if_fail (stack->freeze_count > 0);
stack->freeze_count -= 1;
stack_sync_to_server (stack);
stack_sync_to_xserver (stack);
meta_stack_update_window_tile_matches (stack, NULL);
}
@ -278,7 +295,7 @@ static gboolean
is_focused_foreach (MetaWindow *window,
void *data)
{
if (window == window->display->expected_focus_window)
if (window->has_focus)
{
*((gboolean*) data) = TRUE;
return FALSE;
@ -335,11 +352,11 @@ get_standalone_layer (MetaWindow *window)
layer = META_LAYER_BOTTOM;
else if (window->fullscreen &&
(focused_transient ||
window == window->display->expected_focus_window ||
window->display->expected_focus_window == NULL ||
(window->display->expected_focus_window != NULL &&
window == window->display->focus_window ||
window->display->focus_window == NULL ||
(window->display->focus_window != NULL &&
windows_on_different_monitor (window,
window->display->expected_focus_window))))
window->display->focus_window))))
layer = META_LAYER_FULLSCREEN;
else if (window->wm_state_above && !META_WINDOW_MAXIMIZED (window))
layer = META_LAYER_TOP;
@ -829,7 +846,7 @@ stack_do_window_deletions (MetaStack *stack)
/* We go from the end figuring removals are more
* likely to be recent.
*/
i = stack->windows->len;
i = stack->xwindows->len;
while (i > 0)
{
--i;
@ -840,9 +857,9 @@ stack_do_window_deletions (MetaStack *stack)
* both the window->xwindow and window->frame->xwindow
* in the removal list.
*/
if (xwindow == g_array_index (stack->windows, Window, i))
if (xwindow == g_array_index (stack->xwindows, Window, i))
{
g_array_remove_index (stack->windows, i);
g_array_remove_index (stack->xwindows, i);
goto next;
}
}
@ -871,10 +888,10 @@ stack_do_window_additions (MetaStack *stack)
"Adding %d windows to sorted list\n",
n_added);
old_size = stack->windows->len;
g_array_set_size (stack->windows, old_size + n_added);
old_size = stack->xwindows->len;
g_array_set_size (stack->xwindows, old_size + n_added);
end = &g_array_index (stack->windows, Window, old_size);
end = &g_array_index (stack->xwindows, Window, old_size);
/* stack->added has the most recent additions at the
* front of the list, so we need to reverse it
@ -1029,6 +1046,102 @@ stack_ensure_sorted (MetaStack *stack)
stack_do_resort (stack);
}
static MetaStackWindow *
find_top_most_managed_window (MetaScreen *screen,
const MetaStackWindow *ignore)
{
MetaStackTracker *stack_tracker = screen->stack_tracker;
MetaStackWindow *windows;
int n_windows;
int i;
meta_stack_tracker_get_stack (stack_tracker,
&windows, &n_windows);
/* Children are in order from bottom to top. We want to
* find the topmost managed child, then configure
* our window to be above it.
*/
for (i = n_windows -1; i >= 0; i--)
{
MetaStackWindow *other_window = &windows[i];
if (other_window->any.type == ignore->any.type &&
((other_window->any.type == META_WINDOW_CLIENT_TYPE_X11 &&
other_window->x11.xwindow == ignore->x11.xwindow) ||
other_window->wayland.meta_window == ignore->wayland.meta_window))
{
/* Do nothing. This means we're already the topmost managed
* window, but it DOES NOT mean we are already just above
* the topmost managed window. This is important because if
* an override redirect window is up, and we map a new
* managed window, the new window is probably above the old
* popup by default, and we want to push it below that
* popup. So keep looking for a sibling managed window
* to be moved below.
*/
}
else
{
if (other_window->any.type == META_WINDOW_CLIENT_TYPE_X11)
{
MetaWindow *other = meta_display_lookup_x_window (screen->display,
other_window->x11.xwindow);
if (other != NULL && !other->override_redirect)
return other_window;
}
else
{
/* All wayland windows are currently considered "managed"
* TODO: consider wayland pop-up windows like override
* redirect windows here. */
return other_window;
}
}
}
return NULL;
}
/* When moving an X window we sometimes need an X based sibling.
*
* If the given sibling is X based this function returns it back
* otherwise it searches downwards looking for the nearest X window.
*
* If no X based sibling could be found return NULL. */
static MetaStackWindow *
find_x11_sibling_downwards (MetaScreen *screen,
MetaStackWindow *sibling)
{
MetaStackTracker *stack_tracker = screen->stack_tracker;
MetaStackWindow *windows;
int n_windows;
int i;
if (sibling->any.type == META_WINDOW_CLIENT_TYPE_X11)
return sibling;
meta_stack_tracker_get_stack (stack_tracker,
&windows, &n_windows);
/* NB: Children are in order from bottom to top and we
* want to search downwards for the nearest X window.
*/
for (i = n_windows - 1; i >= 0; i--)
if (meta_stack_window_equal (&windows[i], sibling))
break;
for (; i >= 0; i--)
{
if (windows[i].any.type == META_WINDOW_CLIENT_TYPE_X11)
return &windows[i];
}
return NULL;
}
/**
* raise_window_relative_to_managed_windows:
*
@ -1053,84 +1166,74 @@ stack_ensure_sorted (MetaStack *stack)
*/
static void
raise_window_relative_to_managed_windows (MetaScreen *screen,
Window xwindow)
const MetaStackWindow *window)
{
gulong serial = 0;
MetaStackWindow *sibling;
Window *children;
int n_children;
int i;
meta_stack_tracker_get_stack (screen->stack_tracker,
&children, &n_children);
/* Children are in order from bottom to top. We want to
* find the topmost managed child, then configure
* our window to be above it.
*/
i = n_children - 1;
while (i >= 0)
sibling = find_top_most_managed_window (screen, window);
if (!sibling)
{
if (children[i] == xwindow)
if (window->any.type == META_WINDOW_CLIENT_TYPE_X11)
{
/* Do nothing. This means we're already the topmost managed
* window, but it DOES NOT mean we are already just above
* the topmost managed window. This is important because if
* an override redirect window is up, and we map a new
* managed window, the new window is probably above the old
* popup by default, and we want to push it below that
* popup. So keep looking for a sibling managed window
* to be moved below.
*/
serial = XNextRequest (screen->display->xdisplay);
meta_error_trap_push (screen->display);
XLowerWindow (screen->display->xdisplay,
window->x11.xwindow);
meta_error_trap_pop (screen->display);
}
else
{
MetaWindow *other = meta_display_lookup_x_window (screen->display,
children[i]);
if (other != NULL && !other->override_redirect)
{
XWindowChanges changes;
/* children[i] is the topmost managed child */
/* No sibling to use, just lower ourselves to the bottom
* to be sure we're below any override redirect windows.
*/
meta_stack_tracker_record_lower (screen->stack_tracker,
window,
serial);
return;
}
/* window is the topmost managed child */
meta_topic (META_DEBUG_STACK,
"Moving 0x%lx above topmost managed child window 0x%lx\n",
xwindow, children[i]);
window->any.type == META_WINDOW_CLIENT_TYPE_X11 ? window->x11.xwindow: 0,
sibling->any.type == META_WINDOW_CLIENT_TYPE_X11 ? sibling->x11.xwindow: 0);
changes.sibling = children[i];
if (window->any.type == META_WINDOW_CLIENT_TYPE_X11)
{
XWindowChanges changes;
MetaStackWindow *x11_sibling = find_x11_sibling_downwards (screen, sibling);
serial = XNextRequest (screen->display->xdisplay);
if (x11_sibling)
{
changes.sibling = x11_sibling->x11.xwindow;
changes.stack_mode = Above;
meta_error_trap_push (screen->display);
meta_stack_tracker_record_raise_above (screen->stack_tracker,
xwindow,
children[i],
XNextRequest (screen->display->xdisplay));
XConfigureWindow (screen->display->xdisplay,
xwindow,
window->x11.xwindow,
CWSibling | CWStackMode,
&changes);
meta_error_trap_pop (screen->display);
break;
}
}
--i;
}
if (i < 0)
else
{
/* No sibling to use, just lower ourselves to the bottom
* to be sure we're below any override redirect windows.
*/
meta_error_trap_push (screen->display);
meta_stack_tracker_record_lower (screen->stack_tracker,
xwindow,
XNextRequest (screen->display->xdisplay));
XLowerWindow (screen->display->xdisplay,
xwindow);
window->x11.xwindow);
meta_error_trap_pop (screen->display);
}
}
meta_stack_tracker_record_raise_above (screen->stack_tracker,
window,
sibling,
serial);
}
/**
* stack_sync_to_server:
*
@ -1145,13 +1248,16 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
* job of computing the minimal set of stacking requests needed.
*/
static void
stack_sync_to_server (MetaStack *stack)
stack_sync_to_xserver (MetaStack *stack)
{
GArray *stacked;
GArray *root_children_stacked;
GArray *x11_stacked;
GArray *x11_root_children_stacked;
GArray *all_root_children_stacked; /* wayland OR x11 */
GList *tmp;
GArray *all_hidden;
GArray *x11_hidden;
GArray *x11_hidden_stack_windows;
int n_override_redirect = 0;
MetaStackWindow guard_stack_window;
/* Bail out if frozen */
if (stack->freeze_count > 0)
@ -1166,13 +1272,17 @@ stack_sync_to_server (MetaStack *stack)
* _NET hints, and "root_children_stacked" is in top-to-bottom
* order for XRestackWindows()
*/
stacked = g_array_new (FALSE, FALSE, sizeof (Window));
root_children_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
all_hidden = g_array_new (FALSE, FALSE, sizeof (Window));
x11_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (MetaStackWindow));
x11_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
x11_hidden_stack_windows = g_array_new (FALSE, FALSE, sizeof (MetaStackWindow));
x11_hidden = g_array_new (FALSE, FALSE, sizeof (Window));
/* The screen guard window sits above all hidden windows and acts as
* a barrier to input reaching these windows. */
g_array_append_val (all_hidden, stack->screen->guard_window);
g_array_append_val (x11_hidden, stack->screen->guard_window);
meta_topic (META_DEBUG_STACK, "Top to bottom: ");
meta_push_no_msg_prefix ();
@ -1181,6 +1291,9 @@ stack_sync_to_server (MetaStack *stack)
{
MetaWindow *w = tmp->data;
Window top_level_window;
MetaStackWindow stack_window;
stack_window.any.type = w->client_type;
meta_topic (META_DEBUG_STACK, "%u:%d - %s ",
w->layer, w->stack_position, w->desc);
@ -1189,60 +1302,93 @@ stack_sync_to_server (MetaStack *stack)
if (w->override_redirect)
n_override_redirect++;
else
g_array_prepend_val (stacked, w->xwindow);
g_array_prepend_val (x11_stacked, w->xwindow);
if (w->frame)
top_level_window = w->frame->xwindow;
else
top_level_window = w->xwindow;
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
stack_window.x11.xwindow = top_level_window;
else
stack_window.wayland.meta_window = w;
/* We don't restack hidden windows along with the rest, though they are
* reflected in the _NET hints. Hidden windows all get pushed below
* the screens fullscreen guard_window. */
if (w->hidden)
{
g_array_append_val (all_hidden, top_level_window);
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
{
MetaStackWindow stack_window;
stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
stack_window.x11.xwindow = top_level_window;
g_array_append_val (x11_hidden_stack_windows, stack_window);
g_array_append_val (x11_hidden, top_level_window);
}
continue;
}
g_array_append_val (all_root_children_stacked, stack_window);
/* build XRestackWindows() array from top to bottom */
g_array_append_val (root_children_stacked, top_level_window);
if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
g_array_append_val (x11_root_children_stacked, top_level_window);
else
{
MetaStackWindow *new;
/* So we can determine later if a cached stack window is
* stale because the corresponding window has been freed we
* associate a weak pointer with the new window. */
new = &g_array_index (all_root_children_stacked, MetaStackWindow, all_root_children_stacked->len - 1);
g_object_add_weak_pointer (G_OBJECT (new->wayland.meta_window),
(gpointer *)&new->wayland.meta_window);
}
}
meta_topic (META_DEBUG_STACK, "\n");
meta_pop_no_msg_prefix ();
/* All windows should be in some stacking order */
if (stacked->len != stack->windows->len - n_override_redirect)
/* All X windows should be in some stacking order */
if (x11_stacked->len != stack->xwindows->len - n_override_redirect)
meta_bug ("%u windows stacked, %u windows exist in stack\n",
stacked->len, stack->windows->len);
x11_stacked->len, stack->xwindows->len);
/* Sync to server */
meta_topic (META_DEBUG_STACK, "Restacking %u windows\n",
root_children_stacked->len);
all_root_children_stacked->len);
meta_error_trap_push (stack->screen->display);
if (stack->last_root_children_stacked == NULL)
if (stack->last_all_root_children_stacked == NULL)
{
/* Just impose our stack, we don't know the previous state.
* This involves a ton of circulate requests and may flicker.
*/
meta_topic (META_DEBUG_STACK, "Don't know last stack state, restacking everything\n");
if (root_children_stacked->len > 0)
if (all_root_children_stacked->len > 1)
{
meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
(Window *) root_children_stacked->data,
root_children_stacked->len,
XNextRequest (stack->screen->display->xdisplay));
gulong serial = 0;
if (x11_root_children_stacked->len > 1)
{
serial = XNextRequest (stack->screen->display->xdisplay);
XRestackWindows (stack->screen->display->xdisplay,
(Window *) root_children_stacked->data,
root_children_stacked->len);
(Window *) x11_root_children_stacked->data,
x11_root_children_stacked->len);
}
meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
(MetaStackWindow *) all_root_children_stacked->data,
all_root_children_stacked->len,
serial);
}
}
else if (root_children_stacked->len > 0)
else if (all_root_children_stacked->len > 0)
{
/* Try to do minimal window moves to get the stack in order */
/* A point of note: these arrays include frames not client windows,
@ -1250,28 +1396,34 @@ stack_sync_to_server (MetaStack *stack)
* was saved, then we may have inefficiency, but I don't think things
* break...
*/
const Window *old_stack = (Window *) stack->last_root_children_stacked->data;
const Window *new_stack = (Window *) root_children_stacked->data;
const int old_len = stack->last_root_children_stacked->len;
const int new_len = root_children_stacked->len;
const Window *oldp = old_stack;
const Window *newp = new_stack;
const Window *old_end = old_stack + old_len;
const Window *new_end = new_stack + new_len;
Window last_window = None;
const MetaStackWindow *old_stack = (MetaStackWindow *) stack->last_all_root_children_stacked->data;
const MetaStackWindow *new_stack = (MetaStackWindow *) all_root_children_stacked->data;
const int old_len = stack->last_all_root_children_stacked->len;
const int new_len = all_root_children_stacked->len;
const MetaStackWindow *oldp = old_stack;
const MetaStackWindow *newp = new_stack;
const MetaStackWindow *old_end = old_stack + old_len;
const MetaStackWindow *new_end = new_stack + new_len;
Window last_xwindow = None;
const MetaStackWindow *last_window = NULL;
while (oldp != old_end &&
newp != new_end)
{
if (*oldp == *newp)
if (meta_stack_window_equal (oldp, newp))
{
/* Stacks are the same here, move on */
++oldp;
last_window = *newp;
if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11)
last_xwindow = newp->x11.xwindow;
last_window = newp;
++newp;
}
else if (meta_display_lookup_x_window (stack->screen->display,
*oldp) == NULL)
else if ((oldp->any.type == META_WINDOW_CLIENT_TYPE_X11 &&
meta_display_lookup_x_window (stack->screen->display,
oldp->x11.xwindow) == NULL) ||
(oldp->any.type == META_WINDOW_CLIENT_TYPE_WAYLAND &&
oldp->wayland.meta_window == NULL))
{
/* *oldp is no longer known to us (probably destroyed),
* so we can just skip it
@ -1280,75 +1432,161 @@ stack_sync_to_server (MetaStack *stack)
}
else
{
/* Move *newp below last_window */
if (last_window == None)
/* Move *newp below the last_window */
if (!last_window)
{
meta_topic (META_DEBUG_STACK, "Using window 0x%lx as topmost (but leaving it in-place)\n", *newp);
meta_topic (META_DEBUG_STACK, "Using window 0x%lx as topmost (but leaving it in-place)\n",
newp->x11.xwindow);
raise_window_relative_to_managed_windows (stack->screen,
*newp);
raise_window_relative_to_managed_windows (stack->screen, newp);
}
else if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11 &&
last_xwindow == None)
{
/* In this case we have an X window that we need to
* put below a wayland window and this is the
* topmost X window. */
/* In X terms (because this is the topmost X window)
* we want to
* raise_window_relative_to_managed_windows() to
* ensure the X window is below override-redirect
* pop-up windows.
*
* In Wayland terms we just want to ensure
* newp is lowered below last_window (which
* notably doesn't require an X request because we
* know last_window isn't an X window).
*/
raise_window_relative_to_managed_windows (stack->screen, newp);
meta_stack_tracker_record_lower_below (stack->screen->stack_tracker,
newp, last_window,
0); /* no x request serial */
}
else
{
/* This means that if last_window is dead, but not
gulong serial = 0;
/* This means that if last_xwindow is dead, but not
* *newp, then we fail to restack *newp; but on
* unmanaging last_window, we'll fix it up.
* unmanaging last_xwindow, we'll fix it up.
*/
XWindowChanges changes;
meta_topic (META_DEBUG_STACK, "Placing window 0x%lx below 0x%lx\n",
newp->any.type == META_WINDOW_CLIENT_TYPE_X11 ? newp->x11.xwindow : 0,
last_xwindow);
changes.sibling = last_window;
if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11)
{
XWindowChanges changes;
serial = XNextRequest (stack->screen->display->xdisplay);
changes.sibling = last_xwindow;
changes.stack_mode = Below;
meta_topic (META_DEBUG_STACK, "Placing window 0x%lx below 0x%lx\n",
*newp, last_window);
meta_stack_tracker_record_lower_below (stack->screen->stack_tracker,
*newp, last_window,
XNextRequest (stack->screen->display->xdisplay));
XConfigureWindow (stack->screen->display->xdisplay,
*newp,
newp->x11.xwindow,
CWSibling | CWStackMode,
&changes);
}
last_window = *newp;
meta_stack_tracker_record_lower_below (stack->screen->stack_tracker,
newp, last_window,
serial);
}
if (newp->any.type == META_WINDOW_CLIENT_TYPE_X11)
last_xwindow = newp->x11.xwindow;
last_window = newp;
++newp;
}
}
if (newp != new_end)
{
const MetaStackWindow *x_ref;
unsigned long serial = 0;
/* Restack remaining windows */
meta_topic (META_DEBUG_STACK, "Restacking remaining %d windows\n",
(int) (new_end - newp));
/* rewind until we find the last stacked X window that we can use
* as a reference point for re-stacking remaining X windows */
if (newp != new_stack)
for (x_ref = newp - 1;
x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11 && x_ref > new_stack;
x_ref--)
;
else
x_ref = new_stack;
/* If we didn't find an X window looking backwards then walk forwards
* through the remaining windows to find the first remaining X window
* instead. */
if (x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11)
{
for (x_ref = newp;
x_ref->any.type != META_WINDOW_CLIENT_TYPE_X11 && x_ref > new_stack;
x_ref++)
;
}
/* If there are any X windows remaining unstacked then restack them */
if (x_ref->any.type == META_WINDOW_CLIENT_TYPE_X11)
{
int i;
for (i = x11_root_children_stacked->len - 1; i; i--)
{
Window *reference = &g_array_index (x11_root_children_stacked, Window, i);
if (*reference == x_ref->x11.xwindow)
{
int n = x11_root_children_stacked->len - i;
/* There's no point restacking if there's only one X window */
if (n == 1)
break;
serial = XNextRequest (stack->screen->display->xdisplay);
XRestackWindows (stack->screen->display->xdisplay,
reference, n);
break;
}
}
}
/* We need to include an already-stacked window
* in the restack call, so we get in the proper position
* with respect to it.
*/
if (newp != new_stack)
--newp;
newp = MIN (newp - 1, x_ref);
meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
(Window *) newp, new_end - newp,
XNextRequest (stack->screen->display->xdisplay));
XRestackWindows (stack->screen->display->xdisplay,
(Window *) newp, new_end - newp);
newp, new_end - newp,
serial);
}
}
/* Push hidden windows to the bottom of the stack under the guard window */
/* Push hidden X windows to the bottom of the stack under the guard window */
guard_stack_window.any.type = META_WINDOW_CLIENT_TYPE_X11;
guard_stack_window.x11.xwindow = stack->screen->guard_window;
meta_stack_tracker_record_lower (stack->screen->stack_tracker,
stack->screen->guard_window,
&guard_stack_window,
XNextRequest (stack->screen->display->xdisplay));
XLowerWindow (stack->screen->display->xdisplay, stack->screen->guard_window);
meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
(Window *)all_hidden->data,
all_hidden->len,
(MetaStackWindow *)x11_hidden_stack_windows->data,
x11_hidden_stack_windows->len,
XNextRequest (stack->screen->display->xdisplay));
XRestackWindows (stack->screen->display->xdisplay,
(Window *)all_hidden->data,
all_hidden->len);
g_array_free (all_hidden, TRUE);
(Window *)x11_hidden->data,
x11_hidden->len);
g_array_free (x11_hidden, TRUE);
g_array_free (x11_hidden_stack_windows, TRUE);
meta_error_trap_pop (stack->screen->display);
/* on error, a window was destroyed; it should eventually
@ -1363,21 +1601,23 @@ stack_sync_to_server (MetaStack *stack)
stack->screen->display->atom__NET_CLIENT_LIST,
XA_WINDOW,
32, PropModeReplace,
(unsigned char *)stack->windows->data,
stack->windows->len);
(unsigned char *)stack->xwindows->data,
stack->xwindows->len);
XChangeProperty (stack->screen->display->xdisplay,
stack->screen->xroot,
stack->screen->display->atom__NET_CLIENT_LIST_STACKING,
XA_WINDOW,
32, PropModeReplace,
(unsigned char *)stacked->data,
stacked->len);
(unsigned char *)x11_stacked->data,
x11_stacked->len);
g_array_free (stacked, TRUE);
g_array_free (x11_stacked, TRUE);
if (stack->last_root_children_stacked)
g_array_free (stack->last_root_children_stacked, TRUE);
stack->last_root_children_stacked = root_children_stacked;
if (stack->last_all_root_children_stacked)
free_last_all_root_children_stacked_cache (stack);
stack->last_all_root_children_stacked = all_root_children_stacked;
g_array_free (x11_root_children_stacked, TRUE);
/* That was scary... */
}
@ -1738,7 +1978,7 @@ meta_stack_set_positions (MetaStack *stack,
meta_topic (META_DEBUG_STACK,
"Reset the stack positions of (nearly) all windows\n");
stack_sync_to_server (stack);
stack_sync_to_xserver (stack);
meta_stack_update_window_tile_matches (stack, NULL);
}
@ -1801,7 +2041,7 @@ meta_window_set_stack_position (MetaWindow *window,
int position)
{
meta_window_set_stack_position_no_sync (window, position);
stack_sync_to_server (window->screen->stack);
stack_sync_to_xserver (window->screen->stack);
meta_stack_update_window_tile_matches (window->screen->stack,
window->screen->active_workspace);
}

View File

@ -60,7 +60,7 @@ struct _MetaStack
* A sequence of all the Windows (X handles, not MetaWindows) of the windows
* we manage, sorted in order. Suitable to be passed into _NET_CLIENT_LIST.
*/
GArray *windows;
GArray *xwindows;
/** The MetaWindows of the windows we manage, sorted in order. */
GList *sorted;
@ -99,7 +99,7 @@ struct _MetaStack
* The last-known stack of all windows, bottom to top. We cache it here
* so that subsequent times we'll be able to do incremental moves.
*/
GArray *last_root_children_stacked;
GArray *last_all_root_children_stacked;
/**
* Number of stack positions; same as the length of added, but

37
src/core/util-private.h Normal file
View File

@ -0,0 +1,37 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Mutter utilities */
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2005 Elijah Newren
*
* 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.
*/
#ifndef META_UTIL_PRIVATE_H
#define META_UTIL_PRIVATE_H
#include <meta/util.h>
#include <glib/gi18n-lib.h>
void meta_set_verbose (gboolean setting);
void meta_set_debugging (gboolean setting);
void meta_set_syncing (gboolean setting);
void meta_set_replace_current_wm (gboolean setting);
void meta_set_is_wayland_compositor (gboolean setting);
#endif

View File

@ -31,7 +31,7 @@
#include <config.h>
#include <meta/common.h>
#include <meta/util.h>
#include "util-private.h"
#include <meta/main.h>
#include <clutter/clutter.h> /* For clutter_threads_add_repaint_func() */
@ -55,6 +55,7 @@ static gint verbose_topics = 0;
static gboolean is_debugging = FALSE;
static gboolean replace_current = FALSE;
static int no_prefix = 0;
static gboolean is_wayland_compositor = FALSE;
#ifdef WITH_VERBOSE_MODE
static FILE* logfile = NULL;
@ -81,7 +82,7 @@ ensure_logfile (void)
if (err != NULL)
{
meta_warning (_("Failed to open debug log: %s\n"),
meta_warning ("Failed to open debug log: %s\n",
err->message);
g_error_free (err);
return;
@ -91,13 +92,13 @@ ensure_logfile (void)
if (logfile == NULL)
{
meta_warning (_("Failed to fdopen() log file %s: %s\n"),
meta_warning ("Failed to fdopen() log file %s: %s\n",
filename, strerror (errno));
close (fd);
}
else
{
g_printerr (_("Opened log file %s\n"), filename);
g_printerr ("Opened log file %s\n", filename);
}
g_free (filename);
@ -194,6 +195,18 @@ meta_set_replace_current_wm (gboolean setting)
replace_current = setting;
}
gboolean
meta_is_wayland_compositor (void)
{
return is_wayland_compositor;
}
void
meta_set_is_wayland_compositor (gboolean value)
{
is_wayland_compositor = value;
}
char *
meta_g_utf8_strndup (const gchar *src,
gsize n)
@ -261,7 +274,7 @@ meta_debug_spew_real (const char *format, ...)
out = logfile ? logfile : stderr;
if (no_prefix == 0)
utf8_fputs (_("Window manager: "), out);
utf8_fputs ("Window manager: ", out);
utf8_fputs (str, out);
fflush (out);
@ -332,6 +345,8 @@ topic_name (MetaDebugTopic topic)
return "COMPOSITOR";
case META_DEBUG_EDGE_RESISTANCE:
return "EDGE_RESISTANCE";
case META_DEBUG_DBUS:
return "DBUS";
case META_DEBUG_VERBOSE:
return "VERBOSE";
}
@ -409,7 +424,7 @@ meta_bug (const char *format, ...)
#endif
if (no_prefix == 0)
utf8_fputs (_("Bug in window manager: "), out);
utf8_fputs ("Bug in window manager: ", out);
utf8_fputs (str, out);
fflush (out);
@ -440,7 +455,7 @@ meta_warning (const char *format, ...)
#endif
if (no_prefix == 0)
utf8_fputs (_("Window manager warning: "), out);
utf8_fputs ("Window manager warning: ", out);
utf8_fputs (str, out);
fflush (out);
@ -468,7 +483,7 @@ meta_fatal (const char *format, ...)
#endif
if (no_prefix == 0)
utf8_fputs (_("Window manager error: "), out);
utf8_fputs ("Window manager error: ", out);
utf8_fputs (str, out);
fflush (out);
@ -637,8 +652,13 @@ meta_show_dialog (const char *type,
append_argument (args, "zenity");
append_argument (args, type);
append_argument (args, "--display");
append_argument (args, display);
if (display)
{
append_argument (args, "--display");
append_argument (args, display);
}
append_argument (args, "--class");
append_argument (args, "mutter-dialog");
append_argument (args, "--title");

View File

@ -44,6 +44,7 @@
#include <X11/Xutil.h>
#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "meta-wayland-types.h"
typedef struct _MetaWindowQueue MetaWindowQueue;
@ -69,6 +70,7 @@ typedef enum {
_NET_WM_BYPASS_COMPOSITOR_HINT_OFF = 2,
} MetaBypassCompositorHintValue;
struct _MetaWindow
{
GObject parent_instance;
@ -77,6 +79,10 @@ struct _MetaWindow
MetaScreen *screen;
const MetaMonitorInfo *monitor;
MetaWorkspace *workspace;
MetaWindowClientType client_type;
#ifdef HAVE_WAYLAND
MetaWaylandSurface *surface;
#endif
Window xwindow;
/* may be NULL! not all windows get decorated */
MetaFrame *frame;
@ -121,6 +127,7 @@ struct _MetaWindow
Window xtransient_for;
Window xgroup_leader;
Window xclient_leader;
MetaWindow *transient_for;
/* Initial workspace property */
int initial_workspace;
@ -165,7 +172,7 @@ struct _MetaWindow
* been overridden (via a client message), the window will cover the union of
* these monitors. If not, this is the single monitor which the window's
* origin is on. */
long fullscreen_monitors[4];
gint fullscreen_monitors[4];
/* Whether we're trying to constrain the window to be fully onscreen */
guint require_fully_onscreen : 1;
@ -277,7 +284,7 @@ struct _MetaWindow
/* EWHH demands attention flag */
guint wm_state_demands_attention : 1;
/* this flag tracks receipt of focus_in focus_out */
/* TRUE iff window == window->display->focus_window */
guint has_focus : 1;
/* Have we placed this window? */
@ -325,9 +332,6 @@ struct _MetaWindow
guint using_net_wm_icon_name : 1; /* vs. plain wm_icon_name */
guint using_net_wm_visible_icon_name : 1; /* tracked so we can clear it */
/* has a shape mask */
guint has_shape : 1;
/* icon props have changed */
guint need_reread_icon : 1;
@ -349,9 +353,15 @@ struct _MetaWindow
/* if non-NULL, the bounds of the window frame */
cairo_region_t *frame_bounds;
/* if non-NULL, the bounding shape region of the window */
cairo_region_t *shape_region;
/* 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;
/* if TRUE, the we have the new form of sync request counter which
* also handles application frames */
guint extended_sync_request_counter : 1;
@ -394,6 +404,15 @@ struct _MetaWindow
*/
MetaRectangle rect;
/* The size and position we want the window to be (i.e. what we last asked
* the client to configure).
* This is only used for wayland clients.
*/
MetaRectangle expected_rect;
gboolean has_custom_frame_extents;
GtkBorder custom_frame_extents;
/* The geometry to restore when we unmaximize. The position is in
* root window coords, even if there's a frame, which contrasts with
* window->rect above. Note that this gives the position and size
@ -487,6 +506,10 @@ MetaWindow* meta_window_new_with_attrs (MetaDisplay *display,
gboolean must_be_viewable,
MetaCompEffect effect,
XWindowAttributes *attrs);
MetaWindow *meta_window_new_for_wayland (MetaDisplay *display,
int width,
int height,
MetaWaylandSurface *surface);
void meta_window_unmanage (MetaWindow *window,
guint32 timestamp);
void meta_window_calc_showing (MetaWindow *window);
@ -584,15 +607,19 @@ void meta_window_move_resize_request(MetaWindow *window,
int y,
int width,
int height);
void meta_window_move_resize_wayland (MetaWindow *window,
int width,
int height,
int dx,
int dy);
gboolean meta_window_configure_request (MetaWindow *window,
XEvent *event);
gboolean meta_window_property_notify (MetaWindow *window,
XEvent *event);
gboolean meta_window_client_message (MetaWindow *window,
XEvent *event);
gboolean meta_window_notify_focus (MetaWindow *window,
XIEnterEvent *event);
void meta_window_lost_focus (MetaWindow *window);
void meta_window_set_focused_internal (MetaWindow *window,
gboolean focused);
void meta_window_set_current_workspace_hint (MetaWindow *window);
@ -651,7 +678,9 @@ void meta_window_update_layer (MetaWindow *window);
void meta_window_recalc_features (MetaWindow *window);
/* recalc_window_type is x11 only, wayland does its thing and then calls type_changed */
void meta_window_recalc_window_type (MetaWindow *window);
void meta_window_type_changed (MetaWindow *window);
void meta_window_stack_just_below (MetaWindow *window,
MetaWindow *below_this_one);
@ -663,7 +692,6 @@ void meta_window_update_icon_now (MetaWindow *window);
void meta_window_update_role (MetaWindow *window);
void meta_window_update_net_wm_type (MetaWindow *window);
void meta_window_update_opaque_region (MetaWindow *window);
void meta_window_update_for_monitors_changed (MetaWindow *window);
void meta_window_update_on_all_workspaces (MetaWindow *window);
@ -677,4 +705,32 @@ void meta_window_compute_tile_match (MetaWindow *window);
gboolean meta_window_updates_are_frozen (MetaWindow *window);
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_title (MetaWindow *window,
const char *title);
void meta_window_set_wm_class (MetaWindow *window,
const char *wm_class,
const char *wm_instance);
void meta_window_set_gtk_dbus_properties (MetaWindow *window,
const char *application_id,
const char *unique_bus_name,
const char *appmenu_path,
const char *menubar_path,
const char *application_object_path,
const char *window_object_path);
void meta_window_set_transient_for (MetaWindow *window,
MetaWindow *parent);
#endif

View File

@ -48,6 +48,7 @@
#include <X11/Xatom.h>
#include <unistd.h>
#include <string.h>
#include "util-private.h"
#ifndef HOST_NAME_MAX
/* Solaris headers apparently don't define this so do so manually; #326745 */
@ -289,6 +290,35 @@ reload_icon_geometry (MetaWindow *window,
}
}
static void
reload_gtk_frame_extents (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
if (value->type != META_PROP_VALUE_INVALID)
{
if (value->v.cardinal_list.n_cardinals != 4)
{
meta_verbose ("_GTK_FRAME_EXTENTS on %s has %d values instead of 4\n",
window->desc, value->v.cardinal_list.n_cardinals);
}
else
{
GtkBorder *extents = &window->custom_frame_extents;
window->has_custom_frame_extents = TRUE;
extents->left = (int)value->v.cardinal_list.cardinals[0];
extents->right = (int)value->v.cardinal_list.cardinals[1];
extents->top = (int)value->v.cardinal_list.cardinals[2];
extents->bottom = (int)value->v.cardinal_list.cardinals[3];
}
}
else
{
window->has_custom_frame_extents = FALSE;
}
}
static void
reload_struts (MetaWindow *window,
MetaPropValue *value,
@ -315,7 +345,7 @@ reload_net_wm_pid (MetaWindow *window,
gulong cardinal = (int) value->v.cardinal;
if (cardinal <= 0)
meta_warning (_("Application set a bogus _NET_WM_PID %lu\n"),
meta_warning ("Application set a bogus _NET_WM_PID %lu\n",
cardinal);
else
{
@ -460,28 +490,19 @@ static void
set_window_title (MetaWindow *window,
const char *title)
{
char *str;
char *new_title = NULL;
gboolean modified =
set_title_text (window,
window->using_net_wm_visible_name,
title,
window->display->atom__NET_WM_VISIBLE_NAME,
&window->title);
&new_title);
window->using_net_wm_visible_name = modified;
/* strndup is a hack since GNU libc has broken %.10s */
str = g_strndup (window->title, 10);
g_free (window->desc);
window->desc = g_strdup_printf ("0x%lx (%s)", window->xwindow, str);
g_free (str);
meta_window_set_title (window, new_title);
if (window->frame)
meta_ui_set_frame_title (window->screen->ui,
window->frame->xwindow,
window->title);
g_object_notify (G_OBJECT (window), "title");
g_free (new_title);
}
static void
@ -536,7 +557,7 @@ reload_opaque_region (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
meta_window_update_opaque_region (window);
meta_window_update_opaque_region_x11 (window);
}
static void
@ -846,23 +867,15 @@ reload_wm_class (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
if (window->res_class)
g_free (window->res_class);
if (window->res_name)
g_free (window->res_name);
window->res_class = NULL;
window->res_name = NULL;
if (value->type != META_PROP_VALUE_INVALID)
{
if (value->v.class_hint.res_name)
window->res_name = g_strdup (value->v.class_hint.res_name);
if (value->v.class_hint.res_class)
window->res_class = g_strdup (value->v.class_hint.res_class);
g_object_notify (G_OBJECT (window), "wm-class");
{
meta_window_set_wm_class (window,
value->v.class_hint.res_class,
value->v.class_hint.res_name);
}
else
{
meta_window_set_wm_class (window, NULL, NULL);
}
meta_verbose ("Window %s class: '%s' name: '%s'\n",
@ -1505,7 +1518,7 @@ reload_transient_for (MetaWindow *window,
gboolean initial)
{
MetaWindow *parent = NULL;
Window transient_for, old_transient_for;
Window transient_for;
if (value->type != META_PROP_VALUE_INVALID)
{
@ -1514,8 +1527,7 @@ reload_transient_for (MetaWindow *window,
parent = meta_display_lookup_x_window (window->display, transient_for);
if (!parent)
{
meta_warning (_("Invalid WM_TRANSIENT_FOR window 0x%lx specified "
"for %s.\n"),
meta_warning ("Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n",
transient_for, window->desc);
transient_for = None;
}
@ -1525,8 +1537,7 @@ reload_transient_for (MetaWindow *window,
{
if (parent == window)
{
meta_warning (_("WM_TRANSIENT_FOR window 0x%lx for %s "
"would create loop.\n"),
meta_warning ("WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n",
transient_for, window->desc);
transient_for = None;
break;
@ -1542,10 +1553,6 @@ reload_transient_for (MetaWindow *window,
if (transient_for == window->xtransient_for)
return;
if (meta_window_appears_focused (window) && window->xtransient_for != None)
meta_window_propagate_focus_appearance (window, FALSE);
old_transient_for = window->xtransient_for;
window->xtransient_for = transient_for;
window->transient_parent_is_root_window =
@ -1557,46 +1564,14 @@ reload_transient_for (MetaWindow *window,
else
meta_verbose ("Window %s is not transient\n", window->desc);
/* may now be a dialog */
meta_window_recalc_window_type (window);
if (!window->constructing)
if (window->transient_parent_is_root_window || window->xtransient_for == None)
meta_window_set_transient_for (window, NULL);
else
{
/* If the window attaches, detaches, or changes attached
* parents, we need to destroy the MetaWindow and let a new one
* be created (which happens as a side effect of
* meta_window_unmanage()). The condition below is correct
* because we know window->xtransient_for has changed.
*/
if (window->attached || meta_window_should_attach_to_parent (window))
{
guint32 timestamp;
window->xtransient_for = old_transient_for;
timestamp = meta_display_get_current_time_roundtrip (window->display);
meta_window_unmanage (window, timestamp);
return;
}
parent = meta_display_lookup_x_window (window->display,
window->xtransient_for);
meta_window_set_transient_for (window, parent);
}
/* update stacking constraints */
if (!window->override_redirect)
meta_stack_update_transient (window->screen->stack, window);
/* possibly change its group. We treat being a window's transient as
* equivalent to making it your group leader, to work around shortcomings
* in programs such as xmms-- see #328211.
*/
if (window->xtransient_for != None &&
window->xgroup_leader != None &&
window->xtransient_for != window->xgroup_leader)
meta_window_group_leader_changed (window);
if (!window->constructing && !window->override_redirect)
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
if (meta_window_appears_focused (window) && window->xtransient_for != None)
meta_window_propagate_focus_appearance (window, TRUE);
}
static void
@ -1766,6 +1741,7 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
{ display->atom__GTK_WINDOW_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_window_object_path, TRUE, FALSE },
{ display->atom__GTK_APP_MENU_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_app_menu_object_path, TRUE, FALSE },
{ display->atom__GTK_MENUBAR_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_menubar_object_path, TRUE, FALSE },
{ display->atom__GTK_FRAME_EXTENTS, META_PROP_VALUE_CARDINAL_LIST,reload_gtk_frame_extents, TRUE, FALSE },
{ display->atom__NET_WM_USER_TIME_WINDOW, META_PROP_VALUE_WINDOW, reload_net_wm_user_time_window, TRUE, FALSE },
{ display->atom_WM_STATE, META_PROP_VALUE_INVALID, NULL, FALSE, FALSE },
{ display->atom__NET_WM_ICON, META_PROP_VALUE_INVALID, reload_net_wm_icon, FALSE, FALSE },

File diff suppressed because it is too large Load Diff

View File

@ -78,6 +78,7 @@ static void
meta_workspace_finalize (GObject *object)
{
/* Actual freeing done in meta_workspace_remove() for now */
G_OBJECT_CLASS (meta_workspace_parent_class)->finalize (object);
}
static void

View File

@ -83,7 +83,7 @@ from The Open Group.
#include <config.h>
#include "xprops.h"
#include <meta/errors.h>
#include <meta/util.h>
#include "util-private.h"
#include "async-getprop.h"
#include "ui.h"
#include "mutter-Xatomtype.h"
@ -152,7 +152,7 @@ validate_or_free_results (GetPropertyResults *results,
if (res_name == NULL)
res_name = "unknown";
meta_warning (_("Window 0x%lx has property %s\nthat was expected to have type %s format %d\nand actually has type %s format %d n_items %d.\nThis is most likely an application bug, not a window manager bug.\nThe window has title=\"%s\" class=\"%s\" name=\"%s\"\n"),
meta_warning ("Window 0x%lx has property %s\nthat was expected to have type %s format %d\nand actually has type %s format %d n_items %d.\nThis is most likely an application bug, not a window manager bug.\nThe window has title=\"%s\" class=\"%s\" name=\"%s\"\n",
results->xwindow,
prop_name ? prop_name : "(bad atom)",
expected_name ? expected_name : "(bad atom)",
@ -408,7 +408,7 @@ utf8_string_from_results (GetPropertyResults *results,
char *name;
name = XGetAtomName (results->display->xdisplay, results->xatom);
meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8\n"),
meta_warning ("Property %s on window 0x%lx contained invalid UTF-8\n",
name, results->xwindow);
meta_XFree (name);
XFree (results->prop);
@ -491,7 +491,7 @@ utf8_list_from_results (GetPropertyResults *results,
meta_error_trap_push (results->display);
name = XGetAtomName (results->display->xdisplay, results->xatom);
meta_error_trap_pop (results->display);
meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n"),
meta_warning ("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n",
name, results->xwindow, i);
meta_XFree (name);
meta_XFree (results->prop);

35
src/idle-monitor.xml Normal file
View File

@ -0,0 +1,35 @@
<!DOCTYPE node PUBLIC
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
<node>
<!--
org.gnome.Mutter.IdleMonitor:
@short_description: idle monitor interface
This interface is used by gnome-desktop to implement
user activity monitoring.
-->
<interface name="org.gnome.Mutter.IdleMonitor">
<method name="GetIdletime">
<arg name="idletime" direction="out" type="t"/>
</method>
<method name="AddIdleWatch">
<arg name="interval" direction="in" type="t" />
<arg name="id" direction="out" type="u" />
</method>
<method name="AddUserActiveWatch">
<arg name="id" direction="out" type="u" />
</method>
<method name="RemoveWatch">
<arg name="id" direction="in" type="u" />
</method>
<signal name="WatchFired">
<arg name="id" direction="out" type="u" />
</signal>
</interface>
</node>

View File

@ -0,0 +1,18 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
girdir=@libdir@/mutter-wayland
typelibdir=@libdir@/mutter-wayland
mutter_major_version=@MUTTER_MAJOR_VERSION@
mutter_minor_version=@MUTTER_MINOR_VERSION@
mutter_micro_version=@MUTTER_MICRO_VERSION@
mutter_plugin_api_version=@MUTTER_PLUGIN_API_VERSION@
Name: libmutter-wayland
Description: Mutter window manager library (Wayland branch)
Requires: gsettings-desktop-schemas gtk+-3.0 @CLUTTER_PACKAGE@ x11 wayland-server
Version: @VERSION@
Libs: -L${libdir} -lmutter-wayland
Cflags: -I${includedir}/mutter-wayland -DMUTTER_MAJOR_VERSION=${mutter_major_version} -DMUTTER_MINOR_VERSION=${mutter_minor_version} -DMUTTER_MICRO_VERSION=${mutter_micro_version} -DMUTTER_PLUGIN_API_VERSION=${mutter_plugin_api_version}

View File

@ -1,18 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
girdir=@libdir@/mutter
typelibdir=@libdir@/mutter
mutter_major_version=@MUTTER_MAJOR_VERSION@
mutter_minor_version=@MUTTER_MINOR_VERSION@
mutter_micro_version=@MUTTER_MICRO_VERSION@
mutter_plugin_api_version=@MUTTER_PLUGIN_API_VERSION@
Name: libmutter
Description: Mutter window manager library
Requires: gsettings-desktop-schemas gtk+-3.0 @CLUTTER_PACKAGE@ x11
Version: @VERSION@
Libs: -L${libdir} -lmutter
Cflags: -I${includedir}/mutter -DMUTTER_MAJOR_VERSION=${mutter_major_version} -DMUTTER_MINOR_VERSION=${mutter_minor_version} -DMUTTER_MICRO_VERSION=${mutter_micro_version} -DMUTTER_PLUGIN_API_VERSION=${mutter_plugin_api_version}

View File

@ -54,9 +54,6 @@ item(WM_WINDOW_ROLE)
item(UTF8_STRING)
item(WM_ICON_SIZE)
item(_KWM_WIN_ICON)
item(_MUTTER_RELOAD_THEME_MESSAGE)
item(_MUTTER_SET_KEYBINDINGS_MESSAGE)
item(_MUTTER_TOGGLE_VERBOSE)
item(_MUTTER_HINTS)
item(_GTK_THEME_VARIANT)
item(_GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED)
@ -66,12 +63,16 @@ item(_GTK_APPLICATION_OBJECT_PATH)
item(_GTK_WINDOW_OBJECT_PATH)
item(_GTK_APP_MENU_OBJECT_PATH)
item(_GTK_MENUBAR_OBJECT_PATH)
item(_GTK_FRAME_EXTENTS)
item(_GNOME_WM_KEYBINDINGS)
item(_GNOME_PANEL_ACTION)
item(_GNOME_PANEL_ACTION_MAIN_MENU)
item(_GNOME_PANEL_ACTION_RUN_DIALOG)
item(_MUTTER_TIMESTAMP_PING)
item(_MUTTER_FOCUS_SET)
item(_MUTTER_SENTINEL)
item(_MUTTER_VERSION)
item(_MUTTER_PRESENTATION_OUTPUT)
item(WM_CLIENT_MACHINE)
item(MANAGER)
item(TARGETS)
@ -79,6 +80,7 @@ item(MULTIPLE)
item(TIMESTAMP)
item(VERSION)
item(ATOM_PAIR)
item(BACKLIGHT)
/* Oddities: These are used, and we need atoms for them,
* but when we need all _NET_WM hints (i.e. when we're making

Some files were not shown because too many files have changed in this diff Show More