Compare commits

..

170 Commits

Author SHA1 Message Date
34398b273c wayland: add support for pointer barriers
Use the clutter pointer constrain callback and a lot of copypasted
code from Xorg to implement reactive pointer barriers and pointer
barrier events.

https://bugzilla.gnome.org/show_bug.cgi?id=706655
2013-10-03 21:11:13 +02:00
00a73c5bdc display: shortcut get_time_roundtrip() when running as a wayland compositor
In wayland, we can make some assumptions about the behavior and
configuration of the X server (which is Xwayland), including on
the time it uses, and that way avoiding a roundtrip (potentially deadly, if
by chance the X server is also blocking on us or needs us to flush
the wayland socket buffer).
Note that we bypass get_current_time() entirely, as it is assumed
the function is called always to translated CurrentTime into a real
value.

https://bugzilla.gnome.org/show_bug.cgi?id=707466
2013-10-03 21:11:12 +02:00
20cd02f086 wayland: use the timestamps from events
Clutter has learned to use monotonic times for the events, and
so does X (at least Xwayland, which is an implementation we know
and we can rely upon), so the values are directly comparable.

https://bugzilla.gnome.org/show_bug.cgi?id=707466
2013-10-03 21:11:12 +02:00
0cb9392686 wayland: sync the keymap from X to wayland
When X clients change the keyboard map, the also update a property
on the root window. We can notice that and rebuild our data structures
with the new values, as well as inform the wayland clients.

This is a terrible hack, and it's not how we want to implement things
in 3.12, but it's enough to have the same keyboard layout in the
shell, in X clients and in wayland clients in 3.10, until we decide
on the fate of the keyboard g-s-d plugin.

https://bugzilla.gnome.org/show_bug.cgi?id=707446
2013-10-03 21:11:12 +02:00
57f0b1d46d wayland: implement global and window keybindings
Synthetize XInput events from ClutterEvents in MetaWaylandKeyboard,
and pass them to the keybindings infrastructure for early handling,
so that we can activate them even if the currently focused window
is not an X11 one (or if there is no focused window, or we're
modal)

https://bugzilla.gnome.org/show_bug.cgi?id=706963
2013-10-03 21:11:12 +02:00
e2d8d886a8 [NOT FOR REVIEW] Add the ability to attach a debugger at init 2013-10-03 21:11:12 +02:00
348f3007d9 MetaIdleMonitor: protect the monitor instance while calling destroy notify
The destroy notify for a DBus watch holds a reference to the IdleMonitor,
but the IdleMonitorWatch object doesn't (it knows all watches will
be destroyed before the monitor is, so it doesn't need one). This
means that the DBus watch reference can be the only one keeping
the IdleMonitor alive (expecially true for device idle monitors,
which are only used by g-s-d/cursor), and that means that calling
the destroy notify freezes the monitor (and the next X calls
access garbage).

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

https://bugzilla.gnome.org/show_bug.cgi?id=708718
2013-09-26 16:08:49 +02:00
58622c0515 MetaCursorTracker: fix compilation in big endian arches
The enum name was wrong.
Patch originally by Dan Horák <dan@danny.cz>

https://bugzilla.gnome.org/show_bug.cgi?id=708813
2013-09-26 13:33:23 +02:00
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
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
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
0e098249b1 Merge remote-tracking branch 'origin/master' into wayland 2013-08-13 10:44:09 -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
139 changed files with 30412 additions and 10258 deletions

18
.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,16 +46,16 @@ POTFILES
po/*.pot
50-metacity-desktop-key.xml
50-metacity-key.xml
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
m4/*
mutter-grayscale
mutter-mag
mutter-message
@ -78,6 +78,12 @@ 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,12 +1,8 @@
SUBDIRS=src po doc
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
SUBDIRS=src protocol po doc
EXTRA_DIST = HACKING MAINTAINERS rationales.txt
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}

113
NEWS
View File

@ -1,63 +1,3 @@
3.11.3
======
* xrandr: Use "hotplug_mode_update" property [Marc-André; #711216]
* Fix position of attached dialogs for CSD windows [Giovanni, Owen; #707194]
* Fix focus issues with external OSKs [Jasper; #715030]
* Add a MetaCullable interface [Jasper; #714706]
* Fix window group paint volume [Owen; #719669]
* Fix frame extents problems [Owen; #714707]
* Add shortcut to move windows between monitors [Florian; #671054]
* Fix problems with focus tracking [Owen; #720558]
* Misc. bug fixes and cleanups [Rui, Jasper, Owen; #712833, #678989, #720106,
#720417, #720630]
Contributors:
Robert Bragg, Giovanni Campagna, Marc-André Lureau, Rui Matos, Alberto Milone,
Florian Müllner, Sindhu S, Jasper St. Pierre, Rico Tzschichholz,
Owen W. Taylor
Translations:
甘露(Gan Lu) [zh_CN], Khaled Hosny [ar]
3.11.2
======
* Fix resize operations using mouse-button-modifier [Lionel; #710251]
* Misc. fixes and cleanups [Jasper, Rico, Florian; #711731]
Contributors:
Lionel Landwerlin, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz
3.11.1
======
* Don't require at least one output device to be connected [Giovanni; #709009]
* Name the guard window [Andrew; #710346]
* Use new UPower API [Bastien]
* Expose min-backlight-step [Asad; #710380]
* Don't focus the no-focus-window for globally active windows [Jasper; #710296]
* Misc. fixes and cleanups [Jasper, Rico, Olav, Magdalen; #709776]
Contributors:
Magdalen Berns, Giovanni Campagna, Asad Mehmood, Bastien Nocera,
Jasper St. Pierre, Rico Tzschichholz, Olav Vitters, Andrew Walton
Translations:
Reinout van Schouwen [nl]
3.10.1
======
* Don't apply fullscreen workarounds to CSD windows [Giovanni; #708718]
* Fix hangs during DND operations [Adel; #709340]
* Use nearest-pixel interpolation when possible [Hans; #708389]
* Fix tile previews getting stuck on right click during drags [Lionel; #704759]
* Misc bug fixes [Giovanni, Jasper; #708420]
Contributors:
Giovanni Campagna, Adel Gadllah, Lionel Landwerlin, Hans Petter Jansson,
Jasper St. Pierre
Translations:
Khaled Hosny [ar], Reinout van Schouwen [nl], Carles Ferrando [ca@valencia]
3.10.0.1
========
* Fix bug when a window changed size twice in a single frame - this
@ -68,24 +8,32 @@ Contributors:
3.10.0
======
Translations:
Ask H. Larsen [da], Gabor Kelemen [hu], Duarte Loreto [pt],
Yosef Or Boczko [he]
* Update dependencies [Giovanni; #708210]
3.9.92
======
* Don't create a dummy texture for the texture pipeline template [Neil; #707458]
* Remove holes generated by disabling the laptop lid [Giovanni; #707473]
* https://bugzilla.gnome.org/show_bug.cgi?id=707474 [Giovanni; #707474]
* 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]
* Misc bug fixes [Giovanni, Colin, Pavel; #707649, #707563, #708070]
* Remove holes generated by disabling the laptop lid [Giovanni; #707473]
* Misc bug fixes [Giovanni, Pavel, Adel; #707649, #706124, #707584, #707851, #707929,
#708070]
Contributors:
Giovanni Campagna, Adel Gadllah, Colin Guthrie, Neil Roberts,
Jasper St. Pierre, Ray Strode, Pavel Vasin
Adel Gadllah, Giovanni Campagna, Kalev Lember, Pavel Vasin
Translations:
Мирослав Николић po/sr, sr@latin.po, Мирослав Николић [sr, sr@latin],
@ -98,19 +46,30 @@ Translations:
3.9.91
======
* Drop man pages for removed utilities [Kalev; #706579]
* Add support for idle tracking [Giovanni; #706005]
* 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]
* Turn blending off when drawing entirely opaque regions [Jasper; #706930]
* 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, #707250, #707267]
#706787, #706729, #706825, #707081, #707090, #707267, #706982, #706289]
Contributors:
Giovanni Campagna, Cosimo Cecchi, Adel Gadllah, Colin Guthrie, Kalev Lember,
Tim Lunn, Jasper St. Pierre, Rico Tzschichholz, Seán de Búrca
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],
@ -119,6 +78,8 @@ Translations:
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]
@ -133,8 +94,8 @@ Translations:
Contributors:
Robert Bragg, Giovanni Campagna, Alban Crequy, Adel Gadllah,
Alexander Larsson, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz,
Colin Walters
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],

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,9 +1,8 @@
AC_PREREQ(2.50)
AC_CONFIG_MACRO_DIR([m4])
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [11])
m4_define([mutter_micro_version], [3])
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])
@ -13,14 +12,17 @@ m4_define([mutter_plugin_api_version], [3])
AC_INIT([mutter], [mutter_version],
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
AC_CONFIG_MACRO_DIR([m4])
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
@ -36,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])
@ -69,15 +71,15 @@ CANBERRA_GTK_VERSION=0.26
CLUTTER_PACKAGE=clutter-1.0
MUTTER_PC_MODULES="
gtk+-3.0 >= 3.9.11
gtk+-3.0 >= 3.3.7
gio-2.0 >= 2.25.10
pango >= 1.2.0
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.15.90
cogl-1.0 >= 1.15.6
upower-glib >= 0.99.0
$CLUTTER_PACKAGE >= 1.15.94
cogl-1.0 >= 1.13.3
upower-glib > 0.9.11
gnome-desktop-3.0
"
@ -117,11 +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)
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"
@ -186,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],
@ -437,9 +458,9 @@ doc/man/Makefile
doc/reference/Makefile
doc/reference/meta-docs.sgml
src/Makefile
src/libmutter.pc
src/mutter-plugins.pc
src/libmutter-wayland.pc
src/compositor/plugins/Makefile
protocol/Makefile
po/Makefile.in
])
@ -455,7 +476,7 @@ fi
dnl ==========================================================================
echo "
mutter-$VERSION
mutter-wayland-$VERSION
prefix: ${prefix}
source code location: ${srcdir}

View File

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

@ -207,6 +207,7 @@ meta_key_binding_get_modifiers
meta_key_binding_get_mask
meta_key_binding_is_builtin
meta_keybindings_set_custom_handler
meta_keybindings_switch_window
meta_screen_ungrab_all_keys
meta_screen_grab_all_keys
</SECTION>
@ -388,23 +389,6 @@ MetaWindowActorPrivate
meta_window_actor_get_type
</SECTION>
<SECTION>
<FILE>meta-cullable</FILE>
<TITLE>MetaCullable</TITLE>
MetaCullable
MetaCullableInterface
meta_cullable_cull_out
meta_cullable_reset_culling
meta_cullable_cull_out_children
meta_cullable_reset_culling_children
<SUBSECTION Standard>
META_TYPE_CULLABLE
META_CULLABLE
META_IS_CULLABLE
META_CULLABLE_GET_IFACE
meta_cullable_get_type
</SECTION>
<SECTION>
<FILE>prefs</FILE>
MetaPreference
@ -558,10 +542,7 @@ meta_window_is_override_redirect
meta_window_is_skip_taskbar
meta_window_get_rect
meta_window_get_input_rect
meta_window_get_frame_rect
meta_window_get_outer_rect
meta_window_client_rect_to_frame_rect
meta_window_frame_rect_to_client_rect
meta_window_get_screen
meta_window_get_display
meta_window_get_xwindow

View File

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

View File

@ -21,9 +21,9 @@ 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/org.gnome.mutter.wayland.gschema.xml.in
src/ui/frames.c
src/ui/menu.c
src/ui/metaaccellabel.c

652
po/ar.po

File diff suppressed because it is too large Load Diff

2680
po/ca.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

353
po/cs.po
View File

@ -6,23 +6,22 @@
# Petr Tomeš <ptomes@gmail.com>, 2006.
# Jakub Friedl <jfriedl@suse.cz>, 2006, 2007.
# Petr Kovar <pknbe@volny.cz>, 2007, 2008, 2009, 2010, 2011, 2012, 2013.
# Marek Černocký <marek@manet.cz>, 2012, 2013.
#
# Marek Černocký <marek@manet.cz>, 2012.
msgid ""
msgstr ""
"Project-Id-Version: mutter\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-08-18 20:03+0000\n"
"PO-Revision-Date: 2013-08-20 08:50+0200\n"
"Last-Translator: Marek Černocký <marek@manet.cz>\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-24 20:55+0200\n"
"Last-Translator: Petr Kovar <pknbe@volny.cz>\n"
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
"Language: cs\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
"X-Generator: Gtranslator 2.91.6\n"
"X-Generator: Virtaal 0.7.1\n"
"X-Project-Style: gnome\n"
#: ../src/50-mutter-navigation.xml.in.h:1
@ -187,8 +186,7 @@ msgstr "Přepnout výskyt okna na všech plochách nebo jen na jedné"
#: ../src/50-mutter-windows.xml.in.h:13
msgid "Raise window if covered, otherwise lower it"
msgstr ""
"Přenést okno do popředí, pokud je zakryté, jinak jej odsunout do pozadí"
msgstr "Přenést okno do popředí, pokud je zakryté, jinak jej odsunout do pozadí"
#: ../src/50-mutter-windows.xml.in.h:14
msgid "Raise window above other windows"
@ -216,14 +214,14 @@ msgstr "Zobrazit rozdělení napravo"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: ../src/compositor/compositor.c:589
#: ../src/compositor/compositor.c:568
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
"\"."
msgstr "Jiný kompozitní správce již běží na obrazovce %i displeje „%s“."
#: ../src/compositor/meta-background.c:1076
#: ../src/compositor/meta-background.c:1191
msgid "background texture could not be created from file"
msgstr "textura pozadí nemohla být ze souboru vytvořena"
@ -261,17 +259,17 @@ msgstr "_Počkat"
msgid "_Force Quit"
msgstr "_Vynutit ukončení"
#: ../src/core/display.c:421
#: ../src/core/display.c:401
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Schází rozšíření %s vyžadované funkcemi kompozitoru"
#: ../src/core/display.c:513
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Nelze otevřít displej X Window System „%s“\n"
#: ../src/core/keybindings.c:1136
#: ../src/core/keybindings.c:935
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -279,8 +277,9 @@ msgid ""
msgstr ""
"Klávesu %s s modifikátory %x již jako zkratku používá nějaký jiný program\n"
#: ../src/core/keybindings.c:1333
#: ../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“ není platný akcelerátor\n"
@ -321,19 +320,6 @@ msgstr ""
"Nelze najít motiv! Ujistěte se prosím, že existuje %s a obsahuje obvyklé "
"motivy.\n"
#: ../src/core/monitor.c:711
msgid "Built-in display"
msgstr "Vestavěný 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 %s"
msgstr "Neznámý %s"
#: ../src/core/mutter.c:40
#, c-format
msgid ""
@ -358,7 +344,7 @@ msgstr "Vypíše verzi"
msgid "Mutter plugin to use"
msgstr "Zásuvný modul Mutter, který se má použít"
#: ../src/core/prefs.c:1202
#: ../src/core/prefs.c:1095
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -366,12 +352,12 @@ msgstr ""
"Bylo zakázáno obcházení chyb aplikací. Některé aplikace se možná nebudou "
"chovat správně.\n"
#: ../src/core/prefs.c:1277
#: ../src/core/prefs.c:1170
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Nelze zpracovat popis písma „%s“ v klíči GSettings %s\n"
#: ../src/core/prefs.c:1343
#: ../src/core/prefs.c:1236
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -380,7 +366,7 @@ msgstr ""
"„%s“ nalezené v databázi nastavení není platnou hodnotou modifikátoru "
"tlačítka myši\n"
#: ../src/core/prefs.c:1909
#: ../src/core/prefs.c:1788
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@ -389,17 +375,17 @@ msgstr ""
"„%s“ nalezené v databázi nastavení není platnou hodnotou klávesové zkratky "
"„%s“\n"
#: ../src/core/prefs.c:1999
#: ../src/core/prefs.c:1887
#, c-format
msgid "Workspace %d"
msgstr "Plocha %d"
#: ../src/core/screen.c:534
#: ../src/core/screen.c:691
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Obrazovka %d na displeji „%s“ je neplatná\n"
#: ../src/core/screen.c:550
#: ../src/core/screen.c:707
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@ -408,18 +394,18 @@ msgstr ""
"Obrazovka %d na displeji „%s“ již správce oken má; zkuste prosím nahradit "
"aktuálního správce oken pomocí přepínače --replace.\n"
#: ../src/core/screen.c:577
#: ../src/core/screen.c:734
#, c-format
msgid ""
"Could not acquire window manager selection on screen %d display \"%s\"\n"
msgstr "Nelze získat výběr správce oken na obrazovce %d displeje „%s“\n"
#: ../src/core/screen.c:655
#: ../src/core/screen.c:812
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "Obrazovka %d na displeji „%s“ již má správce oken\n"
#: ../src/core/screen.c:846
#: ../src/core/screen.c:998
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Nelze uvolnit obrazovku %d na displeji „%s“\n"
@ -494,7 +480,8 @@ msgstr "Nelze provést fdopen() soubor záznamu %s: %s\n"
msgid "Opened log file %s\n"
msgstr "Otevřen soubor záznamu %s\n"
#: ../src/core/util.c:119
#: ../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 bylo přeloženo bez podpory podrobného režimu\n"
@ -502,20 +489,20 @@ msgstr "Mutter bylo přeloženo bez podpory podrobného režimu\n"
msgid "Window manager: "
msgstr "Správce oken: "
#: ../src/core/util.c:414
#: ../src/core/util.c:412
msgid "Bug in window manager: "
msgstr "Chyba ve správci oken: "
#: ../src/core/util.c:445
#: ../src/core/util.c:443
msgid "Window manager warning: "
msgstr "Varování správce oken: "
#: ../src/core/util.c:473
#: ../src/core/util.c:471
msgid "Window manager error: "
msgstr "Chyba správce oken: "
#. first time through
#: ../src/core/window.c:7533
#: ../src/core/window.c:7596
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -531,7 +518,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8257
#: ../src/core/window.c:8320
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -541,22 +528,22 @@ msgstr ""
"velikost, ale nastavuje min. velikost %d × %d a max. velikost %d × %d; to "
"nedává smysl.\n"
#: ../src/core/window-props.c:347
#: ../src/core/window-props.c:318
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "Aplikace nastavila neplatný _NET_WM_PID %lu\n"
#: ../src/core/window-props.c:463
#: ../src/core/window-props.c:434
#, c-format
msgid "%s (on %s)"
msgstr "%s (na %s)"
#: ../src/core/window-props.c:1546
#: ../src/core/window-props.c:1517
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "Neplatné okno WM_TRANSIENT_FOR 0x%lx specifikováno pro %s.\n"
#: ../src/core/window-props.c:1557
#: ../src/core/window-props.c:1528
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "Okno WM_TRANSIENT_FOR 0x%lx by vytvořilo smyčku pro %s.\n"
@ -720,104 +707,109 @@ msgstr "Vybrat okno z překryvné nabídky tabulátoru"
msgid "Cancel tab popup"
msgstr "Zrušit překryvné okno tabulátoru"
#: ../src/tools/mutter-message.c:123
#, c-format
msgid "Usage: %s\n"
msgstr "Použití: %s\n"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:67
#: ../src/ui/menu.c:69
msgid "Mi_nimize"
msgstr "Mi_nimalizovat"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:69
#: ../src/ui/menu.c:71
msgid "Ma_ximize"
msgstr "Ma_ximalizovat"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:71
#: ../src/ui/menu.c:73
msgid "Unma_ximize"
msgstr "Zrušit ma_ximalizaci"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:73
#: ../src/ui/menu.c:75
msgid "Roll _Up"
msgstr "Sv_inout"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:75
#: ../src/ui/menu.c:77
msgid "_Unroll"
msgstr "Rozv_inout"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:77
#: ../src/ui/menu.c:79
msgid "_Move"
msgstr "_Přesunout"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:79
#: ../src/ui/menu.c:81
msgid "_Resize"
msgstr "Z_měnit velikost"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:81
#: ../src/ui/menu.c:83
msgid "Move Titlebar On_screen"
msgstr "Přesunout záhlaví okna na _obrazovku"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
msgid "Always on _Top"
msgstr "_Vždy navrchu"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:88
#: ../src/ui/menu.c:90
msgid "_Always on Visible Workspace"
msgstr "Vžd_y na viditelné ploše"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:90
#: ../src/ui/menu.c:92
msgid "_Only on This Workspace"
msgstr "_Jen na této ploše"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:92
#: ../src/ui/menu.c:94
msgid "Move to Workspace _Left"
msgstr "Přesunout na plochu v_levo"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:94
#: ../src/ui/menu.c:96
msgid "Move to Workspace R_ight"
msgstr "Přesunout na plochu vp_ravo"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:96
#: ../src/ui/menu.c:98
msgid "Move to Workspace _Up"
msgstr "Přesunout na plochu na_hoře"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:98
#: ../src/ui/menu.c:100
msgid "Move to Workspace _Down"
msgstr "Přesunout na plochu _dole"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:102
#: ../src/ui/menu.c:104
msgid "_Close"
msgstr "_Zavřít"
#: ../src/ui/menu.c:202
#: ../src/ui/menu.c:204
#, c-format
msgid "Workspace %d%n"
msgstr "Plocha %d%n"
#: ../src/ui/menu.c:212
#: ../src/ui/menu.c:214
#, c-format
msgid "Workspace 1_0"
msgstr "Plocha 1_0"
#: ../src/ui/menu.c:214
#: ../src/ui/menu.c:216
#, c-format
msgid "Workspace %s%d"
msgstr "Plocha %s%d"
#: ../src/ui/menu.c:384
#: ../src/ui/menu.c:397
msgid "Move to Another _Workspace"
msgstr "Přes_unout na jinou plochu"
@ -993,8 +985,8 @@ msgid ""
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
"where NORMAL is the state; could not parse \"%s\""
msgstr ""
"Specifikace GTK barvy musí mít stav v hranatých závorkách, např. gtk:"
"fg[NORMAL], kde NORMAL je stav; nelze analyzovat „%s“"
"Specifikace GTK barvy musí mít stav v hranatých závorkách, např. gtk:fg"
"[NORMAL], kde NORMAL je stav; nelze analyzovat „%s“"
#: ../src/ui/theme.c:1292
#, c-format
@ -1002,8 +994,8 @@ msgid ""
"GTK color specification must have a close bracket after the state, e.g. gtk:"
"fg[NORMAL] where NORMAL is the state; could not parse \"%s\""
msgstr ""
"Specifikace GTK barvy musí mít za stavem hranatou závorku, např. gtk:"
"fg[NORMAL], kde NORMAL je stav; nelze analyzovat „%s“"
"Specifikace GTK barvy musí mít za stavem hranatou závorku, např. gtk:fg"
"[NORMAL], kde NORMAL je stav; nelze analyzovat „%s“"
#: ../src/ui/theme.c:1303
#, c-format
@ -1173,18 +1165,18 @@ msgid ""
msgstr ""
"Chybí <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"cokoliv\"/>"
#: ../src/ui/theme.c:5082
#: ../src/ui/theme.c:5084
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Nelze načíst motiv „%s“: %s\n"
#: ../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
#: ../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 "Není nastaveno <%s> motivu „%s“"
#: ../src/ui/theme.c:5254
#: ../src/ui/theme.c:5256
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@ -1193,7 +1185,7 @@ msgstr ""
"U typu okna „%s“ motivu „%s“ není nastaven typ rámu, přidejte prosím prvek "
"<window type=\"%s\" style_set=\"cokoliv\"/>"
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
#: ../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"
@ -1201,7 +1193,7 @@ msgstr ""
"Uživatelem definované konstanty musí začínat velkým písmenem; „%s“ toto "
"nesplňuje"
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
#: ../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 "Konstanta „%s“ již byla definována"
@ -1580,4 +1572,205 @@ msgstr "<%s> u tohoto motivu definováno dvakrát"
#: ../src/ui/theme-parser.c:4336
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "Nelze nalézt platný soubor motivu %s\n"
msgstr "Nelze nalézt platný soubor motivu %s\n"
#: ../src/ui/theme-viewer.c:99
msgid "_Windows"
msgstr "_Okna"
#: ../src/ui/theme-viewer.c:100
msgid "_Dialog"
msgstr "_Dialogové okno"
#: ../src/ui/theme-viewer.c:101
msgid "_Modal dialog"
msgstr "_Modální dialogové okno"
#: ../src/ui/theme-viewer.c:102
msgid "_Utility"
msgstr "_Nástroje"
#: ../src/ui/theme-viewer.c:103
msgid "_Splashscreen"
msgstr "_Spouštěcí obrazovka"
#: ../src/ui/theme-viewer.c:104
msgid "_Top dock"
msgstr "_Horní dok"
#: ../src/ui/theme-viewer.c:105
msgid "_Bottom dock"
msgstr "Dolní do_k"
#: ../src/ui/theme-viewer.c:106
msgid "_Left dock"
msgstr "_Levý dok"
#: ../src/ui/theme-viewer.c:107
msgid "_Right dock"
msgstr "P_ravý dok"
#: ../src/ui/theme-viewer.c:108
msgid "_All docks"
msgstr "_Všechny doky"
#: ../src/ui/theme-viewer.c:109
msgid "Des_ktop"
msgstr "Pra_covní prostředí"
#: ../src/ui/theme-viewer.c:115
msgid "Open another one of these windows"
msgstr "Otevřít další takové okno"
#: ../src/ui/theme-viewer.c:117
msgid "This is a demo button with an 'open' icon"
msgstr "Toto je demonstrační tlačítko s ikonou „otevřít“"
#: ../src/ui/theme-viewer.c:119
msgid "This is a demo button with a 'quit' icon"
msgstr "Toto je demonstrační tlačítko s ikonou „ukončit“"
#: ../src/ui/theme-viewer.c:248
msgid "This is a sample message in a sample dialog"
msgstr "Toto je ukázková zpráva v ukázkovém dialogu"
#: ../src/ui/theme-viewer.c:328
#, c-format
msgid "Fake menu item %d\n"
msgstr "Falešná položka nabídky %d\n"
#: ../src/ui/theme-viewer.c:363
msgid "Border-only window"
msgstr "Okno jen s okrajem"
#: ../src/ui/theme-viewer.c:365
msgid "Bar"
msgstr "Lišta"
#: ../src/ui/theme-viewer.c:382
msgid "Normal Application Window"
msgstr "Normální okno aplikace"
#: ../src/ui/theme-viewer.c:386
msgid "Dialog Box"
msgstr "Dialogové okno"
#: ../src/ui/theme-viewer.c:390
msgid "Modal Dialog Box"
msgstr "Modální dialogové okno"
#: ../src/ui/theme-viewer.c:394
msgid "Utility Palette"
msgstr "Paleta nástrojů"
#: ../src/ui/theme-viewer.c:398
msgid "Torn-off Menu"
msgstr "Odtržení nabídky"
#: ../src/ui/theme-viewer.c:402
msgid "Border"
msgstr "Okraj"
#: ../src/ui/theme-viewer.c:406
msgid "Attached Modal Dialog"
msgstr "Připojené modální dialogové okno"
#: ../src/ui/theme-viewer.c:737
#, c-format
msgid "Button layout test %d"
msgstr "Test rozložení tlačítek %d"
#: ../src/ui/theme-viewer.c:766
#, c-format
msgid "%g milliseconds to draw one window frame"
msgstr "%g milisekund na nakreslení jednoho rámu okna"
#: ../src/ui/theme-viewer.c:811
#, c-format
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
msgstr "Použití: metacity-theme-viewer [NÁZEVMOTIVU]\n"
#: ../src/ui/theme-viewer.c:818
#, c-format
msgid "Error loading theme: %s\n"
msgstr "Chyba při načítání motivu: %s\n"
#: ../src/ui/theme-viewer.c:824
#, c-format
msgid "Loaded theme \"%s\" in %g seconds\n"
msgstr "Načten motiv „%s“ za %g sekund\n"
#: ../src/ui/theme-viewer.c:869
msgid "Normal Title Font"
msgstr "Normální písmo nadpisu"
#: ../src/ui/theme-viewer.c:875
msgid "Small Title Font"
msgstr "Malé písmo nadpisu"
#: ../src/ui/theme-viewer.c:881
msgid "Large Title Font"
msgstr "Velké písmo nadpisu"
#: ../src/ui/theme-viewer.c:886
msgid "Button Layouts"
msgstr "Rozložení tlačítek"
#: ../src/ui/theme-viewer.c:891
msgid "Benchmark"
msgstr "Test výkonnosti"
#: ../src/ui/theme-viewer.c:947
msgid "Window Title Goes Here"
msgstr "Sem patří nadpis okna"
#: ../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 ""
"Nakresleno %d rámů za %g sekund na straně klienta (%g milisekund na rám) a "
"%g sekund reálného času včetně zdrojů serveru X (%g milisekund na rám)\n"
#: ../src/ui/theme-viewer.c:1273
msgid "position expression test returned TRUE but set error"
msgstr "test výrazu umístění vrátil TRUE, ale nastavil chybu"
#: ../src/ui/theme-viewer.c:1275
msgid "position expression test returned FALSE but didn't set error"
msgstr "test výrazu umístění vrátil FALSE, ale nenastavil chybu"
#: ../src/ui/theme-viewer.c:1279
msgid "Error was expected but none given"
msgstr "Byla očekávána chyba, ale nebyla přijata"
#: ../src/ui/theme-viewer.c:1281
#, c-format
msgid "Error %d was expected but %d given"
msgstr "Byla očekávána chyba %d, ale bylo přijato %d"
#: ../src/ui/theme-viewer.c:1287
#, c-format
msgid "Error not expected but one was returned: %s"
msgstr "Chyba nebyla očekávána, ale byla vrácena: %s"
#: ../src/ui/theme-viewer.c:1291
#, c-format
msgid "x value was %d, %d was expected"
msgstr "Hodnota x byla %d, bylo očekáváno %d"
#: ../src/ui/theme-viewer.c:1294
#, c-format
msgid "y value was %d, %d was expected"
msgstr "Hodnota y byla %d, bylo očekáváno %d"
#: ../src/ui/theme-viewer.c:1359
#, c-format
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
msgstr "Zpracováno %d výrazů souřadnic za %g sekund (průměr %g sekund)\n"
#, fuzzy
#~ msgid "Minimize window"
#~ msgstr "Minimalizovat okno"

540
po/da.po

File diff suppressed because it is too large Load Diff

668
po/el.po

File diff suppressed because it is too large Load Diff

1125
po/es.po

File diff suppressed because it is too large Load Diff

517
po/fr.po

File diff suppressed because it is too large Load Diff

3214
po/ga.po

File diff suppressed because it is too large Load Diff

500
po/gl.po

File diff suppressed because it is too large Load Diff

993
po/he.po

File diff suppressed because it is too large Load Diff

398
po/hu.po
View File

@ -6,21 +6,19 @@
# Gabor Sari <saga at externet dot hu>, 2003.
# Laszlo Dvornik <dvornik at gnome dot hu>, 2004.
# Gabor Kelemen <kelemeng at gnome dot hu>, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013.
# Balázs Úr <urbalazs at gmail dot com>, 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-08-18 20:03+0000\n"
"PO-Revision-Date: 2013-08-25 10:26+0200\n"
"Last-Translator: Balázs Úr <urbalazs at gmail dot com>\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-03-21 00:15+0100\n"
"PO-Revision-Date: 2013-03-21 00:14+0100\n"
"Last-Translator: Gabor Kelemen <kelemeng at gnome dot hu>\n"
"Language-Team: Hungarian <gnome-hu-list at gnome dot org>\n"
"Language: hu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: Lokalize 1.2\n"
"X-Generator: Lokalize 1.4\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../src/50-mutter-navigation.xml.in.h:1
@ -213,7 +211,7 @@ msgstr "Jobb oldali felosztás megjelenítése"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: ../src/compositor/compositor.c:589
#: ../src/compositor/compositor.c:568
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
@ -222,7 +220,7 @@ msgstr ""
"Már fut egy másik kompozitáláskezelő a(z) %i képernyőn a(z) „%s” "
"megjelenítőn."
#: ../src/compositor/meta-background.c:1076
#: ../src/compositor/meta-background.c:1191
msgid "background texture could not be created from file"
msgstr "nem hozható létre a háttér textúrája fájlból"
@ -260,17 +258,17 @@ msgstr "Vá_rakozás"
msgid "_Force Quit"
msgstr "_Erőltetett kilépés"
#: ../src/core/display.c:421
#: ../src/core/display.c:401
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Hiányzik a kompozit ablakkezeléshez szükséges %s kiterjesztés"
#: ../src/core/display.c:513
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Nem sikerült megnyitni a(z) „%s” X Window rendszer képernyőt\n"
#: ../src/core/keybindings.c:1136
#: ../src/core/keybindings.c:935
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -279,7 +277,7 @@ msgstr ""
"Valamely másik program már használja a(z) %s billentyűt %x módosítókkal "
"összekötve\n"
#: ../src/core/keybindings.c:1333
#: ../src/core/keybindings.c:1135
#, c-format
msgid "\"%s\" is not a valid accelerator\n"
msgstr "„%s” érvénytelen hívóbetű\n"
@ -321,20 +319,6 @@ msgstr ""
"Nem található téma! Bizonyosodjon meg róla hogy a(z) %s létezik és "
"tartalmazza a szokásos témákat.\n"
#: ../src/core/monitor.c:711
msgid "Built-in display"
msgstr "Beépített kijelző"
#. 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 "Ismeretlen %s"
#: ../src/core/mutter.c:40
#, c-format
msgid ""
@ -358,7 +342,7 @@ msgstr "Verzió kinyomtatása"
msgid "Mutter plugin to use"
msgstr "Használandó Mutter bővítmény"
#: ../src/core/prefs.c:1202
#: ../src/core/prefs.c:1095
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -366,14 +350,14 @@ msgstr ""
"A hibás alkalmazások hibáinak megkerülése nincs engedélyezve. Néhány "
"alkalmazás lehet, hogy nem fog helyesen működni.\n"
#: ../src/core/prefs.c:1277
#: ../src/core/prefs.c:1170
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr ""
"Nem sikerült feldolgozni a(z) „%s” betűkészlet leírását a(z) „%s” GSettings "
"kulcsból\n"
#: ../src/core/prefs.c:1343
#: ../src/core/prefs.c:1236
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -382,7 +366,7 @@ msgstr ""
"A konfigurációs adatbázisban talált „%s” érvénytelen érték az egérgomb "
"módosítóhoz\n"
#: ../src/core/prefs.c:1909
#: ../src/core/prefs.c:1788
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@ -391,17 +375,17 @@ msgstr ""
"A konfigurációs adatbázisban talált „%s” nem érvényes érték a következő "
"billentyűkombinációhoz: „%s”\n"
#: ../src/core/prefs.c:1999
#: ../src/core/prefs.c:1887
#, c-format
msgid "Workspace %d"
msgstr "%d. munkaterület"
#: ../src/core/screen.c:534
#: ../src/core/screen.c:691
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "A(z) %d képernyő a(z) „%s” megjelenítőn érvénytelen\n"
#: ../src/core/screen.c:550
#: ../src/core/screen.c:707
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@ -410,7 +394,7 @@ msgstr ""
"A(z) %d képernyő a(z) „%s” megjelenítőn már rendelkezik egy ablakkezelővel; "
"próbálja a --replace opcióval helyettesíteni a jelenlegi ablakkezelőt.\n"
#: ../src/core/screen.c:577
#: ../src/core/screen.c:734
#, c-format
msgid ""
"Could not acquire window manager selection on screen %d display \"%s\"\n"
@ -418,12 +402,12 @@ msgstr ""
"Nem sikerült beolvasni az ablakkezelő kiválasztását a(z) %d képernyőn a(z) "
"„%s” megjelenítőn\n"
#: ../src/core/screen.c:655
#: ../src/core/screen.c:812
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "A(z) %d képernyőnek a(z) „%s” megjelenítőn már van ablakkezelője\n"
#: ../src/core/screen.c:846
#: ../src/core/screen.c:998
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Nem sikerült elengedni a(z) %d képernyőt a(z) „%s” kijelzőn\n"
@ -500,7 +484,8 @@ msgstr "Nem sikerült megnyitni az fdopen()-nel a(z) „%s” naplófájlt: %s\n
msgid "Opened log file %s\n"
msgstr "%s naplófájl megnyitva\n"
#: ../src/core/util.c:119
#: ../src/core/util.c:119 ../src/tools/mutter-message.c:149
#, c-format
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "A Mutter ablakkezelőt a részletes mód támogatása nélkül fordították\n"
@ -508,20 +493,20 @@ msgstr "A Mutter ablakkezelőt a részletes mód támogatása nélkül fordítot
msgid "Window manager: "
msgstr "Ablakkezelő: "
#: ../src/core/util.c:414
#: ../src/core/util.c:412
msgid "Bug in window manager: "
msgstr "Hiba az ablakkezelőben: "
#: ../src/core/util.c:445
#: ../src/core/util.c:443
msgid "Window manager warning: "
msgstr "Figyelmeztetés az ablakkezelőtől: "
#: ../src/core/util.c:473
#: ../src/core/util.c:471
msgid "Window manager error: "
msgstr "Hibaüzenet az ablakkezelőtől: "
#. first time through
#: ../src/core/window.c:7533
#: ../src/core/window.c:7596
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -537,7 +522,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8257
#: ../src/core/window.c:8320
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -547,24 +532,24 @@ msgstr ""
"de mégis %d x %d minimális és %d x %d maximális értéket ad meg, amelynek így "
"nincs értelme.\n"
#: ../src/core/window-props.c:347
#: ../src/core/window-props.c:318
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "Az alkalmazás hibás _NET_WM_PID-értéket állított be: %lu\n"
#: ../src/core/window-props.c:463
#: ../src/core/window-props.c:434
#, c-format
msgid "%s (on %s)"
msgstr "%s (ezen: %s)"
#: ../src/core/window-props.c:1546
#: ../src/core/window-props.c:1517
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr ""
"Érvénytelen WM_TRANSIENT_FOR ablak (0x%lx) került megadásra a következőhöz: "
"%s.\n"
#: ../src/core/window-props.c:1557
#: ../src/core/window-props.c:1528
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr ""
@ -662,7 +647,7 @@ msgstr ""
#: ../src/org.gnome.mutter.gschema.xml.in.h:9
msgid "Workspaces only on primary"
msgstr "Munkaterületek csak az elsődlegesen"
msgstr "Munkaterületek csak az elsődlegese"
#: ../src/org.gnome.mutter.gschema.xml.in.h:10
msgid ""
@ -731,104 +716,109 @@ msgstr "Ablakok kiválasztása tab billentyűre felugró ablakból"
msgid "Cancel tab popup"
msgstr "Tab felugró kikapcsolása"
#: ../src/tools/mutter-message.c:123
#, c-format
msgid "Usage: %s\n"
msgstr "Használat: %s\n"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:67
#: ../src/ui/menu.c:69
msgid "Mi_nimize"
msgstr "Mi_nimalizálás"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:69
#: ../src/ui/menu.c:71
msgid "Ma_ximize"
msgstr "Ma_ximalizálás"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:71
#: ../src/ui/menu.c:73
msgid "Unma_ximize"
msgstr "_Eredeti méret"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:73
#: ../src/ui/menu.c:75
msgid "Roll _Up"
msgstr "_Felgördítés"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:75
#: ../src/ui/menu.c:77
msgid "_Unroll"
msgstr "_Legördítés"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:77
#: ../src/ui/menu.c:79
msgid "_Move"
msgstr "Át_helyezés"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:79
#: ../src/ui/menu.c:81
msgid "_Resize"
msgstr "Át_méretezés"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:81
#: ../src/ui/menu.c:83
msgid "Move Titlebar On_screen"
msgstr "_Címsor mozgatása a képernyőn"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
msgid "Always on _Top"
msgstr "Mindig _felül"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:88
#: ../src/ui/menu.c:90
msgid "_Always on Visible Workspace"
msgstr "Mindig a látható m_unkaterületen"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:90
#: ../src/ui/menu.c:92
msgid "_Only on This Workspace"
msgstr "_Csak ezen a munkaterületen"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:92
#: ../src/ui/menu.c:94
msgid "Move to Workspace _Left"
msgstr "Áthelyezés a bal ol_dali munkaterületre"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:94
#: ../src/ui/menu.c:96
msgid "Move to Workspace R_ight"
msgstr "Áthelyezés a j_obb oldali munkaterületre"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:96
#: ../src/ui/menu.c:98
msgid "Move to Workspace _Up"
msgstr "Áthelyezés a fel_ső munkaterületre"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:98
#: ../src/ui/menu.c:100
msgid "Move to Workspace _Down"
msgstr "Áthelyezés az _alsó munkaterületre"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:102
#: ../src/ui/menu.c:104
msgid "_Close"
msgstr "_Bezárás"
#: ../src/ui/menu.c:202
#: ../src/ui/menu.c:204
#, c-format
msgid "Workspace %d%n"
msgstr "%d%n. munkaterület"
#: ../src/ui/menu.c:212
#: ../src/ui/menu.c:214
#, c-format
msgid "Workspace 1_0"
msgstr "1_0. munkaterület"
#: ../src/ui/menu.c:214
#: ../src/ui/menu.c:216
#, c-format
msgid "Workspace %s%d"
msgstr "%s%d. munkaterület"
#: ../src/ui/menu.c:384
#: ../src/ui/menu.c:397
msgid "Move to Another _Workspace"
msgstr "Áthelyezés mási_k munkaterületre"
@ -1189,18 +1179,18 @@ msgid ""
msgstr ""
"Hiányzó <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"bármi\"/> elem"
#: ../src/ui/theme.c:5082
#: ../src/ui/theme.c:5084
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Hiba a(z) „%s” téma betöltése közben: %s\n"
#: ../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
#: ../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 "Nincs <%s> beállítva a(z) „%s” témához"
#: ../src/ui/theme.c:5254
#: ../src/ui/theme.c:5256
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@ -1209,7 +1199,7 @@ msgstr ""
"Nincs keretstílus beállítva a(z) „%s” ablaktípushoz a(z) „%s” témában, adjon "
"hozzá egy <window type=\"%s\" style_set=\"bármi\"/> elemet"
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
#: ../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"
@ -1217,7 +1207,7 @@ msgstr ""
"A felhasználó által meghatározott konstansoknak nagybetűvel kell kezdődniük, "
"a(z) „%s” nem ilyen"
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
#: ../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 "A(z) „%s” konstans már definiálva van"
@ -1610,154 +1600,206 @@ msgstr "<%s> kétszer lett megadva ehhez a témához"
msgid "Failed to find a valid file for theme %s\n"
msgstr "Nem található érvényes fájl a következő témához: %s\n"
#~ msgid "Usage: %s\n"
#~ msgstr "Használat: %s\n"
#: ../src/ui/theme-viewer.c:99
msgid "_Windows"
msgstr "_Ablakok"
#~ msgid "_Windows"
#~ msgstr "_Ablakok"
#: ../src/ui/theme-viewer.c:100
msgid "_Dialog"
msgstr "_Párbeszédablak"
#~ msgid "_Dialog"
#~ msgstr "_Párbeszédablak"
#: ../src/ui/theme-viewer.c:101
msgid "_Modal dialog"
msgstr "_Kizárólagos párbeszédablak"
#~ msgid "_Modal dialog"
#~ msgstr "_Kizárólagos párbeszédablak"
#: ../src/ui/theme-viewer.c:102
msgid "_Utility"
msgstr "_Segédprogram"
#~ msgid "_Utility"
#~ msgstr "_Segédprogram"
#: ../src/ui/theme-viewer.c:103
msgid "_Splashscreen"
msgstr "_Indítóképernyő"
#~ msgid "_Splashscreen"
#~ msgstr "_Indítóképernyő"
#: ../src/ui/theme-viewer.c:104
msgid "_Top dock"
msgstr "_Felső dokk"
#~ msgid "_Top dock"
#~ msgstr "_Felső dokk"
#: ../src/ui/theme-viewer.c:105
msgid "_Bottom dock"
msgstr "_Alsó dokk"
#~ msgid "_Bottom dock"
#~ msgstr "_Alsó dokk"
#: ../src/ui/theme-viewer.c:106
msgid "_Left dock"
msgstr "_Bal dokk"
#~ msgid "_Left dock"
#~ msgstr "_Bal dokk"
#: ../src/ui/theme-viewer.c:107
msgid "_Right dock"
msgstr "_Jobb dokk"
#~ msgid "_Right dock"
#~ msgstr "_Jobb dokk"
#: ../src/ui/theme-viewer.c:108
msgid "_All docks"
msgstr "Össz_es dokk"
#~ msgid "_All docks"
#~ msgstr "Össz_es dokk"
#: ../src/ui/theme-viewer.c:109
msgid "Des_ktop"
msgstr "_Asztal"
#~ msgid "Des_ktop"
#~ msgstr "_Asztal"
#: ../src/ui/theme-viewer.c:115
msgid "Open another one of these windows"
msgstr "Egy újabb példány megnyitása ezekből az ablakokból"
#~ msgid "Open another one of these windows"
#~ msgstr "Egy újabb példány megnyitása ezekből az ablakokból"
#: ../src/ui/theme-viewer.c:117
msgid "This is a demo button with an 'open' icon"
msgstr "Ez egy mintagomb a „Megnyitás” ikonnal"
#~ msgid "This is a demo button with an 'open' icon"
#~ msgstr "Ez egy mintagomb a „Megnyitás” ikonnal"
#: ../src/ui/theme-viewer.c:119
msgid "This is a demo button with a 'quit' icon"
msgstr "Ez egy mintagomb a „Kilépés” ikonnal"
#~ msgid "This is a demo button with a 'quit' icon"
#~ msgstr "Ez egy mintagomb a „Kilépés” ikonnal"
#: ../src/ui/theme-viewer.c:248
msgid "This is a sample message in a sample dialog"
msgstr "Ez egy mintaüzenet egy minta párbeszédben"
#~ msgid "This is a sample message in a sample dialog"
#~ msgstr "Ez egy mintaüzenet egy minta párbeszédben"
#: ../src/ui/theme-viewer.c:328
#, c-format
msgid "Fake menu item %d\n"
msgstr "%d. hamis menüelem\n"
#~ msgid "Fake menu item %d\n"
#~ msgstr "%d. hamis menüelem\n"
#: ../src/ui/theme-viewer.c:363
msgid "Border-only window"
msgstr "Csak keretes ablak"
#~ msgid "Border-only window"
#~ msgstr "Csak keretes ablak"
#: ../src/ui/theme-viewer.c:365
msgid "Bar"
msgstr "Sáv"
#~ msgid "Bar"
#~ msgstr "Sáv"
#: ../src/ui/theme-viewer.c:382
msgid "Normal Application Window"
msgstr "Normál alkalmazásablak"
#~ msgid "Normal Application Window"
#~ msgstr "Normál alkalmazásablak"
#: ../src/ui/theme-viewer.c:386
msgid "Dialog Box"
msgstr "Párbeszédablak"
#~ msgid "Dialog Box"
#~ msgstr "Párbeszédablak"
#: ../src/ui/theme-viewer.c:390
msgid "Modal Dialog Box"
msgstr "Kizárólagos párbeszéd doboz"
#~ msgid "Modal Dialog Box"
#~ msgstr "Kizárólagos párbeszéd doboz"
#: ../src/ui/theme-viewer.c:394
msgid "Utility Palette"
msgstr "Eszközpaletta"
#~ msgid "Utility Palette"
#~ msgstr "Eszközpaletta"
#: ../src/ui/theme-viewer.c:398
msgid "Torn-off Menu"
msgstr "Leválasztott menü"
#~ msgid "Torn-off Menu"
#~ msgstr "Leválasztott menü"
#: ../src/ui/theme-viewer.c:402
msgid "Border"
msgstr "Szegély"
#~ msgid "Border"
#~ msgstr "Szegély"
#: ../src/ui/theme-viewer.c:406
msgid "Attached Modal Dialog"
msgstr "Csatolt kizárólagos párbeszédablak"
#~ msgid "Attached Modal Dialog"
#~ msgstr "Csatolt kizárólagos párbeszédablak"
#: ../src/ui/theme-viewer.c:737
#, c-format
msgid "Button layout test %d"
msgstr "Gombelrendezés teszt %d"
#~ msgid "Button layout test %d"
#~ msgstr "Gombelrendezés teszt %d"
#: ../src/ui/theme-viewer.c:766
#, c-format
msgid "%g milliseconds to draw one window frame"
msgstr "%g ezredmásodpercig tartott egy ablakkeret kirajzolása"
#~ msgid "%g milliseconds to draw one window frame"
#~ msgstr "%g ezredmásodpercig tartott egy ablakkeret kirajzolása"
#: ../src/ui/theme-viewer.c:811
#, c-format
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
msgstr "Használat: metacity-theme-viewer [TÉMANÉV]\n"
#~ msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
#~ msgstr "Használat: metacity-theme-viewer [TÉMANÉV]\n"
#: ../src/ui/theme-viewer.c:818
#, c-format
msgid "Error loading theme: %s\n"
msgstr "Hiba történt a téma betöltése közben: %s\n"
#~ msgid "Error loading theme: %s\n"
#~ msgstr "Hiba történt a téma betöltése közben: %s\n"
#: ../src/ui/theme-viewer.c:824
#, c-format
msgid "Loaded theme \"%s\" in %g seconds\n"
msgstr "A(z) „%s” téma %g másodperc alatt betöltve\n"
#~ msgid "Loaded theme \"%s\" in %g seconds\n"
#~ msgstr "A(z) „%s” téma %g másodperc alatt betöltve\n"
#: ../src/ui/theme-viewer.c:869
msgid "Normal Title Font"
msgstr "Normál cím betűtípus"
#~ msgid "Normal Title Font"
#~ msgstr "Normál cím betűtípus"
#: ../src/ui/theme-viewer.c:875
msgid "Small Title Font"
msgstr "Kicsi cím betűtípus"
#~ msgid "Small Title Font"
#~ msgstr "Kicsi cím betűtípus"
#: ../src/ui/theme-viewer.c:881
msgid "Large Title Font"
msgstr "Nagy cím betűtípus"
#~ msgid "Large Title Font"
#~ msgstr "Nagy cím betűtípus"
#: ../src/ui/theme-viewer.c:886
msgid "Button Layouts"
msgstr "Gombelrendezések"
#~ msgid "Button Layouts"
#~ msgstr "Gombelrendezések"
#: ../src/ui/theme-viewer.c:891
msgid "Benchmark"
msgstr "Teljesítményteszt"
#~ msgid "Benchmark"
#~ msgstr "Teljesítményteszt"
#: ../src/ui/theme-viewer.c:947
msgid "Window Title Goes Here"
msgstr "Ide kerül az ablak címe"
#~ msgid "Window Title Goes Here"
#~ msgstr "Ide kerül az ablak címe"
#: ../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 keret kirajzolása %g kliens-oldali másodperc alatt (%g ezredmásodperc "
"képkeretenként) és %g összes idő beleértve az X szerver erőforrásokat (%g "
"ezredmásodperc képkeretenként)\n"
#~ 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 keret kirajzolása %g kliens-oldali másodperc alatt (%g ezredmásodperc "
#~ "képkeretenként) és %g összes idő beleértve az X szerver erőforrásokat (%g "
#~ "ezredmásodperc képkeretenként)\n"
#: ../src/ui/theme-viewer.c:1273
msgid "position expression test returned TRUE but set error"
msgstr "a pozíció kifejezés teszt IGAZ értéket adott vissza, de hiba történt"
#~ msgid "position expression test returned TRUE but set error"
#~ msgstr ""
#~ "a pozíció kifejezés teszt IGAZ értéket adott vissza, de hiba történt"
#: ../src/ui/theme-viewer.c:1275
msgid "position expression test returned FALSE but didn't set error"
msgstr ""
"a pozíció kifejezés teszt HAMIS értéket adott vissza, de nem történt hiba"
#~ msgid "position expression test returned FALSE but didn't set error"
#~ msgstr ""
#~ "a pozíció kifejezés teszt HAMIS értéket adott vissza, de nem történt hiba"
#: ../src/ui/theme-viewer.c:1279
msgid "Error was expected but none given"
msgstr "Hibát vártunk, de nem történt egy sem"
#~ msgid "Error was expected but none given"
#~ msgstr "Hibát vártunk, de nem történt egy sem"
#: ../src/ui/theme-viewer.c:1281
#, c-format
msgid "Error %d was expected but %d given"
msgstr "A(z) %d hibát vártuk, de a(z) %d hiba következett be"
#~ msgid "Error %d was expected but %d given"
#~ msgstr "A(z) %d hibát vártuk, de a(z) %d hiba következett be"
#: ../src/ui/theme-viewer.c:1287
#, c-format
msgid "Error not expected but one was returned: %s"
msgstr "Nem várt hiba következett be: %s"
#~ msgid "Error not expected but one was returned: %s"
#~ msgstr "Nem várt hiba következett be: %s"
#: ../src/ui/theme-viewer.c:1291
#, c-format
msgid "x value was %d, %d was expected"
msgstr "x értéke %d volt, de a várt érték %d volt"
#~ msgid "x value was %d, %d was expected"
#~ msgstr "x értéke %d volt, de a várt érték %d volt"
#: ../src/ui/theme-viewer.c:1294
#, c-format
msgid "y value was %d, %d was expected"
msgstr "y értéke %d volt, de a várt érték %d volt"
#~ msgid "y value was %d, %d was expected"
#~ msgstr "y értéke %d volt, de a várt érték %d volt"
#~ msgid ""
#~ "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
#~ msgstr ""
#~ "A %d koordináta kifejezések %g másodperc alatt lettek feldolgozva "
#~ "(átlagosan %g másodperc)\n"
#: ../src/ui/theme-viewer.c:1359
#, c-format
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
msgstr ""
"A %d koordináta kifejezések %g másodperc alatt lettek feldolgozva (átlagosan "
"%g másodperc)\n"
#, fuzzy
#~ msgid "Minimize window"

606
po/it.po

File diff suppressed because it is too large Load Diff

443
po/lt.po
View File

@ -13,8 +13,8 @@ msgstr ""
"Project-Id-Version: lt\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-08-18 20:03+0000\n"
"PO-Revision-Date: 2013-08-28 23:06+0300\n"
"POT-Creation-Date: 2013-03-01 15:50+0000\n"
"PO-Revision-Date: 2013-03-02 22:57+0200\n"
"Last-Translator: Aurimas Černius <aurisc4@gmail.com>\n"
"Language-Team: Lietuvių <gnome-lt@lists.akl.lt>\n"
"Language: lt\n"
@ -216,18 +216,18 @@ msgstr "Rodyti skyrimą dešinėje"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: ../src/compositor/compositor.c:589
#: ../src/compositor/compositor.c:507
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
"\"."
msgstr "Kita kompozicijos valdyklė jau veikia ekrane %i vaizduoklyje „%s“."
#: ../src/compositor/meta-background.c:1076
#: ../src/compositor/meta-background.c:1111
msgid "background texture could not be created from file"
msgstr "nepavyko sukurti fono tekstūros iš failo"
#: ../src/core/bell.c:322
#: ../src/core/bell.c:320
msgid "Bell event"
msgstr "Skambučio įvykis"
@ -259,17 +259,17 @@ msgstr "_Laukti"
msgid "_Force Quit"
msgstr "_Priverstinai išeiti"
#: ../src/core/display.c:421
#: ../src/core/display.c:401
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Trūksta %s priedo, reikalingo komponavimui"
#: ../src/core/display.c:513
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Nepavyko atverti X Window sistemos ekrano „%s“\n"
#: ../src/core/keybindings.c:1136
#: ../src/core/keybindings.c:929
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -278,41 +278,42 @@ msgstr ""
"Kažkokia kita programa jau naudoja %s klavišą su modifikatoriais %x kaip "
"susiejimą\n"
#: ../src/core/keybindings.c:1333
#: ../src/core/keybindings.c:1129
#, c-format
#| msgid "\"%s\" is not a valid value for focus attribute"
msgid "\"%s\" is not a valid accelerator\n"
msgstr "„%s“ yra nepriimtinas spartusis klavišas\n"
#: ../src/core/main.c:197
#: ../src/core/main.c:196
msgid "Disable connection to session manager"
msgstr "Išjungti susijungimą su sesijos valdykle"
#: ../src/core/main.c:203
#: ../src/core/main.c:202
msgid "Replace the running window manager"
msgstr "Pakeisti veikiančią langų valdyklę"
#: ../src/core/main.c:209
#: ../src/core/main.c:208
msgid "Specify session management ID"
msgstr "Nurodyti sesijos valdymo ID"
#: ../src/core/main.c:214
#: ../src/core/main.c:213
msgid "X Display to use"
msgstr "Naudotinas X ekranas"
#: ../src/core/main.c:220
#: ../src/core/main.c:219
msgid "Initialize session from savefile"
msgstr "Inicializuoti sesiją iš išsaugojimo failo"
#: ../src/core/main.c:226
#: ../src/core/main.c:225
msgid "Make X calls synchronous"
msgstr "Sinchronizuoti X iškvietimus"
#: ../src/core/main.c:534
#: ../src/core/main.c:494
#, c-format
msgid "Failed to scan themes directory: %s\n"
msgstr "Nepavyko nuskanuoti temų aplanko: %s\n"
#: ../src/core/main.c:550
#: ../src/core/main.c:510
#, c-format
msgid ""
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
@ -320,20 +321,6 @@ msgstr ""
"Nepavyko rasti temos! Įsitikinkite, kad %s egzistuoja ir kad ten yra "
"įprastos temos.\n"
#: ../src/core/monitor.c:711
msgid "Built-in display"
msgstr "Integruotas vaizduoklis"
#. 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 "Nežinomas %s"
#: ../src/core/mutter.c:40
#, c-format
msgid ""
@ -359,7 +346,7 @@ msgstr "Parodyti versiją"
msgid "Mutter plugin to use"
msgstr "Naudojamas Mutter įskiepis"
#: ../src/core/prefs.c:1202
#: ../src/core/prefs.c:1087
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -367,12 +354,12 @@ msgstr ""
"Apsauga nuo sugadintų programų atjungta. Kai kurios programos gali pradėti "
"keistai elgtis.\n"
#: ../src/core/prefs.c:1277
#: ../src/core/prefs.c:1162
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Nepavyko perskaityti šrifto aprašymo „%s“ saugomo GSettings rakte %s\n"
#: ../src/core/prefs.c:1343
#: ../src/core/prefs.c:1228
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -381,7 +368,7 @@ msgstr ""
"„%s“ reikšmė rasta nustatymų duomenų bazėje yra netinkama pelės mygtuko "
"keitiklio aprašymui\n"
#: ../src/core/prefs.c:1909
#: ../src/core/prefs.c:1780
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@ -390,17 +377,17 @@ msgstr ""
"„%s“ reikšmė rasta konfiguracijos duomenų bazė yra netinkama klavišų "
"kombinacijai „%s“\n"
#: ../src/core/prefs.c:1999
#: ../src/core/prefs.c:1879
#, c-format
msgid "Workspace %d"
msgstr "Darbalaukis %d"
#: ../src/core/screen.c:534
#: ../src/core/screen.c:673
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Ekranas %d vaizduoklyje „%s“ netinkamas\n"
#: ../src/core/screen.c:550
#: ../src/core/screen.c:689
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@ -409,19 +396,19 @@ msgstr ""
"Ekranas %d vaizduoklyje „%s“ jau turi langų valdyklę; pabandykite "
"pasinaudoti parinktimi --replace, jei norite pakeisti esamą langų valdyklę.\n"
#: ../src/core/screen.c:577
#: ../src/core/screen.c:716
#, c-format
msgid ""
"Could not acquire window manager selection on screen %d display \"%s\"\n"
msgstr ""
"Nepavyko aptikti langų valdyklės pasirinkimo ekrano %d vaizduoklyje „%s“\n"
#: ../src/core/screen.c:655
#: ../src/core/screen.c:794
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "Ekranas %d vaizduoklyje „%s“ jau turi langų valdyklę\n"
#: ../src/core/screen.c:846
#: ../src/core/screen.c:979
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Nepavyko pasitraukti iš ekrano %d vaizduoklyje „%s“\n"
@ -481,43 +468,44 @@ msgstr ""
"Šie langai nepalaiko &quot;išsaugoti esamus nustatymus&quot; komandos ir "
"turi būti paleisti rankiniu būdu, kai prisijungsite kitą kartą."
#: ../src/core/util.c:84
#: ../src/core/util.c:80
#, c-format
msgid "Failed to open debug log: %s\n"
msgstr "Nepavyko atverti derinimo žurnalo: %s\n"
#: ../src/core/util.c:94
#: ../src/core/util.c:90
#, c-format
msgid "Failed to fdopen() log file %s: %s\n"
msgstr "Funkcija fdopen() su žurnalo failu %s nesėkminga: %s\n"
#: ../src/core/util.c:100
#: ../src/core/util.c:96
#, c-format
msgid "Opened log file %s\n"
msgstr "Atvertas žurnalo failas %s\n"
#: ../src/core/util.c:119
#: ../src/core/util.c:115 ../src/tools/mutter-message.c:149
#, c-format
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter buvo sukompiliuota be išsamaus veikimo veiksenos\n"
#: ../src/core/util.c:264
#: ../src/core/util.c:259
msgid "Window manager: "
msgstr "Langų valdyklė:"
#: ../src/core/util.c:414
#: ../src/core/util.c:407
msgid "Bug in window manager: "
msgstr "Klaida langų valdyklėje:"
#: ../src/core/util.c:445
#: ../src/core/util.c:438
msgid "Window manager warning: "
msgstr "Langų valdyklės perspėjimas:"
#: ../src/core/util.c:473
#: ../src/core/util.c:466
msgid "Window manager error: "
msgstr "Langų valdyklės klaida:"
#. first time through
#: ../src/core/window.c:7533
#: ../src/core/window.c:7539
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -533,7 +521,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8257
#: ../src/core/window.c:8263
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -543,22 +531,22 @@ msgstr ""
"tuo pat metu nustatė ir leistinas mažiausio dydžio %d x %d bei didžiausio "
"dydžio %d x %d reikšmes; tai yra beprasmiška.\n"
#: ../src/core/window-props.c:347
#: ../src/core/window-props.c:318
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "Programa nustatė netinkamą _NET_WM_PID %lu\n"
#: ../src/core/window-props.c:463
#: ../src/core/window-props.c:434
#, c-format
msgid "%s (on %s)"
msgstr "%s (kompiuteryje %s)"
#: ../src/core/window-props.c:1546
#: ../src/core/window-props.c:1517
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "Nekorektiškas WM_TRANSIENT_FOR langas 0x%lx nurodytas %s.\n"
#: ../src/core/window-props.c:1557
#: ../src/core/window-props.c:1528
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "WM_TRANSIENT_FOR langas 0x%lx nurodytas %s sukurtų ciklą.\n"
@ -722,104 +710,109 @@ msgstr "Pasirinkti langą iš tab iššokimo"
msgid "Cancel tab popup"
msgstr "Atšaukti tab iššokimą"
#: ../src/tools/mutter-message.c:123
#, c-format
msgid "Usage: %s\n"
msgstr "Naudojimas: %s\n"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:67
#: ../src/ui/menu.c:69
msgid "Mi_nimize"
msgstr "Sumaži_nti"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:69
#: ../src/ui/menu.c:71
msgid "Ma_ximize"
msgstr "Iš_didinti"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:71
#: ../src/ui/menu.c:73
msgid "Unma_ximize"
msgstr "_Grąžinti iš išdidinimo"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:73
#: ../src/ui/menu.c:75
msgid "Roll _Up"
msgstr "Su_vynioti"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:75
#: ../src/ui/menu.c:77
msgid "_Unroll"
msgstr "_Išvynioti"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:77
#: ../src/ui/menu.c:79
msgid "_Move"
msgstr "Pe_rkelti"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:79
#: ../src/ui/menu.c:81
msgid "_Resize"
msgstr "_Keisti dydį"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:81
#: ../src/ui/menu.c:83
msgid "Move Titlebar On_screen"
msgstr "Perkelti lango juostą ant _ekrano"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
msgid "Always on _Top"
msgstr "Visada _viršuje"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:88
#: ../src/ui/menu.c:90
msgid "_Always on Visible Workspace"
msgstr "_Visada matomame darbalaukyje"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:90
#: ../src/ui/menu.c:92
msgid "_Only on This Workspace"
msgstr "_Tik šiame darbalaukyje"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:92
#: ../src/ui/menu.c:94
msgid "Move to Workspace _Left"
msgstr "Perkelti _langą į kairįjį darbalaukį"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:94
#: ../src/ui/menu.c:96
msgid "Move to Workspace R_ight"
msgstr "Pe_rkelti langą į dešinįjį darbalaukį"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:96
#: ../src/ui/menu.c:98
msgid "Move to Workspace _Up"
msgstr "Perkelti langą į a_ukštesnįjį darbalaukį"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:98
#: ../src/ui/menu.c:100
msgid "Move to Workspace _Down"
msgstr "Perkelti langą į ž_emesnįjį darbalaukį"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:102
#: ../src/ui/menu.c:104
msgid "_Close"
msgstr "_Užverti"
#: ../src/ui/menu.c:202
#: ../src/ui/menu.c:204
#, c-format
msgid "Workspace %d%n"
msgstr "Darbalaukis %d%n"
#: ../src/ui/menu.c:212
#: ../src/ui/menu.c:214
#, c-format
msgid "Workspace 1_0"
msgstr "1_0-tas darbalaukis"
#: ../src/ui/menu.c:214
#: ../src/ui/menu.c:216
#, c-format
msgid "Workspace %s%d"
msgstr "Darbalaukis %s%d"
#: ../src/ui/menu.c:384
#: ../src/ui/menu.c:397
msgid "Move to Another _Workspace"
msgstr "Perkelti langą į kitą _darbalaukį"
@ -921,48 +914,48 @@ msgstr "Mod5"
msgid "%d x %d"
msgstr "%d x %d"
#: ../src/ui/theme.c:236
#: ../src/ui/theme.c:235
msgid "top"
msgstr "viršus"
#: ../src/ui/theme.c:238
#: ../src/ui/theme.c:237
msgid "bottom"
msgstr "apačia"
#: ../src/ui/theme.c:240
#: ../src/ui/theme.c:239
msgid "left"
msgstr "kairė"
#: ../src/ui/theme.c:242
#: ../src/ui/theme.c:241
msgid "right"
msgstr "dešinė"
#: ../src/ui/theme.c:270
#: ../src/ui/theme.c:269
#, c-format
msgid "frame geometry does not specify \"%s\" dimension"
msgstr "rėmelio aprašyme nenurodytas „%s“ matmuo"
#: ../src/ui/theme.c:289
#: ../src/ui/theme.c:288
#, c-format
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
msgstr "rėmelio aprašyme nenurodytas paraštės „%2$s“ „%1$s“ matmuo"
#: ../src/ui/theme.c:326
#: ../src/ui/theme.c:325
#, c-format
msgid "Button aspect ratio %g is not reasonable"
msgstr "Mygtuko dydžio santykis %g yra nenuosaikus"
#: ../src/ui/theme.c:338
#: ../src/ui/theme.c:337
#, c-format
msgid "Frame geometry does not specify size of buttons"
msgstr "Rėmelio aprašyme nenurodytas mygtukų dydis"
#: ../src/ui/theme.c:1051
#: ../src/ui/theme.c:1050
#, c-format
msgid "Gradients should have at least two colors"
msgstr "Aprašant persiliejančias spalvas reikia nurodyti bent dvi spalvas"
#: ../src/ui/theme.c:1203
#: ../src/ui/theme.c:1202
#, c-format
msgid ""
"GTK custom color specification must have color name and fallback in "
@ -972,7 +965,7 @@ msgstr ""
"uždarančius laužtinius skliaustus, pvz.: gtk:custom(foo,bar); nepavyko "
"perskaityti „%s“"
#: ../src/ui/theme.c:1219
#: ../src/ui/theme.c:1218
#, c-format
msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
@ -981,7 +974,7 @@ msgstr ""
"Netinkamas simbolis „%c“ gtk:custom parametre color_name, leidžiama tik A-Za-"
"z0-9_"
#: ../src/ui/theme.c:1233
#: ../src/ui/theme.c:1232
#, c-format
msgid ""
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
@ -990,7 +983,7 @@ msgstr ""
"Gtk:custom formatas yra „gtk:custom(color_name,fallback)“, „%s“ neatitinka "
"šio formato"
#: ../src/ui/theme.c:1278
#: ../src/ui/theme.c:1277
#, c-format
msgid ""
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
@ -1000,7 +993,7 @@ msgstr ""
"skliaustų, pvz.: gtk:fg[NORMAL], kur NORMAL yra būsena; nepavyko apdoroti "
"\"%s\""
#: ../src/ui/theme.c:1292
#: ../src/ui/theme.c:1291
#, c-format
msgid ""
"GTK color specification must have a close bracket after the state, e.g. gtk:"
@ -1010,17 +1003,17 @@ msgstr ""
"skliaustus, pvz.: gtk:fg[NORMAL], kur NORMAL yra būsena; nepavyko apdoroti "
"\"%s\""
#: ../src/ui/theme.c:1303
#: ../src/ui/theme.c:1302
#, c-format
msgid "Did not understand state \"%s\" in color specification"
msgstr "Nesuprantama spalvų aprašymo būsena \"%s\""
#: ../src/ui/theme.c:1316
#: ../src/ui/theme.c:1315
#, c-format
msgid "Did not understand color component \"%s\" in color specification"
msgstr "Spalvų aprašyme nurodytas nesuprantamas spalvos komponentas \"%s\""
#: ../src/ui/theme.c:1345
#: ../src/ui/theme.c:1344
#, c-format
msgid ""
"Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the "
@ -1029,19 +1022,19 @@ msgstr ""
"Išplaukimo formatas yra \"blend/bg_color/fg_color/alpha\", \"%s\" neatitinka "
"šio formato"
#: ../src/ui/theme.c:1356
#: ../src/ui/theme.c:1355
#, c-format
msgid "Could not parse alpha value \"%s\" in blended color"
msgstr ""
"Nepavyko aprodoti skaidrumo reikšmės \"%s\" priskirtos išplaukiančiai spalva"
#: ../src/ui/theme.c:1366
#: ../src/ui/theme.c:1365
#, c-format
msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
msgstr ""
"Skaidrumo reikšmė \"%s\" tarp išplaukiančios spalvos yra ne tarp 0.0 ir 1.0"
#: ../src/ui/theme.c:1413
#: ../src/ui/theme.c:1412
#, c-format
msgid ""
"Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
@ -1049,27 +1042,27 @@ msgstr ""
"Šešėlio formatas yra \"shade/base_color/factor\", \"%s\" neatitinka šio "
"formato"
#: ../src/ui/theme.c:1424
#: ../src/ui/theme.c:1423
#, c-format
msgid "Could not parse shade factor \"%s\" in shaded color"
msgstr "Nepavyko apdoroti šešėlinės spalvos šešėlių rodiklio \"%s\""
#: ../src/ui/theme.c:1434
#: ../src/ui/theme.c:1433
#, c-format
msgid "Shade factor \"%s\" in shaded color is negative"
msgstr "Šešėlio rodiklis \"%s\" tarp šešėlinės spalvos yra neigiamas"
#: ../src/ui/theme.c:1463
#: ../src/ui/theme.c:1462
#, c-format
msgid "Could not parse color \"%s\""
msgstr "Nepavyko apdoroti spalvos \"%s\""
#: ../src/ui/theme.c:1780
#: ../src/ui/theme.c:1779
#, c-format
msgid "Coordinate expression contains character '%s' which is not allowed"
msgstr "Koordinačių išraiška turi neleistiną simbolį '%s'"
#: ../src/ui/theme.c:1807
#: ../src/ui/theme.c:1806
#, c-format
msgid ""
"Coordinate expression contains floating point number '%s' which could not be "
@ -1078,13 +1071,13 @@ msgstr ""
"Koordinačių išraiška turi skaičių su slankiu kableliu '%s', kuris negali "
"būti apdorotas"
#: ../src/ui/theme.c:1821
#: ../src/ui/theme.c:1820
#, c-format
msgid "Coordinate expression contains integer '%s' which could not be parsed"
msgstr ""
"Koordinačių išraiška turi sveiką skaičių '%s', kuris negali būti apdorotas"
#: ../src/ui/theme.c:1942
#: ../src/ui/theme.c:1941
#, c-format
msgid ""
"Coordinate expression contained unknown operator at the start of this text: "
@ -1093,17 +1086,17 @@ msgstr ""
"Koordinačių išraiškoje nurodytas nežinomas operatorius šio teksto pradžioje: "
"\"%s\""
#: ../src/ui/theme.c:1999
#: ../src/ui/theme.c:1998
#, c-format
msgid "Coordinate expression was empty or not understood"
msgstr "Koordinačių išraiška tuščia arba nesuprantama"
#: ../src/ui/theme.c:2112 ../src/ui/theme.c:2122 ../src/ui/theme.c:2156
#: ../src/ui/theme.c:2111 ../src/ui/theme.c:2121 ../src/ui/theme.c:2155
#, c-format
msgid "Coordinate expression results in division by zero"
msgstr "Koordinačių išraiška sukelia dalybą iš nulio"
#: ../src/ui/theme.c:2164
#: ../src/ui/theme.c:2163
#, c-format
msgid ""
"Coordinate expression tries to use mod operator on a floating-point number"
@ -1111,7 +1104,7 @@ msgstr ""
"Koordinačių išraiška bando panaudoti liekanos operatorių (mod) slankaus "
"kablelio skaičiui"
#: ../src/ui/theme.c:2220
#: ../src/ui/theme.c:2219
#, c-format
msgid ""
"Coordinate expression has an operator \"%s\" where an operand was expected"
@ -1119,17 +1112,17 @@ msgstr ""
"Koordinačių išraiškoje įvestas operatorius \"%s\" ten, kur turi būti vedamas "
"operandas"
#: ../src/ui/theme.c:2229
#: ../src/ui/theme.c:2228
#, c-format
msgid "Coordinate expression had an operand where an operator was expected"
msgstr "Koordinačių išraiškoje operandas įrašytas operatoriaus vietoje"
#: ../src/ui/theme.c:2237
#: ../src/ui/theme.c:2236
#, c-format
msgid "Coordinate expression ended with an operator instead of an operand"
msgstr "Koordinačių išraiška pasibaigė operatoriumi, o ne operandu"
#: ../src/ui/theme.c:2247
#: ../src/ui/theme.c:2246
#, c-format
msgid ""
"Coordinate expression has operator \"%c\" following operator \"%c\" with no "
@ -1138,41 +1131,41 @@ msgstr ""
"Koordinačių išraiškoje operatorius \"%c\" eina po operatoriaus \"%c\" be "
"tarpinio operando"
#: ../src/ui/theme.c:2398 ../src/ui/theme.c:2443
#: ../src/ui/theme.c:2397 ../src/ui/theme.c:2442
#, c-format
msgid "Coordinate expression had unknown variable or constant \"%s\""
msgstr "Koordinačių išraiška saugo nežinomą kintamąjį arba konstantą \"%s\""
#: ../src/ui/theme.c:2497
#: ../src/ui/theme.c:2496
#, c-format
msgid "Coordinate expression parser overflowed its buffer."
msgstr "Koordinačių išraiškų skaitytuvas perpildė buferį."
#: ../src/ui/theme.c:2526
#: ../src/ui/theme.c:2525
#, c-format
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
msgstr ""
"Koordinačių išraiškoje įvesti uždarantys skliaustai, nors atidarančių "
"skliaustų nerasta"
#: ../src/ui/theme.c:2590
#: ../src/ui/theme.c:2589
#, c-format
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
msgstr ""
"Koordinačių išraiškoje po atidarančių skliaustų neįvesti uždarantys "
"skliaustai"
#: ../src/ui/theme.c:2601
#: ../src/ui/theme.c:2600
#, c-format
msgid "Coordinate expression doesn't seem to have any operators or operands"
msgstr "Koordinačių išraiška neturi jokių operatorių ar operandų"
#: ../src/ui/theme.c:2814 ../src/ui/theme.c:2834 ../src/ui/theme.c:2854
#: ../src/ui/theme.c:2813 ../src/ui/theme.c:2833 ../src/ui/theme.c:2853
#, c-format
msgid "Theme contained an expression that resulted in an error: %s\n"
msgstr "Temoje esanti išraiška sukėlė klaidą: %s\n"
#: ../src/ui/theme.c:4500
#: ../src/ui/theme.c:4499
#, c-format
msgid ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
@ -1181,25 +1174,25 @@ msgstr ""
"Šiam rėmelio stiliui turi būti nurodytas <button function=\"%s\" state=\"%s"
"\" draw_ops=\"kažkokswhatever\"/> požymis"
#: ../src/ui/theme.c:5011 ../src/ui/theme.c:5036
#: ../src/ui/theme.c:5010 ../src/ui/theme.c:5035
#, c-format
msgid ""
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
msgstr ""
"Trūksta <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"kažkoks\"/>"
#: ../src/ui/theme.c:5082
#: ../src/ui/theme.c:5083
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Nepavyko paleisti temos \"%s\": %s\n"
#: ../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
#: ../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
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "Temoje \"%2$s\" trūksta <%1$s> nustatymų"
#: ../src/ui/theme.c:5254
#: ../src/ui/theme.c:5255
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@ -1208,7 +1201,7 @@ msgstr ""
"Rėmelio stilius nenurodytas lango tipui \"%s\" temoje \"%s\", pridėkite "
"<window type=\"%s\" style_set=\"kažkoks\"/> elementą"
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
#: ../src/ui/theme.c:5662 ../src/ui/theme.c:5724 ../src/ui/theme.c:5787
#, c-format
msgid ""
"User-defined constants must begin with a capital letter; \"%s\" does not"
@ -1216,7 +1209,7 @@ msgstr ""
"Naudotojo nustatytos konstantos turi prasidėti didžiąja raide; „%s“ nėra "
"didžioji"
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
#: ../src/ui/theme.c:5670 ../src/ui/theme.c:5732 ../src/ui/theme.c:5795
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "Konstanta „%s“ jau aprašyta"
@ -1600,8 +1593,210 @@ msgstr "Elemente <%s> tekstas negalimas"
msgid "<%s> specified twice for this theme"
msgstr "<%s> elementas temos aprašyme nurodytas du kartus"
#: ../src/ui/theme-parser.c:4336
#: ../src/ui/theme-parser.c:4334
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "Nepavyko rasti tinkamo temos %s failo\n"
#: ../src/ui/theme-viewer.c:99
msgid "_Windows"
msgstr "_Langai"
#: ../src/ui/theme-viewer.c:100
msgid "_Dialog"
msgstr "_Dialogas"
#: ../src/ui/theme-viewer.c:101
msgid "_Modal dialog"
msgstr "_Modalinis dialogas"
#: ../src/ui/theme-viewer.c:102
msgid "_Utility"
msgstr "_Įrankis"
#: ../src/ui/theme-viewer.c:103
msgid "_Splashscreen"
msgstr "_Pristatymo langas"
#: ../src/ui/theme-viewer.c:104
msgid "_Top dock"
msgstr "_Viršutinis dokas"
#: ../src/ui/theme-viewer.c:105
msgid "_Bottom dock"
msgstr "_Apatinis dokas"
#: ../src/ui/theme-viewer.c:106
msgid "_Left dock"
msgstr "_Kairysis dokas"
#: ../src/ui/theme-viewer.c:107
msgid "_Right dock"
msgstr "_Kairysis dokas"
#: ../src/ui/theme-viewer.c:108
msgid "_All docks"
msgstr "Visi dok_ai"
#: ../src/ui/theme-viewer.c:109
msgid "Des_ktop"
msgstr "Dar_bastalis"
#: ../src/ui/theme-viewer.c:115
msgid "Open another one of these windows"
msgstr "Atverti dar vieną tokį langą"
#: ../src/ui/theme-viewer.c:117
msgid "This is a demo button with an 'open' icon"
msgstr "Tai yra bandomasis mygtukas su „atverti“ piktograma"
#: ../src/ui/theme-viewer.c:119
msgid "This is a demo button with a 'quit' icon"
msgstr "Tai yra bandomasis mygtukas su „uždaryti“ piktograma"
#: ../src/ui/theme-viewer.c:248
msgid "This is a sample message in a sample dialog"
msgstr "Tai yra pavydžio pranešimas pavyzdžio dialoge"
#: ../src/ui/theme-viewer.c:328
#, c-format
msgid "Fake menu item %d\n"
msgstr "Netikras meniu punktas %d\n"
#: ../src/ui/theme-viewer.c:363
msgid "Border-only window"
msgstr "Tik rėmelį turintis langas"
#: ../src/ui/theme-viewer.c:365
msgid "Bar"
msgstr "Juosta"
#: ../src/ui/theme-viewer.c:382
msgid "Normal Application Window"
msgstr "Normalus programos langas"
#: ../src/ui/theme-viewer.c:386
msgid "Dialog Box"
msgstr "Dialogo langas"
#: ../src/ui/theme-viewer.c:390
msgid "Modal Dialog Box"
msgstr "Modalinis dialogo langas"
#: ../src/ui/theme-viewer.c:394
msgid "Utility Palette"
msgstr "Įrankių paletė"
#: ../src/ui/theme-viewer.c:398
msgid "Torn-off Menu"
msgstr "Atkabinamas meniu"
#: ../src/ui/theme-viewer.c:402
msgid "Border"
msgstr "Paraštė"
#: ../src/ui/theme-viewer.c:406
msgid "Attached Modal Dialog"
msgstr "Prikabintas modalinis dialogas"
#: ../src/ui/theme-viewer.c:737
#, c-format
msgid "Button layout test %d"
msgstr "Mygtukų išdėstymo testas %d"
#: ../src/ui/theme-viewer.c:766
#, c-format
msgid "%g milliseconds to draw one window frame"
msgstr "vienam lango kadrui išvesti yra skirta %g milisekundžių"
#: ../src/ui/theme-viewer.c:811
#, c-format
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
msgstr "Panaudojimas: metacity-theme-viewer [TEMOS PAVADINIMAS]\n"
#: ../src/ui/theme-viewer.c:818
#, c-format
msgid "Error loading theme: %s\n"
msgstr "Klaida įkeliant temą: %s\n"
#: ../src/ui/theme-viewer.c:824
#, c-format
msgid "Loaded theme \"%s\" in %g seconds\n"
msgstr "Tema „%s“ įkelta per %g sekundžių\n"
#: ../src/ui/theme-viewer.c:869
msgid "Normal Title Font"
msgstr "Normalus antraštės šriftas"
#: ../src/ui/theme-viewer.c:875
msgid "Small Title Font"
msgstr "Smulkus antraštės šriftas"
#: ../src/ui/theme-viewer.c:881
msgid "Large Title Font"
msgstr "Didelis antraštės šriftas"
#: ../src/ui/theme-viewer.c:886
msgid "Button Layouts"
msgstr "Mygtukų išdėstymai"
#: ../src/ui/theme-viewer.c:891
msgid "Benchmark"
msgstr "Greičio testas"
#: ../src/ui/theme-viewer.c:947
msgid "Window Title Goes Here"
msgstr "Čia rodomo lango antraštė"
#: ../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 kadrai buvo išvesti per %g klientines sekundes (%g milisekunčių kadrui) "
"ir per %g bendrinio laiko sekundes įskaitant X serverio resursus (%g "
"milisekundžių kadrui)\n"
#: ../src/ui/theme-viewer.c:1273
msgid "position expression test returned TRUE but set error"
msgstr ""
"padėties išraiškos testas grąžino teigiamą reikšmę, bet kartu nustatė "
"klaidos pranešimą"
#: ../src/ui/theme-viewer.c:1275
msgid "position expression test returned FALSE but didn't set error"
msgstr ""
"padėties išraiškos testas grąžino neigiamą reikšmę, bet nenustatė klaidos "
"pranešimo"
#: ../src/ui/theme-viewer.c:1279
msgid "Error was expected but none given"
msgstr "Tikėtasi sulaukti klaidos pranešimo, tačiau nieko nesulaukta"
#: ../src/ui/theme-viewer.c:1281
#, c-format
msgid "Error %d was expected but %d given"
msgstr "Tikėtasi klaidos %d, tačiau gauta %d"
#: ../src/ui/theme-viewer.c:1287
#, c-format
msgid "Error not expected but one was returned: %s"
msgstr "Klaidos nesitikėta, tačiau grąžinta klaida: %s"
#: ../src/ui/theme-viewer.c:1291
#, c-format
msgid "x value was %d, %d was expected"
msgstr "x reikšmė buvo %d, tikėtasi %d"
#: ../src/ui/theme-viewer.c:1294
#, c-format
msgid "y value was %d, %d was expected"
msgstr "y reikšmė buvo %d, tikėtasi %d"
#: ../src/ui/theme-viewer.c:1359
#, c-format
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
msgstr ""
"Koordinačių %d išraiška apdorota per %g sekundžių (%g sekundžių vidurkis)\n"

309
po/nb.po
View File

@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter 3.9.x\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-08-22 16:11+0200\n"
"PO-Revision-Date: 2013-08-22 16:12+0200\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,7 +205,7 @@ 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:596
#: ../src/compositor/compositor.c:589
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
@ -260,7 +260,7 @@ msgstr "Mangler utvidelsen %s som kreves for komposittfunksjon"
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:1136
#: ../src/core/keybindings.c:1138
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -269,7 +269,7 @@ msgstr ""
"Et annet program bruker allerede nøkkelen %s med modifikatorer %x som "
"binding\n"
#: ../src/core/keybindings.c:1333
#: ../src/core/keybindings.c:1335
#, c-format
msgid "\"%s\" is not a valid accelerator\n"
msgstr "«%s» er ikke en gyldig aksellerator\n"
@ -311,19 +311,6 @@ msgstr ""
"Kunne ikke finne et tema! Sjekk at %s eksisterer og inneholder de vanlige "
"temaene.\n"
#: ../src/core/monitor.c:702
msgid "Built-in display"
msgstr "Innebygget skjerm"
#. 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:730
#, c-format
msgid "Unknown %s"
msgstr "Ukjent %s"
#: ../src/core/mutter.c:40
#, c-format
msgid ""
@ -382,12 +369,12 @@ msgstr ""
msgid "Workspace %d"
msgstr "Arbeidsområde %d"
#: ../src/core/screen.c:537
#: ../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:553
#: ../src/core/screen.c:707
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@ -396,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:580
#: ../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:658
#: ../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:850
#: ../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"
@ -483,7 +470,8 @@ msgstr "Feil under fdopen() av loggfil %s: %s\n"
msgid "Opened log file %s\n"
msgstr "Åpnet loggfil %s\n"
#: ../src/core/util.c:119
#: ../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"
@ -491,20 +479,20 @@ msgstr "Mutter er kompilert uten støtte for «verbose» modus\n"
msgid "Window manager: "
msgstr "Vindushåndterer: "
#: ../src/core/util.c:414
#: ../src/core/util.c:412
msgid "Bug in window manager: "
msgstr "Feil i vindushåndterer: "
#: ../src/core/util.c:445
#: ../src/core/util.c:443
msgid "Window manager warning: "
msgstr "Advarsel fra vindushåndterer: "
#: ../src/core/util.c:473
#: ../src/core/util.c:471
msgid "Window manager error: "
msgstr "Feil i vindushåndterer: "
#. first time through
#: ../src/core/window.c:7533
#: ../src/core/window.c:7513
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -520,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:8257
#: ../src/core/window.c:8237
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -530,22 +518,22 @@ msgstr ""
"men setter minste størrelse %d x %d og maks størrelse %d x %d; dette virker "
"ikke fornuftig.\n"
#: ../src/core/window-props.c:347
#: ../src/core/window-props.c:318
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "Programmet satte en feil _NET_WM_PID %lu\n"
#: ../src/core/window-props.c:463
#: ../src/core/window-props.c:434
#, c-format
msgid "%s (on %s)"
msgstr "%s (på %s)"
#: ../src/core/window-props.c:1546
#: ../src/core/window-props.c:1517
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "Ugyldig WM_TRANSIENT_FOR vindu 0x%lx oppgitt for %s.\n"
#: ../src/core/window-props.c:1557
#: ../src/core/window-props.c:1528
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "WM_TRANSIENT_FOR vindu 0x%lx for %s ville skapt en løkke.\n"
@ -708,104 +696,109 @@ msgstr "Fjern vindu fra tabulatordialog"
msgid "Cancel tab popup"
msgstr "Avbryt tabulatordialog"
#: ../src/tools/mutter-message.c:123
#, c-format
msgid "Usage: %s\n"
msgstr " Bruk: %s\n"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:67
#: ../src/ui/menu.c:69
msgid "Mi_nimize"
msgstr "Mi_nimer"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:69
#: ../src/ui/menu.c:71
msgid "Ma_ximize"
msgstr "Ma_ksimer"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:71
#: ../src/ui/menu.c:73
msgid "Unma_ximize"
msgstr "G_jenopprett"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:73
#: ../src/ui/menu.c:75
msgid "Roll _Up"
msgstr "Rull _opp"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:75
#: ../src/ui/menu.c:77
msgid "_Unroll"
msgstr "R_ull ned"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:77
#: ../src/ui/menu.c:79
msgid "_Move"
msgstr "_Flytt"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:79
#: ../src/ui/menu.c:81
msgid "_Resize"
msgstr "End_re størrelse"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:81
#: ../src/ui/menu.c:83
msgid "Move Titlebar On_screen"
msgstr "Flytt tittellinje på _skjermen"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
msgid "Always on _Top"
msgstr "All_tid øverst"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:88
#: ../src/ui/menu.c:90
msgid "_Always on Visible Workspace"
msgstr "_Alltid på synlig arbeidsområde"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:90
#: ../src/ui/menu.c:92
msgid "_Only on This Workspace"
msgstr "K_un på dette arbeidsområdet"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:92
#: ../src/ui/menu.c:94
msgid "Move to Workspace _Left"
msgstr "Flytt til arbeidsområdet ti_l venstre"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:94
#: ../src/ui/menu.c:96
msgid "Move to Workspace R_ight"
msgstr "Flytt til a_rbeidsområdet til høyre"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:96
#: ../src/ui/menu.c:98
msgid "Move to Workspace _Up"
msgstr "Flytt til arbeidsområdet _over"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:98
#: ../src/ui/menu.c:100
msgid "Move to Workspace _Down"
msgstr "Flytt til arbeidsområdet ne_denfor"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:102
#: ../src/ui/menu.c:104
msgid "_Close"
msgstr "_Lukk"
#: ../src/ui/menu.c:202
#: ../src/ui/menu.c:204
#, c-format
msgid "Workspace %d%n"
msgstr "Arbeidsområde %d%n"
#: ../src/ui/menu.c:212
#: ../src/ui/menu.c:214
#, c-format
msgid "Workspace 1_0"
msgstr "Arbeidsområde 1_0"
#: ../src/ui/menu.c:214
#: ../src/ui/menu.c:216
#, c-format
msgid "Workspace %s%d"
msgstr "Arbeidsområde %s%d"
#: ../src/ui/menu.c:384
#: ../src/ui/menu.c:397
msgid "Move to Another _Workspace"
msgstr "Flytt til et annet ar_beidsområde"
@ -1158,18 +1151,18 @@ msgid ""
msgstr ""
"Mangler <frame state=«%s» resize=«%s» focus=«%s» stil=«ett-eller-annet»/>"
#: ../src/ui/theme.c:5082
#: ../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:5218 ../src/ui/theme.c:5225 ../src/ui/theme.c:5232
#: ../src/ui/theme.c:5239 ../src/ui/theme.c:5246
#: ../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:5254
#: ../src/ui/theme.c:5256
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@ -1178,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:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
#: ../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:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
#: ../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"
@ -1570,3 +1563,201 @@ msgstr "<%s> spesifisert to ganger for dette temaet"
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "Fant ikke en gyldig fil for tema %s\n"
#: ../src/ui/theme-viewer.c:99
msgid "_Windows"
msgstr "_Vinduer"
#: ../src/ui/theme-viewer.c:100
msgid "_Dialog"
msgstr "_Dialog"
#: ../src/ui/theme-viewer.c:101
msgid "_Modal dialog"
msgstr "_Modal dialog"
#: ../src/ui/theme-viewer.c:102
msgid "_Utility"
msgstr "_Verktøy"
#: ../src/ui/theme-viewer.c:103
msgid "_Splashscreen"
msgstr "Opp_startskjerm"
#: ../src/ui/theme-viewer.c:104
msgid "_Top dock"
msgstr "_Toppdokk"
#: ../src/ui/theme-viewer.c:105
msgid "_Bottom dock"
msgstr "_Bunndokk"
#: ../src/ui/theme-viewer.c:106
msgid "_Left dock"
msgstr "_Venstre dokk"
#: ../src/ui/theme-viewer.c:107
msgid "_Right dock"
msgstr "Høy_re dokk"
#: ../src/ui/theme-viewer.c:108
msgid "_All docks"
msgstr "_Alle dokker"
#: ../src/ui/theme-viewer.c:109
msgid "Des_ktop"
msgstr "S_krivebord"
#: ../src/ui/theme-viewer.c:115
msgid "Open another one of these windows"
msgstr "Åpne et til av disse vinduene"
#: ../src/ui/theme-viewer.c:117
msgid "This is a demo button with an 'open' icon"
msgstr "Dette er en demoknapp med et «åpne»-ikon"
#: ../src/ui/theme-viewer.c:119
msgid "This is a demo button with a 'quit' icon"
msgstr "Dette er en demoknapp med et «avslutt»-ikon"
#: ../src/ui/theme-viewer.c:248
msgid "This is a sample message in a sample dialog"
msgstr "Dette er en eksempelbeskjed i en eksempeldialog"
#: ../src/ui/theme-viewer.c:328
#, c-format
msgid "Fake menu item %d\n"
msgstr "Falsk menyoppføring %d\n"
#: ../src/ui/theme-viewer.c:363
msgid "Border-only window"
msgstr "Vindu uten innhold"
#: ../src/ui/theme-viewer.c:365
msgid "Bar"
msgstr "Linje"
#: ../src/ui/theme-viewer.c:382
msgid "Normal Application Window"
msgstr "Normalt programvindu"
#: ../src/ui/theme-viewer.c:386
msgid "Dialog Box"
msgstr "Dialogboks"
#: ../src/ui/theme-viewer.c:390
msgid "Modal Dialog Box"
msgstr "Modal dialogboks"
#: ../src/ui/theme-viewer.c:394
msgid "Utility Palette"
msgstr "Verktøypalett"
#: ../src/ui/theme-viewer.c:398
msgid "Torn-off Menu"
msgstr "Avrevet meny"
#: ../src/ui/theme-viewer.c:402
msgid "Border"
msgstr "Kant"
#: ../src/ui/theme-viewer.c:406
msgid "Attached Modal Dialog"
msgstr "Festet modal dialog"
#: ../src/ui/theme-viewer.c:737
#, c-format
msgid "Button layout test %d"
msgstr "Test av knappeplassering %d"
#: ../src/ui/theme-viewer.c:766
#, c-format
msgid "%g milliseconds to draw one window frame"
msgstr "%g millisekunder for å tegne en vindusramme"
#: ../src/ui/theme-viewer.c:811
#, c-format
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
msgstr "Bruk: metacity-theme-viewer [TEMANAVN]\n"
#: ../src/ui/theme-viewer.c:818
#, c-format
msgid "Error loading theme: %s\n"
msgstr "Feil under lasting av tema: %s\n"
#: ../src/ui/theme-viewer.c:824
#, c-format
msgid "Loaded theme \"%s\" in %g seconds\n"
msgstr "Lastet tema «%s» på %g sekunder\n"
#: ../src/ui/theme-viewer.c:869
msgid "Normal Title Font"
msgstr "Normal tittelskrift"
#: ../src/ui/theme-viewer.c:875
msgid "Small Title Font"
msgstr "Liten tittelskrift"
#: ../src/ui/theme-viewer.c:881
msgid "Large Title Font"
msgstr "Stor tittelskrift"
#: ../src/ui/theme-viewer.c:886
msgid "Button Layouts"
msgstr "Knappeplasseringer"
#: ../src/ui/theme-viewer.c:891
msgid "Benchmark"
msgstr "Ytelsestest"
#: ../src/ui/theme-viewer.c:947
msgid "Window Title Goes Here"
msgstr "Vindutittel skal her"
#: ../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 ""
"Tegnet %d rammer på %g sekunder hos klienten (%g millisekunder per ramme) og "
"%g sekunder på klokken inklusive ressurser på X-tjener (%g millisekunder per "
"ramme)\n"
#: ../src/ui/theme-viewer.c:1273
msgid "position expression test returned TRUE but set error"
msgstr "test av posisjonsuttrykk returnerte TRUE, men satte en feilkode"
#: ../src/ui/theme-viewer.c:1275
msgid "position expression test returned FALSE but didn't set error"
msgstr "test av posisjonsuttrykk returnerte FALSE, men satte ikke en feilkode"
#: ../src/ui/theme-viewer.c:1279
msgid "Error was expected but none given"
msgstr "Feil var ventet men ingen ble gitt"
#: ../src/ui/theme-viewer.c:1281
#, c-format
msgid "Error %d was expected but %d given"
msgstr "Feil %d var ventet men %d ble gitt"
#: ../src/ui/theme-viewer.c:1287
#, c-format
msgid "Error not expected but one was returned: %s"
msgstr "Feil ikke ventet men en ble returnert: %s"
#: ../src/ui/theme-viewer.c:1291
#, c-format
msgid "x value was %d, %d was expected"
msgstr "x-verdi var %d, %d var ventet"
#: ../src/ui/theme-viewer.c:1294
#, c-format
msgid "y value was %d, %d was expected"
msgstr "y-verdi var %d, %d var ventet"
#: ../src/ui/theme-viewer.c:1359
#, c-format
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
msgstr "%d koordinatuttrykk lest på %g sekunder (%g sekunder i snitt)\n"

1194
po/nl.po

File diff suppressed because it is too large Load Diff

440
po/pl.po
View File

@ -15,8 +15,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2013-08-22 01:49+0200\n"
"PO-Revision-Date: 2013-08-22 01:50+0200\n"
"POT-Creation-Date: 2013-03-02 01:52+0100\n"
"PO-Revision-Date: 2013-03-02 01:53+0100\n"
"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
"Language-Team: Polish <gnomepl@aviary.pl>\n"
"Language: pl\n"
@ -220,7 +220,7 @@ msgstr "Podział widoku po prawej"
#. 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:596
#: ../src/compositor/compositor.c:507
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
@ -228,11 +228,11 @@ msgid ""
msgstr ""
"Inny menedżer składania jest już uruchomiony na podekranie %i ekranu \"%s\"."
#: ../src/compositor/meta-background.c:1076
#: ../src/compositor/meta-background.c:1111
msgid "background texture could not be created from file"
msgstr "nie można utworzyć tekstury tła z pliku"
#: ../src/core/bell.c:322
#: ../src/core/bell.c:320
msgid "Bell event"
msgstr "Zdarzenie sygnału dźwiękowego"
@ -264,18 +264,18 @@ msgstr "_Czekaj"
msgid "_Force Quit"
msgstr "_Zakończ"
#: ../src/core/display.c:421
#: ../src/core/display.c:401
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Brak rozszerzenia %s, wymaganego przez składanie"
#: ../src/core/display.c:513
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr ""
"Otwarcie połączenia z ekranem \"%s\" systemu X Window się nie powiodło\n"
#: ../src/core/keybindings.c:1136
#: ../src/core/keybindings.c:929
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -284,41 +284,41 @@ msgstr ""
"Skrótu klawiszowego z klawiszem %s i modyfikatorami %x używa już inny "
"program\n"
#: ../src/core/keybindings.c:1333
#: ../src/core/keybindings.c:1129
#, c-format
msgid "\"%s\" is not a valid accelerator\n"
msgstr "\"%s\" nie jest prawidłowym skrótem\n"
#: ../src/core/main.c:197
#: ../src/core/main.c:196
msgid "Disable connection to session manager"
msgstr "Rozłącza połączenie z menedżerem sesji"
#: ../src/core/main.c:203
#: ../src/core/main.c:202
msgid "Replace the running window manager"
msgstr "Zastępuje uruchomionego menedżera okien"
#: ../src/core/main.c:209
#: ../src/core/main.c:208
msgid "Specify session management ID"
msgstr "Podaje identyfikator zarządzania sesją"
#: ../src/core/main.c:214
#: ../src/core/main.c:213
msgid "X Display to use"
msgstr "Używany ekran X"
#: ../src/core/main.c:220
#: ../src/core/main.c:219
msgid "Initialize session from savefile"
msgstr "Inicjuje sesję z zapisanego pliku"
#: ../src/core/main.c:226
#: ../src/core/main.c:225
msgid "Make X calls synchronous"
msgstr "Synchroniczne wywołania X"
#: ../src/core/main.c:534
#: ../src/core/main.c:533
#, c-format
msgid "Failed to scan themes directory: %s\n"
msgstr "Przejrzenie katalogu z motywami się nie powiodło: %s\n"
#: ../src/core/main.c:550
#: ../src/core/main.c:549
#, c-format
msgid ""
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
@ -326,19 +326,6 @@ msgstr ""
"Nie można odnaleźć żadnego motywu. Proszę sprawdzić, czy katalog %s istnieje "
"i zawiera standardowe motywy.\n"
#: ../src/core/monitor.c:702
msgid "Built-in display"
msgstr "Wbudowany ekran"
#. 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:730
#, c-format
msgid "Unknown %s"
msgstr "Nieznany %s"
#: ../src/core/mutter.c:40
#, c-format
msgid ""
@ -363,7 +350,7 @@ msgstr "Wyświetla wersję"
msgid "Mutter plugin to use"
msgstr "Używana wtyczka programu Mutter"
#: ../src/core/prefs.c:1202
#: ../src/core/prefs.c:1087
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -371,14 +358,14 @@ msgstr ""
"Obejścia dla błędnie działających programów są wyłączone. Niektóre z nich "
"mogą się zachowywać w sposób nieprzewidywalny.\n"
#: ../src/core/prefs.c:1277
#: ../src/core/prefs.c:1162
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr ""
"Nie można przetworzyć opisu czcionki \"%s\", powiązanego z kluczem GSettings "
"%s\n"
#: ../src/core/prefs.c:1343
#: ../src/core/prefs.c:1228
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -387,7 +374,7 @@ msgstr ""
"Wartość \"%s\", odnaleziona w bazie danych konfiguracji nie opisuje "
"prawidłowo modyfikatora przycisku myszy\n"
#: ../src/core/prefs.c:1909
#: ../src/core/prefs.c:1780
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@ -396,17 +383,17 @@ msgstr ""
"Wartość \"%s\", odnaleziona w bazie danych konfiguracji nie opisuje "
"prawidłowo skrótu klawiszowego \"%s\"\n"
#: ../src/core/prefs.c:1999
#: ../src/core/prefs.c:1879
#, c-format
msgid "Workspace %d"
msgstr "Obszar roboczy %d"
#: ../src/core/screen.c:537
#: ../src/core/screen.c:673
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Podekran %d ekranu \"%s\" jest nieprawidłowy\n"
#: ../src/core/screen.c:553
#: ../src/core/screen.c:689
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@ -415,7 +402,7 @@ msgstr ""
"Na podekranie %d ekranu \"%s\" działa już menedżer okien. Aby zastąpić "
"działającego menedżera okien, proszę spróbować użyć opcji --replace.\n"
#: ../src/core/screen.c:580
#: ../src/core/screen.c:716
#, c-format
msgid ""
"Could not acquire window manager selection on screen %d display \"%s\"\n"
@ -423,12 +410,12 @@ msgstr ""
"Nie można uzyskać zaznaczenia menedżera okien na podekranie %d ekranu \"%s"
"\"\n"
#: ../src/core/screen.c:658
#: ../src/core/screen.c:794
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "Na podekranie %d ekranu \"%s\" działa już menedżer okien\n"
#: ../src/core/screen.c:850
#: ../src/core/screen.c:979
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Nie można zwolnić podekranu %d ekranu \"%s\"\n"
@ -490,44 +477,45 @@ msgstr ""
"Te okna nie obsługują opcji zapisu aktualnego stanu (\"save current setup"
"\"), więc przy następnym zalogowaniu będą musiały zostać uruchomione ręcznie."
#: ../src/core/util.c:84
#: ../src/core/util.c:80
#, c-format
msgid "Failed to open debug log: %s\n"
msgstr "Otwarcie dziennika z zapisem wykonania się nie powiodło: %s\n"
#: ../src/core/util.c:94
#: ../src/core/util.c:90
#, c-format
msgid "Failed to fdopen() log file %s: %s\n"
msgstr "Wykonać fdopen() na pliku dziennika %s się nie powiodło: %s\n"
#: ../src/core/util.c:100
#: ../src/core/util.c:96
#, c-format
msgid "Opened log file %s\n"
msgstr "Otwarty plik dziennika %s\n"
#: ../src/core/util.c:119
#: ../src/core/util.c:115 ../src/tools/mutter-message.c:149
#, c-format
msgid "Mutter was compiled without support for verbose mode\n"
msgstr ""
"Program Mutter został skompilowany bez obsługi trybu z obszerną informacją\n"
#: ../src/core/util.c:264
#: ../src/core/util.c:259
msgid "Window manager: "
msgstr "Menedżer okien: "
#: ../src/core/util.c:414
#: ../src/core/util.c:407
msgid "Bug in window manager: "
msgstr "Błąd w programie menedżera okien: "
#: ../src/core/util.c:445
#: ../src/core/util.c:438
msgid "Window manager warning: "
msgstr "Ostrzeżenie menedżera okien: "
#: ../src/core/util.c:473
#: ../src/core/util.c:466
msgid "Window manager error: "
msgstr "Błąd menedżera okien: "
#. first time through
#: ../src/core/window.c:7533
#: ../src/core/window.c:7539
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -543,7 +531,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8257
#: ../src/core/window.c:8263
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -553,23 +541,23 @@ msgstr ""
"niezmienny, lecz jednocześnie ustawia minimalny rozmiar na %d x %d, a "
"maksymalny rozmiar na %d x %d. To nie ma żadnego sensu.\n"
#: ../src/core/window-props.c:347
#: ../src/core/window-props.c:318
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "Program ustawił błędną wartość _NET_WM_PID %lu\n"
#: ../src/core/window-props.c:463
#: ../src/core/window-props.c:434
#, c-format
msgid "%s (on %s)"
msgstr "%s (na %s)"
#: ../src/core/window-props.c:1546
#: ../src/core/window-props.c:1517
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr ""
"Nieprawidłowa wartość WM_TRANSIENT_FOR dla okna 0x%lx określona w %s.\n"
#: ../src/core/window-props.c:1557
#: ../src/core/window-props.c:1528
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "WM_TRANSIENT_FOR okna 0x%lx dla %s utworzyłoby pętlę.\n"
@ -742,104 +730,109 @@ msgstr "Wybór okna z wyskakującego okna dla tabulacji"
msgid "Cancel tab popup"
msgstr "Anulowanie wyskakującego okna dla tabulacji"
#: ../src/tools/mutter-message.c:123
#, c-format
msgid "Usage: %s\n"
msgstr "Użycie: %s\n"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:67
#: ../src/ui/menu.c:69
msgid "Mi_nimize"
msgstr "Zm_inimalizuj"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:69
#: ../src/ui/menu.c:71
msgid "Ma_ximize"
msgstr "Zm_aksymalizuj"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:71
#: ../src/ui/menu.c:73
msgid "Unma_ximize"
msgstr "Cofnij m_aksymalizację"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:73
#: ../src/ui/menu.c:75
msgid "Roll _Up"
msgstr "_Zwiń"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:75
#: ../src/ui/menu.c:77
msgid "_Unroll"
msgstr "Ro_zwiń"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:77
#: ../src/ui/menu.c:79
msgid "_Move"
msgstr "Prz_esuń"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:79
#: ../src/ui/menu.c:81
msgid "_Resize"
msgstr "Zmień _rozmiar"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:81
#: ../src/ui/menu.c:83
msgid "Move Titlebar On_screen"
msgstr "Przeno_szenie paska tytułowego na ekranie"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
msgid "Always on _Top"
msgstr "Zawsze na _wierzchu"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:88
#: ../src/ui/menu.c:90
msgid "_Always on Visible Workspace"
msgstr "_Zawsze na widocznym obszarze roboczym"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:90
#: ../src/ui/menu.c:92
msgid "_Only on This Workspace"
msgstr "_Tylko na tym obszarze roboczym"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:92
#: ../src/ui/menu.c:94
msgid "Move to Workspace _Left"
msgstr "Przenieś na _lewy obszar roboczy"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:94
#: ../src/ui/menu.c:96
msgid "Move to Workspace R_ight"
msgstr "Przen_ieś na prawy obszar roboczy"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:96
#: ../src/ui/menu.c:98
msgid "Move to Workspace _Up"
msgstr "_Przenieś na górny obszar roboczy"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:98
#: ../src/ui/menu.c:100
msgid "Move to Workspace _Down"
msgstr "Przenieś na _dolny obszar roboczy"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:102
#: ../src/ui/menu.c:104
msgid "_Close"
msgstr "Za_mknij"
#: ../src/ui/menu.c:202
#: ../src/ui/menu.c:204
#, c-format
msgid "Workspace %d%n"
msgstr "Obszar roboczy %d%n"
#: ../src/ui/menu.c:212
#: ../src/ui/menu.c:214
#, c-format
msgid "Workspace 1_0"
msgstr "Obszar roboczy 1_0"
#: ../src/ui/menu.c:214
#: ../src/ui/menu.c:216
#, c-format
msgid "Workspace %s%d"
msgstr "Obszar roboczy %s%d"
#: ../src/ui/menu.c:384
#: ../src/ui/menu.c:397
msgid "Move to Another _Workspace"
msgstr "Przeniesienie na inny _obszar roboczy"
@ -941,49 +934,49 @@ msgstr "Mod5"
msgid "%d x %d"
msgstr "%d x %d"
#: ../src/ui/theme.c:236
#: ../src/ui/theme.c:235
msgid "top"
msgstr "góra"
#: ../src/ui/theme.c:238
#: ../src/ui/theme.c:237
msgid "bottom"
msgstr "dół"
#: ../src/ui/theme.c:240
#: ../src/ui/theme.c:239
msgid "left"
msgstr "lewa"
#: ../src/ui/theme.c:242
#: ../src/ui/theme.c:241
msgid "right"
msgstr "prawa"
#: ../src/ui/theme.c:270
#: ../src/ui/theme.c:269
#, c-format
msgid "frame geometry does not specify \"%s\" dimension"
msgstr "Rozmiar ramki nie określa wymiaru \"%s\""
#: ../src/ui/theme.c:289
#: ../src/ui/theme.c:288
#, c-format
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
msgstr "Rozmiar ramki nie określa wymiaru \"%s\" dla krawędzi \"%s\""
#: ../src/ui/theme.c:326
#: ../src/ui/theme.c:325
#, c-format
msgid "Button aspect ratio %g is not reasonable"
msgstr ""
"Współczynnik proporcji przycisku %g nie mieści się w rozsądnych granicach"
#: ../src/ui/theme.c:338
#: ../src/ui/theme.c:337
#, c-format
msgid "Frame geometry does not specify size of buttons"
msgstr "Rozmiar ramki nie określa liczby przycisków"
#: ../src/ui/theme.c:1051
#: ../src/ui/theme.c:1050
#, c-format
msgid "Gradients should have at least two colors"
msgstr "Gradienty powinny się składać co najmniej z dwóch kolorów"
#: ../src/ui/theme.c:1203
#: ../src/ui/theme.c:1202
#, c-format
msgid ""
"GTK custom color specification must have color name and fallback in "
@ -993,7 +986,7 @@ msgstr ""
"kolor zastępczy w nawiasach, np. gtk:custom(foo,bar); nie można przetworzyć "
"\"%s\""
#: ../src/ui/theme.c:1219
#: ../src/ui/theme.c:1218
#, c-format
msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
@ -1002,7 +995,7 @@ msgstr ""
"Nieprawidłowy znak \"%c\" w parametrze nazwa_koloru opcji gtk:custom, tylko "
"znaki A-Za-z0-9-_ są prawidłowe"
#: ../src/ui/theme.c:1233
#: ../src/ui/theme.c:1232
#, c-format
msgid ""
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
@ -1011,7 +1004,7 @@ msgstr ""
"Formatem Gtk:custom jest \"gtk:custom(nazwa_koloru,kolor_zastępczy)\", \"%s"
"\" nie pasuje do formatu"
#: ../src/ui/theme.c:1278
#: ../src/ui/theme.c:1277
#, c-format
msgid ""
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
@ -1021,7 +1014,7 @@ msgstr ""
"kwadratowych, np. gtk:fg[NORMAL], gdzie NORMAL jest nazwą stanu; nie można "
"przetworzyć \"%s\""
#: ../src/ui/theme.c:1292
#: ../src/ui/theme.c:1291
#, c-format
msgid ""
"GTK color specification must have a close bracket after the state, e.g. gtk:"
@ -1031,17 +1024,17 @@ msgstr ""
"nawias kwadratowy, np. gtk:fg[NORMAL], gdzie NORMAL jest nazwą stanu; nie "
"można przetworzyć \"%s\""
#: ../src/ui/theme.c:1303
#: ../src/ui/theme.c:1302
#, c-format
msgid "Did not understand state \"%s\" in color specification"
msgstr "Niezrozumiały stan \"%s\" w specyfikacji koloru"
#: ../src/ui/theme.c:1316
#: ../src/ui/theme.c:1315
#, c-format
msgid "Did not understand color component \"%s\" in color specification"
msgstr "Niezrozumiała definicja koloru \"%s\" w specyfikacji koloru"
#: ../src/ui/theme.c:1345
#: ../src/ui/theme.c:1344
#, c-format
msgid ""
"Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the "
@ -1050,19 +1043,19 @@ msgstr ""
"Formatem przenikania jest \"blend/bg_color/fg_color/alpha\", \"%s\" nie "
"pasuje do formatu"
#: ../src/ui/theme.c:1356
#: ../src/ui/theme.c:1355
#, c-format
msgid "Could not parse alpha value \"%s\" in blended color"
msgstr "Nie można przetworzyć wartości alfa \"%s\" w przenikającym kolorze"
#: ../src/ui/theme.c:1366
#: ../src/ui/theme.c:1365
#, c-format
msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
msgstr ""
"Wartość alfa \"%s\" w przenikającym kolorze nie zawiera się pomiędzy 0,0 i "
"1,0"
#: ../src/ui/theme.c:1413
#: ../src/ui/theme.c:1412
#, c-format
msgid ""
"Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
@ -1070,29 +1063,29 @@ msgstr ""
"Formatem przenikania jest \"shade/base_color/factor\", \"%s\" nie pasuje do "
"formatu"
#: ../src/ui/theme.c:1424
#: ../src/ui/theme.c:1423
#, c-format
msgid "Could not parse shade factor \"%s\" in shaded color"
msgstr ""
"Nie można przetworzyć współczynnika przenikania \"%s\" w przenikającym "
"kolorze"
#: ../src/ui/theme.c:1434
#: ../src/ui/theme.c:1433
#, c-format
msgid "Shade factor \"%s\" in shaded color is negative"
msgstr "Współczynnik przenikania \"%s\" w przenikającym kolorze jest ujemny"
#: ../src/ui/theme.c:1463
#: ../src/ui/theme.c:1462
#, c-format
msgid "Could not parse color \"%s\""
msgstr "Nie można przetworzyć koloru \"%s\""
#: ../src/ui/theme.c:1780
#: ../src/ui/theme.c:1779
#, c-format
msgid "Coordinate expression contains character '%s' which is not allowed"
msgstr "Wyrażenie określające współrzędne zawiera niedozwolony znak \"%s\""
#: ../src/ui/theme.c:1807
#: ../src/ui/theme.c:1806
#, c-format
msgid ""
"Coordinate expression contains floating point number '%s' which could not be "
@ -1101,14 +1094,14 @@ msgstr ""
"Wyrażenie określające współrzędne zawiera liczbę zmiennoprzecinkową \"%s\", "
"której nie można przetworzyć"
#: ../src/ui/theme.c:1821
#: ../src/ui/theme.c:1820
#, c-format
msgid "Coordinate expression contains integer '%s' which could not be parsed"
msgstr ""
"Wyrażenie określające współrzędne zawiera liczbę całkowitą \"%s\", której "
"nie można przetworzyć"
#: ../src/ui/theme.c:1942
#: ../src/ui/theme.c:1941
#, c-format
msgid ""
"Coordinate expression contained unknown operator at the start of this text: "
@ -1117,18 +1110,18 @@ msgstr ""
"Wyrażenie określające współrzędne zawiera nieznany operator na początku "
"tekstu: \"%s\""
#: ../src/ui/theme.c:1999
#: ../src/ui/theme.c:1998
#, c-format
msgid "Coordinate expression was empty or not understood"
msgstr ""
"Wyrażenie określające współrzędne jest puste lub nie można go rozpoznać"
#: ../src/ui/theme.c:2112 ../src/ui/theme.c:2122 ../src/ui/theme.c:2156
#: ../src/ui/theme.c:2111 ../src/ui/theme.c:2121 ../src/ui/theme.c:2155
#, c-format
msgid "Coordinate expression results in division by zero"
msgstr "Wyrażenie opisujące położenie zawiera dzielenie przez zero"
#: ../src/ui/theme.c:2164
#: ../src/ui/theme.c:2163
#, c-format
msgid ""
"Coordinate expression tries to use mod operator on a floating-point number"
@ -1136,7 +1129,7 @@ msgstr ""
"Wyrażenie opisujące położenie używa operatora dzielenia modulo z liczbą "
"zmiennoprzecinkową"
#: ../src/ui/theme.c:2220
#: ../src/ui/theme.c:2219
#, c-format
msgid ""
"Coordinate expression has an operator \"%s\" where an operand was expected"
@ -1144,19 +1137,19 @@ msgstr ""
"Wyrażenie opisujące położenie zawiera operator \"%s\" w miejscu, w którym "
"oczekiwano operandu"
#: ../src/ui/theme.c:2229
#: ../src/ui/theme.c:2228
#, c-format
msgid "Coordinate expression had an operand where an operator was expected"
msgstr ""
"Wyrażenie opisujące położenie zawiera operand w miejscu, w którym oczekiwano "
"operatora"
#: ../src/ui/theme.c:2237
#: ../src/ui/theme.c:2236
#, c-format
msgid "Coordinate expression ended with an operator instead of an operand"
msgstr "Wyrażenie opisujące położenie kończy się operatorem zamiast operandem"
#: ../src/ui/theme.c:2247
#: ../src/ui/theme.c:2246
#, c-format
msgid ""
"Coordinate expression has operator \"%c\" following operator \"%c\" with no "
@ -1165,43 +1158,43 @@ msgstr ""
"Wyrażenie opisujące położenie zawiera operator \"%c\" bezpośrednio po "
"operatorze \"%c\" bez rozdzielającego ich operandu"
#: ../src/ui/theme.c:2398 ../src/ui/theme.c:2443
#: ../src/ui/theme.c:2397 ../src/ui/theme.c:2442
#, c-format
msgid "Coordinate expression had unknown variable or constant \"%s\""
msgstr ""
"Wyrażenie opisujące położenie zawiera nieznaną zmienną lub stałą \"%s\""
#: ../src/ui/theme.c:2497
#: ../src/ui/theme.c:2496
#, c-format
msgid "Coordinate expression parser overflowed its buffer."
msgstr "Parser wyrażeń określających współrzędne przepełnił swój bufor."
#: ../src/ui/theme.c:2526
#: ../src/ui/theme.c:2525
#, c-format
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
msgstr ""
"Wyrażenie opisujące położenie zawiera nawias zamykający bez odpowiadającego "
"mu nawiasu otwierającego"
#: ../src/ui/theme.c:2590
#: ../src/ui/theme.c:2589
#, c-format
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
msgstr ""
"Wyrażenie opisujące położenie zawiera nawias otwierający bez odpowiadającego "
"mu nawiasu zamykającego"
#: ../src/ui/theme.c:2601
#: ../src/ui/theme.c:2600
#, c-format
msgid "Coordinate expression doesn't seem to have any operators or operands"
msgstr ""
"Wyrażenie opisujące położenie nie zawiera żadnych operatorów ani operandów"
#: ../src/ui/theme.c:2814 ../src/ui/theme.c:2834 ../src/ui/theme.c:2854
#: ../src/ui/theme.c:2813 ../src/ui/theme.c:2833 ../src/ui/theme.c:2853
#, c-format
msgid "Theme contained an expression that resulted in an error: %s\n"
msgstr "Motyw zawiera wyrażenie, przy którego obliczaniu wystąpił błąd: %s\n"
#: ../src/ui/theme.c:4500
#: ../src/ui/theme.c:4499
#, c-format
msgid ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
@ -1210,25 +1203,25 @@ msgstr ""
"Przy tym stylu ramki należy podać <button function=\"%s\" state=\"%s\" "
"draw_ops=\"cokolwiek\"/>"
#: ../src/ui/theme.c:5011 ../src/ui/theme.c:5036
#: ../src/ui/theme.c:5010 ../src/ui/theme.c:5035
#, c-format
msgid ""
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
msgstr ""
"Brak <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"cokolwiek\"/>"
#: ../src/ui/theme.c:5082
#: ../src/ui/theme.c:5083
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Wczytanie motywu \"%s\" się nie powiodło: %s\n"
#: ../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
#: ../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
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "Nie określono elementu <%s> dla motywu \"%s\""
#: ../src/ui/theme.c:5254
#: ../src/ui/theme.c:5255
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@ -1237,7 +1230,7 @@ msgstr ""
"Przy typie okna \"%s\" w motywie \"%s\" nie ustawiono stylu ramki. Należy "
"dodać element <window type=\"%s\" style_set=\"cokolwiek\"/>"
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
#: ../src/ui/theme.c:5662 ../src/ui/theme.c:5724 ../src/ui/theme.c:5787
#, c-format
msgid ""
"User-defined constants must begin with a capital letter; \"%s\" does not"
@ -1245,7 +1238,7 @@ msgstr ""
"Stałe definiowane przez użytkownika powinny rozpoczynać się wielką literą, "
"natomiast \"%s\" nie spełnia tego warunku"
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
#: ../src/ui/theme.c:5670 ../src/ui/theme.c:5732 ../src/ui/theme.c:5795
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "Stała \"%s\" została już określona"
@ -1633,7 +1626,208 @@ msgstr "Wewnątrz elementu <%s> nie jest dopuszczalny tekst"
msgid "<%s> specified twice for this theme"
msgstr "<%s> określono dwukrotnie dla tego motywu"
#: ../src/ui/theme-parser.c:4336
#: ../src/ui/theme-parser.c:4334
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "Odnalezienie prawidłowego pliku dla motywu %s się nie powiodło\n"
#: ../src/ui/theme-viewer.c:99
msgid "_Windows"
msgstr "_Okna"
#: ../src/ui/theme-viewer.c:100
msgid "_Dialog"
msgstr "Okno _dialogowe"
#: ../src/ui/theme-viewer.c:101
msgid "_Modal dialog"
msgstr "_Modalne okno dialogowe"
#: ../src/ui/theme-viewer.c:102
msgid "_Utility"
msgstr "_Narzędzie"
#: ../src/ui/theme-viewer.c:103
msgid "_Splashscreen"
msgstr "_Ekran powitalny"
#: ../src/ui/theme-viewer.c:104
msgid "_Top dock"
msgstr "_Górny dok"
#: ../src/ui/theme-viewer.c:105
msgid "_Bottom dock"
msgstr "_Dolny dok"
#: ../src/ui/theme-viewer.c:106
msgid "_Left dock"
msgstr "_Lewy dok"
#: ../src/ui/theme-viewer.c:107
msgid "_Right dock"
msgstr "_Prawy dok"
#: ../src/ui/theme-viewer.c:108
msgid "_All docks"
msgstr "_Wszystkie doki"
#: ../src/ui/theme-viewer.c:109
msgid "Des_ktop"
msgstr "Pu_lpit"
#: ../src/ui/theme-viewer.c:115
msgid "Open another one of these windows"
msgstr "Otwiera kolejne okno tego typu"
#: ../src/ui/theme-viewer.c:117
msgid "This is a demo button with an 'open' icon"
msgstr "To jest przycisk demonstracyjny z ikoną \"otwórz\""
#: ../src/ui/theme-viewer.c:119
msgid "This is a demo button with a 'quit' icon"
msgstr "To jest przycisk demonstracyjny z ikoną \"zakończ\""
#: ../src/ui/theme-viewer.c:248
msgid "This is a sample message in a sample dialog"
msgstr "To jest przykładowy komunikat w prostym oknie dialogowym"
#: ../src/ui/theme-viewer.c:328
#, c-format
msgid "Fake menu item %d\n"
msgstr "Imitacja elementu menu %d\n"
#: ../src/ui/theme-viewer.c:363
msgid "Border-only window"
msgstr "Okno zawierające tylko krawędzie"
#: ../src/ui/theme-viewer.c:365
msgid "Bar"
msgstr "Pasek"
#: ../src/ui/theme-viewer.c:382
msgid "Normal Application Window"
msgstr "Zwykłe okno programu"
#: ../src/ui/theme-viewer.c:386
msgid "Dialog Box"
msgstr "Okno dialogowe"
#: ../src/ui/theme-viewer.c:390
msgid "Modal Dialog Box"
msgstr "Modalne okno dialogowe"
#: ../src/ui/theme-viewer.c:394
msgid "Utility Palette"
msgstr "Paleta narzędziowa"
#: ../src/ui/theme-viewer.c:398
msgid "Torn-off Menu"
msgstr "Menu oderwane"
#: ../src/ui/theme-viewer.c:402
msgid "Border"
msgstr "Krawędź"
#: ../src/ui/theme-viewer.c:406
msgid "Attached Modal Dialog"
msgstr "Dołączone modalne okno dialogowe"
#: ../src/ui/theme-viewer.c:737
#, c-format
msgid "Button layout test %d"
msgstr "Test układu przycisków %d"
#: ../src/ui/theme-viewer.c:766
#, c-format
msgid "%g milliseconds to draw one window frame"
msgstr "%g milisekundy do narysowania jednej ramki okna"
#: ../src/ui/theme-viewer.c:811
#, c-format
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
msgstr "Użycie: metacity-theme-viewer [NAZWA_MOTYWU]\n"
#: ../src/ui/theme-viewer.c:818
#, c-format
msgid "Error loading theme: %s\n"
msgstr "Błąd podczas wczytywania motywu: %s\n"
#: ../src/ui/theme-viewer.c:824
#, c-format
msgid "Loaded theme \"%s\" in %g seconds\n"
msgstr "Wczytano motyw \"%s\" w ciągu %g sekund\n"
#: ../src/ui/theme-viewer.c:869
msgid "Normal Title Font"
msgstr "Zwykła czcionka tytułu"
#: ../src/ui/theme-viewer.c:875
msgid "Small Title Font"
msgstr "Mała czcionka tytułu"
#: ../src/ui/theme-viewer.c:881
msgid "Large Title Font"
msgstr "Duża czcionka tytułu"
#: ../src/ui/theme-viewer.c:886
msgid "Button Layouts"
msgstr "Układy przycisków"
#: ../src/ui/theme-viewer.c:891
msgid "Benchmark"
msgstr "Test wydajności"
#: ../src/ui/theme-viewer.c:947
msgid "Window Title Goes Here"
msgstr "Tutaj znajduje się tytuł okna"
# FIXME - bełkot
#: ../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 ""
"Narysowano %d ramek w ciągu %g sekund klienta (%g milisekund na ramkę) oraz "
"%g sekund rzeczywistych, włączając w to zasoby serwera X (%g milisekund na "
"ramkę)\n"
#: ../src/ui/theme-viewer.c:1273
msgid "position expression test returned TRUE but set error"
msgstr "Test wyrażenia pozycji zwrócił wartość PRAWDA, lecz ustawił błąd"
#: ../src/ui/theme-viewer.c:1275
msgid "position expression test returned FALSE but didn't set error"
msgstr "Test wyrażenia pozycji zwrócił wartość FAŁSZ, lecz nie ustawił błędu"
#: ../src/ui/theme-viewer.c:1279
msgid "Error was expected but none given"
msgstr "Oczekiwano błędu, lecz nie otrzymano żadnego"
#: ../src/ui/theme-viewer.c:1281
#, c-format
msgid "Error %d was expected but %d given"
msgstr "Oczekiwano błędu %d, lecz otrzymano %d"
#: ../src/ui/theme-viewer.c:1287
#, c-format
msgid "Error not expected but one was returned: %s"
msgstr "Nie oczekiwano błędu, lecz został on zwrócony: %s"
#: ../src/ui/theme-viewer.c:1291
#, c-format
msgid "x value was %d, %d was expected"
msgstr "Wartością X było %d, oczekiwano wartości %d"
#: ../src/ui/theme-viewer.c:1294
#, c-format
msgid "y value was %d, %d was expected"
msgstr "Wartością Y było %d, oczekiwano wartości %d"
#: ../src/ui/theme-viewer.c:1359
#, c-format
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
msgstr ""
"Wyrażenia współrzędnych %d zostało przetworzone w %g sekund (średnio %g "
"sekund)\n"

654
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

417
po/sk.po
View File

@ -13,9 +13,9 @@ msgstr ""
"Project-Id-Version: mutter\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2013-08-21 17:41+0000\n"
"PO-Revision-Date: 2013-08-02 14:46+0200\n"
"Last-Translator: Ján Kyselica <kyselica.jan@gmail.com>\n"
"POT-Creation-Date: 2013-05-24 21:44+0000\n"
"PO-Revision-Date: 2013-05-18 16:53+0100\n"
"Last-Translator: Jan Kyselica <kyselica.jan@gmail.com>\n"
"Language-Team: Slovak <gnome-sk-list@gnome.org>\n"
"Language: sk\n"
"MIME-Version: 1.0\n"
@ -87,8 +87,9 @@ msgstr "Prepnúť okná aplikácie"
# PK: zisti co to robi
# description
#: ../src/50-mutter-navigation.xml.in.h:13
#, fuzzy
msgid "Switch system controls"
msgstr "Prepnúť medzi ovládacími prvkami systému"
msgstr "Prepnúť medzi systémovými ovládacími prvkami"
# description
#: ../src/50-mutter-navigation.xml.in.h:14
@ -103,8 +104,9 @@ msgstr "Prepnúť okná aplikácie priamo"
# MČ: podobne ako vyššie: „cycle-panels“
# description
#: ../src/50-mutter-navigation.xml.in.h:16
#, fuzzy
msgid "Switch system controls directly"
msgstr "Prepnúť medzi ovládacími prvkami systému priamo"
msgstr "Prepnúť medzi systémovými ovládacími prvkami priamo"
# description
#: ../src/50-mutter-navigation.xml.in.h:17
@ -265,13 +267,13 @@ msgstr "Zobraziť rozdelenie napravo"
# PK: je %i cislo obrazovky? ak ano tak "č. %i"
#. 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:596
#, c-format
#: ../src/compositor/compositor.c:571
#, fuzzy, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
"\"."
msgstr ""
"Pre obrazovku č. %i na displeji „%s“ je spustený už iný správca rozloženia."
"Pre obrazovku %i na displeji „%s“ je spustený už iný správca rozloženia."
#: ../src/compositor/meta-background.c:1076
msgid "background texture could not be created from file"
@ -311,18 +313,18 @@ msgstr "_Počkať"
msgid "_Force Quit"
msgstr "_Vynútiť ukončenie"
#: ../src/core/display.c:421
#: ../src/core/display.c:401
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Rozšírenie %s, potrebné pre kompozitné prostredie, chýba"
# X window system preloz, napr. system na spravu okien X
#: ../src/core/display.c:513
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Zlyhalo otvorenie displeja systému na správu okien X „%s“\n"
#: ../src/core/keybindings.c:1136
#: ../src/core/keybindings.c:970
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -330,7 +332,7 @@ msgid ""
msgstr ""
"Iný program už používa kláves %s s modifikátormi %x ako klávesovú skratku\n"
#: ../src/core/keybindings.c:1333
#: ../src/core/keybindings.c:1151
#, c-format
msgid "\"%s\" is not a valid accelerator\n"
msgstr "„%s“ nie je platný akcelerátor\n"
@ -376,20 +378,6 @@ msgid ""
msgstr ""
"Nepodarilo sa nájsť tému! Overte, že %s existuje a obsahuje obvyklé témy.\n"
#: ../src/core/monitor.c:702
msgid "Built-in display"
msgstr "Vstavaný 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:730
#, c-format
#| msgid "Unknown element %s"
msgid "Unknown %s"
msgstr "Neznámy %s"
#: ../src/core/mutter.c:40
#, c-format
msgid ""
@ -415,7 +403,7 @@ msgstr "Zobrazí verziu"
msgid "Mutter plugin to use"
msgstr "Použije zásuvný modul Mutter"
#: ../src/core/prefs.c:1202
#: ../src/core/prefs.c:1193
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -423,12 +411,12 @@ msgstr ""
"Náhradné riešenia pre chybné aplikácie nie sú povolené. Niektoré aplikácie "
"sa nemusia správať správne.\n"
#: ../src/core/prefs.c:1277
#: ../src/core/prefs.c:1268
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Nepodarilo sa spracovať popis písma „%s“ z kľúča GSettings %s\n"
#: ../src/core/prefs.c:1343
#: ../src/core/prefs.c:1334
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -437,7 +425,7 @@ msgstr ""
"V konfiguračnej databáze sa našlo „%s“, čo nie je platná hodnota pre "
"modifikátor tlačidla myši\n"
#: ../src/core/prefs.c:1909
#: ../src/core/prefs.c:1881
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@ -446,17 +434,17 @@ msgstr ""
"V konfiguračnej databáze sa našlo „%s“, čo nie je platná hodnota pre "
"klávesovú skratku „%s“\n"
#: ../src/core/prefs.c:1999
#: ../src/core/prefs.c:1945
#, c-format
msgid "Workspace %d"
msgstr "Pracovný priestor č. %d"
#: ../src/core/screen.c:537
#: ../src/core/screen.c:691
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Obrazovka č. %d na displeji „%s“ nie je platná\n"
#: ../src/core/screen.c:553
#: ../src/core/screen.c:707
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@ -465,7 +453,7 @@ msgstr ""
"Obrazovka č. %d na displeji „%s“ už má správcu okien. Skúste použiť prepínač "
"--replace, aby sa aktuálny správca nahradil.\n"
#: ../src/core/screen.c:580
#: ../src/core/screen.c:734
#, c-format
msgid ""
"Could not acquire window manager selection on screen %d display \"%s\"\n"
@ -473,12 +461,12 @@ msgstr ""
"Nepodarilo sa získať výber správcu okien pre obrazovku č. %d na displeji "
"„%s“\n"
#: ../src/core/screen.c:658
#: ../src/core/screen.c:812
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "Obrazovka č. %d na displeji „%s“ už má správcu okien\n"
#: ../src/core/screen.c:850
#: ../src/core/screen.c:998
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Nepodarilo sa uvoľniť obrazovku č. %d na displeji „%s“\n"
@ -554,7 +542,8 @@ msgstr "Zlyhalo otvorenie súboru so záznamom pomocou fdopen() %s: %s\n"
msgid "Opened log file %s\n"
msgstr "Otvorený súbor so záznamom %s\n"
#: ../src/core/util.c:119
#: ../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 bol skompilovaný bez výpisu podrobností pri behu\n"
@ -562,20 +551,20 @@ msgstr "Mutter bol skompilovaný bez výpisu podrobností pri behu\n"
msgid "Window manager: "
msgstr "Správca okien: "
#: ../src/core/util.c:414
#: ../src/core/util.c:412
msgid "Bug in window manager: "
msgstr "Chyba v správcovi okien: "
#: ../src/core/util.c:445
#: ../src/core/util.c:443
msgid "Window manager warning: "
msgstr "Varovanie správcu okien: "
#: ../src/core/util.c:473
#: ../src/core/util.c:471
msgid "Window manager error: "
msgstr "Chyba správcu okien: "
#. first time through
#: ../src/core/window.c:7533
#: ../src/core/window.c:7505
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -591,7 +580,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8257
#: ../src/core/window.c:8229
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -601,7 +590,7 @@ msgstr ""
"nastavuje minimálnu veľkosť %d x %d a maximálnu veľkosť %d x %d. To nedáva "
"zmysel.\n"
#: ../src/core/window-props.c:347
#: ../src/core/window-props.c:318
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "Aplikácia nastavila neplatné _NET_WM_PID %lu\n"
@ -609,18 +598,18 @@ msgstr "Aplikácia nastavila neplatné _NET_WM_PID %lu\n"
# PK: co je toto?
# JK: nedokazem zistit
# PM: vyžiadaj komentár od vývojárov, pomožeme aj ostatným prekladateľom
#: ../src/core/window-props.c:463
#: ../src/core/window-props.c:434
#, fuzzy, c-format
msgid "%s (on %s)"
msgstr "%s (na %s)"
#: ../src/core/window-props.c:1546
#: ../src/core/window-props.c:1517
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "Neplatné WM_TRANSIENT_FOR okno 0x%lx nastavené pre %s.\n"
# MČ: zacykliť sa, alebo vytvoriť slučku.
#: ../src/core/window-props.c:1557
#: ../src/core/window-props.c:1528
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "WM_TRANSIENT_FOR okno 0x%lx pre %s môže vytvoriť slučku.\n"
@ -708,9 +697,9 @@ msgid ""
"vertically and resizes them horizontally to cover half of the available "
"area. Dropping windows on the top screen edge maximizes them completely."
msgstr ""
"Ak je povolené, upustenie okien pri zvislých okrajoch obrazovky ich zvislo "
"maximalizuje a vodorovná veľkosť sa zmení na polovicu dostupnej plochy. "
"Upustenie okien pri vrchnom okraji obrazovky ich maximalizuje úplne."
"Ak je povolené, upustenie okien pri zvislých okrajoch obrazovky ich "
"zvislo maximalizuje a vodorovná veľkosť sa zmení na polovicu dostupnej "
"plochy. Upustenie okien pri vrchnom okraji obrazovky ich maximalizuje úplne."
# summary
#: ../src/org.gnome.mutter.gschema.xml.in.h:7
@ -746,8 +735,9 @@ msgstr ""
# PM: ja by som dal Bez vyvovlávania tabulátorom
# summary
#: ../src/org.gnome.mutter.gschema.xml.in.h:11
#, fuzzy
msgid "No tab popup"
msgstr "Bez vyvolávania tabulátorom"
msgstr "Nepoužívať prekryvnú ponuku tabulátora"
# MČ: Neviem, čo to presne má robiť, ale popis som pochopil inak. „…či sa má používať rozbaľovacia ponuka a zvýraznenie rámikom sa má vypnúť…“
# description
@ -816,104 +806,109 @@ msgstr "Vybrať okno z rozbaľovacej ponuky tabulátoru"
msgid "Cancel tab popup"
msgstr "Zrušit rozbaľovaciu ponuku tabulátoru"
#: ../src/tools/mutter-message.c:123
#, c-format
msgid "Usage: %s\n"
msgstr "Použitie: %s\n"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:67
#: ../src/ui/menu.c:69
msgid "Mi_nimize"
msgstr "Mi_nimalizovať"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:69
#: ../src/ui/menu.c:71
msgid "Ma_ximize"
msgstr "Ma_ximalizovať"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:71
#: ../src/ui/menu.c:73
msgid "Unma_ximize"
msgstr "Zrušiť ma_ximalizáciu"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:73
#: ../src/ui/menu.c:75
msgid "Roll _Up"
msgstr "_Zabaliť"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:75
#: ../src/ui/menu.c:77
msgid "_Unroll"
msgstr "_Rozbaliť"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:77
#: ../src/ui/menu.c:79
msgid "_Move"
msgstr "Pre_miestniť"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:79
#: ../src/ui/menu.c:81
msgid "_Resize"
msgstr "Zmeniť veľko_sť"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:81
#: ../src/ui/menu.c:83
msgid "Move Titlebar On_screen"
msgstr "Presunúť titulok na _obrazovku"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
msgid "Always on _Top"
msgstr "Vždy na_vrchu"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:88
#: ../src/ui/menu.c:90
msgid "_Always on Visible Workspace"
msgstr "Vž_dy na viditeľnom pracovnom priestore"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:90
#: ../src/ui/menu.c:92
msgid "_Only on This Workspace"
msgstr "_Len na tomto pracovnom priestore"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:92
#: ../src/ui/menu.c:94
msgid "Move to Workspace _Left"
msgstr "Presunúť na pracovný priestor vľav_o"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:94
#: ../src/ui/menu.c:96
msgid "Move to Workspace R_ight"
msgstr "Presunúť na pracovný priestor v_pravo"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:96
#: ../src/ui/menu.c:98
msgid "Move to Workspace _Up"
msgstr "Presunúť na pracovný priestor _hore"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:98
#: ../src/ui/menu.c:100
msgid "Move to Workspace _Down"
msgstr "Presunúť na pracovný priestor _dole"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:102
#: ../src/ui/menu.c:104
msgid "_Close"
msgstr "_Zavrieť"
#: ../src/ui/menu.c:202
#: ../src/ui/menu.c:204
#, c-format
msgid "Workspace %d%n"
msgstr "Pracovná priestor %d%n"
#: ../src/ui/menu.c:212
#: ../src/ui/menu.c:214
#, c-format
msgid "Workspace 1_0"
msgstr "Pracovný priestor 1_0"
#: ../src/ui/menu.c:214
#: ../src/ui/menu.c:216
#, c-format
msgid "Workspace %s%d"
msgstr "Pracovný priestor %s%d"
#: ../src/ui/menu.c:384
#: ../src/ui/menu.c:397
msgid "Move to Another _Workspace"
msgstr "P_resunúť na iný pracovný priestor"
@ -1071,21 +1066,21 @@ msgstr ""
# MČ: Preformuloval by som koniec: „platné sú len znaky A-Za-z0-9-_“
# PK: color_name je asi nejaky atribut, to sa nepreklada, ked tak do zatvorky
#: ../src/ui/theme.c:1219
#, c-format
#, fuzzy, c-format
msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
"_ are valid"
msgstr ""
"V parametri color_name (názov farby) pre gtk:custom je neplatný znak „%c“, platné sú len "
"V parametri názov_farby pre gtk:custom je neplatný znak „%c“, platné sú len "
"znaky A-Za-z0-9-_"
#: ../src/ui/theme.c:1233
#, c-format
#, fuzzy, c-format
msgid ""
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
"fit the format"
msgstr ""
"Formát Gtk:custom je „gtk:custom(color_name,fallback)“, „%s“ tomu "
"Formát Gtk:custom je „gtk:custom(názov_farby,fallback)“, „%s“ tomu "
"nezodpovedá"
#: ../src/ui/theme.c:1278
@ -1271,20 +1266,20 @@ msgid ""
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
msgstr "Chýbajúce <frame state=„%s“ resize=„%s“ focus=„%s“ style=„whatever“/>"
#: ../src/ui/theme.c:5082
#: ../src/ui/theme.c:5084
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Zlyhalo načítanie témy „%s“: %s\n"
# PK: prvok?
# JK: XML značka (XML tag)
#: ../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
#: ../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 "Pre tému „%s“ nie je nastavená <%s>"
#: ../src/ui/theme.c:5254
#: ../src/ui/theme.c:5256
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@ -1293,13 +1288,13 @@ msgstr ""
"Pre typ okna „%s“ nie je sada štýlov v téme „%s“, pridajte prvok <window "
"type=„%s“ style_set=„whatever“/>"
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
#: ../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 "Používateľské konštanty musia začínať veľkým písmenom, „%s“ nezačína"
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
#: ../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 "Konštanta „%s“ už je definovaná"
@ -1402,7 +1397,7 @@ msgstr "<%s> musí uvádzať buď geometriu alebo rodiča, ktorý má geometriu"
msgid "You must specify a background for an alpha value to be meaningful"
msgstr "Ak má byť hodnota alpha zmysluplná, tak musíte vybrať nejaké pozadie"
#  PM: asi atribút type
# PM: asi atribút type
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
#: ../src/ui/theme-parser.c:1264
#, fuzzy, c-format
@ -1564,7 +1559,6 @@ msgid "\"%s\" is not a valid value for resize attribute"
msgstr "„%s“ nie je platná hodnota pre atribút zmeny veľkosti"
# PK: shaded states? to zatvorky daj popis co je resize
# PM: skôr "pre stavy maximized (maximalizovaný)/shaded (zatienený)"
#: ../src/ui/theme-parser.c:3147
#, fuzzy, c-format
msgid ""
@ -1706,172 +1700,221 @@ msgstr "<%s> uvedený dvakrát pre túto tému"
msgid "Failed to find a valid file for theme %s\n"
msgstr "Zlyhalo nájdenie platného súboru pre tému%s\n"
#~ msgid "Usage: %s\n"
#~ msgstr "Použitie: %s\n"
#: ../src/ui/theme-viewer.c:99
msgid "_Windows"
msgstr "_Okná"
#~ msgid "_Windows"
#~ msgstr "_Okná"
#: ../src/ui/theme-viewer.c:100
msgid "_Dialog"
msgstr "_Dialógové okno"
#~ msgid "_Dialog"
#~ msgstr "_Dialógové okno"
#: ../src/ui/theme-viewer.c:101
msgid "_Modal dialog"
msgstr "_Modálne dialógové okno"
#~ msgid "_Modal dialog"
#~ msgstr "_Modálne dialógové okno"
#: ../src/ui/theme-viewer.c:102
msgid "_Utility"
msgstr "_Nástroje"
#~ msgid "_Utility"
#~ msgstr "_Nástroje"
#~ msgid "_Splashscreen"
#~ msgstr "Ú_vodná obrazovka"
#: ../src/ui/theme-viewer.c:103
msgid "_Splashscreen"
msgstr "Ú_vodná obrazovka"
# MČ: nie som si istý prekladom „dok“, nemal by to byť „panel“?
#~ msgid "_Top dock"
#~ msgstr "_Horný panel"
#: ../src/ui/theme-viewer.c:104
msgid "_Top dock"
msgstr "_Horný panel"
#~ msgid "_Bottom dock"
#~ msgstr "_Spodný panel"
#: ../src/ui/theme-viewer.c:105
msgid "_Bottom dock"
msgstr "_Spodný panel"
#~ msgid "_Left dock"
#~ msgstr "Ľ_avý panel"
#: ../src/ui/theme-viewer.c:106
msgid "_Left dock"
msgstr "Ľ_avý panel"
#~ msgid "_Right dock"
#~ msgstr "_Pravý panel"
#: ../src/ui/theme-viewer.c:107
msgid "_Right dock"
msgstr "_Pravý panel"
#~ msgid "_All docks"
#~ msgstr "_Všetky panely"
#: ../src/ui/theme-viewer.c:108
msgid "_All docks"
msgstr "_Všetky panely"
#~ msgid "Des_ktop"
#~ msgstr "P_racovná plocha"
#: ../src/ui/theme-viewer.c:109
msgid "Des_ktop"
msgstr "P_racovná plocha"
# tooltip
#~ msgid "Open another one of these windows"
#~ msgstr "Otvorí ďalšie z týchto okien"
#: ../src/ui/theme-viewer.c:115
msgid "Open another one of these windows"
msgstr "Otvorí ďalšie z týchto okien"
# PK: prekladat to v uvodzovkach? nahlas bug
# tooltip
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
#: ../src/ui/theme-viewer.c:117
#, fuzzy
#~ msgid "This is a demo button with an 'open' icon"
#~ msgstr "Toto je ukážkové tlačidlo s ikonou „open“"
msgid "This is a demo button with an 'open' icon"
msgstr "Toto je ukážkové tlačidlo s ikonou „open“"
# tooltip
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=698123
#: ../src/ui/theme-viewer.c:119
#, fuzzy
#~ msgid "This is a demo button with a 'quit' icon"
#~ msgstr "Toto je ukážkové tlačidlo s ikonou „quit“"
msgid "This is a demo button with a 'quit' icon"
msgstr "Toto je ukážkové tlačidlo s ikonou „quit“"
# label
#~ msgid "This is a sample message in a sample dialog"
#~ msgstr "Toto je ukážková správa v ukážkovom dialógovom okne"
#: ../src/ui/theme-viewer.c:248
msgid "This is a sample message in a sample dialog"
msgstr "Toto je ukážková správa v ukážkovom dialógovom okne"
# PK: falosna
#~ msgid "Fake menu item %d\n"
#~ msgstr "Falošná položka ponuky č. %d\n"
#: ../src/ui/theme-viewer.c:328
#, c-format
msgid "Fake menu item %d\n"
msgstr "Falošná položka ponuky č. %d\n"
#~ msgid "Border-only window"
#~ msgstr "Okno len s okrajom"
#: ../src/ui/theme-viewer.c:363
msgid "Border-only window"
msgstr "Okno len s okrajom"
#~ msgid "Bar"
#~ msgstr "Lišta"
#: ../src/ui/theme-viewer.c:365
msgid "Bar"
msgstr "Lišta"
#~ msgid "Normal Application Window"
#~ msgstr "Normálne aplikačné okno"
#: ../src/ui/theme-viewer.c:382
msgid "Normal Application Window"
msgstr "Normálne aplikačné okno"
#~ msgid "Dialog Box"
#~ msgstr "Dialógové okno"
#: ../src/ui/theme-viewer.c:386
msgid "Dialog Box"
msgstr "Dialógové okno"
#~ msgid "Modal Dialog Box"
#~ msgstr "Modálne dialógové okno"
#: ../src/ui/theme-viewer.c:390
msgid "Modal Dialog Box"
msgstr "Modálne dialógové okno"
#~ msgid "Utility Palette"
#~ msgstr "Paleta nástrojov"
#: ../src/ui/theme-viewer.c:394
msgid "Utility Palette"
msgstr "Paleta nástrojov"
#~ msgid "Torn-off Menu"
#~ msgstr "Vypnúť ponuku"
#: ../src/ui/theme-viewer.c:398
msgid "Torn-off Menu"
msgstr "Vypnúť ponuku"
#~ msgid "Border"
#~ msgstr "Okraj"
#: ../src/ui/theme-viewer.c:402
msgid "Border"
msgstr "Okraj"
#~ msgid "Attached Modal Dialog"
#~ msgstr "Pričlenené modálne okno"
#: ../src/ui/theme-viewer.c:406
msgid "Attached Modal Dialog"
msgstr "Pričlenené modálne okno"
#~ msgid "Button layout test %d"
#~ msgstr "Test rozloženia tlačidiel č. %d"
#: ../src/ui/theme-viewer.c:737
#, c-format
msgid "Button layout test %d"
msgstr "Test rozloženia tlačidiel č. %d"
# PK: plural forms
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
#, fuzzy
#~ msgid "%g milliseconds to draw one window frame"
#~ msgstr "%g milisekúnd pre vykreslenie jedného rámca okna"
#: ../src/ui/theme-viewer.c:766
#, fuzzy, c-format
msgid "%g milliseconds to draw one window frame"
msgstr "%g milisekúnd pre vykreslenie jedného rámca okna"
#~ msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
#~ msgstr "Použitie: metacity-theme-viewer [NÁZOVTÉMY]\n"
#: ../src/ui/theme-viewer.c:811
#, c-format
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
msgstr "Použitie: metacity-theme-viewer [NÁZOVTÉMY]\n"
#~ msgid "Error loading theme: %s\n"
#~ msgstr "Chyba pri načítavaní témy: %s\n"
#: ../src/ui/theme-viewer.c:818
#, c-format
msgid "Error loading theme: %s\n"
msgstr "Chyba pri načítavaní témy: %s\n"
# PK: plural forms
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
#, fuzzy
#~ msgid "Loaded theme \"%s\" in %g seconds\n"
#~ msgstr "Téma „%s“ načítaná za %g send\n"
#: ../src/ui/theme-viewer.c:824
#, fuzzy, c-format
msgid "Loaded theme \"%s\" in %g seconds\n"
msgstr "Téma „%s“ načítaná za %g sekúnd\n"
# PK: inde titulku, aky je rozdiel
#~ msgid "Normal Title Font"
#~ msgstr "Obyčajné písmo titulku"
#: ../src/ui/theme-viewer.c:869
msgid "Normal Title Font"
msgstr "Obyčajné písmo titulku"
#~ msgid "Small Title Font"
#~ msgstr "Malé písmo titulku"
#: ../src/ui/theme-viewer.c:875
msgid "Small Title Font"
msgstr "Malé písmo titulku"
#~ msgid "Large Title Font"
#~ msgstr "Veľké písmo titulku"
#: ../src/ui/theme-viewer.c:881
msgid "Large Title Font"
msgstr "Veľké písmo titulku"
#~ msgid "Button Layouts"
#~ msgstr "Rozloženia tlačidiel"
#: ../src/ui/theme-viewer.c:886
msgid "Button Layouts"
msgstr "Rozloženia tlačidiel"
#~ msgid "Benchmark"
#~ msgstr "Test rýchlosti"
#: ../src/ui/theme-viewer.c:891
msgid "Benchmark"
msgstr "Test rýchlosti"
#~ msgid "Window Title Goes Here"
#~ msgstr "Sem príde názov okna"
#: ../src/ui/theme-viewer.c:947
msgid "Window Title Goes Here"
msgstr "Sem príde názov okna"
# PK: plural forms
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
#, fuzzy
#~ 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 ""
#~ "Vykreslených %d rámcov za %g sekúnd na strane klienta (%g milisekúnd na "
#~ "rámec) a %g sekúnd celkového času vrátane zdrojov servera X (%g "
#~ "milisekúnd na rámec)\n"
#: ../src/ui/theme-viewer.c:1053
#, fuzzy, 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 ""
"Vykreslených %d rámcov za %g sekúnd na strane klienta (%g milisekúnd na "
"rámec) a %g sekúnd celkového času vrátane zdrojov servera X (%g milisekúnd "
"na rámec)\n"
#~ msgid "position expression test returned TRUE but set error"
#~ msgstr "test výrazu polohy vrátil TRUE, ale nastavil chybu"
#: ../src/ui/theme-viewer.c:1273
msgid "position expression test returned TRUE but set error"
msgstr "test výrazu polohy vrátil TRUE, ale nastavil chybu"
#~ msgid "position expression test returned FALSE but didn't set error"
#~ msgstr "test výrazu polohy vrátil FALSE, ale nenastavil chybu"
#: ../src/ui/theme-viewer.c:1275
msgid "position expression test returned FALSE but didn't set error"
msgstr "test výrazu polohy vrátil FALSE, ale nenastavil chybu"
#~ msgid "Error was expected but none given"
#~ msgstr "Bola očakávaná chyba, ale žiadna nenastala"
#: ../src/ui/theme-viewer.c:1279
msgid "Error was expected but none given"
msgstr "Bola očakávaná chyba, ale žiadna nenastala"
#~ msgid "Error %d was expected but %d given"
#~ msgstr "Bola očakávaná chyba %d, ale nastala %d"
#: ../src/ui/theme-viewer.c:1281
#, c-format
msgid "Error %d was expected but %d given"
msgstr "Bola očakávaná chyba %d, ale nastala %d"
#~ msgid "Error not expected but one was returned: %s"
#~ msgstr "Chyba nebola očakávaná, ale bola vrátená: %s"
#: ../src/ui/theme-viewer.c:1287
#, c-format
msgid "Error not expected but one was returned: %s"
msgstr "Chyba nebola očakávaná, ale bola vrátená: %s"
#~ msgid "x value was %d, %d was expected"
#~ msgstr "hodnota x bola %d, očakávaná bola %d"
#: ../src/ui/theme-viewer.c:1291
#, c-format
msgid "x value was %d, %d was expected"
msgstr "hodnota x bola %d, očakávaná bola %d"
#~ msgid "y value was %d, %d was expected"
#~ msgstr "hodnota y bola %d, očakávaná bola %d"
#: ../src/ui/theme-viewer.c:1294
#, c-format
msgid "y value was %d, %d was expected"
msgstr "hodnota y bola %d, očakávaná bola %d"
# PK: plural forms
# JK: https://bugzilla.gnome.org/show_bug.cgi?id=697987
#, fuzzy
#~ msgid ""
#~ "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
#~ msgstr ""
#~ "%d výrazov pre súradnice analyzovaných za %g sekúnd (priemer %g sekúnd)\n"
#: ../src/ui/theme-viewer.c:1359
#, fuzzy, c-format
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
msgstr ""
"%d výrazov pre súradnice analyzovaných za %g sekúnd (priemer %g sekúnd)\n"

501
po/sl.po

File diff suppressed because it is too large Load Diff

425
po/sr.po
View File

@ -212,7 +212,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:589
#: ../src/compositor/compositor.c:507
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
@ -220,11 +220,11 @@ msgid ""
msgstr ""
"Неки други композитни управник је већ покренут на приказу %i еркана „%s“."
#: ../src/compositor/meta-background.c:1076
#: ../src/compositor/meta-background.c:1111
msgid "background texture could not be created from file"
msgstr "склоп позадине не може бити створен из датотеке"
#: ../src/core/bell.c:322
#: ../src/core/bell.c:320
msgid "Bell event"
msgstr "Звонца"
@ -258,17 +258,17 @@ msgstr "_Сачекај"
msgid "_Force Quit"
msgstr "_Приморај излаз"
#: ../src/core/display.c:421
#: ../src/core/display.c:401
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Недостаје потребан композитни додатак %s"
#: ../src/core/display.c:513
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Нисам успео да отворим екран „%s“ Икс система прозора\n"
#: ../src/core/keybindings.c:1136
#: ../src/core/keybindings.c:929
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -277,41 +277,42 @@ msgstr ""
"Неки други програм већ користи тастер %s са измењивачима %x за неку "
"функцију\n"
#: ../src/core/keybindings.c:1333
#: ../src/core/keybindings.c:1129
#, 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
#: ../src/core/main.c:196
msgid "Disable connection to session manager"
msgstr "Искључује везу са управником сесије"
#: ../src/core/main.c:203
#: ../src/core/main.c:202
msgid "Replace the running window manager"
msgstr "Мења текућег управника прозорима"
#: ../src/core/main.c:209
#: ../src/core/main.c:208
msgid "Specify session management ID"
msgstr "Наводи ИБ управника сесије"
#: ../src/core/main.c:214
#: ../src/core/main.c:213
msgid "X Display to use"
msgstr "Икс екран који ће бити коришћен"
#: ../src/core/main.c:220
#: ../src/core/main.c:219
msgid "Initialize session from savefile"
msgstr "Покреће сесију из датотеке чувања"
#: ../src/core/main.c:226
#: ../src/core/main.c:225
msgid "Make X calls synchronous"
msgstr "Чини Икс позиве усклађеним"
#: ../src/core/main.c:534
#: ../src/core/main.c:494
#, c-format
msgid "Failed to scan themes directory: %s\n"
msgstr "Нисам успео да прочитам директоријум тема: %s\n"
#: ../src/core/main.c:550
#: ../src/core/main.c:510
#, c-format
msgid ""
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
@ -356,7 +357,7 @@ msgstr "Исписује издање"
msgid "Mutter plugin to use"
msgstr "Прикључци Матера за коришћење"
#: ../src/core/prefs.c:1202
#: ../src/core/prefs.c:1087
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -364,12 +365,12 @@ msgstr ""
"Решења за оштећене програме су искључена. Неке апликације се могу понашати "
"чудно.\n"
#: ../src/core/prefs.c:1277
#: ../src/core/prefs.c:1162
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Не могу да обрадим опис „%s“ из кључа „%s“ у Гномовим подешавањима\n"
#: ../src/core/prefs.c:1343
#: ../src/core/prefs.c:1228
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -378,24 +379,24 @@ msgstr ""
"„%s“ је пронађен у бази подешавања што није исправна вредност која мења "
"понашање тастера миша\n"
#: ../src/core/prefs.c:1909
#: ../src/core/prefs.c:1780
#, 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:1999
#: ../src/core/prefs.c:1879
#, c-format
msgid "Workspace %d"
msgstr "%d. радни простор"
#: ../src/core/screen.c:534
#: ../src/core/screen.c:673
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Приказ „%d“ на екрану „%s“ није исправан\n"
#: ../src/core/screen.c:550
#: ../src/core/screen.c:689
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@ -404,18 +405,18 @@ msgstr ""
"Приказ „%d“ на екрану „%s“ већ има управника прозора; покушајте да користите "
"опцију „--replace“ да замените тренутног управника прозора.\n"
#: ../src/core/screen.c:577
#: ../src/core/screen.c:716
#, c-format
msgid ""
"Could not acquire window manager selection on screen %d display \"%s\"\n"
msgstr "Не могу да добијем избор управника прозора на приказу %d еркана „%s“\n"
#: ../src/core/screen.c:655
#: ../src/core/screen.c:794
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "Приказ %d на екрану „%s“ већ има управника прозора\n"
#: ../src/core/screen.c:846
#: ../src/core/screen.c:979
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Не могу да отпустим приказ %d на екрану „%s“\n"
@ -475,43 +476,44 @@ msgstr ""
"Ови прозори не подржавају могућност „сачувај тренутна подешавања“ па ћете "
"морати ручно да их поново покренете када се следећи пут пријавите."
#: ../src/core/util.c:84
#: ../src/core/util.c:80
#, c-format
msgid "Failed to open debug log: %s\n"
msgstr "Нисам успео да отворим дневник грешака: %s\n"
#: ../src/core/util.c:94
#: ../src/core/util.c:90
#, c-format
msgid "Failed to fdopen() log file %s: %s\n"
msgstr "Нисам успео да „fdopen()“ датотеку дневника „%s“: %s\n"
#: ../src/core/util.c:100
#: ../src/core/util.c:96
#, c-format
msgid "Opened log file %s\n"
msgstr "Отворена је датотека дневника „%s“\n"
#: ../src/core/util.c:119
#: ../src/core/util.c:115 ../src/tools/mutter-message.c:149
#, c-format
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Матер је преведен без подршке за опширан режим\n"
#: ../src/core/util.c:264
#: ../src/core/util.c:259
msgid "Window manager: "
msgstr "Управник прозора: "
#: ../src/core/util.c:414
#: ../src/core/util.c:407
msgid "Bug in window manager: "
msgstr "Грешка у управнику прозора: "
#: ../src/core/util.c:445
#: ../src/core/util.c:438
msgid "Window manager warning: "
msgstr "Упозорење управника прозора: "
#: ../src/core/util.c:473
#: ../src/core/util.c:466
msgid "Window manager error: "
msgstr "Грешка управника прозора: "
#. first time through
#: ../src/core/window.c:7533
#: ../src/core/window.c:7539
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -527,7 +529,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8257
#: ../src/core/window.c:8263
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -537,22 +539,22 @@ msgstr ""
"али је поставио најмању величину %d x %d и највећу величину %d x %d што нема "
"много смисла.\n"
#: ../src/core/window-props.c:347
#: ../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:463
#: ../src/core/window-props.c:434
#, c-format
msgid "%s (on %s)"
msgstr "%s (на %s)"
#: ../src/core/window-props.c:1546
#: ../src/core/window-props.c:1517
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "Неисправан прозор 0x%lx наведен као WM_TRANSIENT_FOR за %s.\n"
#: ../src/core/window-props.c:1557
#: ../src/core/window-props.c:1528
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "WM_TRANSIENT_FOR прозор 0x%lx за %s ће направити петљу.\n"
@ -717,104 +719,109 @@ 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:67
#: ../src/ui/menu.c:69
msgid "Mi_nimize"
msgstr "Уањи"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:69
#: ../src/ui/menu.c:71
msgid "Ma_ximize"
msgstr "Уећај"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:71
#: ../src/ui/menu.c:73
msgid "Unma_ximize"
msgstr "Поништи уећање"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:73
#: ../src/ui/menu.c:75
msgid "Roll _Up"
msgstr "_Замотај"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:75
#: ../src/ui/menu.c:77
msgid "_Unroll"
msgstr "_Одмотај"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:77
#: ../src/ui/menu.c:79
msgid "_Move"
msgstr "_Премести"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:79
#: ../src/ui/menu.c:81
msgid "_Resize"
msgstr "П_ромени величину"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:81
#: ../src/ui/menu.c:83
msgid "Move Titlebar On_screen"
msgstr "Премести траку _наслова на екран"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
msgid "Always on _Top"
msgstr "Увек _изнад осталих"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:88
#: ../src/ui/menu.c:90
msgid "_Always on Visible Workspace"
msgstr "_Увек на видљивом радном простору"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:90
#: ../src/ui/menu.c:92
msgid "_Only on This Workspace"
msgstr "Само на _овом радном простору"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:92
#: ../src/ui/menu.c:94
msgid "Move to Workspace _Left"
msgstr "Премести на радни простор лео"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:94
#: ../src/ui/menu.c:96
msgid "Move to Workspace R_ight"
msgstr "Премести на радни простор де_сно"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:96
#: ../src/ui/menu.c:98
msgid "Move to Workspace _Up"
msgstr "Премести на радни простор го_ре"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:98
#: ../src/ui/menu.c:100
msgid "Move to Workspace _Down"
msgstr "Премести на радни простор дое"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:102
#: ../src/ui/menu.c:104
msgid "_Close"
msgstr "_Затвори"
#: ../src/ui/menu.c:202
#: ../src/ui/menu.c:204
#, c-format
msgid "Workspace %d%n"
msgstr "Радни простор %d%n"
#: ../src/ui/menu.c:212
#: ../src/ui/menu.c:214
#, c-format
msgid "Workspace 1_0"
msgstr "1_0. радни простор"
#: ../src/ui/menu.c:214
#: ../src/ui/menu.c:216
#, c-format
msgid "Workspace %s%d"
msgstr "%s%d. радни простор"
#: ../src/ui/menu.c:384
#: ../src/ui/menu.c:397
msgid "Move to Another _Workspace"
msgstr "Премести на други _радни простор"
@ -916,48 +923,48 @@ msgstr "Мод5"
msgid "%d x %d"
msgstr "%d x %d"
#: ../src/ui/theme.c:236
#: ../src/ui/theme.c:235
msgid "top"
msgstr "горњу"
#: ../src/ui/theme.c:238
#: ../src/ui/theme.c:237
msgid "bottom"
msgstr "доњу"
#: ../src/ui/theme.c:240
#: ../src/ui/theme.c:239
msgid "left"
msgstr "леву"
#: ../src/ui/theme.c:242
#: ../src/ui/theme.c:241
msgid "right"
msgstr "десну"
#: ../src/ui/theme.c:270
#: ../src/ui/theme.c:269
#, c-format
msgid "frame geometry does not specify \"%s\" dimension"
msgstr "геометрија оквира не подешава „%s“ димензију"
#: ../src/ui/theme.c:289
#: ../src/ui/theme.c:288
#, c-format
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
msgstr "геометрија оквира не подешава „%s“ димензију за ивицу „%s“"
#: ../src/ui/theme.c:326
#: ../src/ui/theme.c:325
#, c-format
msgid "Button aspect ratio %g is not reasonable"
msgstr "Однос размере дугмета %g није разуман"
#: ../src/ui/theme.c:338
#: ../src/ui/theme.c:337
#, c-format
msgid "Frame geometry does not specify size of buttons"
msgstr "Геометрија оквира не подешава величину дугмића"
#: ../src/ui/theme.c:1051
#: ../src/ui/theme.c:1050
#, c-format
msgid "Gradients should have at least two colors"
msgstr "Преливи морају имати најмање две боје"
#: ../src/ui/theme.c:1203
#: ../src/ui/theme.c:1202
#, c-format
msgid ""
"GTK custom color specification must have color name and fallback in "
@ -966,7 +973,7 @@ msgstr ""
"Спецификација произвољне ГТК боје мора имати назив боје и пребацивање у "
"загради, на пример gtk:custom(foo,bar); не могу да обрадим „%s“"
#: ../src/ui/theme.c:1219
#: ../src/ui/theme.c:1218
#, c-format
msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
@ -975,7 +982,7 @@ msgstr ""
"Неисправан знак „%c“ параметра назив_боје у gtk:custom, иасправни су само A-"
"Za-z0-9-_"
#: ../src/ui/theme.c:1233
#: ../src/ui/theme.c:1232
#, c-format
msgid ""
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
@ -984,7 +991,7 @@ msgstr ""
"Гтк:произвољни формат је „gtk:custom(назив_боје,пребацивање)“, „%s“ се не "
"уклапа у формат"
#: ../src/ui/theme.c:1278
#: ../src/ui/theme.c:1277
#, c-format
msgid ""
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
@ -993,7 +1000,7 @@ msgstr ""
"Спецификација ГТК боје мора имати наведено стање у загради, на пример „gtk:fg"
"[NORMAL]“ где је „NORMAL“ стање; не могу да обрадим „%s“"
#: ../src/ui/theme.c:1292
#: ../src/ui/theme.c:1291
#, c-format
msgid ""
"GTK color specification must have a close bracket after the state, e.g. gtk:"
@ -1002,17 +1009,17 @@ msgstr ""
"Спецификација ГТК боје мора имати наведено стање у загради, на пример „gtk:fg"
"[NORMAL]“ где је „NORMAL“ стање; не могу да обрадим „%s“"
#: ../src/ui/theme.c:1303
#: ../src/ui/theme.c:1302
#, c-format
msgid "Did not understand state \"%s\" in color specification"
msgstr "Нисам разумео стање „%s“ у спецификацији боје"
#: ../src/ui/theme.c:1316
#: ../src/ui/theme.c:1315
#, c-format
msgid "Did not understand color component \"%s\" in color specification"
msgstr "Нисам разумео део боје „%s“ у спецификацији боје"
#: ../src/ui/theme.c:1345
#: ../src/ui/theme.c:1344
#, c-format
msgid ""
"Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the "
@ -1021,55 +1028,55 @@ msgstr ""
"Формат смеше је „blend/bg_color/fg_color/alpha“, „%s“ се не уклапа у тражени "
"формат записа"
#: ../src/ui/theme.c:1356
#: ../src/ui/theme.c:1355
#, c-format
msgid "Could not parse alpha value \"%s\" in blended color"
msgstr "Не могу да обрадим алфа вредност „%s“ у смешаној боји"
#: ../src/ui/theme.c:1366
#: ../src/ui/theme.c:1365
#, 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:1413
#: ../src/ui/theme.c:1412
#, 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:1424
#: ../src/ui/theme.c:1423
#, c-format
msgid "Could not parse shade factor \"%s\" in shaded color"
msgstr "Не могу да обрадим фактор сенке „%s“ у осенченој боји"
#: ../src/ui/theme.c:1434
#: ../src/ui/theme.c:1433
#, c-format
msgid "Shade factor \"%s\" in shaded color is negative"
msgstr "Фактор сенке „%s“ у осенченој боји је негативан"
#: ../src/ui/theme.c:1463
#: ../src/ui/theme.c:1462
#, c-format
msgid "Could not parse color \"%s\""
msgstr "Не могу да обрадим боју „%s“"
#: ../src/ui/theme.c:1780
#: ../src/ui/theme.c:1779
#, c-format
msgid "Coordinate expression contains character '%s' which is not allowed"
msgstr "Израз координата садржи знак „%s“ који није дозвољен"
#: ../src/ui/theme.c:1807
#: ../src/ui/theme.c:1806
#, c-format
msgid ""
"Coordinate expression contains floating point number '%s' which could not be "
"parsed"
msgstr "Израз координата садржи децимални број „%s“ који не може бити обрађен"
#: ../src/ui/theme.c:1821
#: ../src/ui/theme.c:1820
#, c-format
msgid "Coordinate expression contains integer '%s' which could not be parsed"
msgstr "Израз координата садржи цели број „%s“ који не може бити обрађен"
#: ../src/ui/theme.c:1942
#: ../src/ui/theme.c:1941
#, c-format
msgid ""
"Coordinate expression contained unknown operator at the start of this text: "
@ -1077,17 +1084,17 @@ msgid ""
msgstr ""
"Израз са координатама садржи непознати оператор на почетку овог текста: „%s“"
#: ../src/ui/theme.c:1999
#: ../src/ui/theme.c:1998
#, c-format
msgid "Coordinate expression was empty or not understood"
msgstr "Израз са координатама је био празан или неразумљив"
#: ../src/ui/theme.c:2112 ../src/ui/theme.c:2122 ../src/ui/theme.c:2156
#: ../src/ui/theme.c:2111 ../src/ui/theme.c:2121 ../src/ui/theme.c:2155
#, c-format
msgid "Coordinate expression results in division by zero"
msgstr "Израз са координатама резултира у дељењу нулом"
#: ../src/ui/theme.c:2164
#: ../src/ui/theme.c:2163
#, c-format
msgid ""
"Coordinate expression tries to use mod operator on a floating-point number"
@ -1095,23 +1102,23 @@ msgstr ""
"Израз са координатам покушава да користи оператор остатка при дељењу за "
"децимални број"
#: ../src/ui/theme.c:2220
#: ../src/ui/theme.c:2219
#, c-format
msgid ""
"Coordinate expression has an operator \"%s\" where an operand was expected"
msgstr "Израз са координатама има оператор „%s“ где је очекиван операнд"
#: ../src/ui/theme.c:2229
#: ../src/ui/theme.c:2228
#, c-format
msgid "Coordinate expression had an operand where an operator was expected"
msgstr "Израз са координатама имаше операнд где је очекиван оператор"
#: ../src/ui/theme.c:2237
#: ../src/ui/theme.c:2236
#, c-format
msgid "Coordinate expression ended with an operator instead of an operand"
msgstr "Израз са координарама је завршио са оператором уместо са операндом"
#: ../src/ui/theme.c:2247
#: ../src/ui/theme.c:2246
#, c-format
msgid ""
"Coordinate expression has operator \"%c\" following operator \"%c\" with no "
@ -1120,37 +1127,37 @@ msgstr ""
"Израз са координатама има оператор „%c“, а затим оператор „%c“ без операнда "
"између"
#: ../src/ui/theme.c:2398 ../src/ui/theme.c:2443
#: ../src/ui/theme.c:2397 ../src/ui/theme.c:2442
#, c-format
msgid "Coordinate expression had unknown variable or constant \"%s\""
msgstr "Израз са координатама има непознату променљиву или константи „%s“"
#: ../src/ui/theme.c:2497
#: ../src/ui/theme.c:2496
#, c-format
msgid "Coordinate expression parser overflowed its buffer."
msgstr "Израз са координатама је био превелики за смештај и обраду."
#: ../src/ui/theme.c:2526
#: ../src/ui/theme.c:2525
#, c-format
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
msgstr "Израз са координатама има затворене заграде без отворених заграда"
#: ../src/ui/theme.c:2590
#: ../src/ui/theme.c:2589
#, c-format
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
msgstr "Израз са координатама има отворену заграду без затворене заграде"
#: ../src/ui/theme.c:2601
#: ../src/ui/theme.c:2600
#, c-format
msgid "Coordinate expression doesn't seem to have any operators or operands"
msgstr "Израз са координатама изгледа да нема ни један оператор или операнд"
#: ../src/ui/theme.c:2814 ../src/ui/theme.c:2834 ../src/ui/theme.c:2854
#: ../src/ui/theme.c:2813 ../src/ui/theme.c:2833 ../src/ui/theme.c:2853
#, c-format
msgid "Theme contained an expression that resulted in an error: %s\n"
msgstr "Тема садржи израз који резултира грешком: %s\n"
#: ../src/ui/theme.c:4500
#: ../src/ui/theme.c:4499
#, c-format
msgid ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
@ -1159,25 +1166,25 @@ msgstr ""
"<button function=„%s“ state=„%s“ draw_ops=\"whatever\"/> мора бити наведен "
"за овај стил оквира"
#: ../src/ui/theme.c:5011 ../src/ui/theme.c:5036
#: ../src/ui/theme.c:5010 ../src/ui/theme.c:5035
#, 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:5082
#: ../src/ui/theme.c:5083
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Нисам успео да учитам тему „%s“: %s\n"
#: ../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
#: ../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
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "Није дефинисан елемент <%s> за тему „%s“"
#: ../src/ui/theme.c:5254
#: ../src/ui/theme.c:5255
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@ -1186,14 +1193,14 @@ msgstr ""
"Није подешен стил оквира за прозор типа „%s“ у теми „%s“. Додајте <window "
"type=„%s“ style_set=\"whatever\"/> елемент"
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
#: ../src/ui/theme.c:5662 ../src/ui/theme.c:5724 ../src/ui/theme.c:5787
#, c-format
msgid ""
"User-defined constants must begin with a capital letter; \"%s\" does not"
msgstr ""
"Кориснички дефинисане константе морају почети великим словом; „%s“ не почиње"
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
#: ../src/ui/theme.c:5670 ../src/ui/theme.c:5732 ../src/ui/theme.c:5795
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "Константа „%s“ је већ дефинисана"
@ -1576,7 +1583,209 @@ msgstr "Није дозвољен текст унутар елемента <%s>"
msgid "<%s> specified twice for this theme"
msgstr "<%s> је наведен два пута у овој теми"
#: ../src/ui/theme-parser.c:4336
#: ../src/ui/theme-parser.c:4334
#, 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"
# bug: plural-forms
#: ../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"
# bug: plural-forms
#: ../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 "Овде иде наслов прозора"
# bug: plural-forms
#: ../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 секунди времена на зидном часовнику укључујући и ресурсе Икс сервера (%g "
"милисекунди по оквиру)\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 "x вредност је била „%d“, а очекивана је „%d“"
#: ../src/ui/theme-viewer.c:1294
#, c-format
msgid "y value was %d, %d was expected"
msgstr "y вредност је била „%d“, а очекивана је „%d“"
# bug: plural-forms
#: ../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"

View File

@ -212,7 +212,7 @@ msgstr "Prikažite podelu na desno"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: ../src/compositor/compositor.c:589
#: ../src/compositor/compositor.c:507
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
@ -220,11 +220,11 @@ msgid ""
msgstr ""
"Neki drugi kompozitni upravnik je već pokrenut na prikazu %i erkana „%s“."
#: ../src/compositor/meta-background.c:1076
#: ../src/compositor/meta-background.c:1111
msgid "background texture could not be created from file"
msgstr "sklop pozadine ne može biti stvoren iz datoteke"
#: ../src/core/bell.c:322
#: ../src/core/bell.c:320
msgid "Bell event"
msgstr "Zvonca"
@ -258,17 +258,17 @@ msgstr "_Sačekaj"
msgid "_Force Quit"
msgstr "_Primoraj izlaz"
#: ../src/core/display.c:421
#: ../src/core/display.c:401
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Nedostaje potreban kompozitni dodatak %s"
#: ../src/core/display.c:513
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Nisam uspeo da otvorim ekran „%s“ Iks sistema prozora\n"
#: ../src/core/keybindings.c:1136
#: ../src/core/keybindings.c:929
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -277,41 +277,42 @@ msgstr ""
"Neki drugi program već koristi taster %s sa izmenjivačima %x za neku "
"funkciju\n"
#: ../src/core/keybindings.c:1333
#: ../src/core/keybindings.c:1129
#, c-format
#| msgid "\"%s\" is not a valid value for focus attribute"
msgid "\"%s\" is not a valid accelerator\n"
msgstr "„%s“ nije ispravna prečica\n"
#: ../src/core/main.c:197
#: ../src/core/main.c:196
msgid "Disable connection to session manager"
msgstr "Isključuje vezu sa upravnikom sesije"
#: ../src/core/main.c:203
#: ../src/core/main.c:202
msgid "Replace the running window manager"
msgstr "Menja tekućeg upravnika prozorima"
#: ../src/core/main.c:209
#: ../src/core/main.c:208
msgid "Specify session management ID"
msgstr "Navodi IB upravnika sesije"
#: ../src/core/main.c:214
#: ../src/core/main.c:213
msgid "X Display to use"
msgstr "Iks ekran koji će biti korišćen"
#: ../src/core/main.c:220
#: ../src/core/main.c:219
msgid "Initialize session from savefile"
msgstr "Pokreće sesiju iz datoteke čuvanja"
#: ../src/core/main.c:226
#: ../src/core/main.c:225
msgid "Make X calls synchronous"
msgstr "Čini Iks pozive usklađenim"
#: ../src/core/main.c:534
#: ../src/core/main.c:494
#, c-format
msgid "Failed to scan themes directory: %s\n"
msgstr "Nisam uspeo da pročitam direktorijum tema: %s\n"
#: ../src/core/main.c:550
#: ../src/core/main.c:510
#, c-format
msgid ""
"Could not find a theme! Be sure %s exists and contains the usual themes.\n"
@ -356,7 +357,7 @@ msgstr "Ispisuje izdanje"
msgid "Mutter plugin to use"
msgstr "Priključci Matera za korišćenje"
#: ../src/core/prefs.c:1202
#: ../src/core/prefs.c:1087
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -364,12 +365,12 @@ msgstr ""
"Rešenja za oštećene programe su isključena. Neke aplikacije se mogu ponašati "
"čudno.\n"
#: ../src/core/prefs.c:1277
#: ../src/core/prefs.c:1162
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Ne mogu da obradim opis „%s“ iz ključa „%s“ u Gnomovim podešavanjima\n"
#: ../src/core/prefs.c:1343
#: ../src/core/prefs.c:1228
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -378,24 +379,24 @@ msgstr ""
"„%s“ je pronađen u bazi podešavanja što nije ispravna vrednost koja menja "
"ponašanje tastera miša\n"
#: ../src/core/prefs.c:1909
#: ../src/core/prefs.c:1780
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
"\"%s\"\n"
msgstr "„%s“ iz baze sa podešavanjima nije ispravna kombinacija tastera „%s“\n"
#: ../src/core/prefs.c:1999
#: ../src/core/prefs.c:1879
#, c-format
msgid "Workspace %d"
msgstr "%d. radni prostor"
#: ../src/core/screen.c:534
#: ../src/core/screen.c:673
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "Prikaz „%d“ na ekranu „%s“ nije ispravan\n"
#: ../src/core/screen.c:550
#: ../src/core/screen.c:689
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@ -404,18 +405,18 @@ msgstr ""
"Prikaz „%d“ na ekranu „%s“ već ima upravnika prozora; pokušajte da koristite "
"opciju „--replace“ da zamenite trenutnog upravnika prozora.\n"
#: ../src/core/screen.c:577
#: ../src/core/screen.c:716
#, c-format
msgid ""
"Could not acquire window manager selection on screen %d display \"%s\"\n"
msgstr "Ne mogu da dobijem izbor upravnika prozora na prikazu %d erkana „%s“\n"
#: ../src/core/screen.c:655
#: ../src/core/screen.c:794
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "Prikaz %d na ekranu „%s“ već ima upravnika prozora\n"
#: ../src/core/screen.c:846
#: ../src/core/screen.c:979
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Ne mogu da otpustim prikaz %d na ekranu „%s“\n"
@ -475,43 +476,44 @@ msgstr ""
"Ovi prozori ne podržavaju mogućnost „sačuvaj trenutna podešavanja“ pa ćete "
"morati ručno da ih ponovo pokrenete kada se sledeći put prijavite."
#: ../src/core/util.c:84
#: ../src/core/util.c:80
#, c-format
msgid "Failed to open debug log: %s\n"
msgstr "Nisam uspeo da otvorim dnevnik grešaka: %s\n"
#: ../src/core/util.c:94
#: ../src/core/util.c:90
#, c-format
msgid "Failed to fdopen() log file %s: %s\n"
msgstr "Nisam uspeo da „fdopen()“ datoteku dnevnika „%s“: %s\n"
#: ../src/core/util.c:100
#: ../src/core/util.c:96
#, c-format
msgid "Opened log file %s\n"
msgstr "Otvorena je datoteka dnevnika „%s“\n"
#: ../src/core/util.c:119
#: ../src/core/util.c:115 ../src/tools/mutter-message.c:149
#, c-format
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mater je preveden bez podrške za opširan režim\n"
#: ../src/core/util.c:264
#: ../src/core/util.c:259
msgid "Window manager: "
msgstr "Upravnik prozora: "
#: ../src/core/util.c:414
#: ../src/core/util.c:407
msgid "Bug in window manager: "
msgstr "Greška u upravniku prozora: "
#: ../src/core/util.c:445
#: ../src/core/util.c:438
msgid "Window manager warning: "
msgstr "Upozorenje upravnika prozora: "
#: ../src/core/util.c:473
#: ../src/core/util.c:466
msgid "Window manager error: "
msgstr "Greška upravnika prozora: "
#. first time through
#: ../src/core/window.c:7533
#: ../src/core/window.c:7539
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -527,7 +529,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:8257
#: ../src/core/window.c:8263
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -537,22 +539,22 @@ msgstr ""
"ali je postavio najmanju veličinu %d x %d i najveću veličinu %d x %d što nema "
"mnogo smisla.\n"
#: ../src/core/window-props.c:347
#: ../src/core/window-props.c:318
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "Program je postavio netačan _NET_WM_PID %lu\n"
#: ../src/core/window-props.c:463
#: ../src/core/window-props.c:434
#, c-format
msgid "%s (on %s)"
msgstr "%s (na %s)"
#: ../src/core/window-props.c:1546
#: ../src/core/window-props.c:1517
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "Neispravan prozor 0x%lx naveden kao WM_TRANSIENT_FOR za %s.\n"
#: ../src/core/window-props.c:1557
#: ../src/core/window-props.c:1528
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "WM_TRANSIENT_FOR prozor 0x%lx za %s će napraviti petlju.\n"
@ -717,104 +719,109 @@ msgstr "Bira prozor iz jezička iskakanja"
msgid "Cancel tab popup"
msgstr "Otkazivanje jezička iskakanja"
#: ../src/tools/mutter-message.c:123
#, c-format
msgid "Usage: %s\n"
msgstr "Upotreba: %s\n"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:67
#: ../src/ui/menu.c:69
msgid "Mi_nimize"
msgstr "U_manji"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:69
#: ../src/ui/menu.c:71
msgid "Ma_ximize"
msgstr "U_većaj"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:71
#: ../src/ui/menu.c:73
msgid "Unma_ximize"
msgstr "Poništi u_većanje"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:73
#: ../src/ui/menu.c:75
msgid "Roll _Up"
msgstr "_Zamotaj"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:75
#: ../src/ui/menu.c:77
msgid "_Unroll"
msgstr "_Odmotaj"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:77
#: ../src/ui/menu.c:79
msgid "_Move"
msgstr "_Premesti"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:79
#: ../src/ui/menu.c:81
msgid "_Resize"
msgstr "P_romeni veličinu"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:81
#: ../src/ui/menu.c:83
msgid "Move Titlebar On_screen"
msgstr "Premesti traku _naslova na ekran"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:84 ../src/ui/menu.c:86
#: ../src/ui/menu.c:86 ../src/ui/menu.c:88
msgid "Always on _Top"
msgstr "Uvek _iznad ostalih"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:88
#: ../src/ui/menu.c:90
msgid "_Always on Visible Workspace"
msgstr "_Uvek na vidljivom radnom prostoru"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:90
#: ../src/ui/menu.c:92
msgid "_Only on This Workspace"
msgstr "Samo na _ovom radnom prostoru"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:92
#: ../src/ui/menu.c:94
msgid "Move to Workspace _Left"
msgstr "Premesti na radni prostor le_vo"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:94
#: ../src/ui/menu.c:96
msgid "Move to Workspace R_ight"
msgstr "Premesti na radni prostor de_sno"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:96
#: ../src/ui/menu.c:98
msgid "Move to Workspace _Up"
msgstr "Premesti na radni prostor go_re"
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:98
#: ../src/ui/menu.c:100
msgid "Move to Workspace _Down"
msgstr "Premesti na radni prostor do_le"
#. separator
#. Translators: Translate this string the same way as you do in libwnck!
#: ../src/ui/menu.c:102
#: ../src/ui/menu.c:104
msgid "_Close"
msgstr "_Zatvori"
#: ../src/ui/menu.c:202
#: ../src/ui/menu.c:204
#, c-format
msgid "Workspace %d%n"
msgstr "Radni prostor %d%n"
#: ../src/ui/menu.c:212
#: ../src/ui/menu.c:214
#, c-format
msgid "Workspace 1_0"
msgstr "1_0. radni prostor"
#: ../src/ui/menu.c:214
#: ../src/ui/menu.c:216
#, c-format
msgid "Workspace %s%d"
msgstr "%s%d. radni prostor"
#: ../src/ui/menu.c:384
#: ../src/ui/menu.c:397
msgid "Move to Another _Workspace"
msgstr "Premesti na drugi _radni prostor"
@ -916,48 +923,48 @@ msgstr "Mod5"
msgid "%d x %d"
msgstr "%d x %d"
#: ../src/ui/theme.c:236
#: ../src/ui/theme.c:235
msgid "top"
msgstr "gornju"
#: ../src/ui/theme.c:238
#: ../src/ui/theme.c:237
msgid "bottom"
msgstr "donju"
#: ../src/ui/theme.c:240
#: ../src/ui/theme.c:239
msgid "left"
msgstr "levu"
#: ../src/ui/theme.c:242
#: ../src/ui/theme.c:241
msgid "right"
msgstr "desnu"
#: ../src/ui/theme.c:270
#: ../src/ui/theme.c:269
#, c-format
msgid "frame geometry does not specify \"%s\" dimension"
msgstr "geometrija okvira ne podešava „%s“ dimenziju"
#: ../src/ui/theme.c:289
#: ../src/ui/theme.c:288
#, c-format
msgid "frame geometry does not specify dimension \"%s\" for border \"%s\""
msgstr "geometrija okvira ne podešava „%s“ dimenziju za ivicu „%s“"
#: ../src/ui/theme.c:326
#: ../src/ui/theme.c:325
#, c-format
msgid "Button aspect ratio %g is not reasonable"
msgstr "Odnos razmere dugmeta %g nije razuman"
#: ../src/ui/theme.c:338
#: ../src/ui/theme.c:337
#, c-format
msgid "Frame geometry does not specify size of buttons"
msgstr "Geometrija okvira ne podešava veličinu dugmića"
#: ../src/ui/theme.c:1051
#: ../src/ui/theme.c:1050
#, c-format
msgid "Gradients should have at least two colors"
msgstr "Prelivi moraju imati najmanje dve boje"
#: ../src/ui/theme.c:1203
#: ../src/ui/theme.c:1202
#, c-format
msgid ""
"GTK custom color specification must have color name and fallback in "
@ -966,7 +973,7 @@ msgstr ""
"Specifikacija proizvoljne GTK boje mora imati naziv boje i prebacivanje u "
"zagradi, na primer gtk:custom(foo,bar); ne mogu da obradim „%s“"
#: ../src/ui/theme.c:1219
#: ../src/ui/theme.c:1218
#, c-format
msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
@ -975,7 +982,7 @@ msgstr ""
"Neispravan znak „%c“ parametra naziv_boje u gtk:custom, iaspravni su samo A-"
"Za-z0-9-_"
#: ../src/ui/theme.c:1233
#: ../src/ui/theme.c:1232
#, c-format
msgid ""
"Gtk:custom format is \"gtk:custom(color_name,fallback)\", \"%s\" does not "
@ -984,7 +991,7 @@ msgstr ""
"Gtk:proizvoljni format je „gtk:custom(naziv_boje,prebacivanje)“, „%s“ se ne "
"uklapa u format"
#: ../src/ui/theme.c:1278
#: ../src/ui/theme.c:1277
#, c-format
msgid ""
"GTK color specification must have the state in brackets, e.g. gtk:fg[NORMAL] "
@ -993,7 +1000,7 @@ msgstr ""
"Specifikacija GTK boje mora imati navedeno stanje u zagradi, na primer „gtk:fg"
"[NORMAL]“ gde je „NORMAL“ stanje; ne mogu da obradim „%s“"
#: ../src/ui/theme.c:1292
#: ../src/ui/theme.c:1291
#, c-format
msgid ""
"GTK color specification must have a close bracket after the state, e.g. gtk:"
@ -1002,17 +1009,17 @@ msgstr ""
"Specifikacija GTK boje mora imati navedeno stanje u zagradi, na primer „gtk:fg"
"[NORMAL]“ gde je „NORMAL“ stanje; ne mogu da obradim „%s“"
#: ../src/ui/theme.c:1303
#: ../src/ui/theme.c:1302
#, c-format
msgid "Did not understand state \"%s\" in color specification"
msgstr "Nisam razumeo stanje „%s“ u specifikaciji boje"
#: ../src/ui/theme.c:1316
#: ../src/ui/theme.c:1315
#, c-format
msgid "Did not understand color component \"%s\" in color specification"
msgstr "Nisam razumeo deo boje „%s“ u specifikaciji boje"
#: ../src/ui/theme.c:1345
#: ../src/ui/theme.c:1344
#, c-format
msgid ""
"Blend format is \"blend/bg_color/fg_color/alpha\", \"%s\" does not fit the "
@ -1021,55 +1028,55 @@ msgstr ""
"Format smeše je „blend/bg_color/fg_color/alpha“, „%s“ se ne uklapa u traženi "
"format zapisa"
#: ../src/ui/theme.c:1356
#: ../src/ui/theme.c:1355
#, c-format
msgid "Could not parse alpha value \"%s\" in blended color"
msgstr "Ne mogu da obradim alfa vrednost „%s“ u smešanoj boji"
#: ../src/ui/theme.c:1366
#: ../src/ui/theme.c:1365
#, c-format
msgid "Alpha value \"%s\" in blended color is not between 0.0 and 1.0"
msgstr "Alfa vrednost „%s“ u smešanoj boji nije između 0.0 i 1.0"
#: ../src/ui/theme.c:1413
#: ../src/ui/theme.c:1412
#, c-format
msgid ""
"Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
msgstr "Format senke je „shade/base_color/factor“, „%s“ se ne uklapa u format"
#: ../src/ui/theme.c:1424
#: ../src/ui/theme.c:1423
#, c-format
msgid "Could not parse shade factor \"%s\" in shaded color"
msgstr "Ne mogu da obradim faktor senke „%s“ u osenčenoj boji"
#: ../src/ui/theme.c:1434
#: ../src/ui/theme.c:1433
#, c-format
msgid "Shade factor \"%s\" in shaded color is negative"
msgstr "Faktor senke „%s“ u osenčenoj boji je negativan"
#: ../src/ui/theme.c:1463
#: ../src/ui/theme.c:1462
#, c-format
msgid "Could not parse color \"%s\""
msgstr "Ne mogu da obradim boju „%s“"
#: ../src/ui/theme.c:1780
#: ../src/ui/theme.c:1779
#, c-format
msgid "Coordinate expression contains character '%s' which is not allowed"
msgstr "Izraz koordinata sadrži znak „%s“ koji nije dozvoljen"
#: ../src/ui/theme.c:1807
#: ../src/ui/theme.c:1806
#, c-format
msgid ""
"Coordinate expression contains floating point number '%s' which could not be "
"parsed"
msgstr "Izraz koordinata sadrži decimalni broj „%s“ koji ne može biti obrađen"
#: ../src/ui/theme.c:1821
#: ../src/ui/theme.c:1820
#, c-format
msgid "Coordinate expression contains integer '%s' which could not be parsed"
msgstr "Izraz koordinata sadrži celi broj „%s“ koji ne može biti obrađen"
#: ../src/ui/theme.c:1942
#: ../src/ui/theme.c:1941
#, c-format
msgid ""
"Coordinate expression contained unknown operator at the start of this text: "
@ -1077,17 +1084,17 @@ msgid ""
msgstr ""
"Izraz sa koordinatama sadrži nepoznati operator na početku ovog teksta: „%s“"
#: ../src/ui/theme.c:1999
#: ../src/ui/theme.c:1998
#, c-format
msgid "Coordinate expression was empty or not understood"
msgstr "Izraz sa koordinatama je bio prazan ili nerazumljiv"
#: ../src/ui/theme.c:2112 ../src/ui/theme.c:2122 ../src/ui/theme.c:2156
#: ../src/ui/theme.c:2111 ../src/ui/theme.c:2121 ../src/ui/theme.c:2155
#, c-format
msgid "Coordinate expression results in division by zero"
msgstr "Izraz sa koordinatama rezultira u deljenju nulom"
#: ../src/ui/theme.c:2164
#: ../src/ui/theme.c:2163
#, c-format
msgid ""
"Coordinate expression tries to use mod operator on a floating-point number"
@ -1095,23 +1102,23 @@ msgstr ""
"Izraz sa koordinatam pokušava da koristi operator ostatka pri deljenju za "
"decimalni broj"
#: ../src/ui/theme.c:2220
#: ../src/ui/theme.c:2219
#, c-format
msgid ""
"Coordinate expression has an operator \"%s\" where an operand was expected"
msgstr "Izraz sa koordinatama ima operator „%s“ gde je očekivan operand"
#: ../src/ui/theme.c:2229
#: ../src/ui/theme.c:2228
#, c-format
msgid "Coordinate expression had an operand where an operator was expected"
msgstr "Izraz sa koordinatama imaše operand gde je očekivan operator"
#: ../src/ui/theme.c:2237
#: ../src/ui/theme.c:2236
#, c-format
msgid "Coordinate expression ended with an operator instead of an operand"
msgstr "Izraz sa koordinarama je završio sa operatorom umesto sa operandom"
#: ../src/ui/theme.c:2247
#: ../src/ui/theme.c:2246
#, c-format
msgid ""
"Coordinate expression has operator \"%c\" following operator \"%c\" with no "
@ -1120,37 +1127,37 @@ msgstr ""
"Izraz sa koordinatama ima operator „%c“, a zatim operator „%c“ bez operanda "
"između"
#: ../src/ui/theme.c:2398 ../src/ui/theme.c:2443
#: ../src/ui/theme.c:2397 ../src/ui/theme.c:2442
#, c-format
msgid "Coordinate expression had unknown variable or constant \"%s\""
msgstr "Izraz sa koordinatama ima nepoznatu promenljivu ili konstanti „%s“"
#: ../src/ui/theme.c:2497
#: ../src/ui/theme.c:2496
#, c-format
msgid "Coordinate expression parser overflowed its buffer."
msgstr "Izraz sa koordinatama je bio preveliki za smeštaj i obradu."
#: ../src/ui/theme.c:2526
#: ../src/ui/theme.c:2525
#, c-format
msgid "Coordinate expression had a close parenthesis with no open parenthesis"
msgstr "Izraz sa koordinatama ima zatvorene zagrade bez otvorenih zagrada"
#: ../src/ui/theme.c:2590
#: ../src/ui/theme.c:2589
#, c-format
msgid "Coordinate expression had an open parenthesis with no close parenthesis"
msgstr "Izraz sa koordinatama ima otvorenu zagradu bez zatvorene zagrade"
#: ../src/ui/theme.c:2601
#: ../src/ui/theme.c:2600
#, c-format
msgid "Coordinate expression doesn't seem to have any operators or operands"
msgstr "Izraz sa koordinatama izgleda da nema ni jedan operator ili operand"
#: ../src/ui/theme.c:2814 ../src/ui/theme.c:2834 ../src/ui/theme.c:2854
#: ../src/ui/theme.c:2813 ../src/ui/theme.c:2833 ../src/ui/theme.c:2853
#, c-format
msgid "Theme contained an expression that resulted in an error: %s\n"
msgstr "Tema sadrži izraz koji rezultira greškom: %s\n"
#: ../src/ui/theme.c:4500
#: ../src/ui/theme.c:4499
#, c-format
msgid ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
@ -1159,25 +1166,25 @@ msgstr ""
"<button function=„%s“ state=„%s“ draw_ops=\"whatever\"/> mora biti naveden "
"za ovaj stil okvira"
#: ../src/ui/theme.c:5011 ../src/ui/theme.c:5036
#: ../src/ui/theme.c:5010 ../src/ui/theme.c:5035
#, c-format
msgid ""
"Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
msgstr ""
"Nedostaje <frame state=„%s“ resize=„%s“ focus=„%s“ style=\"whatever\"/>"
#: ../src/ui/theme.c:5082
#: ../src/ui/theme.c:5083
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Nisam uspeo da učitam temu „%s“: %s\n"
#: ../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
#: ../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
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "Nije definisan element <%s> za temu „%s“"
#: ../src/ui/theme.c:5254
#: ../src/ui/theme.c:5255
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@ -1186,14 +1193,14 @@ msgstr ""
"Nije podešen stil okvira za prozor tipa „%s“ u temi „%s“. Dodajte <window "
"type=„%s“ style_set=\"whatever\"/> element"
#: ../src/ui/theme.c:5661 ../src/ui/theme.c:5723 ../src/ui/theme.c:5786
#: ../src/ui/theme.c:5662 ../src/ui/theme.c:5724 ../src/ui/theme.c:5787
#, c-format
msgid ""
"User-defined constants must begin with a capital letter; \"%s\" does not"
msgstr ""
"Korisnički definisane konstante moraju početi velikim slovom; „%s“ ne počinje"
#: ../src/ui/theme.c:5669 ../src/ui/theme.c:5731 ../src/ui/theme.c:5794
#: ../src/ui/theme.c:5670 ../src/ui/theme.c:5732 ../src/ui/theme.c:5795
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "Konstanta „%s“ je već definisana"
@ -1576,7 +1583,209 @@ msgstr "Nije dozvoljen tekst unutar elementa <%s>"
msgid "<%s> specified twice for this theme"
msgstr "<%s> je naveden dva puta u ovoj temi"
#: ../src/ui/theme-parser.c:4336
#: ../src/ui/theme-parser.c:4334
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "Nisam uspeo da pronađem ispravnu datoteku za temu „%s“\n"
#: ../src/ui/theme-viewer.c:99
msgid "_Windows"
msgstr "_Prozori"
#: ../src/ui/theme-viewer.c:100
msgid "_Dialog"
msgstr "_Prozorče"
#: ../src/ui/theme-viewer.c:101
msgid "_Modal dialog"
msgstr "_Važno prozorče"
#: ../src/ui/theme-viewer.c:102
msgid "_Utility"
msgstr "_Alatka"
#: ../src/ui/theme-viewer.c:103
msgid "_Splashscreen"
msgstr "_Uvodni ekran"
#: ../src/ui/theme-viewer.c:104
msgid "_Top dock"
msgstr "_Gornje pripajanje"
#: ../src/ui/theme-viewer.c:105
msgid "_Bottom dock"
msgstr "_Donje pripajanje"
#: ../src/ui/theme-viewer.c:106
msgid "_Left dock"
msgstr "_Levo pripajanje"
#: ../src/ui/theme-viewer.c:107
msgid "_Right dock"
msgstr "D_esno pripajanje"
#: ../src/ui/theme-viewer.c:108
msgid "_All docks"
msgstr "_Sva pripajanja"
#: ../src/ui/theme-viewer.c:109
msgid "Des_ktop"
msgstr "_Radna površ"
#: ../src/ui/theme-viewer.c:115
msgid "Open another one of these windows"
msgstr "Otvori neki drugi od ovih prozora"
#: ../src/ui/theme-viewer.c:117
msgid "This is a demo button with an 'open' icon"
msgstr "Ovo je probno dugme sa „otvori“ ikonom"
#: ../src/ui/theme-viewer.c:119
msgid "This is a demo button with a 'quit' icon"
msgstr "Ovo je probno dugme sa „izađi“ ikonicom"
#: ../src/ui/theme-viewer.c:248
msgid "This is a sample message in a sample dialog"
msgstr "Ovo je primer poruke u probnom prozorčetu"
#: ../src/ui/theme-viewer.c:328
#, c-format
msgid "Fake menu item %d\n"
msgstr "Lažna stavka izbornika %d\n"
#: ../src/ui/theme-viewer.c:363
msgid "Border-only window"
msgstr "Prozor samo sa ivicom"
#: ../src/ui/theme-viewer.c:365
msgid "Bar"
msgstr "Traka"
#: ../src/ui/theme-viewer.c:382
msgid "Normal Application Window"
msgstr "Običan prozor programa"
#: ../src/ui/theme-viewer.c:386
msgid "Dialog Box"
msgstr "Prozorče"
#: ../src/ui/theme-viewer.c:390
msgid "Modal Dialog Box"
msgstr "Važno prozorče"
#: ../src/ui/theme-viewer.c:394
msgid "Utility Palette"
msgstr "Paleta alata"
#: ../src/ui/theme-viewer.c:398
msgid "Torn-off Menu"
msgstr "Otkinuti izbornik"
#: ../src/ui/theme-viewer.c:402
msgid "Border"
msgstr "Ivica"
#: ../src/ui/theme-viewer.c:406
msgid "Attached Modal Dialog"
msgstr "Priloženo važno prozorče"
#: ../src/ui/theme-viewer.c:737
#, c-format
msgid "Button layout test %d"
msgstr "Proba rasporeda dugmića %d"
# bug: plural-forms
#: ../src/ui/theme-viewer.c:766
#, c-format
msgid "%g milliseconds to draw one window frame"
msgstr "%g milisekundi za iscrtavanje okvira jednog prozora"
#: ../src/ui/theme-viewer.c:811
#, c-format
msgid "Usage: metacity-theme-viewer [THEMENAME]\n"
msgstr "Upotreba: metacity-theme-viewer [NAZIV_TEME]\n"
#: ../src/ui/theme-viewer.c:818
#, c-format
msgid "Error loading theme: %s\n"
msgstr "Greška prilikom učitavanja teme: %s\n"
# bug: plural-forms
#: ../src/ui/theme-viewer.c:824
#, c-format
msgid "Loaded theme \"%s\" in %g seconds\n"
msgstr "Učitana je tema „%s“ za %g sekunde\n"
#: ../src/ui/theme-viewer.c:869
msgid "Normal Title Font"
msgstr "Običan slovni lik naslova"
#: ../src/ui/theme-viewer.c:875
msgid "Small Title Font"
msgstr "Mali slovni lik naslova"
#: ../src/ui/theme-viewer.c:881
msgid "Large Title Font"
msgstr "Veliki slovni lik naslova"
#: ../src/ui/theme-viewer.c:886
msgid "Button Layouts"
msgstr "Raspored dugmića"
#: ../src/ui/theme-viewer.c:891
msgid "Benchmark"
msgstr "Provera brzine"
#: ../src/ui/theme-viewer.c:947
msgid "Window Title Goes Here"
msgstr "Ovde ide naslov prozora"
# bug: plural-forms
#: ../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 ""
"Nacrtao je %d okvira za %g klijentskih sekundi (%g milisekundi po okviru) i "
"%g sekundi vremena na zidnom časovniku uključujući i resurse Iks servera (%g "
"milisekundi po okviru)\n"
#: ../src/ui/theme-viewer.c:1273
msgid "position expression test returned TRUE but set error"
msgstr "provera izraza položaja je vratila tačno, ali je postavila grešku"
#: ../src/ui/theme-viewer.c:1275
msgid "position expression test returned FALSE but didn't set error"
msgstr "provera izraza položaja je vratila netačno, ali nije postavila grešku"
#: ../src/ui/theme-viewer.c:1279
msgid "Error was expected but none given"
msgstr "Očekivana je greška, ali nije data"
#: ../src/ui/theme-viewer.c:1281
#, c-format
msgid "Error %d was expected but %d given"
msgstr "Očekivana je greška „%d“, ali je data „%d“"
#: ../src/ui/theme-viewer.c:1287
#, c-format
msgid "Error not expected but one was returned: %s"
msgstr "Greška nije očekivana, ali je vraćena jedna: %s"
#: ../src/ui/theme-viewer.c:1291
#, c-format
msgid "x value was %d, %d was expected"
msgstr "x vrednost je bila „%d“, a očekivana je „%d“"
#: ../src/ui/theme-viewer.c:1294
#, c-format
msgid "y value was %d, %d was expected"
msgstr "y vrednost je bila „%d“, a očekivana je „%d“"
# bug: plural-forms
#: ../src/ui/theme-viewer.c:1359
#, c-format
msgid "%d coordinate expressions parsed in %g seconds (%g seconds average)\n"
msgstr "%d izraza koordinata je obrađeno za %g sekunde (prosek %g sekunde)\n"

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,7 +1,7 @@
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
.AUTOPARALLEL:
lib_LTLIBRARIES = libmutter.la
lib_LTLIBRARIES = libmutter-wayland.la
SUBDIRS=compositor/plugins
@ -10,6 +10,7 @@ INCLUDES= \
-DCOGL_ENABLE_EXPERIMENTAL_API \
-DCOGL_ENABLE_EXPERIMENTAL_2_0_API \
$(MUTTER_CFLAGS) \
-I$(top_builddir) \
-I$(srcdir) \
-I$(srcdir)/core \
-I$(srcdir)/ui \
@ -29,17 +30,29 @@ INCLUDES= \
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
mutter_built_sources = \
$(dbus_idle_built_sources) \
$(dbus_xrandr_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 \
meta/barrier.h \
core/barrier-private.h \
core/bell.c \
core/bell.h \
core/boxes.c \
@ -55,8 +68,7 @@ libmutter_la_SOURCES = \
compositor/meta-background-actor.c \
compositor/meta-background-actor-private.h \
compositor/meta-background-group.c \
compositor/meta-cullable.c \
compositor/meta-cullable.h \
compositor/meta-background-group-private.h \
compositor/meta-module.c \
compositor/meta-module.h \
compositor/meta-plugin.c \
@ -65,6 +77,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 \
@ -122,6 +135,7 @@ libmutter_la_SOURCES = \
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 \
@ -141,6 +155,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 \
@ -169,13 +184,33 @@ libmutter_la_SOURCES = \
ui/theme.c \
meta/theme.h \
ui/theme-private.h \
ui/ui.c
nodist_libmutter_la_SOURCES = \
ui/ui.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
@ -213,16 +248,27 @@ libmutterinclude_base_headers = \
libmutterinclude_extra_headers = \
meta/atomnames.h
libmutterincludedir = $(includedir)/mutter/meta
libmutterincludedir = $(includedir)/mutter-wayland/meta
libmutterinclude_HEADERS = \
$(libmutterinclude_base_headers) \
$(libmutterinclude_extra_headers)
bin_PROGRAMS=mutter
bin_PROGRAMS=mutter-wayland
mutter_SOURCES = core/mutter.c
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
mutter_wayland_SOURCES = core/mutter.c
mutter_wayland_LDADD = $(MUTTER_LIBS) libmutter-wayland.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)
@ -244,15 +290,15 @@ 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) $(nodist_libmutter_la_SOURCES))
$(filter %.c,$(libmutter_wayland_la_SOURCES))
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
endif
@ -263,22 +309,17 @@ 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 \
@ -286,7 +327,9 @@ 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@
@ -294,9 +337,10 @@ convertdir = $(datadir)/GConf/gsettings
convert_DATA = mutter-schemas.convert
CLEANFILES = \
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) \
@ -304,7 +348,7 @@ CLEANFILES = \
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmutter.pc mutter-plugins.pc
pkgconfig_DATA = libmutter-wayland.pc
EXTRA_DIST=$(desktopfiles_files) \
$(wmproperties_files) \
@ -313,13 +357,12 @@ EXTRA_DIST=$(desktopfiles_files) \
$(wmproperties_in_files) \
$(xml_in_files) \
org.gnome.mutter.gschema.xml.in \
idle-monitor.xml \
xrandr.xml \
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)
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
@ -362,3 +405,13 @@ $(dbus_idle_built_sources) : Makefile.am idle-monitor.xml
--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

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

View File

@ -84,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>
@ -172,7 +176,32 @@ 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
process_property_notify (MetaCompositor *compositor,
XPropertyEvent *event,
MetaWindow *window)
{
MetaWindowActor *window_actor;
if (window == NULL)
return;
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (window_actor == NULL)
return;
/* Check for the opacity changing */
if (event->atom == compositor->atom_net_wm_window_opacity)
{
meta_window_actor_update_opacity (window_actor);
DEBUG_TRACE ("process_property_notify: net_wm_window_opacity\n");
return;
}
DEBUG_TRACE ("process_property_notify: unknown\n");
}
static Window
@ -302,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
@ -355,63 +392,55 @@ meta_focus_stage_window (MetaScreen *screen,
if (!stage)
return;
window = clutter_x11_get_stage_window (stage);
if (!meta_is_wayland_compositor ())
{
window = clutter_x11_get_stage_window (stage);
if (window == None)
return;
if (window == None)
return;
meta_display_set_input_focus_xwindow (screen->display,
screen,
window,
timestamp);
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;
Window window;
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
if (!stage)
return FALSE;
window = clutter_x11_get_stage_window (stage);
if (window == None)
return FALSE;
return (screen->display->focus_xwindow == window);
return (screen->display->focus_type == META_FOCUS_STAGE);
}
gboolean
meta_begin_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
MetaModalOptions options,
guint32 timestamp)
static gboolean
begin_modal_x11 (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);
Display *xdpy = meta_display_get_xdisplay (display);
MetaCompositor *compositor = display->compositor;
ClutterStage *stage;
Window grab_window;
Cursor cursor = None;
gboolean pointer_grabbed = FALSE;
gboolean keyboard_grabbed = FALSE;
int result;
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
if (!stage)
return FALSE;
grab_window = clutter_x11_get_stage_window (stage);
if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
return FALSE;
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)
{
@ -461,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:
@ -480,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,
@ -491,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;
@ -544,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
@ -584,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))
@ -598,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;
@ -609,7 +728,56 @@ 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;
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,
@ -618,90 +786,74 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
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);
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);
}
info->window_group = meta_window_group_new (screen);
info->top_window_group = meta_window_group_new (screen);
clutter_actor_add_child (info->stage, info->window_group);
clutter_actor_add_child (info->stage, info->top_window_group);
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)
{
XFixesDestroyRegion (xdisplay, info->pending_input_region);
info->pending_input_region = None;
}
info->plugin_mgr = meta_plugin_manager_new (screen);
/* Map overlay window before redirecting windows offscreen so we catch their
* contents until we show the stage.
*/
XMapWindow (xdisplay, info->output);
if (meta_is_wayland_compositor ())
{
/* 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);
redirect_windows (compositor, screen);
/* 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)
{
XFixesDestroyRegion (xdisplay, info->pending_input_region);
info->pending_input_region = None;
}
/* 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);
}
}
/*
@ -724,7 +876,7 @@ meta_shape_cow_for_window (MetaScreen *screen,
int width, height;
MetaRectangle rect;
meta_window_get_frame_rect (metaWindow, &rect);
meta_window_get_outer_rect (metaWindow, &rect);
window_bounds.x = rect.x;
window_bounds.y = rect.y;
@ -773,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);
@ -852,18 +1007,6 @@ meta_compositor_window_shape_changed (MetaCompositor *compositor,
meta_window_actor_update_shape (window_actor);
}
void
meta_compositor_window_opacity_changed (MetaCompositor *compositor,
MetaWindow *window)
{
MetaWindowActor *window_actor;
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (!window_actor)
return;
meta_window_actor_update_opacity (window_actor);
}
/* Clutter makes the assumption that there is only one X window
* per stage, which is a valid assumption to make for a generic
* application toolkit. As such, it will ignore any events sent
@ -970,24 +1113,34 @@ meta_compositor_process_event (MetaCompositor *compositor,
}
}
if (event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
switch (event->type)
{
/* Core code doesn't handle damage events, so we need to extract the MetaWindow
* ourselves
*/
if (window == NULL)
{
Window xwin = ((XDamageNotifyEvent *) event)->drawable;
window = meta_display_lookup_x_window (compositor->display, xwin);
}
case PropertyNotify:
process_property_notify (compositor, (XPropertyEvent *) event, window);
break;
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
process_damage (compositor, (XDamageNotifyEvent *) event, window);
default:
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
*/
if (window == NULL)
{
Window xwin = ((XDamageNotifyEvent *) event)->drawable;
window = meta_display_lookup_x_window (compositor->display, xwin);
}
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
process_damage (compositor, (XDamageNotifyEvent *) event, window);
}
break;
}
/* 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
@ -1332,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
@ -1409,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)
@ -1486,7 +1660,13 @@ on_shadow_factory_changed (MetaShadowFactory *factory,
MetaCompositor *
meta_compositor_new (MetaDisplay *display)
{
char *atom_names[] = {
"_XROOTPMAP_ID",
"_NET_WM_WINDOW_OPACITY",
};
Atom atoms[G_N_ELEMENTS(atom_names)];
MetaCompositor *compositor;
Display *xdisplay = meta_display_get_xdisplay (display);
if (!composite_at_least_version (display, 0, 3))
return NULL;
@ -1498,11 +1678,18 @@ meta_compositor_new (MetaDisplay *display)
if (g_getenv("META_DISABLE_MIPMAPS"))
compositor->no_mipmaps = TRUE;
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
False, atoms);
g_signal_connect (meta_shadow_factory_get_default (),
"changed",
G_CALLBACK (on_shadow_factory_changed),
compositor);
compositor->atom_x_root_pixmap = atoms[0];
compositor->atom_net_wm_window_opacity = atoms[1];
compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
compositor,
NULL);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -189,10 +189,20 @@ _meta_plugin_xevent_filter (MetaPlugin *plugin,
{
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
else if (!meta_is_wayland_compositor ())
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
else
return FALSE;
}
void

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,9 +30,13 @@
#include <config.h>
#include <meta/meta-shaped-texture.h>
#include "clutter-utils.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>
@ -56,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);
@ -66,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;
cairo_region_t *clip_region;
cairo_region_t *opaque_region;
cairo_region_t *input_shape_region;
cairo_region_t *opaque_region;
guint tex_width, tex_height;
@ -104,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;
}
@ -198,6 +223,50 @@ paint_clipped_rectangle (CoglFramebuffer *fb,
}
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)
{
@ -211,7 +280,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
CoglTexture *paint_tex;
ClutterActorBox alloc;
cairo_region_t *blended_region = NULL;
CoglPipelineFilter filter;
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
return;
@ -248,22 +316,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
if (tex_width == 0 || tex_height == 0) /* no contents yet */
return;
/* Use nearest-pixel interpolation if the texture is unscaled. This
* improves performance, especially with software rendering.
*/
filter = COGL_PIPELINE_FILTER_LINEAR;
if (!clutter_actor_is_in_clone_paint (actor))
{
int x_origin, y_origin;
if (meta_actor_is_untransformed (actor,
&x_origin,
&y_origin))
filter = COGL_PIPELINE_FILTER_NEAREST;
}
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
fb = cogl_get_draw_framebuffer ();
@ -292,7 +344,6 @@ meta_shaped_texture_paint (ClutterActor *actor)
opaque_pipeline = get_unblended_pipeline (ctx);
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
n_rects = cairo_region_num_rectangles (region);
for (i = 0; i < n_rects; i++)
@ -334,11 +385,9 @@ meta_shaped_texture_paint (ClutterActor *actor)
{
pipeline = get_masked_pipeline (ctx);
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
cogl_pipeline_set_layer_filters (pipeline, 1, filter, filter);
}
cogl_pipeline_set_layer_texture (pipeline, 0, paint_tex);
cogl_pipeline_set_layer_filters (pipeline, 0, filter, filter);
{
CoglColor color;
@ -499,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
@ -522,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);
}
}
@ -549,6 +631,111 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
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:
@ -577,18 +764,29 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
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 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);
has_clip = get_clip (stex, x, y, width, height, &clip);
if (unobscured_region)
{
cairo_region_t *intersection;
@ -597,7 +795,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
return FALSE;
intersection = cairo_region_copy (unobscured_region);
cairo_region_intersect_rectangle (intersection, &clip);
if (has_clip)
cairo_region_intersect_rectangle (intersection, &clip);
if (!cairo_region_is_empty (intersection))
{
@ -614,52 +813,14 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex,
return FALSE;
}
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
if (has_clip)
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stex), &clip);
else
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
return TRUE;
}
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 (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 inavlid texture */
priv->tex_width = 0;
priv->tex_height = 0;
clutter_actor_queue_relayout (CLUTTER_ACTOR (stex));
}
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
/**
* meta_shaped_texture_set_pixmap:
* @stex: The #MetaShapedTexture
@ -675,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);
@ -694,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

View File

@ -62,7 +62,6 @@ struct _MetaTextureTower
CoglTexture *textures[MAX_TEXTURE_LEVELS];
CoglOffscreen *fbos[MAX_TEXTURE_LEVELS];
Box invalid[MAX_TEXTURE_LEVELS];
CoglPipeline *pipeline_template;
};
/**
@ -94,9 +93,6 @@ meta_texture_tower_free (MetaTextureTower *tower)
{
g_return_if_fail (tower != NULL);
if (tower->pipeline_template != NULL)
cogl_object_unref (tower->pipeline_template);
meta_texture_tower_set_base_texture (tower, NULL);
g_slice_free (MetaTextureTower, tower);
@ -387,7 +383,7 @@ texture_tower_create_texture (MetaTextureTower *tower,
tower->invalid[level].y2 = height;
}
static void
static gboolean
texture_tower_revalidate_fbo (MetaTextureTower *tower,
int level)
{
@ -398,50 +394,174 @@ texture_tower_revalidate_fbo (MetaTextureTower *tower,
int dest_texture_width = cogl_texture_get_width (dest_texture);
int dest_texture_height = cogl_texture_get_height (dest_texture);
Box *invalid = &tower->invalid[level];
CoglFramebuffer *fb;
CoglError *catch_error = NULL;
CoglPipeline *pipeline;
CoglMatrix modelview;
if (tower->fbos[level] == NULL)
tower->fbos[level] = cogl_offscreen_new_with_texture (dest_texture);
tower->fbos[level] = cogl_offscreen_new_to_texture (dest_texture);
fb = COGL_FRAMEBUFFER (tower->fbos[level]);
if (tower->fbos[level] == NULL)
return FALSE;
if (!cogl_framebuffer_allocate (fb, &catch_error))
cogl_push_framebuffer (COGL_FRAMEBUFFER (tower->fbos[level]));
cogl_ortho (0, dest_texture_width, dest_texture_height, 0, -1., 1.);
cogl_matrix_init_identity (&modelview);
cogl_set_modelview_matrix (&modelview);
cogl_set_source_texture (tower->textures[level - 1]);
cogl_rectangle_with_texture_coords (invalid->x1, invalid->y1,
invalid->x2, invalid->y2,
(2. * invalid->x1) / source_texture_width,
(2. * invalid->y1) / source_texture_height,
(2. * invalid->x2) / source_texture_width,
(2. * invalid->y2) / source_texture_height);
cogl_pop_framebuffer ();
return TRUE;
}
static void
fill_copy (guchar *buf,
const guchar *source,
int width)
{
memcpy (buf, source, width * 4);
}
static void
fill_scale_down (guchar *buf,
const guchar *source,
int width)
{
while (width > 1)
{
cogl_error_free (catch_error);
return;
buf[0] = (source[0] + source[4]) / 2;
buf[1] = (source[1] + source[5]) / 2;
buf[2] = (source[2] + source[6]) / 2;
buf[3] = (source[3] + source[7]) / 2;
buf += 4;
source += 8;
width -= 2;
}
cogl_framebuffer_orthographic (fb, 0, 0, dest_texture_width, dest_texture_height, -1., 1.);
if (!tower->pipeline_template)
if (width > 0)
{
CoglContext *ctx =
clutter_backend_get_cogl_context (clutter_get_default_backend ());
tower->pipeline_template = cogl_pipeline_new (ctx);
cogl_pipeline_set_blend (tower->pipeline_template, "RGBA = ADD (SRC_COLOR, 0)", NULL);
buf[0] = source[0] / 2;
buf[1] = source[1] / 2;
buf[2] = source[2] / 2;
buf[3] = source[3] / 2;
}
}
static void
texture_tower_revalidate_client (MetaTextureTower *tower,
int level)
{
CoglTexture *source_texture = tower->textures[level - 1];
int source_texture_width = cogl_texture_get_width (source_texture);
int source_texture_height = cogl_texture_get_height (source_texture);
guint source_rowstride;
guchar *source_data;
CoglTexture *dest_texture = tower->textures[level];
int dest_texture_width = cogl_texture_get_width (dest_texture);
int dest_texture_height = cogl_texture_get_height (dest_texture);
int dest_x = tower->invalid[level].x1;
int dest_y = tower->invalid[level].y1;
int dest_width = tower->invalid[level].x2 - tower->invalid[level].x1;
int dest_height = tower->invalid[level].y2 - tower->invalid[level].y1;
guchar *dest_data;
guchar *source_tmp1 = NULL, *source_tmp2 = NULL;
int i, j;
source_rowstride = source_texture_width * 4;
source_data = g_malloc (source_texture_height * source_rowstride);
cogl_texture_get_data (source_texture, TEXTURE_FORMAT, source_rowstride,
source_data);
dest_data = g_malloc (dest_height * dest_width * 4);
if (dest_texture_height < source_texture_height)
{
source_tmp1 = g_malloc (dest_width * 4);
source_tmp2 = g_malloc (dest_width * 4);
}
pipeline = cogl_pipeline_copy (tower->pipeline_template);
cogl_pipeline_set_layer_texture (pipeline, 0, tower->textures[level - 1]);
for (i = 0; i < dest_height; i++)
{
guchar *dest_row = dest_data + i * dest_width * 4;
if (dest_texture_height < source_texture_height)
{
guchar *source1, *source2;
guchar *dest;
cogl_framebuffer_draw_textured_rectangle (fb, pipeline,
invalid->x1, invalid->y1,
invalid->x2, invalid->y2,
(2. * invalid->x1) / source_texture_width,
(2. * invalid->y1) / source_texture_height,
(2. * invalid->x2) / source_texture_width,
(2. * invalid->y2) / source_texture_height);
if (dest_texture_width < source_texture_width)
{
fill_scale_down (source_tmp1,
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 2 * 4,
dest_width * 2);
fill_scale_down (source_tmp2,
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 2 * 4,
dest_width * 2);
}
else
{
fill_copy (source_tmp1,
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 4,
dest_width);
fill_copy (source_tmp2,
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 4,
dest_width);
}
cogl_object_unref (pipeline);
source1 = source_tmp1;
source2 = source_tmp2;
dest = dest_row;
for (j = 0; j < dest_width * 4; j++)
*(dest++) = (*(source1++) + *(source2++)) / 2;
}
else
{
if (dest_texture_width < source_texture_width)
fill_scale_down (dest_row,
source_data + (i + dest_y) * source_rowstride + dest_x * 2 * 4,
dest_width * 2);
else
fill_copy (dest_row,
source_data + (i + dest_y) * source_rowstride,
dest_width);
}
}
cogl_texture_set_region (dest_texture,
0, 0,
dest_x, dest_y,
dest_width, dest_height,
dest_width, dest_height,
TEXTURE_FORMAT,
4 * dest_width,
dest_data);
if (dest_texture_height < source_texture_height)
{
g_free (source_tmp1);
g_free (source_tmp2);
}
g_free (source_data);
g_free (dest_data);
}
static void
texture_tower_revalidate (MetaTextureTower *tower,
int level)
{
texture_tower_revalidate_fbo (tower, level);
if (!texture_tower_revalidate_fbo (tower, level))
texture_tower_revalidate_client (tower, level);
}
/**

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);
@ -55,6 +68,14 @@ void meta_window_actor_set_updates_frozen (MetaWindowActor *self,
void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
gboolean no_delay_frame);
cairo_region_t *meta_window_actor_get_obscured_region (MetaWindowActor *self);
void meta_window_actor_set_clip_region (MetaWindowActor *self,
cairo_region_t *clip_region);
void meta_window_actor_set_clip_region_beneath (MetaWindowActor *self,
cairo_region_t *beneath_region);
void meta_window_actor_reset_clip_regions (MetaWindowActor *self);
void meta_window_actor_set_unobscured_region (MetaWindowActor *self,
cairo_region_t *unobscured_region);

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@ -21,15 +21,14 @@
* 02111-1307, USA.
*/
#include <config.h>
#include <meta/meta-plugin.h>
#include <meta/window.h>
#include <meta/util.h>
#include <meta/meta-background-group.h>
#include <meta/meta-background-actor.h>
#include <libintl.h>
#define _(x) dgettext (GETTEXT_PACKAGE, x)
#define N_(x) x
#include <meta/util.h>
#include <glib/gi18n-lib.h>
#include <clutter/clutter.h>
#include <gmodule.h>

View File

@ -0,0 +1,39 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/*
* Copyright 2012, 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors: Jaster St. Pierre <jstpierr@redhat.com>
* Giovanni Campagna <gcampagn@redhat.com>
*/
#ifndef BARRIER_PRIVATE_H
#define BARRIER_PRIVATE_H
typedef struct _MetaBarrierManager MetaBarrierManager;
MetaBarrierManager *meta_barrier_manager_get (void);
void meta_barrier_manager_constrain_cursor (MetaBarrierManager *manager,
guint32 time,
float current_x,
float current_y,
float *new_x,
float *new_y);
#endif

View File

@ -1,5 +1,27 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
/*
* Copyright 2012, 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Authors: Jaster St. Pierre <jstpierr@redhat.com>
* Giovanni Campagna <gcampagn@redhat.com>
*/
/**
* SECTION:barrier
* @Title: MetaBarrier
@ -9,6 +31,7 @@
#include "config.h"
#include <glib-object.h>
#include <math.h>
#include <X11/extensions/XInput2.h>
#include <X11/extensions/Xfixes.h>
@ -16,6 +39,7 @@
#include <meta/barrier.h>
#include "display-private.h"
#include "mutter-enum-types.h"
#include "barrier-private.h"
#include "core.h"
G_DEFINE_TYPE (MetaBarrier, meta_barrier, G_TYPE_OBJECT)
@ -56,9 +80,23 @@ struct _MetaBarrierPrivate
MetaBarrierDirection directions;
/* x11 */
PointerBarrier xbarrier;
/* wayland */
gboolean active;
gboolean seen, hit;
int barrier_event_id;
int release_event_id;
guint32 last_timestamp;
};
struct _MetaBarrierManager
{
GList *barriers;
} *global_barrier_manager;
static void meta_barrier_event_unref (MetaBarrierEvent *event);
static void
@ -148,7 +186,10 @@ meta_barrier_dispose (GObject *object)
gboolean
meta_barrier_is_active (MetaBarrier *barrier)
{
return barrier->priv->xbarrier != 0;
if (meta_is_wayland_compositor ())
return barrier->priv->active;
else
return barrier->priv->xbarrier != 0;
}
/**
@ -165,15 +206,25 @@ void
meta_barrier_release (MetaBarrier *barrier,
MetaBarrierEvent *event)
{
#ifdef HAVE_XI23
MetaBarrierPrivate *priv = barrier->priv;
if (META_DISPLAY_HAS_XINPUT_23 (priv->display))
MetaBarrierPrivate *priv;
priv = barrier->priv;
if (meta_is_wayland_compositor ())
{
XIBarrierReleasePointer (priv->display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
priv->xbarrier, event->event_id);
priv->release_event_id = event->event_id;
}
else
{
#ifdef HAVE_XI23
if (META_DISPLAY_HAS_XINPUT_23 (priv->display))
{
XIBarrierReleasePointer (priv->display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
priv->xbarrier, event->event_id);
}
#endif /* HAVE_XI23 */
}
}
static void
@ -192,19 +243,29 @@ meta_barrier_constructed (GObject *object)
return;
}
dpy = priv->display->xdisplay;
root = DefaultRootWindow (dpy);
if (meta_is_wayland_compositor ())
{
MetaBarrierManager *manager = meta_barrier_manager_get ();
priv->xbarrier = XFixesCreatePointerBarrier (dpy, root,
priv->x1, priv->y1,
priv->x2, priv->y2,
priv->directions, 0, NULL);
manager->barriers = g_list_prepend (manager->barriers, g_object_ref (barrier));
priv->active = TRUE;
}
else
{
dpy = priv->display->xdisplay;
root = DefaultRootWindow (dpy);
/* Take a ref that we'll release when the XID dies inside destroy(),
* so that the object stays alive and doesn't get GC'd. */
g_object_ref (barrier);
priv->xbarrier = XFixesCreatePointerBarrier (dpy, root,
priv->x1, priv->y1,
priv->x2, priv->y2,
priv->directions, 0, NULL);
g_hash_table_insert (priv->display->xids, &priv->xbarrier, barrier);
/* Take a ref that we'll release when the XID dies inside destroy(),
* so that the object stays alive and doesn't get GC'd. */
g_object_ref (barrier);
g_hash_table_insert (priv->display->xids, &priv->xbarrier, barrier);
}
G_OBJECT_CLASS (meta_barrier_parent_class)->constructed (object);
}
@ -312,16 +373,26 @@ meta_barrier_destroy (MetaBarrier *barrier)
if (priv->display == NULL)
return;
dpy = priv->display->xdisplay;
if (meta_is_wayland_compositor ())
{
MetaBarrierManager *manager = meta_barrier_manager_get ();
if (!meta_barrier_is_active (barrier))
return;
manager->barriers = g_list_remove (manager->barriers, barrier);
g_object_unref (barrier);
}
else
{
dpy = priv->display->xdisplay;
XFixesDestroyPointerBarrier (dpy, priv->xbarrier);
g_hash_table_remove (priv->display->xids, &priv->xbarrier);
priv->xbarrier = 0;
if (!meta_barrier_is_active (barrier))
return;
g_object_unref (barrier);
XFixesDestroyPointerBarrier (dpy, priv->xbarrier);
g_hash_table_remove (priv->display->xids, &priv->xbarrier);
priv->xbarrier = 0;
g_object_unref (barrier);
}
}
static void
@ -371,6 +442,9 @@ meta_display_process_barrier_event (MetaDisplay *display,
{
MetaBarrier *barrier;
if (meta_is_wayland_compositor ())
return FALSE;
barrier = g_hash_table_lookup (display->xids, &xev->barrier);
if (barrier != NULL)
{
@ -382,6 +456,405 @@ meta_display_process_barrier_event (MetaDisplay *display,
}
#endif /* HAVE_XI23 */
/*
* The following code was copied and adapted from the X server (Xi/xibarriers.c)
*
* Copyright 2012 Red Hat, Inc.
* Copyright © 2002 Keith Packard
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
static gboolean
barrier_is_horizontal(MetaBarrier *barrier)
{
return barrier->priv->y1 == barrier->priv->y2;
}
static gboolean
barrier_is_vertical(MetaBarrier *barrier)
{
return barrier->priv->x1 == barrier->priv->x2;
}
/*
* @return The set of barrier movement directions the movement vector
* x1/y1 → x2/y2 represents.
*/
static int
barrier_get_direction(int x1, int y1, int x2, int y2)
{
int direction = 0;
/* which way are we trying to go */
if (x2 > x1)
direction |= META_BARRIER_DIRECTION_POSITIVE_X;
if (x2 < x1)
direction |= META_BARRIER_DIRECTION_NEGATIVE_X;
if (y2 > y1)
direction |= META_BARRIER_DIRECTION_POSITIVE_Y;
if (y2 < y1)
direction |= META_BARRIER_DIRECTION_NEGATIVE_Y;
return direction;
}
/*
* Test if the barrier may block movement in the direction defined by
* x1/y1 → x2/y2. This function only tests whether the directions could be
* blocked, it does not test if the barrier actually blocks the movement.
*
* @return TRUE if the barrier blocks the direction of movement or FALSE
* otherwise.
*/
static gboolean
barrier_is_blocking_direction(MetaBarrier *barrier,
MetaBarrierDirection direction)
{
/* Barriers define which way is ok, not which way is blocking */
return (barrier->priv->directions & direction) != direction;
}
static gboolean
inside_segment(int v, int v1, int v2)
{
if (v1 < 0 && v2 < 0) /* line */
return TRUE;
else if (v1 < 0) /* ray */
return v <= v2;
else if (v2 < 0) /* ray */
return v >= v1;
else /* line segment */
return v >= v1 && v <= v2;
}
#define T(v, a, b) (((float)v) - (a)) / ((b) - (a))
#define F(t, a, b) ((t) * ((a) - (b)) + (a))
/*
* Test if the movement vector x1/y1 → x2/y2 is intersecting with the
* barrier. A movement vector with the startpoint or endpoint adjacent to
* the barrier itself counts as intersecting.
*
* @param x1 X start coordinate of movement vector
* @param y1 Y start coordinate of movement vector
* @param x2 X end coordinate of movement vector
* @param y2 Y end coordinate of movement vector
* @param[out] distance The distance between the start point and the
* intersection with the barrier (if applicable).
* @return TRUE if the barrier intersects with the given vector
*/
static gboolean
barrier_is_blocking(MetaBarrier *barrier,
int x1, int y1, int x2, int y2, double *distance)
{
if (barrier_is_vertical (barrier))
{
float t, y;
t = T (barrier->priv->x1, x1, x2);
if (t < 0 || t > 1)
return FALSE;
/* Edge case: moving away from barrier. */
if (x2 > x1 && t == 0)
return FALSE;
y = F (t, y1, y2);
if (!inside_segment (y, barrier->priv->y1, barrier->priv->y2))
return FALSE;
*distance = sqrt ((y - y1) * (y - y1) + (barrier->priv->x1 - x1) * (barrier->priv->x1 - x1));
return TRUE;
}
else
{
float t, x;
t = T (barrier->priv->y1, y1, y2);
if (t < 0 || t > 1)
return FALSE;
/* Edge case: moving away from barrier. */
if (y2 > y1 && t == 0)
return FALSE;
x = F(t, x1, x2);
if (!inside_segment (x, barrier->priv->x1, barrier->priv->x2))
return FALSE;
*distance = sqrt ((x - x1) * (x - x1) + (barrier->priv->y1 - y1) * (barrier->priv->y1 - y1));
return TRUE;
}
}
#define HIT_EDGE_EXTENTS 2
static gboolean
barrier_inside_hit_box(MetaBarrier *barrier, int x, int y)
{
int x1, x2, y1, y2;
int dir;
x1 = barrier->priv->x1;
x2 = barrier->priv->x2;
y1 = barrier->priv->y1;
y2 = barrier->priv->y2;
dir = ~(barrier->priv->directions);
if (barrier_is_vertical (barrier))
{
if (dir & META_BARRIER_DIRECTION_POSITIVE_X)
x1 -= HIT_EDGE_EXTENTS;
if (dir & META_BARRIER_DIRECTION_NEGATIVE_X)
x2 += HIT_EDGE_EXTENTS;
}
if (barrier_is_horizontal (barrier))
{
if (dir & META_BARRIER_DIRECTION_POSITIVE_Y)
y1 -= HIT_EDGE_EXTENTS;
if (dir & META_BARRIER_DIRECTION_NEGATIVE_Y)
y2 += HIT_EDGE_EXTENTS;
}
return x >= x1 && x <= x2 && y >= y1 && y <= y2;
}
/*
* Find the nearest barrier client that is blocking movement from x1/y1 to x2/y2.
*
* @param dir Only barriers blocking movement in direction dir are checked
* @param x1 X start coordinate of movement vector
* @param y1 Y start coordinate of movement vector
* @param x2 X end coordinate of movement vector
* @param y2 Y end coordinate of movement vector
* @return The barrier nearest to the movement origin that blocks this movement.
*/
static MetaBarrier *
barrier_find_nearest(MetaBarrierManager *manager,
int dir,
int x1,
int y1,
int x2,
int y2)
{
GList *iter;
MetaBarrier *nearest = NULL;
double min_distance = INT_MAX; /* can't get higher than that in X anyway */
for (iter = manager->barriers; iter; iter = iter->next)
{
MetaBarrier *b = iter->data;
double distance;
if (b->priv->seen || !b->priv->active)
continue;
if (!barrier_is_blocking_direction (b, dir))
continue;
if (barrier_is_blocking (b, x1, y1, x2, y2, &distance))
{
if (min_distance > distance)
{
min_distance = distance;
nearest = b;
}
}
}
return nearest;
}
/*
* Clamp to the given barrier given the movement direction specified in dir.
*
* @param barrier The barrier to clamp to
* @param dir The movement direction
* @param[out] x The clamped x coordinate.
* @param[out] y The clamped x coordinate.
*/
static void
barrier_clamp_to_barrier(MetaBarrier *barrier,
int dir,
float *x,
float *y)
{
if (barrier_is_vertical (barrier))
{
if ((dir & META_BARRIER_DIRECTION_NEGATIVE_X) & ~barrier->priv->directions)
*x = barrier->priv->x1;
if ((dir & META_BARRIER_DIRECTION_POSITIVE_X) & ~barrier->priv->directions)
*x = barrier->priv->x1 - 1;
}
if (barrier_is_horizontal (barrier))
{
if ((dir & META_BARRIER_DIRECTION_NEGATIVE_Y) & ~barrier->priv->directions)
*y = barrier->priv->y1;
if ((dir & META_BARRIER_DIRECTION_POSITIVE_Y) & ~barrier->priv->directions)
*y = barrier->priv->y1 - 1;
}
}
static gboolean
emit_hit_event (gpointer data)
{
MetaBarrierEvent *event = data;
g_signal_emit (event->barrier, obj_signals[HIT], 0, event);
meta_barrier_event_unref (event);
return FALSE;
}
static gboolean
emit_left_event (gpointer data)
{
MetaBarrierEvent *event = data;
g_signal_emit (event->barrier, obj_signals[LEFT], 0, event);
meta_barrier_event_unref (event);
return FALSE;
}
void
meta_barrier_manager_constrain_cursor (MetaBarrierManager *manager,
guint32 time,
float current_x,
float current_y,
float *new_x,
float *new_y)
{
float x = *new_x;
float y = *new_y;
int dir;
MetaBarrier *nearest = NULL;
GList *iter;
float dx = x - current_x;
float dy = y - current_y;
/* How this works:
* Given the origin and the movement vector, get the nearest barrier
* to the origin that is blocking the movement.
* Clamp to that barrier.
* Then, check from the clamped intersection to the original
* destination, again finding the nearest barrier and clamping.
*/
dir = barrier_get_direction (current_x, current_y, x, y);
while (dir != 0)
{
MetaBarrierEvent *event;
gboolean new_sequence;
nearest = barrier_find_nearest (manager, dir, current_x, current_y, x, y);
if (!nearest)
break;
new_sequence = !nearest->priv->hit;
nearest->priv->seen = TRUE;
nearest->priv->hit = TRUE;
if (nearest->priv->barrier_event_id == nearest->priv->release_event_id)
continue;
barrier_clamp_to_barrier (nearest, dir, &x, &y);
if (barrier_is_vertical (nearest))
{
dir &= ~(META_BARRIER_DIRECTION_NEGATIVE_X | META_BARRIER_DIRECTION_POSITIVE_X);
current_x = x;
}
else if (barrier_is_horizontal (nearest))
{
dir &= ~(META_BARRIER_DIRECTION_NEGATIVE_Y | META_BARRIER_DIRECTION_POSITIVE_Y);
current_y = y;
}
event = g_slice_new0 (MetaBarrierEvent);
event->ref_count = 1;
event->barrier = g_object_ref (nearest);
event->event_id = nearest->priv->barrier_event_id;
event->time = time;
event->dt = new_sequence ? 0 : time - nearest->priv->last_timestamp;
event->x = current_x;
event->y = current_y;
event->dx = dx;
event->dy = dy;
event->released = FALSE;
event->grabbed = FALSE;
g_idle_add (emit_hit_event, event);
}
for (iter = manager->barriers; iter; iter = iter->next)
{
MetaBarrierEvent *event;
MetaBarrier *barrier = iter->data;
if (!barrier->priv->active)
continue;
barrier->priv->seen = FALSE;
if (!barrier->priv->hit)
continue;
if (barrier_inside_hit_box (barrier, x, y))
continue;
barrier->priv->hit = FALSE;
event = g_slice_new0 (MetaBarrierEvent);
event->ref_count = 1;
event->barrier = g_object_ref (barrier);
event->event_id = barrier->priv->barrier_event_id;
event->time = time;
event->dt = time - barrier->priv->last_timestamp;
event->x = current_x;
event->y = current_y;
event->dx = dx;
event->dy = dy;
event->released = barrier->priv->barrier_event_id == barrier->priv->release_event_id;
event->grabbed = FALSE;
g_idle_add (emit_left_event, event);
/* If we've left the hit box, this is the
* start of a new event ID. */
barrier->priv->barrier_event_id++;
}
*new_x = x;
*new_y = y;
}
MetaBarrierManager *
meta_barrier_manager_get (void)
{
if (!global_barrier_manager)
global_barrier_manager = g_new0 (MetaBarrierManager, 1);
return global_barrier_manager;
}
static MetaBarrierEvent *
meta_barrier_event_ref (MetaBarrierEvent *event)
{
@ -399,7 +872,12 @@ meta_barrier_event_unref (MetaBarrierEvent *event)
g_return_if_fail (event->ref_count > 0);
if (g_atomic_int_dec_and_test ((volatile int *)&event->ref_count))
g_slice_free (MetaBarrierEvent, event);
{
if (event->barrier)
g_object_unref (event->barrier);
g_slice_free (MetaBarrierEvent, event);
}
}
G_DEFINE_BOXED_TYPE (MetaBarrierEvent,

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

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

View File

@ -35,10 +35,12 @@ 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,
MetaFrameBorders *orig_borders,
MetaMoveResizeFlags flags,
int resize_gravity,
const MetaRectangle *orig,

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.
@ -154,7 +155,7 @@ 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);
@ -171,7 +172,6 @@ meta_core_queue_frame_resize (Display *xdisplay,
MetaWindow *window = get_window (xdisplay, frame_xwindow);
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
meta_window_frame_size_changed (window);
}
void
@ -271,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);
@ -280,11 +282,16 @@ meta_core_lower_beneath_grab_window (Display *xdisplay,
return;
changes.stack_mode = Below;
changes.sibling = meta_window_get_toplevel_xwindow (grab_window);
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);
@ -469,6 +476,26 @@ meta_core_change_workspace (Display *xdisplay,
new_workspace));
}
int
meta_core_get_num_workspaces (Screen *xscreen)
{
MetaScreen *screen;
screen = meta_screen_for_x_screen (xscreen);
return meta_screen_get_n_workspaces (screen);
}
int
meta_core_get_active_workspace (Screen *xscreen)
{
MetaScreen *screen;
screen = meta_screen_for_x_screen (xscreen);
return meta_workspace_index (screen->active_workspace);
}
void
meta_core_show_window_menu (Display *xdisplay,
Window frame_xwindow,

View File

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

View File

@ -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;
@ -117,6 +125,7 @@ struct _MetaDisplay
* 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;
@ -138,14 +147,6 @@ struct _MetaDisplay
*/
guint allow_terminal_deactivation : 1;
/* If true, server->focus_serial refers to us changing the focus; in
* this case, we can ignore focus events that have exactly focus_serial,
* since we take care to make another request immediately afterwards.
* But if focus is being changed by another client, we have to accept
* multiple events with the same serial.
*/
guint focused_by_us : 1;
guint static_gravity_works : 1;
/*< private-ish >*/
@ -153,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);
@ -379,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);
@ -475,14 +482,18 @@ 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,
Window window,
guint32 timestamp);
void meta_display_set_input_focus_xwindow (MetaDisplay *display,
MetaScreen *screen,
MetaFocusType type,
Window window,
guint32 timestamp);
#endif

View File

@ -34,7 +34,7 @@
#include <config.h>
#include "display-private.h"
#include <meta/util.h>
#include "util-private.h"
#include <meta/main.h>
#include "screen-private.h"
#include "window-private.h"
@ -51,6 +51,7 @@
#include <meta/compositor.h>
#include <meta/compositor-mutter.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#include "mutter-enum-types.h"
#include "meta-idle-monitor-private.h"
@ -63,9 +64,7 @@
#ifdef HAVE_XKB
#include <X11/XKBlib.h>
#endif
#ifdef HAVE_XCURSOR
#include <X11/Xcursor/Xcursor.h>
#endif
#include <X11/extensions/Xrender.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xdamage.h>
@ -74,6 +73,8 @@
#include <string.h>
#include <unistd.h>
#include "meta-xwayland-private.h"
#define GRAB_OP_IS_WINDOW_SWITCH(g) \
(g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \
g == META_GRAB_OP_KEYBOARD_TABBING_DOCK || \
@ -117,6 +118,12 @@ typedef struct
guint ping_timeout_id;
} MetaPingData;
typedef struct
{
MetaDisplay *display;
Window xwindow;
} MetaAutoRaiseData;
typedef struct
{
MetaDisplay *display;
@ -412,7 +419,7 @@ enable_compositor (MetaDisplay *display)
!META_DISPLAY_HAS_DAMAGE (display) ||
!META_DISPLAY_HAS_RENDER (display))
{
meta_warning (_("Missing %s extension required for compositing"),
meta_warning ("Missing %s extension required for compositing",
!META_DISPLAY_HAS_COMPOSITE (display) ? "composite" :
!META_DISPLAY_HAS_DAMAGE (display) ? "damage" : "render");
return;
@ -509,6 +516,9 @@ meta_display_open (void)
return FALSE;
}
if (meta_is_wayland_compositor ())
meta_xwayland_complete_init ();
if (meta_is_syncing ())
XSynchronize (xdisplay, True);
@ -597,6 +607,7 @@ meta_display_open (void)
the_display->xids = g_hash_table_new (meta_unsigned_long_hash,
meta_unsigned_long_equal);
the_display->wayland_windows = g_hash_table_new (NULL, NULL);
i = 0;
while (i < N_IGNORED_CROSSING_SERIALS)
@ -816,14 +827,10 @@ meta_display_open (void)
meta_fatal ("X server doesn't have the XInput extension, version 2.2 or newer\n");
}
#ifdef HAVE_XCURSOR
{
XcursorSetTheme (the_display->xdisplay, meta_prefs_get_cursor_theme ());
XcursorSetDefaultSize (the_display->xdisplay, meta_prefs_get_cursor_size ());
}
#else /* HAVE_XCURSOR */
meta_verbose ("Not compiled with Xcursor support\n");
#endif /* !HAVE_XCURSOR */
/* Create the leader window here. Set its properties and
* use the timestamp from one of the PropertyNotify events
@ -918,13 +925,31 @@ meta_display_open (void)
enable_compositor (the_display);
meta_display_grab (the_display);
/* Now manage all existing windows */
tmp = the_display->screens;
while (tmp != NULL)
{
MetaScreen *screen = tmp->data;
meta_screen_manage_all_windows (screen);
if (meta_is_wayland_compositor ())
{
/* Instead of explicitly enumerating all windows during
* initialization, when we run as a wayland compositor we can rely on
* xwayland notifying us of all top level windows so we create
* MetaWindows when we get those notifications.
*
* We still want a guard window so we can avoid
* unmapping/withdrawing minimized windows for live
* thumbnails...
*/
if (screen->guard_window == None)
screen->guard_window =
meta_screen_create_guard_window (screen->display->xdisplay, screen);
}
else
meta_screen_manage_all_windows (screen);
tmp = tmp->next;
}
@ -969,6 +994,8 @@ meta_display_open (void)
meta_idle_monitor_init_dbus ();
meta_display_ungrab (the_display);
/* Done opening new display */
the_display->display_opening = FALSE;
@ -1022,6 +1049,19 @@ meta_display_list_windows (MetaDisplay *display,
winlist = g_slist_prepend (winlist, window);
}
g_hash_table_iter_init (&iter, display->wayland_windows);
while (g_hash_table_iter_next (&iter, &key, &value))
{
MetaWindow *window = value;
if (!META_IS_WINDOW (window))
continue;
if (!window->override_redirect ||
(flags & META_LIST_INCLUDE_OVERRIDE_REDIRECT) != 0)
winlist = g_slist_prepend (winlist, window);
}
/* Uniquify the list, since both frame windows and plain
* windows are in the hash
*/
@ -1213,18 +1253,7 @@ meta_display_screen_for_x_screen (MetaDisplay *display,
return NULL;
}
/* Grab/ungrab routines taken from fvwm.
* Calling this function will cause X to ignore all other clients until
* you ungrab. This may not be quite as bad as it sounds, yet there is
* agreement that avoiding server grabs except when they are clearly needed
* is a good thing.
*
* If you do use such grabs, please clearly explain the necessity for their
* usage in a comment. Try to keep their scope extremely limited. In
* particular, try to avoid emitting any signals or notifications while
* a grab is active (if the signal receiver tries to block on an X request
* from another client at this point, you will have a deadlock).
*/
/* Grab/ungrab routines taken from fvwm */
void
meta_display_grab (MetaDisplay *display)
{
@ -1486,20 +1515,27 @@ guint32
meta_display_get_current_time_roundtrip (MetaDisplay *display)
{
guint32 timestamp;
timestamp = meta_display_get_current_time (display);
if (timestamp == CurrentTime)
{
XEvent property_event;
XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
display->atom__MUTTER_TIMESTAMP_PING,
XA_STRING, 8, PropModeAppend, NULL, 0);
XIfEvent (display->xdisplay,
&property_event,
find_timestamp_predicate,
(XPointer) display);
timestamp = property_event.xproperty.time;
if (meta_is_wayland_compositor ())
{
timestamp = g_get_monotonic_time () / 1000;
}
else
{
timestamp = meta_display_get_current_time (display);
if (timestamp == CurrentTime)
{
XEvent property_event;
XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
display->atom__MUTTER_TIMESTAMP_PING,
XA_STRING, 8, PropModeAppend, NULL, 0);
XIfEvent (display->xdisplay,
&property_event,
find_timestamp_predicate,
(XPointer) display);
timestamp = property_event.xproperty.time;
}
}
sanity_check_timestamps (display, timestamp);
@ -1586,10 +1622,23 @@ reset_ignored_crossing_serials (MetaDisplay *display)
static gboolean
window_raise_with_delay_callback (void *data)
{
MetaWindow *window = data;
MetaWindow *window;
MetaAutoRaiseData *auto_raise;
window->display->autoraise_timeout_id = 0;
window->display->autoraise_window = NULL;
auto_raise = data;
meta_topic (META_DEBUG_FOCUS,
"In autoraise callback for window 0x%lx\n",
auto_raise->xwindow);
auto_raise->display->autoraise_timeout_id = 0;
auto_raise->display->autoraise_window = NULL;
window = meta_display_lookup_x_window (auto_raise->display,
auto_raise->xwindow);
if (window == NULL)
return FALSE;
/* If we aren't already on top, check whether the pointer is inside
* the window and raise the window if so.
@ -1598,7 +1647,6 @@ window_raise_with_delay_callback (void *data)
{
int x, y, root_x, root_y;
Window root, child;
MetaRectangle frame_rect;
unsigned int mask;
gboolean same_screen;
gboolean point_in_window;
@ -1610,8 +1658,9 @@ window_raise_with_delay_callback (void *data)
&root_x, &root_y, &x, &y, &mask);
meta_error_trap_pop (window->display);
meta_window_get_frame_rect (window, &frame_rect);
point_in_window = POINT_IN_RECT (root_x, root_y, frame_rect);
point_in_window =
(window->frame && POINT_IN_RECT (root_x, root_y, window->frame->rect)) ||
(window->frame == NULL && POINT_IN_RECT (root_x, root_y, window->rect));
if (same_screen && point_in_window)
meta_window_raise (window);
else
@ -1626,8 +1675,7 @@ window_raise_with_delay_callback (void *data)
static void
meta_display_mouse_mode_focus (MetaDisplay *display,
MetaWindow *window,
guint32 timestamp)
{
guint32 timestamp) {
if (window->type != META_WINDOW_DESKTOP)
{
meta_topic (META_DEBUG_FOCUS,
@ -1666,8 +1714,7 @@ meta_display_mouse_mode_focus (MetaDisplay *display,
}
static gboolean
window_focus_on_pointer_rest_callback (gpointer data)
{
window_focus_on_pointer_rest_callback (gpointer data) {
MetaFocusData *focus_data;
MetaDisplay *display;
MetaScreen *screen;
@ -1712,9 +1759,9 @@ window_focus_on_pointer_rest_callback (gpointer data)
goto out;
window =
meta_stack_get_default_focus_window_at_point (screen->stack,
screen->active_workspace,
None, root_x, root_y);
meta_stack_get_default_focus_window_at_point (screen->stack,
screen->active_workspace,
None, root_x, root_y);
if (window == NULL)
goto out;
@ -1722,7 +1769,7 @@ window_focus_on_pointer_rest_callback (gpointer data)
timestamp = meta_display_get_current_time_roundtrip (display);
meta_display_mouse_mode_focus (display, window, timestamp);
out:
out:
display->focus_timeout_id = 0;
return FALSE;
}
@ -1731,11 +1778,17 @@ void
meta_display_queue_autoraise_callback (MetaDisplay *display,
MetaWindow *window)
{
MetaAutoRaiseData *auto_raise_data;
meta_topic (META_DEBUG_FOCUS,
"Queuing an autoraise timeout for %s with delay %d\n",
window->desc,
meta_prefs_get_auto_raise_delay ());
auto_raise_data = g_new (MetaAutoRaiseData, 1);
auto_raise_data->display = window->display;
auto_raise_data->xwindow = window->xwindow;
if (display->autoraise_timeout_id != 0)
g_source_remove (display->autoraise_timeout_id);
@ -1743,7 +1796,8 @@ meta_display_queue_autoraise_callback (MetaDisplay *display,
g_timeout_add_full (G_PRIORITY_DEFAULT,
meta_prefs_get_auto_raise_delay (),
window_raise_with_delay_callback,
window, NULL);
auto_raise_data,
g_free);
display->autoraise_window = window;
}
@ -1869,16 +1923,19 @@ get_input_event (MetaDisplay *display,
}
static void
update_focus_window (MetaDisplay *display,
MetaWindow *window,
Window xwindow,
gulong serial,
gboolean focused_by_us)
update_focus_window (MetaDisplay *display,
MetaFocusType type,
MetaWindow *window,
Window xwindow,
gulong serial)
{
display->focus_serial = serial;
display->focused_by_us = focused_by_us;
MetaWaylandCompositor *compositor;
if (display->focus_xwindow == xwindow)
display->focus_serial = serial;
if (display->focus_xwindow == xwindow &&
display->focus_type == type &&
display->focus_window == window)
return;
if (display->focus_window)
@ -1900,6 +1957,7 @@ update_focus_window (MetaDisplay *display,
meta_window_set_focused_internal (previous, FALSE);
}
display->focus_type = type;
display->focus_window = window;
display->focus_xwindow = xwindow;
@ -1912,6 +1970,19 @@ update_focus_window (MetaDisplay *display,
else
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial);
if (meta_is_wayland_compositor ())
{
compositor = meta_wayland_compositor_get_default ();
if (display->focus_type == META_FOCUS_NO_FOCUS_WINDOW ||
display->focus_type == META_FOCUS_STAGE)
meta_wayland_compositor_set_input_focus (compositor, NULL);
else if (window && window->surface)
meta_wayland_compositor_set_input_focus (compositor, window);
else
meta_topic (META_DEBUG_FOCUS, "Focus change has no effect, because there is no matching wayland surface");
}
g_object_notify (G_OBJECT (display), "focus-window");
meta_display_update_active_window_hint (display);
}
@ -1946,19 +2017,18 @@ timestamp_too_old (MetaDisplay *display,
}
static void
request_xserver_input_focus_change (MetaDisplay *display,
MetaScreen *screen,
Window xwindow,
guint32 timestamp)
request_xserver_input_focus_change (MetaDisplay *display,
MetaScreen *screen,
MetaFocusType type,
MetaWindow *meta_window,
Window xwindow,
guint32 timestamp)
{
MetaWindow *meta_window;
gulong serial;
if (timestamp_too_old (display, &timestamp))
return;
meta_window = meta_display_lookup_x_window (display, xwindow);
meta_error_trap_push (display);
/* In order for mutter to know that the focus request succeeded, we track
@ -1985,10 +2055,10 @@ request_xserver_input_focus_change (MetaDisplay *display,
meta_display_ungrab (display);
update_focus_window (display,
type,
meta_window,
xwindow,
serial,
TRUE);
serial);
meta_error_trap_pop (display);
@ -2006,9 +2076,12 @@ handle_window_focus_event (MetaDisplay *display,
unsigned long serial)
{
MetaWindow *focus_window;
MetaFocusType type;
#ifdef WITH_VERBOSE_MODE
const char *window_type;
type = META_FOCUS_NONE;
/* Note the event can be on either the window or the frame,
* we focus the frame for shaded windows
*/
@ -2020,14 +2093,26 @@ handle_window_focus_event (MetaDisplay *display,
window_type = "frame window";
else
window_type = "unknown client window";
if (window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND)
type = META_FOCUS_WAYLAND_CLIENT;
else
type = META_FOCUS_X_CLIENT;
}
else if (meta_display_xwindow_is_a_no_focus_window (display, event->event))
window_type = "no_focus_window";
{
window_type = "no_focus_window";
type = META_FOCUS_NO_FOCUS_WINDOW;
}
else if (meta_display_screen_for_root (display, event->event))
window_type = "root window";
else
window_type = "unknown window";
/* Don't change type if we don't know the new window */
if (type == META_FOCUS_NONE)
type = display->focus_type;
meta_topic (META_DEBUG_FOCUS,
"Focus %s event received on %s 0x%lx (%s) "
"mode %s detail %s serial %lu\n",
@ -2102,41 +2187,54 @@ handle_window_focus_event (MetaDisplay *display,
else
g_return_if_reached ();
/* If display->focused_by_us, then the focus_serial will be used only
* for a focus change we made and have already accounted for.
* (See request_xserver_input_focus_change().) Otherwise, we can get
* multiple focus events with the same serial.
*/
if (display->server_focus_serial > display->focus_serial ||
(!display->focused_by_us &&
display->server_focus_serial == display->focus_serial))
if (display->server_focus_serial > display->focus_serial)
{
update_focus_window (display,
type,
focus_window,
focus_window ? focus_window->xwindow : None,
display->server_focus_serial,
FALSE);
display->server_focus_serial);
}
}
static gboolean
window_has_xwindow (MetaWindow *window,
Window xwindow)
static void
reload_xkb_rules (MetaScreen *screen)
{
if (window->xwindow == xwindow)
return TRUE;
MetaWaylandCompositor *compositor;
char **names;
int n_names;
gboolean ok;
const char *rules, *model, *layout, *variant, *options;
if (window->frame && window->frame->xwindow == xwindow)
return TRUE;
compositor = meta_wayland_compositor_get_default ();
return FALSE;
ok = meta_prop_get_latin1_list (screen->display, screen->xroot,
screen->display->atom__XKB_RULES_NAMES,
&names, &n_names);
if (!ok)
return;
if (n_names != 5)
goto out;
rules = names[0];
model = names[1];
layout = names[2];
variant = names[3];
options = names[4];
meta_wayland_keyboard_set_keymap_names (&compositor->seat->keyboard,
rules, model, layout, variant, options,
META_WAYLAND_KEYBOARD_SKIP_XCLIENTS);
out:
g_strfreev (names);
}
/**
* event_callback:
* meta_display_handle_event:
* @display: The MetaDisplay that events are coming from
* @event: The event that just happened
* @data: The #MetaDisplay that events are coming from, cast to a gpointer
* so that it can be sent to a callback
*
* This is the most important function in the whole program. It is the heart,
* it is the nexus, it is the Grand Central Station of Mutter's world.
@ -2146,13 +2244,12 @@ window_has_xwindow (MetaWindow *window,
* busy around here. Most of this function is a ginormous switch statement
* dealing with all the kinds of events that might turn up.
*/
static gboolean
event_callback (XEvent *event,
gpointer data)
gboolean
meta_display_handle_event (MetaDisplay *display,
XEvent *event)
{
MetaWindow *window;
MetaWindow *property_for_window;
MetaDisplay *display;
Window modified;
gboolean frame_was_receiver;
gboolean bypass_compositor;
@ -2161,8 +2258,6 @@ event_callback (XEvent *event,
MetaMonitorManager *monitor;
MetaScreen *screen;
display = data;
#ifdef WITH_VERBOSE_MODE
if (dump_events)
meta_spew_event (display, event);
@ -2185,18 +2280,17 @@ event_callback (XEvent *event,
display->current_time = event_get_time (display, event);
display->monitor_cache_invalidated = TRUE;
if (display->focused_by_us &&
event->xany.serial > display->focus_serial &&
if (event->xany.serial > display->focus_serial &&
display->focus_window &&
!window_has_xwindow (display->focus_window, display->server_focus_window))
display->focus_window->xwindow != display->server_focus_window)
{
meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed\n",
display->focus_window->desc);
update_focus_window (display,
META_FOCUS_NONE,
meta_display_lookup_x_window (display, display->server_focus_window),
display->server_focus_window,
display->server_focus_serial,
FALSE);
display->server_focus_serial);
}
screen = meta_display_screen_for_root (display, event->xany.window);
@ -2295,6 +2389,8 @@ event_callback (XEvent *event,
if (sev->kind == ShapeBounding)
meta_window_update_shape_region_x11 (window);
else if (sev->kind == ShapeInput)
meta_window_update_input_region_x11 (window);
}
else
{
@ -2312,7 +2408,7 @@ event_callback (XEvent *event,
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
if (window && !window->override_redirect &&
((input_event->evtype == XI_KeyPress) || (input_event->evtype == XI_ButtonPress)))
((input_event->type == XI_KeyPress) || (input_event->type == XI_ButtonPress)))
{
if (CurrentTime == display->current_time)
{
@ -2357,7 +2453,6 @@ event_callback (XEvent *event,
if ((window &&
meta_grab_op_is_mouse (display->grab_op) &&
(device_event->mods.effective & display->window_grab_modifiers) &&
display->grab_button != device_event->detail &&
display->grab_window == window) ||
grab_op_is_keyboard (display->grab_op))
@ -2444,15 +2539,15 @@ event_callback (XEvent *event,
{
gboolean north, south;
gboolean west, east;
MetaRectangle frame_rect;
int root_x, root_y;
MetaGrabOp op;
meta_window_get_frame_rect (window, &frame_rect);
meta_window_get_position (window, &root_x, &root_y);
west = device_event->root_x < (frame_rect.x + 1 * frame_rect.width / 3);
east = device_event->root_x > (frame_rect.x + 2 * frame_rect.width / 3);
north = device_event->root_y < (frame_rect.y + 1 * frame_rect.height / 3);
south = device_event->root_y > (frame_rect.y + 2 * frame_rect.height / 3);
west = device_event->root_x < (root_x + 1 * window->rect.width / 3);
east = device_event->root_x > (root_x + 2 * window->rect.width / 3);
north = device_event->root_y < (root_y + 1 * window->rect.height / 3);
south = device_event->root_y > (root_y + 2 * window->rect.height / 3);
if (north && west)
op = META_GRAB_OP_RESIZING_NW;
@ -2782,14 +2877,14 @@ event_callback (XEvent *event,
&& meta_display_screen_for_root (display, event->xmap.event))
{
window = meta_window_new (display, event->xmap.window,
FALSE, META_COMP_EFFECT_CREATE);
FALSE);
}
break;
case MapRequest:
if (window == NULL)
{
window = meta_window_new (display, event->xmaprequest.window,
FALSE, META_COMP_EFFECT_CREATE);
FALSE);
}
/* if frame was receiver it's some malicious send event or something */
else if (!frame_was_receiver && window)
@ -2908,6 +3003,10 @@ event_callback (XEvent *event,
else if (event->xproperty.atom ==
display->atom__NET_DESKTOP_NAMES)
meta_screen_update_workspace_names (screen);
else if (meta_is_wayland_compositor () &&
event->xproperty.atom ==
display->atom__XKB_RULES_NAMES)
reload_xkb_rules (screen);
#if 0
else if (event->xproperty.atom ==
display->atom__NET_RESTACK_WINDOW)
@ -3125,6 +3224,32 @@ event_callback (XEvent *event,
return filter_out_event;
}
static gboolean
event_callback (XEvent *event,
gpointer data)
{
MetaDisplay *display = data;
/* Under Wayland we want to filter out mouse motion events so we can
synthesize them from the Clutter events instead. This is
necessary because the position in the mouse events is passed to
the X server relative to the position of the surface. The X
server then translates these back to screen coordinates based on
the window position. If we rely on this translatation when
dragging a window around then the window will jump around
erratically because of the lag between updating the window
position from the surface position. Instead we bypass the
translation altogether by directly using the Clutter events */
if (meta_is_wayland_compositor () &&
event->type == GenericEvent &&
(event->xcookie.evtype == XI_Motion ||
event->xcookie.evtype == XI_KeyPress ||
event->xcookie.evtype == XI_KeyRelease))
return FALSE;
return meta_display_handle_event (display, event);
}
/* Return the window this has to do with, if any, rather
* than the frame or root window that was selecting
* for substructure
@ -3800,6 +3925,20 @@ meta_display_unregister_x_window (MetaDisplay *display,
remove_pending_pings_for_window (display, xwindow);
}
void
meta_display_register_wayland_window (MetaDisplay *display,
MetaWindow *window)
{
g_hash_table_add (display->wayland_windows, window);
}
void
meta_display_unregister_wayland_window (MetaDisplay *display,
MetaWindow *window)
{
g_hash_table_remove (display->wayland_windows, window);
}
#ifdef HAVE_XSYNC
/* We store sync alarms in the window ID hash table, because they are
* just more types of XIDs in the same global space, but we have
@ -3867,6 +4006,85 @@ meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
return is_a_no_focus_window;
}
Cursor
meta_display_create_x_cursor (MetaDisplay *display,
MetaCursor cursor)
{
Cursor xcursor;
guint glyph = XC_num_glyphs;
const char *name = NULL;
switch (cursor)
{
case META_CURSOR_DEFAULT:
glyph = XC_left_ptr;
break;
case META_CURSOR_NORTH_RESIZE:
glyph = XC_top_side;
break;
case META_CURSOR_SOUTH_RESIZE:
glyph = XC_bottom_side;
break;
case META_CURSOR_WEST_RESIZE:
glyph = XC_left_side;
break;
case META_CURSOR_EAST_RESIZE:
glyph = XC_right_side;
break;
case META_CURSOR_SE_RESIZE:
glyph = XC_bottom_right_corner;
break;
case META_CURSOR_SW_RESIZE:
glyph = XC_bottom_left_corner;
break;
case META_CURSOR_NE_RESIZE:
glyph = XC_top_right_corner;
break;
case META_CURSOR_NW_RESIZE:
glyph = XC_top_left_corner;
break;
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
glyph = XC_fleur;
break;
case META_CURSOR_BUSY:
glyph = XC_watch;
break;
case META_CURSOR_DND_IN_DRAG:
name = "dnd-none";
break;
case META_CURSOR_DND_MOVE:
name = "dnd-move";
break;
case META_CURSOR_DND_COPY:
name = "dnd-copy";
break;
case META_CURSOR_DND_UNSUPPORTED_TARGET:
name = "dnd-none";
break;
case META_CURSOR_POINTING_HAND:
glyph = XC_hand2;
break;
case META_CURSOR_CROSSHAIR:
glyph = XC_crosshair;
break;
case META_CURSOR_IBEAM:
glyph = XC_xterm;
break;
default:
g_assert_not_reached ();
glyph = 0; /* silence compiler */
break;
}
if (name != NULL)
xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
else
xcursor = XCreateFontCursor (display->xdisplay, glyph);
return xcursor;
}
static Cursor
xcursor_for_op (MetaDisplay *display,
MetaGrabOp op)
@ -4028,7 +4246,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
* key grab on the RootWindow.
*/
if (grab_window)
grab_xwindow = meta_window_get_toplevel_xwindow (grab_window);
grab_xwindow = grab_window->frame ? grab_window->frame->xwindow : grab_window->xwindow;
else
grab_xwindow = screen->xroot;
@ -4556,7 +4774,6 @@ meta_display_queue_retheme_all_windows (MetaDisplay *display)
MetaWindow *window = tmp->data;
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
meta_window_frame_size_changed (window);
if (window->frame)
{
meta_frame_queue_draw (window->frame);
@ -4578,7 +4795,6 @@ void
meta_display_set_cursor_theme (const char *theme,
int size)
{
#ifdef HAVE_XCURSOR
GSList *tmp;
MetaDisplay *display = meta_get_display ();
@ -4595,8 +4811,6 @@ meta_display_set_cursor_theme (const char *theme,
tmp = tmp->next;
}
#endif
}
/*
@ -5723,6 +5937,9 @@ meta_display_set_input_focus_window (MetaDisplay *display,
{
request_xserver_input_focus_change (display,
window->screen,
window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND ?
META_FOCUS_WAYLAND_CLIENT : META_FOCUS_X_CLIENT,
window,
focus_frame ? window->frame->xwindow : window->xwindow,
timestamp);
}
@ -5738,19 +5955,41 @@ meta_display_request_take_focus (MetaDisplay *display,
meta_topic (META_DEBUG_FOCUS, "WM_TAKE_FOCUS(%s, %u)\n",
window->desc, timestamp);
if (window != display->focus_window)
{
/* The "Globally Active Input" window case, where the window
* doesn't want us to call XSetInputFocus on it, but does
* want us to send a WM_TAKE_FOCUS.
*
* We can't just set display->focus_window to @window, since we
* we don't know when (or even if) the window will actually take
* focus, so we could end up being wrong for arbitrarily long.
* But we also can't leave it set to the current window, or else
* bug #597352 would come back. So we focus the no_focus_window
* now (and set display->focus_window to that), send the
* WM_TAKE_FOCUS, and then just forget about @window
* until/unless we get a FocusIn.
*/
meta_display_focus_the_no_focus_window (display,
window->screen,
timestamp);
}
meta_window_send_icccm_message (window,
display->atom_WM_TAKE_FOCUS,
timestamp);
}
void
meta_display_set_input_focus_xwindow (MetaDisplay *display,
MetaScreen *screen,
Window window,
guint32 timestamp)
meta_display_set_input_focus_xwindow (MetaDisplay *display,
MetaScreen *screen,
MetaFocusType type,
Window window,
guint32 timestamp)
{
request_xserver_input_focus_change (display,
screen,
type,
NULL,
window,
timestamp);
}
@ -5762,6 +6001,8 @@ meta_display_focus_the_no_focus_window (MetaDisplay *display,
{
request_xserver_input_focus_change (display,
screen,
META_FOCUS_NO_FOCUS_WINDOW,
NULL,
screen->no_focus_window,
timestamp);
}
@ -5837,7 +6078,7 @@ meta_display_get_xinput_opcode (MetaDisplay *display)
gboolean
meta_display_supports_extended_barriers (MetaDisplay *display)
{
return META_DISPLAY_HAS_XINPUT_23 (display);
return meta_is_wayland_compositor () || META_DISPLAY_HAS_XINPUT_23 (display);
}
/**

View File

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

View File

@ -47,10 +47,14 @@ meta_window_ensure_frame (MetaWindow *window)
XSetWindowAttributes attrs;
Visual *visual;
gulong create_serial;
MetaStackWindow stack_window;
if (window->frame)
return;
/* See comment below for why this is required. */
meta_display_grab (window->display);
frame = g_new (MetaFrame, 1);
frame->window = window;
@ -65,7 +69,6 @@ meta_window_ensure_frame (MetaWindow *window)
frame->mapped = FALSE;
frame->is_flashing = FALSE;
frame->borders_cached = FALSE;
meta_verbose ("Framing window %s: visual %s default, depth %d default depth %d\n",
window->desc,
@ -103,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);
@ -114,6 +119,14 @@ meta_window_ensure_frame (MetaWindow *window)
meta_display_register_x_window (window->display, &frame->xwindow, window);
/* Reparent the client window; it may be destroyed,
* thus the error trap. We'll get a destroy notify later
* and free everything. Comment in FVWM source code says
* we need a server grab or the child can get its MapNotify
* before we've finished reparenting and getting the decoration
* window onscreen, so ensure_frame must be called with
* a grab.
*/
meta_error_trap_push (window->display);
if (window->mapped)
{
@ -128,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,
@ -155,6 +169,8 @@ meta_window_ensure_frame (MetaWindow *window)
/* Move keybindings to frame instead of window */
meta_window_grab_keys (window);
meta_display_ungrab (window->display);
}
void
@ -162,6 +178,7 @@ meta_window_destroy_frame (MetaWindow *window)
{
MetaFrame *frame;
MetaFrameBorders borders;
MetaStackWindow stack_window;
if (window->frame == NULL)
return;
@ -188,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,
@ -315,23 +334,9 @@ meta_frame_calc_borders (MetaFrame *frame,
if (frame == NULL)
meta_frame_borders_clear (borders);
else
{
if (!frame->borders_cached)
{
meta_ui_get_frame_borders (frame->window->screen->ui,
frame->xwindow,
&frame->cached_borders);
frame->borders_cached = TRUE;
}
*borders = frame->cached_borders;
}
}
void
meta_frame_clear_cached_borders (MetaFrame *frame)
{
frame->borders_cached = FALSE;
meta_ui_get_frame_borders (frame->window->screen->ui,
frame->xwindow,
borders);
}
gboolean

View File

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

View File

@ -41,9 +41,8 @@
#include "ui.h"
#include "frame.h"
#include "place.h"
#include "screen-private.h"
#include <meta/prefs.h>
#include <meta/util.h>
#include "util-private.h"
#include <X11/keysym.h>
#include <string.h>
@ -54,8 +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"
#define SCHEMA_MUTTER_WAYLAND_KEYBINDINGS "org.gnome.mutter.wayland.keybindings"
static gboolean add_builtin_keybinding (MetaDisplay *display,
const char *name,
@ -1134,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",
@ -1278,7 +1282,7 @@ meta_window_grab_keys (MetaWindow *window)
}
meta_window_change_keygrabs (window,
meta_window_get_toplevel_xwindow (window),
window->frame ? window->frame->xwindow : window->xwindow,
TRUE);
window->keys_grabbed = TRUE;
@ -1331,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;
}
@ -1581,7 +1585,7 @@ meta_window_grab_all_keys (MetaWindow *window,
window->desc);
meta_window_focus (window, timestamp);
grabwindow = meta_window_get_toplevel_xwindow (window);
grabwindow = window->frame ? window->frame->xwindow : window->xwindow;
meta_topic (META_DEBUG_KEYBINDINGS,
"Grabbing all keys on window %s\n", window->desc);
@ -1836,6 +1840,7 @@ invoke_handler_by_name (MetaDisplay *display,
invoke_handler (display, screen, handler, window, event, NULL);
}
/* now called from only one place, may be worth merging */
static gboolean
process_event (MetaKeyBinding *bindings,
int n_bindings,
@ -1843,6 +1848,7 @@ process_event (MetaKeyBinding *bindings,
MetaScreen *screen,
MetaWindow *window,
XIDeviceEvent *event,
KeySym keysym,
gboolean on_window)
{
int i;
@ -1860,6 +1866,7 @@ process_event (MetaKeyBinding *bindings,
MetaKeyHandler *handler = bindings[i].handler;
if ((!on_window && handler->flags & META_KEY_BINDING_PER_WINDOW) ||
event->evtype != XI_KeyPress ||
bindings[i].keycode != event->detail ||
((event->mods.effective & 0xff & ~(display->ignored_modifier_mask)) !=
bindings[i].mask) ||
@ -1926,7 +1933,7 @@ process_overlay_key (MetaDisplay *display,
*/
if (process_event (display->key_bindings,
display->n_key_bindings,
display, screen, NULL, event,
display, screen, NULL, event, keysym,
FALSE))
{
/* As normally, after we've handled a global key
@ -2058,22 +2065,22 @@ meta_display_process_key_event (MetaDisplay *display,
gboolean handled;
const char *str;
MetaScreen *screen;
gboolean was_current_time;
/* if key event was on root window, we have a shortcut */
screen = meta_display_screen_for_root (display, event->event);
/* else round-trip to server */
if (screen == NULL)
screen = meta_display_screen_for_xwindow (display, event->event);
if (screen == NULL)
return FALSE; /* event window is destroyed */
/* We only ever have one screen */
screen = display->screens->data;
/* ignore key events on popup menus and such. */
if (meta_ui_window_is_widget (screen->ui, event->event))
return FALSE;
/* window may be NULL */
if (display->current_time == CurrentTime)
{
display->current_time = event->time;
was_current_time = TRUE;
}
else
was_current_time = FALSE;
keysym = XKeycodeToKeysym (display->xdisplay, event->detail, 0);
@ -2091,11 +2098,11 @@ meta_display_process_key_event (MetaDisplay *display,
{
handled = process_overlay_key (display, screen, event, keysym);
if (handled)
return TRUE;
goto out;
handled = process_iso_next_group (display, screen, event, keysym);
if (handled)
return TRUE;
goto out;
}
XIAllowEvents (display->xdisplay, event->deviceid,
@ -2105,7 +2112,11 @@ meta_display_process_key_event (MetaDisplay *display,
if (all_keys_grabbed)
{
if (display->grab_op == META_GRAB_OP_NONE)
return TRUE;
{
handled = TRUE;
goto out;
}
/* If we get here we have a global grab, because
* we're in some special keyboard mode such as window move
* mode.
@ -2184,14 +2195,20 @@ meta_display_process_key_event (MetaDisplay *display,
meta_display_end_grab_op (display, event->time);
}
return TRUE;
handled = TRUE;
goto out;
}
/* Do the normal keybindings */
return process_event (display->key_bindings,
display->n_key_bindings,
display, screen, window, event,
!all_keys_grabbed && window);
handled = process_event (display->key_bindings,
display->n_key_bindings,
display, screen, window, event, keysym,
!all_keys_grabbed && window);
out:
if (was_current_time)
display->current_time = CurrentTime;
return handled;
}
static gboolean
@ -3138,20 +3155,6 @@ handle_maximize_horizontally (MetaDisplay *display,
}
}
static void
handle_always_on_top (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
XIDeviceEvent *event,
MetaKeyBinding *binding,
gpointer dummy)
{
if (window->wm_state_above == FALSE)
meta_window_make_above (window);
else
meta_window_unmake_above (window);
}
/* Move a window to a corner; to_bottom/to_right are FALSE for the
* top or left edge, or TRUE for the bottom/right edge. xchange/ychange
* are FALSE if that dimension is not to be changed, TRUE otherwise.
@ -3169,17 +3172,17 @@ handle_move_to_corner_backend (MetaDisplay *display,
gpointer dummy)
{
MetaRectangle work_area;
MetaRectangle frame_rect;
MetaRectangle outer;
int orig_x, orig_y;
int new_x, new_y;
meta_window_get_work_area_all_monitors (window, &work_area);
meta_window_get_frame_rect (window, &frame_rect);
meta_window_get_outer_rect (window, &outer);
meta_window_get_position (window, &orig_x, &orig_y);
if (xchange) {
new_x = work_area.x + (to_right ?
work_area.width - frame_rect.width :
work_area.width - outer.width :
0);
} else {
new_x = orig_x;
@ -3187,7 +3190,7 @@ handle_move_to_corner_backend (MetaDisplay *display,
if (ychange) {
new_y = work_area.y + (to_bottom ?
work_area.height - frame_rect.height :
work_area.height - outer.height :
0);
} else {
new_y = orig_y;
@ -3296,12 +3299,12 @@ handle_move_to_center (MetaDisplay *display,
gpointer dummy)
{
MetaRectangle work_area;
MetaRectangle frame_rect;
MetaRectangle outer;
int orig_x, orig_y;
int frame_width, frame_height;
meta_window_get_work_area_all_monitors (window, &work_area);
meta_window_get_frame_rect (window, &frame_rect);
meta_window_get_outer_rect (window, &outer);
meta_window_get_position (window, &orig_x, &orig_y);
frame_width = (window->frame ? window->frame->child_x : 0);
@ -3309,8 +3312,8 @@ handle_move_to_center (MetaDisplay *display,
meta_window_move_resize (window,
TRUE,
work_area.x + (work_area.width +frame_width -frame_rect.width )/2,
work_area.y + (work_area.height+frame_height-frame_rect.height)/2,
work_area.x + (work_area.width +frame_width -outer.width )/2,
work_area.y + (work_area.height+frame_height-outer.height)/2,
window->rect.width,
window->rect.height);
}
@ -3974,26 +3977,6 @@ handle_move_to_workspace (MetaDisplay *display,
}
}
static void
handle_move_to_monitor (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
XIDeviceEvent *event,
MetaKeyBinding *binding,
gpointer dummy)
{
gint which = binding->handler->data;
const MetaMonitorInfo *current, *new;
current = meta_screen_get_monitor_for_window (screen, window);
new = meta_screen_get_monitor_neighbor (screen, current->number, which);
if (new == NULL)
return;
meta_window_move_to_monitor (window, new->number);
}
static void
handle_raise_or_lower (MetaDisplay *display,
MetaScreen *screen,
@ -4023,8 +4006,8 @@ handle_raise_or_lower (MetaDisplay *display,
if (above->mapped)
{
meta_window_get_frame_rect (window, &win_rect);
meta_window_get_frame_rect (above, &above_rect);
meta_window_get_outer_rect (window, &win_rect);
meta_window_get_outer_rect (above, &above_rect);
/* Check if obscured */
if (meta_rectangle_intersect (&win_rect, &above_rect, &tmp))
@ -4130,6 +4113,40 @@ handle_set_spew_mark (MetaDisplay *display,
meta_verbose ("-- MARK MARK MARK MARK --\n");
}
#ifdef HAVE_WAYLAND
static void
handle_switch_vt (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
XIDeviceEvent *event,
MetaKeyBinding *binding,
gpointer dummy)
{
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:
* @name: The name of the keybinding to set
@ -4164,6 +4181,28 @@ meta_keybindings_set_custom_handler (const gchar *name,
return TRUE;
}
/**
* meta_keybindings_switch_window: (skip)
* @display: a #MetaDisplay
* @screen: a #MetaScreen
* @event_window: a #MetaWindow
* @event: a #XIDeviceEvent
* @binding: a #MetaKeyBinding
*
*/
void
meta_keybindings_switch_window (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *event_window,
XIDeviceEvent *event,
MetaKeyBinding *binding)
{
gint backwards = (binding->handler->flags & META_KEY_BINDING_IS_REVERSED) != 0;
do_choose_window (display, screen, event_window, event, binding,
backwards, FALSE);
}
static void
init_builtin_key_bindings (MetaDisplay *display)
{
@ -4171,6 +4210,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",
@ -4432,6 +4472,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 ************************/
@ -4650,34 +4744,6 @@ init_builtin_key_bindings (MetaDisplay *display)
META_KEYBINDING_ACTION_MOVE_TO_WORKSPACE_DOWN,
handle_move_to_workspace, META_MOTION_DOWN);
add_builtin_keybinding (display,
"move-to-monitor-left",
common_keybindings,
META_KEY_BINDING_PER_WINDOW,
META_KEYBINDING_ACTION_MOVE_TO_MONITOR_LEFT,
handle_move_to_monitor, META_SCREEN_LEFT);
add_builtin_keybinding (display,
"move-to-monitor-right",
common_keybindings,
META_KEY_BINDING_PER_WINDOW,
META_KEYBINDING_ACTION_MOVE_TO_MONITOR_RIGHT,
handle_move_to_monitor, META_SCREEN_RIGHT);
add_builtin_keybinding (display,
"move-to-monitor-down",
common_keybindings,
META_KEY_BINDING_PER_WINDOW,
META_KEYBINDING_ACTION_MOVE_TO_MONITOR_DOWN,
handle_move_to_monitor, META_SCREEN_DOWN);
add_builtin_keybinding (display,
"move-to-monitor-up",
common_keybindings,
META_KEY_BINDING_PER_WINDOW,
META_KEYBINDING_ACTION_MOVE_TO_MONITOR_UP,
handle_move_to_monitor, META_SCREEN_UP);
add_builtin_keybinding (display,
"raise-or-lower",
common_keybindings,
@ -4713,13 +4779,6 @@ init_builtin_key_bindings (MetaDisplay *display)
META_KEYBINDING_ACTION_MAXIMIZE_HORIZONTALLY,
handle_maximize_horizontally, 0);
add_builtin_keybinding (display,
"always-on-top",
common_keybindings,
META_KEY_BINDING_PER_WINDOW,
META_KEYBINDING_ACTION_ALWAYS_ON_TOP,
handle_always_on_top, 0);
add_builtin_keybinding (display,
"move-to-corner-nw",
common_keybindings,

View File

@ -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,18 @@ 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));
if (getenv ("MUTTER_SLEEP_INIT"))
sleep (60);
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 +424,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 +445,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 ();
}
}
/**

View File

@ -1,7 +1,7 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2013 Red Hat, Inc.
* 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
@ -25,10 +25,24 @@
#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

View File

@ -24,38 +24,64 @@
/**
* SECTION:cursor-tracker
* @title: MetaCursorTracker
* @short_description: Mutter cursor tracking helper
* @short_description: Mutter cursor tracking helper. Originally only
* tracking the cursor image, now more of a "core
* pointer abstraction"
*/
#include <config.h>
#include <string.h>
#include <meta/main.h>
#include <meta/util.h>
#include <meta/errors.h>
#include <cogl/cogl.h>
#include <cogl/cogl-wayland-server.h>
#include <clutter/clutter.h>
#include <gbm.h>
#include <gdk/gdk.h>
#include <X11/cursorfont.h>
#include <X11/extensions/Xfixes.h>
#include <X11/Xcursor/Xcursor.h>
#include "meta-cursor-tracker-private.h"
#include "screen-private.h"
#include "meta-wayland-private.h"
#include "monitor-private.h"
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X 7
#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y 4
typedef struct {
CoglTexture2D *texture;
struct gbm_bo *bo;
int hot_x, hot_y;
int ref_count;
} MetaCursorReference;
struct _MetaCursorTracker {
GObject parent_instance;
MetaScreen *screen;
gboolean is_showing;
gboolean has_cursor;
gboolean has_hw_cursor;
CoglTexture2D *sprite;
int hot_x, hot_y;
MetaCursorReference *sprite;
MetaCursorReference *root_cursor;
MetaCursorReference *default_cursors[META_CURSOR_LAST];
int current_x, current_y;
MetaRectangle current_rect;
MetaRectangle previous_rect;
gboolean previous_is_valid;
CoglPipeline *pipeline;
int drm_fd;
struct gbm_device *gbm;
};
struct _MetaCursorTrackerClass {
@ -71,114 +97,367 @@ enum {
static guint signals[LAST_SIGNAL];
static void
translate_meta_cursor (MetaCursor cursor,
guint *glyph_out,
const char **name_out)
{
guint glyph = XC_num_glyphs;
const char *name = NULL;
static void meta_cursor_tracker_set_sprite (MetaCursorTracker *tracker,
MetaCursorReference *sprite);
static void meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
MetaCRTC *crtc,
gboolean has_hw_cursor);
static MetaCursorReference *
meta_cursor_reference_ref (MetaCursorReference *self)
{
g_assert (self->ref_count > 0);
self->ref_count++;
return self;
}
static void
meta_cursor_reference_unref (MetaCursorReference *self)
{
self->ref_count--;
if (self->ref_count == 0)
{
cogl_object_unref (self->texture);
if (self->bo)
gbm_bo_destroy (self->bo);
g_slice_free (MetaCursorReference, self);
}
}
static const char *
get_cursor_filename (MetaCursor cursor)
{
switch (cursor)
{
case META_CURSOR_DEFAULT:
glyph = XC_left_ptr;
return "left_ptr";
break;
case META_CURSOR_NORTH_RESIZE:
glyph = XC_top_side;
return "top_side";
break;
case META_CURSOR_SOUTH_RESIZE:
glyph = XC_bottom_side;
return "bottom_side";
break;
case META_CURSOR_WEST_RESIZE:
glyph = XC_left_side;
return "left_side";
break;
case META_CURSOR_EAST_RESIZE:
glyph = XC_right_side;
return "right_side";
break;
case META_CURSOR_SE_RESIZE:
glyph = XC_bottom_right_corner;
return "bottom_right_corner";
break;
case META_CURSOR_SW_RESIZE:
glyph = XC_bottom_left_corner;
return "bottom_left_corner";
break;
case META_CURSOR_NE_RESIZE:
glyph = XC_top_right_corner;
return "top_right_corner";
break;
case META_CURSOR_NW_RESIZE:
glyph = XC_top_left_corner;
return "top_left_corner";
break;
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
glyph = XC_fleur;
return "fleur";
break;
case META_CURSOR_BUSY:
glyph = XC_watch;
return "watch";
break;
case META_CURSOR_DND_IN_DRAG:
name = "dnd-none";
return "dnd-in-drag";
break;
case META_CURSOR_DND_MOVE:
name = "dnd-move";
break;
case META_CURSOR_DND_COPY:
name = "dnd-copy";
return "dnd-copy";
break;
case META_CURSOR_DND_UNSUPPORTED_TARGET:
name = "dnd-none";
return "dnd-none";
break;
case META_CURSOR_POINTING_HAND:
glyph = XC_hand2;
return "hand";
break;
case META_CURSOR_CROSSHAIR:
glyph = XC_crosshair;
return "crosshair";
break;
case META_CURSOR_IBEAM:
glyph = XC_xterm;
return "xterm";
break;
default:
g_assert_not_reached ();
glyph = 0; /* silence compiler */
break;
return NULL;
}
}
static MetaCursorReference *
meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
MetaCursor cursor)
{
const char *theme;
const char *filename;
int size;
XcursorImage *image;
int width, height, rowstride;
CoglPixelFormat cogl_format;
uint32_t gbm_format;
ClutterBackend *clutter_backend;
CoglContext *cogl_context;
MetaCursorReference *self;
filename = get_cursor_filename (cursor);
theme = XcursorGetTheme (tracker->screen->display->xdisplay);
size = XcursorGetDefaultSize (tracker->screen->display->xdisplay);
image = XcursorLibraryLoadImage (filename, theme, size);
if (!image)
return NULL;
width = image->width;
height = image->height;
rowstride = width * 4;
gbm_format = GBM_FORMAT_ARGB8888;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
#else
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
#endif
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
self->hot_x = image->xhot;
self->hot_y = image->yhot;
clutter_backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (clutter_backend);
self->texture = cogl_texture_2d_new_from_data (cogl_context,
width, height,
cogl_format,
COGL_PIXEL_FORMAT_ANY,
rowstride,
(uint8_t*)image->pixels,
NULL);
if (tracker->gbm)
{
if (width > 64 || height > 64)
{
meta_warning ("Invalid theme cursor size (must be at most 64x64)\n");
goto out;
}
if (gbm_device_is_format_supported (tracker->gbm, gbm_format,
GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
{
uint32_t buf[64 * 64];
int i;
self->bo = gbm_bo_create (tracker->gbm, 64, 64,
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
memset (buf, 0, sizeof(buf));
for (i = 0; i < height; i++)
memcpy (buf + i * 64, image->pixels + i * width, width * 4);
gbm_bo_write (self->bo, buf, 64 * 64 * 4);
}
else
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
}
*glyph_out = glyph;
*name_out = name;
out:
XcursorImageDestroy (image);
return self;
}
static Cursor
load_cursor_on_server (MetaDisplay *display,
MetaCursor cursor)
static MetaCursorReference *
meta_cursor_reference_take_texture (CoglTexture2D *texture)
{
Cursor xcursor;
guint glyph;
const char *name;
MetaCursorReference *self;
translate_meta_cursor (cursor, &glyph, &name);
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
if (name != NULL)
xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
self->texture = texture;
return self;
}
static MetaCursorReference *
meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y)
{
ClutterBackend *backend;
CoglContext *cogl_context;
MetaCursorReference *self;
CoglPixelFormat cogl_format, cogl_internal_format;
struct wl_shm_buffer *shm_buffer;
uint32_t gbm_format;
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend);
shm_buffer = wl_shm_buffer_get (buffer);
if (shm_buffer)
{
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
int width = wl_shm_buffer_get_width (shm_buffer);
int height = wl_shm_buffer_get_height (shm_buffer);
switch (wl_shm_buffer_get_format (shm_buffer))
{
#if G_BYTE_ORDER == G_BIG_ENDIAN
case WL_SHM_FORMAT_ARGB8888:
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888_PRE;
cogl_internal_format = COGL_PIXEL_FORMAT_ANY;
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
cogl_internal_format = COGL_PIXEL_FORMAT_RGB_888;
gbm_format = GBM_FORMAT_XRGB8888;
break;
#else
case WL_SHM_FORMAT_ARGB8888:
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888_PRE;
cogl_internal_format = COGL_PIXEL_FORMAT_ANY;
gbm_format = GBM_FORMAT_ARGB8888;
break;
case WL_SHM_FORMAT_XRGB8888:
cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
cogl_internal_format = COGL_PIXEL_FORMAT_BGR_888;
gbm_format = GBM_FORMAT_XRGB8888;
break;
#endif
default:
g_warn_if_reached ();
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
cogl_internal_format = COGL_PIXEL_FORMAT_ANY;
gbm_format = GBM_FORMAT_ARGB8888;
}
self->texture = cogl_texture_2d_new_from_data (cogl_context,
width, height,
cogl_format,
cogl_internal_format,
rowstride,
wl_shm_buffer_get_data (shm_buffer),
NULL);
if (width > 64 || height > 64)
{
meta_warning ("Invalid cursor size (must be at most 64x64), falling back to software (GL) cursors\n");
return self;
}
if (tracker->gbm)
{
if (gbm_device_is_format_supported (tracker->gbm, gbm_format,
GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE))
{
uint8_t *data;
uint8_t buf[4 * 64 * 64];
int i;
self->bo = gbm_bo_create (tracker->gbm, 64, 64,
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
data = wl_shm_buffer_get_data (shm_buffer);
memset (buf, 0, sizeof(buf));
for (i = 0; i < height; i++)
memcpy (buf + i * 4 * 64, data + i * rowstride, 4 * width);
gbm_bo_write (self->bo, buf, 64 * 64 * 4);
}
else
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
}
}
else
xcursor = XCreateFontCursor (display->xdisplay, glyph);
{
int width, height;
return xcursor;
}
self->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
width = cogl_texture_get_width (COGL_TEXTURE (self->texture));
height = cogl_texture_get_height (COGL_TEXTURE (self->texture));
Cursor
meta_display_create_x_cursor (MetaDisplay *display,
MetaCursor cursor)
{
return load_cursor_on_server (display, cursor);
/* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
that, so themed cursors must be padded with transparent pixels to fill the
overlay. This is trivial if we have CPU access to the data, but it's not
possible if the buffer is in GPU memory (and possibly tiled too), so if we
don't get the right size, we fallback to GL.
*/
if (width != 64 || height != 64)
{
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
return self;
}
if (tracker->gbm)
{
cogl_format = cogl_texture_get_format (COGL_TEXTURE (self->texture));
switch (cogl_format)
{
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
case COGL_PIXEL_FORMAT_ARGB_8888_PRE:
case COGL_PIXEL_FORMAT_ARGB_8888:
gbm_format = GBM_FORMAT_BGRA8888;
break;
case COGL_PIXEL_FORMAT_BGRA_8888_PRE:
case COGL_PIXEL_FORMAT_BGRA_8888:
break;
case COGL_PIXEL_FORMAT_RGB_888:
break;
#else
case COGL_PIXEL_FORMAT_ARGB_8888_PRE:
case COGL_PIXEL_FORMAT_ARGB_8888:
gbm_format = GBM_FORMAT_ARGB8888;
break;
case COGL_PIXEL_FORMAT_BGRA_8888_PRE:
case COGL_PIXEL_FORMAT_BGRA_8888:
gbm_format = GBM_FORMAT_BGRA8888;
break;
case COGL_PIXEL_FORMAT_RGB_888:
gbm_format = GBM_FORMAT_RGB888;
break;
#endif
default:
meta_warning ("Unknown cogl format %d\n", cogl_format);
return self;
}
if (gbm_device_is_format_supported (tracker->gbm, gbm_format,
GBM_BO_USE_CURSOR_64X64))
{
self->bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER,
buffer, GBM_BO_USE_CURSOR_64X64);
if (!self->bo)
meta_warning ("Importing HW cursor from wl_buffer failed\n");
}
else
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
}
}
return self;
}
static void
meta_cursor_tracker_init (MetaCursorTracker *self)
{
/* (JS) Best (?) that can be assumed since XFixes doesn't provide a way of
* detecting if the system mouse cursor is showing or not.
*
* On wayland we start with the cursor showing
*/
detecting if the system mouse cursor is showing or not.
On wayland we start with the cursor showing
*/
self->is_showing = TRUE;
}
@ -186,9 +465,21 @@ static void
meta_cursor_tracker_finalize (GObject *object)
{
MetaCursorTracker *self = META_CURSOR_TRACKER (object);
int i;
if (self->sprite)
cogl_object_unref (self->sprite);
meta_cursor_reference_unref (self->sprite);
if (self->root_cursor)
meta_cursor_reference_unref (self->root_cursor);
for (i = 0; i < META_CURSOR_LAST; i++)
if (self->default_cursors[i])
meta_cursor_reference_unref (self->default_cursors[i]);
if (self->pipeline)
cogl_object_unref (self->pipeline);
if (self->gbm)
gbm_device_destroy (self->gbm);
G_OBJECT_CLASS (meta_cursor_tracker_parent_class)->finalize (object);
}
@ -208,6 +499,60 @@ meta_cursor_tracker_class_init (MetaCursorTrackerClass *klass)
G_TYPE_NONE, 0);
}
static void
on_monitors_changed (MetaMonitorManager *monitors,
MetaCursorTracker *tracker)
{
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
if (!tracker->has_hw_cursor)
return;
/* Go through the new list of monitors, find out where the cursor is */
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = meta_rectangle_overlap (&tracker->current_rect, rect);
/* Need to do it unconditionally here, our tracking is
wrong because we reloaded the CRTCs */
meta_cursor_tracker_set_crtc_has_hw_cursor (tracker, &crtcs[i], has);
}
}
static MetaCursorTracker *
make_wayland_cursor_tracker (MetaScreen *screen)
{
MetaWaylandCompositor *compositor;
CoglContext *ctx;
MetaMonitorManager *monitors;
MetaCursorTracker *self;
self = g_object_new (META_TYPE_CURSOR_TRACKER, NULL);
self->screen = screen;
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
self->pipeline = cogl_pipeline_new (ctx);
compositor = meta_wayland_compositor_get_default ();
compositor->seat->cursor_tracker = self;
self->drm_fd = compositor->drm_fd;
if (self->drm_fd >= 0)
self->gbm = gbm_create_device (compositor->drm_fd);
monitors = meta_monitor_manager_get ();
g_signal_connect_object (monitors, "monitors-changed",
G_CALLBACK (on_monitors_changed), self, 0);
return self;
}
static MetaCursorTracker *
make_x11_cursor_tracker (MetaScreen *screen)
{
@ -237,7 +582,12 @@ meta_cursor_tracker_get_for_screen (MetaScreen *screen)
if (screen->cursor_tracker)
return screen->cursor_tracker;
self = make_x11_cursor_tracker (screen);
#ifdef HAVE_WAYLAND
if (meta_is_wayland_compositor ())
self = make_wayland_cursor_tracker (screen);
else
#endif
self = make_x11_cursor_tracker (screen);
screen->cursor_tracker = self;
return self;
@ -249,6 +599,9 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
{
XFixesCursorNotifyEvent *notify_event;
if (meta_is_wayland_compositor ())
return FALSE;
if (xevent->xany.type != tracker->screen->display->xfixes_event_base + XFixesCursorNotify)
return FALSE;
@ -256,7 +609,7 @@ meta_cursor_tracker_handle_xevent (MetaCursorTracker *tracker,
if (notify_event->subtype != XFixesDisplayCursorNotify)
return FALSE;
g_clear_pointer (&tracker->sprite, cogl_object_unref);
g_clear_pointer (&tracker->sprite, meta_cursor_reference_unref);
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
return TRUE;
@ -319,9 +672,9 @@ ensure_xfixes_cursor (MetaCursorTracker *tracker)
if (sprite != NULL)
{
tracker->sprite = sprite;
tracker->hot_x = cursor_image->xhot;
tracker->hot_y = cursor_image->yhot;
tracker->sprite = meta_cursor_reference_take_texture (sprite);
tracker->sprite->hot_x = cursor_image->xhot;
tracker->sprite->hot_y = cursor_image->yhot;
}
XFree (cursor_image);
}
@ -336,9 +689,13 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker)
{
g_return_val_if_fail (META_IS_CURSOR_TRACKER (tracker), NULL);
ensure_xfixes_cursor (tracker);
if (!meta_is_wayland_compositor ())
ensure_xfixes_cursor (tracker);
return COGL_TEXTURE (tracker->sprite);
if (tracker->sprite)
return COGL_TEXTURE (tracker->sprite->texture);
else
return NULL;
}
/**
@ -355,12 +712,37 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker,
{
g_return_if_fail (META_IS_CURSOR_TRACKER (tracker));
ensure_xfixes_cursor (tracker);
if (!meta_is_wayland_compositor ())
ensure_xfixes_cursor (tracker);
if (x)
*x = tracker->hot_x;
if (y)
*y = tracker->hot_y;
if (tracker->sprite)
{
if (x)
*x = tracker->sprite->hot_x;
if (y)
*y = tracker->sprite->hot_y;
}
else
{
if (x)
*x = 0;
if (y)
*y = 0;
}
}
static MetaCursorReference *
ensure_wayland_cursor (MetaCursorTracker *tracker,
MetaCursor cursor)
{
if (tracker->default_cursors[cursor])
return tracker->default_cursors[cursor];
tracker->default_cursors[cursor] = meta_cursor_reference_from_theme (tracker, cursor);
if (!tracker->default_cursors[cursor])
meta_warning ("Failed to load cursor from theme\n");
return tracker->default_cursors[cursor];
}
void
@ -376,13 +758,236 @@ meta_cursor_tracker_set_root_cursor (MetaCursorTracker *tracker,
XDefineCursor (display->xdisplay, tracker->screen->xroot, xcursor);
XFlush (display->xdisplay);
XFreeCursor (display->xdisplay, xcursor);
/* Now update the real root cursor */
if (meta_is_wayland_compositor ())
{
MetaCursorReference *ref;
ref = ensure_wayland_cursor (tracker, cursor);
g_clear_pointer (&tracker->root_cursor, meta_cursor_reference_unref);
tracker->root_cursor = meta_cursor_reference_ref (ref);
}
}
void
meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker,
int *x,
int *y,
ClutterModifierType *mods)
meta_cursor_tracker_revert_root (MetaCursorTracker *tracker)
{
meta_cursor_tracker_set_sprite (tracker, tracker->root_cursor);
}
static void
update_hw_cursor (MetaCursorTracker *tracker)
{
MetaMonitorManager *monitors;
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
gboolean enabled;
enabled = tracker->has_cursor && tracker->sprite->bo != NULL;
tracker->has_hw_cursor = enabled;
monitors = meta_monitor_manager_get ();
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = enabled && meta_rectangle_overlap (&tracker->current_rect, rect);
if (has || crtcs[i].has_hw_cursor)
meta_cursor_tracker_set_crtc_has_hw_cursor (tracker, &crtcs[i], has);
}
}
static void
move_hw_cursor (MetaCursorTracker *tracker)
{
MetaMonitorManager *monitors;
MetaCRTC *crtcs;
unsigned int i, n_crtcs;
monitors = meta_monitor_manager_get ();
meta_monitor_manager_get_resources (monitors, NULL, NULL, &crtcs, &n_crtcs, NULL, NULL);
g_assert (tracker->has_hw_cursor);
for (i = 0; i < n_crtcs; i++)
{
MetaRectangle *rect = &crtcs[i].rect;
gboolean has;
has = meta_rectangle_overlap (&tracker->current_rect, rect);
if (has != crtcs[i].has_hw_cursor)
meta_cursor_tracker_set_crtc_has_hw_cursor (tracker, &crtcs[i], has);
if (has)
drmModeMoveCursor (tracker->drm_fd, crtcs[i].crtc_id,
tracker->current_rect.x - rect->x,
tracker->current_rect.y - rect->y);
}
}
void
meta_cursor_tracker_set_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y)
{
MetaCursorReference *new_cursor;
if (buffer)
{
new_cursor = meta_cursor_reference_from_buffer (tracker, buffer, hot_x, hot_y);
meta_cursor_tracker_set_sprite (tracker, new_cursor);
meta_cursor_reference_unref (new_cursor);
}
else
meta_cursor_tracker_set_sprite (tracker, NULL);
}
static void
meta_cursor_tracker_set_sprite (MetaCursorTracker *tracker,
MetaCursorReference *sprite)
{
g_assert (meta_is_wayland_compositor ());
if (sprite == tracker->sprite)
return;
g_clear_pointer (&tracker->sprite, meta_cursor_reference_unref);
if (sprite)
{
tracker->sprite = meta_cursor_reference_ref (sprite);
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, COGL_TEXTURE (tracker->sprite->texture));
}
else
cogl_pipeline_set_layer_texture (tracker->pipeline, 0, NULL);
tracker->has_cursor = tracker->sprite != NULL && tracker->is_showing;
update_hw_cursor (tracker);
g_signal_emit (tracker, signals[CURSOR_CHANGED], 0);
meta_cursor_tracker_update_position (tracker, tracker->current_x, tracker->current_y);
}
void
meta_cursor_tracker_update_position (MetaCursorTracker *tracker,
int new_x,
int new_y)
{
g_assert (meta_is_wayland_compositor ());
tracker->current_x = new_x;
tracker->current_y = new_y;
if (tracker->sprite)
{
tracker->current_rect.x = tracker->current_x - tracker->sprite->hot_x;
tracker->current_rect.y = tracker->current_y - tracker->sprite->hot_y;
tracker->current_rect.width = cogl_texture_get_width (COGL_TEXTURE (tracker->sprite->texture));
tracker->current_rect.height = cogl_texture_get_height (COGL_TEXTURE (tracker->sprite->texture));
}
else
{
tracker->current_rect.x = 0;
tracker->current_rect.y = 0;
tracker->current_rect.width = 0;
tracker->current_rect.height = 0;
}
if (tracker->has_hw_cursor)
move_hw_cursor (tracker);
}
void
meta_cursor_tracker_paint (MetaCursorTracker *tracker)
{
g_assert (meta_is_wayland_compositor ());
if (tracker->has_hw_cursor || !tracker->has_cursor)
return;
cogl_framebuffer_draw_rectangle (cogl_get_draw_framebuffer (),
tracker->pipeline,
tracker->current_rect.x,
tracker->current_rect.y,
tracker->current_rect.x +
tracker->current_rect.width,
tracker->current_rect.y +
tracker->current_rect.height);
tracker->previous_rect = tracker->current_rect;
tracker->previous_is_valid = TRUE;
}
void
meta_cursor_tracker_queue_redraw (MetaCursorTracker *tracker,
ClutterActor *stage)
{
cairo_rectangle_int_t clip;
g_assert (meta_is_wayland_compositor ());
if (tracker->previous_is_valid)
{
cairo_rectangle_int_t clip = {
.x = tracker->previous_rect.x,
.y = tracker->previous_rect.y,
.width = tracker->previous_rect.width,
.height = tracker->previous_rect.height
};
clutter_actor_queue_redraw_with_clip (stage, &clip);
tracker->previous_is_valid = FALSE;
}
if (tracker->has_hw_cursor || !tracker->has_cursor)
return;
clip.x = tracker->current_rect.x;
clip.y = tracker->current_rect.y;
clip.width = tracker->current_rect.width;
clip.height = tracker->current_rect.height;
clutter_actor_queue_redraw_with_clip (stage, &clip);
}
static void
meta_cursor_tracker_set_crtc_has_hw_cursor (MetaCursorTracker *tracker,
MetaCRTC *crtc,
gboolean has)
{
if (has)
{
union gbm_bo_handle handle;
int width, height;
int hot_x, hot_y;
handle = gbm_bo_get_handle (tracker->sprite->bo);
width = gbm_bo_get_width (tracker->sprite->bo);
height = gbm_bo_get_height (tracker->sprite->bo);
hot_x = tracker->sprite->hot_x;
hot_y = tracker->sprite->hot_y;
drmModeSetCursor2 (tracker->drm_fd, crtc->crtc_id, handle.u32,
width, height, hot_x, hot_y);
crtc->has_hw_cursor = TRUE;
}
else
{
drmModeSetCursor2 (tracker->drm_fd, crtc->crtc_id, 0, 0, 0, 0, 0);
crtc->has_hw_cursor = FALSE;
}
}
static void
get_pointer_position_gdk (int *x,
int *y,
int *mods)
{
GdkDeviceManager *gmanager;
GdkDevice *gdevice;
@ -397,6 +1002,41 @@ meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker,
NULL, (GdkModifierType*)mods);
}
static void
get_pointer_position_clutter (int *x,
int *y,
int *mods)
{
ClutterDeviceManager *cmanager;
ClutterInputDevice *cdevice;
ClutterPoint point;
cmanager = clutter_device_manager_get_default ();
cdevice = clutter_device_manager_get_core_device (cmanager, CLUTTER_POINTER_DEVICE);
clutter_input_device_get_coords (cdevice, NULL, &point);
*x = point.x;
*y = point.y;
*mods = clutter_input_device_get_modifier_state (cdevice);
}
void
meta_cursor_tracker_get_pointer (MetaCursorTracker *tracker,
int *x,
int *y,
ClutterModifierType *mods)
{
/* We can't use the clutter interface when not running as a wayland compositor,
because we need to query the server, rather than using the last cached value.
OTOH, on wayland we can't use GDK, because that only sees the events
we forward to xwayland.
*/
if (meta_is_wayland_compositor ())
get_pointer_position_clutter (x, y, (int*)mods);
else
get_pointer_position_gdk (x, y, (int*)mods);
}
void
meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
gboolean visible)
@ -405,10 +1045,23 @@ meta_cursor_tracker_set_pointer_visible (MetaCursorTracker *tracker,
return;
tracker->is_showing = visible;
if (visible)
XFixesShowCursor (tracker->screen->display->xdisplay,
tracker->screen->xroot);
if (meta_is_wayland_compositor ())
{
MetaWaylandCompositor *compositor;
compositor = meta_wayland_compositor_get_default ();
tracker->has_cursor = tracker->sprite != NULL && visible;
update_hw_cursor (tracker);
meta_cursor_tracker_queue_redraw (tracker, compositor->stage);
}
else
XFixesHideCursor (tracker->screen->display->xdisplay,
tracker->screen->xroot);
{
if (visible)
XFixesShowCursor (tracker->screen->display->xdisplay,
tracker->screen->xroot);
else
XFixesHideCursor (tracker->screen->display->xdisplay,
tracker->screen->xroot);
}
}

View File

@ -26,5 +26,6 @@
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

@ -57,6 +57,9 @@ struct _MetaIdleMonitor
int sync_event_base;
XSyncCounter counter;
XSyncAlarm user_active_alarm;
/* Wayland implementation */
guint64 last_event_time;
};
struct _MetaIdleMonitorClass
@ -76,6 +79,9 @@ typedef struct
/* x11 */
XSyncAlarm xalarm;
int idle_source_id;
/* wayland */
GSource *timeout_source;
} MetaIdleMonitorWatch;
enum
@ -305,6 +311,9 @@ idle_monitor_watch_free (MetaIdleMonitorWatch *watch)
g_hash_table_remove (monitor->alarms, (gpointer) watch->xalarm);
}
if (watch->timeout_source != NULL)
g_source_destroy (watch->timeout_source);
g_object_unref (monitor);
g_slice_free (MetaIdleMonitorWatch, watch);
}
@ -384,8 +393,11 @@ meta_idle_monitor_constructed (GObject *object)
{
MetaIdleMonitor *monitor = META_IDLE_MONITOR (object);
monitor->display = meta_get_display ()->xdisplay;
init_xsync (monitor);
if (!meta_is_wayland_compositor ())
{
monitor->display = meta_get_display ()->xdisplay;
init_xsync (monitor);
}
}
static void
@ -464,6 +476,25 @@ meta_idle_monitor_get_for_device (int 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)
{
@ -492,20 +523,37 @@ make_watch (MetaIdleMonitor *monitor,
watch->notify = notify;
watch->timeout_msec = timeout_msec;
if (timeout_msec != 0)
if (meta_is_wayland_compositor ())
{
watch->xalarm = _xsync_alarm_set (monitor, XSyncPositiveTransition, timeout_msec, TRUE);
if (timeout_msec != 0)
{
GSource *source = g_source_new (&wayland_source_funcs, sizeof (GSource));
g_hash_table_add (monitor->alarms, (gpointer) watch->xalarm);
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);
if (meta_idle_monitor_get_idletime (monitor) > (gint64)timeout_msec)
watch->idle_source_id = g_idle_add (fire_watch_idle, watch);
watch->timeout_source = source;
}
}
else
{
watch->xalarm = monitor->user_active_alarm;
if (timeout_msec != 0)
{
watch->xalarm = _xsync_alarm_set (monitor, XSyncPositiveTransition, timeout_msec, TRUE);
set_alarm_enabled (monitor->display, monitor->user_active_alarm, 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,
@ -622,10 +670,69 @@ meta_idle_monitor_get_idletime (MetaIdleMonitor *monitor)
{
XSyncValue value;
if (!XSyncQueryCounter (monitor->display, monitor->counter, &value))
return -1;
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);
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
@ -842,8 +949,6 @@ on_bus_acquired (GDBusConnection *connection,
for (iter = devices; iter; iter = iter->next)
on_device_added (device_manager, iter->data, manager);
g_slist_free (devices);
g_signal_connect_object (device_manager, "device-added",
G_CALLBACK (on_device_added), manager, 0);
g_signal_connect_object (device_manager, "device-removed",

View File

@ -99,9 +99,8 @@ static gboolean meta_monitor_config_assign_crtcs (MetaConfiguration *config,
GPtrArray *crtcs,
GPtrArray *outputs);
static void power_client_changed_cb (UpClient *client,
GParamSpec *pspec,
gpointer user_data);
static void power_client_changed_cb (UpClient *client,
gpointer user_data);
static void
free_output_key (MetaOutputKey *key)
@ -233,7 +232,7 @@ meta_monitor_config_init (MetaMonitorConfig *self)
self->up_client = up_client_new ();
self->lid_is_closed = up_client_get_lid_is_closed (self->up_client);
g_signal_connect_object (self->up_client, "notify::lid-is-closed",
g_signal_connect_object (self->up_client, "changed",
G_CALLBACK (power_client_changed_cb), self, 0);
}
@ -817,22 +816,6 @@ meta_monitor_config_match_current (MetaMonitorConfig *self,
return ok;
}
gboolean
meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
{
MetaOutput *outputs;
unsigned n_outputs;
unsigned int i;
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
for (i = 0; i < n_outputs; i++)
if (outputs[i].hotplug_mode_update)
return TRUE;
return FALSE;
}
static MetaConfiguration *
meta_monitor_config_get_stored (MetaMonitorConfig *self,
MetaOutput *outputs,
@ -841,9 +824,6 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self,
MetaConfiguration key;
MetaConfiguration *stored;
if (n_outputs == 0)
return NULL;
make_config_key (&key, outputs, n_outputs, -1);
stored = g_hash_table_lookup (self->configs, &key);
@ -1251,12 +1231,6 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height);
if (n_outputs == 0)
{
meta_verbose ("No output connected, not applying configuration\n");
return;
}
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
if (default_config != NULL)
@ -1361,9 +1335,8 @@ turn_off_laptop_display (MetaMonitorConfig *self,
}
static void
power_client_changed_cb (UpClient *client,
GParamSpec *pspec,
gpointer user_data)
power_client_changed_cb (UpClient *client,
gpointer user_data)
{
MetaMonitorManager *manager = meta_monitor_manager_get ();
MetaMonitorConfig *self = user_data;

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;
}

View File

@ -117,8 +117,8 @@ struct _MetaOutput
gboolean is_primary;
gboolean is_presentation;
/* get a new preferred mode on hotplug events, to handle dynamic guest resizing */
gboolean hotplug_mode_update;
gpointer driver_private;
GDestroyNotify driver_notify;
};
struct _MetaCRTC
@ -136,16 +136,23 @@ struct _MetaCRTC
/* 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;
};
/**
@ -354,6 +361,18 @@ 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))
@ -386,7 +405,8 @@ void meta_output_info_free (MetaOutputInfo *info);
void meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
int n_old_outputs);
gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager);
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 */

View File

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

View File

@ -33,9 +33,10 @@
#include <clutter/clutter.h>
#include <meta/main.h>
#include <meta/util.h>
#include "util-private.h"
#include <meta/errors.h>
#include "monitor-private.h"
#include "meta-wayland-private.h"
#include "meta-dbus-xrandr.h"
@ -64,59 +65,23 @@ static void initialize_dbus_interface (MetaMonitorManager *manager);
static void
read_current_dummy (MetaMonitorManager *manager)
{
/* The dummy monitor config has:
- one enabled output, LVDS, primary, at 0x0 and 1024x768
- one free CRTC
- two disabled outputs
- three modes, 1024x768, 800x600 and 640x480
- no clones are possible (use different CRTCs)
Low-level IDs should be assigned sequentially, to
mimick what XRandR and KMS do
*/
manager->max_screen_width = 65535;
manager->max_screen_height = 65535;
manager->screen_width = 1024;
manager->screen_height = 768;
manager->modes = g_new0 (MetaMonitorMode, 6);
manager->n_modes = 6;
manager->modes = g_new0 (MetaMonitorMode, 1);
manager->n_modes = 1;
manager->modes[0].mode_id = 1;
manager->modes[0].mode_id = 0;
manager->modes[0].width = 1024;
manager->modes[0].height = 768;
manager->modes[0].refresh_rate = 60.0;
manager->modes[1].mode_id = 2;
manager->modes[1].width = 800;
manager->modes[1].height = 600;
manager->modes[1].refresh_rate = 60.0;
manager->crtcs = g_new0 (MetaCRTC, 1);
manager->n_crtcs = 1;
manager->modes[2].mode_id = 3;
manager->modes[2].width = 640;
manager->modes[2].height = 480;
manager->modes[2].refresh_rate = 60.0;
manager->modes[3].mode_id = 4;
manager->modes[3].width = 1920;
manager->modes[3].height = 1080;
manager->modes[3].refresh_rate = 60.0;
manager->modes[4].mode_id = 5;
manager->modes[4].width = 1920;
manager->modes[4].height = 1080;
manager->modes[4].refresh_rate = 55.0;
manager->modes[5].mode_id = 6;
manager->modes[5].width = 1600;
manager->modes[5].height = 900;
manager->modes[5].refresh_rate = 60.0;
manager->crtcs = g_new0 (MetaCRTC, 3);
manager->n_crtcs = 3;
manager->crtcs[0].crtc_id = 4;
manager->crtcs[0].crtc_id = 1;
manager->crtcs[0].rect.x = 0;
manager->crtcs[0].rect.y = 0;
manager->crtcs[0].rect.width = manager->modes[0].width;
@ -127,111 +92,30 @@ read_current_dummy (MetaMonitorManager *manager)
manager->crtcs[0].is_dirty = FALSE;
manager->crtcs[0].logical_monitor = NULL;
manager->crtcs[1].crtc_id = 5;
manager->crtcs[1].rect.x = 0;
manager->crtcs[1].rect.y = 0;
manager->crtcs[1].rect.width = 0;
manager->crtcs[1].rect.height = 0;
manager->crtcs[1].current_mode = NULL;
manager->crtcs[1].transform = WL_OUTPUT_TRANSFORM_NORMAL;
manager->crtcs[1].all_transforms = ALL_WL_TRANSFORMS;
manager->crtcs[1].is_dirty = FALSE;
manager->crtcs[1].logical_monitor = NULL;
manager->outputs = g_new0 (MetaOutput, 1);
manager->n_outputs = 1;
manager->crtcs[2].crtc_id = 5;
manager->crtcs[2].rect.x = 0;
manager->crtcs[2].rect.y = 0;
manager->crtcs[2].rect.width = 0;
manager->crtcs[2].rect.height = 0;
manager->crtcs[2].current_mode = NULL;
manager->crtcs[2].transform = WL_OUTPUT_TRANSFORM_NORMAL;
manager->crtcs[2].all_transforms = ALL_WL_TRANSFORMS;
manager->crtcs[2].is_dirty = FALSE;
manager->crtcs[2].logical_monitor = NULL;
manager->outputs = g_new0 (MetaOutput, 3);
manager->n_outputs = 3;
manager->outputs[0].crtc = NULL;
manager->outputs[0].output_id = 6;
manager->outputs[0].name = g_strdup ("HDMI");
manager->outputs[0].crtc = &manager->crtcs[0];
manager->outputs[0].output_id = 1;
manager->outputs[0].name = g_strdup ("LVDS");
manager->outputs[0].vendor = g_strdup ("MetaProducts Inc.");
manager->outputs[0].product = g_strdup ("unknown");
manager->outputs[0].serial = g_strdup ("0xC0F01A");
manager->outputs[0].width_mm = 510;
manager->outputs[0].height_mm = 287;
manager->outputs[0].serial = g_strdup ("0xC0FFEE");
manager->outputs[0].width_mm = 222;
manager->outputs[0].height_mm = 125;
manager->outputs[0].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
manager->outputs[0].preferred_mode = &manager->modes[3];
manager->outputs[0].n_modes = 5;
manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 5);
manager->outputs[0].preferred_mode = &manager->modes[0];
manager->outputs[0].n_modes = 1;
manager->outputs[0].modes = g_new0 (MetaMonitorMode *, 1);
manager->outputs[0].modes[0] = &manager->modes[0];
manager->outputs[0].modes[1] = &manager->modes[1];
manager->outputs[0].modes[2] = &manager->modes[2];
manager->outputs[0].modes[3] = &manager->modes[3];
manager->outputs[0].modes[4] = &manager->modes[4];
manager->outputs[0].n_possible_crtcs = 3;
manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 3);
manager->outputs[0].n_possible_crtcs = 1;
manager->outputs[0].possible_crtcs = g_new0 (MetaCRTC *, 1);
manager->outputs[0].possible_crtcs[0] = &manager->crtcs[0];
manager->outputs[0].possible_crtcs[1] = &manager->crtcs[1];
manager->outputs[0].possible_crtcs[2] = &manager->crtcs[2];
manager->outputs[0].n_possible_clones = 0;
manager->outputs[0].possible_clones = g_new0 (MetaOutput *, 0);
manager->outputs[0].backlight = -1;
manager->outputs[0].backlight_min = 0;
manager->outputs[0].backlight_max = 0;
manager->outputs[1].crtc = &manager->crtcs[0];
manager->outputs[1].output_id = 7;
manager->outputs[1].name = g_strdup ("LVDS");
manager->outputs[1].vendor = g_strdup ("MetaProducts Inc.");
manager->outputs[1].product = g_strdup ("unknown");
manager->outputs[1].serial = g_strdup ("0xC0FFEE");
manager->outputs[1].width_mm = 222;
manager->outputs[1].height_mm = 125;
manager->outputs[1].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
manager->outputs[1].preferred_mode = &manager->modes[5];
manager->outputs[1].n_modes = 4;
manager->outputs[1].modes = g_new0 (MetaMonitorMode *, 4);
manager->outputs[1].modes[0] = &manager->modes[0];
manager->outputs[1].modes[1] = &manager->modes[1];
manager->outputs[1].modes[2] = &manager->modes[2];
manager->outputs[1].modes[3] = &manager->modes[5];
manager->outputs[1].n_possible_crtcs = 3;
manager->outputs[1].possible_crtcs = g_new0 (MetaCRTC *, 3);
manager->outputs[1].possible_crtcs[0] = &manager->crtcs[0];
manager->outputs[1].possible_crtcs[1] = &manager->crtcs[1];
manager->outputs[1].possible_crtcs[2] = &manager->crtcs[2];
manager->outputs[1].n_possible_clones = 0;
manager->outputs[1].possible_clones = g_new0 (MetaOutput *, 0);
manager->outputs[1].backlight = -1;
manager->outputs[1].backlight_min = 0;
manager->outputs[1].backlight_max = 0;
manager->outputs[2].crtc = NULL;
manager->outputs[2].output_id = 8;
manager->outputs[2].name = g_strdup ("VGA");
manager->outputs[2].vendor = g_strdup ("MetaProducts Inc.");
manager->outputs[2].product = g_strdup ("unknown");
manager->outputs[2].serial = g_strdup ("0xC4FE");
manager->outputs[2].width_mm = 309;
manager->outputs[2].height_mm = 174;
manager->outputs[2].subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
manager->outputs[2].preferred_mode = &manager->modes[0];
manager->outputs[2].n_modes = 3;
manager->outputs[2].modes = g_new0 (MetaMonitorMode *, 3);
manager->outputs[2].modes[0] = &manager->modes[0];
manager->outputs[2].modes[1] = &manager->modes[1];
manager->outputs[2].modes[2] = &manager->modes[2];
manager->outputs[2].n_possible_crtcs = 3;
manager->outputs[2].possible_crtcs = g_new0 (MetaCRTC *, 3);
manager->outputs[2].possible_crtcs[0] = &manager->crtcs[0];
manager->outputs[2].possible_crtcs[1] = &manager->crtcs[1];
manager->outputs[2].possible_crtcs[2] = &manager->crtcs[2];
manager->outputs[2].n_possible_clones = 0;
manager->outputs[2].possible_clones = g_new0 (MetaOutput *, 0);
manager->outputs[2].backlight = -1;
manager->outputs[2].backlight_min = 0;
manager->outputs[2].backlight_max = 0;
}
static void
@ -471,6 +355,24 @@ make_logical_config (MetaMonitorManager *manager)
manager->monitor_infos = (void*)g_array_free (monitor_infos, FALSE);
}
static GType
get_default_backend (void)
{
if (meta_is_wayland_compositor ())
{
MetaWaylandCompositor *compositor;
compositor = meta_wayland_compositor_get_default ();
if (meta_wayland_compositor_is_native (compositor))
return META_TYPE_MONITOR_MANAGER_KMS;
else
return META_TYPE_MONITOR_MANAGER;
}
else
return META_TYPE_MONITOR_MANAGER_XRANDR;
}
static MetaMonitorManager *
meta_monitor_manager_new (void)
{
@ -480,7 +382,7 @@ meta_monitor_manager_new (void)
env = g_getenv ("META_DEBUG_MULTIMONITOR");
if (env == NULL)
type = META_TYPE_MONITOR_MANAGER_XRANDR;
type = get_default_backend ();
else if (strcmp (env, "xrandr") == 0)
type = META_TYPE_MONITOR_MANAGER_XRANDR;
else
@ -515,17 +417,18 @@ meta_monitor_manager_constructed (GObject *object)
MetaOutput *old_outputs;
MetaCRTC *old_crtcs;
MetaMonitorMode *old_modes;
int n_old_outputs;
unsigned int n_old_outputs, n_old_modes;
old_outputs = manager->outputs;
n_old_outputs = manager->n_outputs;
old_modes = manager->modes;
n_old_modes = manager->n_modes;
old_crtcs = manager->crtcs;
read_current_config (manager);
meta_monitor_manager_free_output_array (old_outputs, n_old_outputs);
g_free (old_modes);
meta_monitor_manager_free_mode_array (old_modes, n_old_modes);
g_free (old_crtcs);
}
@ -567,19 +470,39 @@ meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
g_free (old_outputs[i].modes);
g_free (old_outputs[i].possible_crtcs);
g_free (old_outputs[i].possible_clones);
if (old_outputs[i].driver_notify)
old_outputs[i].driver_notify (&old_outputs[i]);
}
g_free (old_outputs);
}
void
meta_monitor_manager_free_mode_array (MetaMonitorMode *old_modes,
int n_old_modes)
{
int i;
for (i = 0; i < n_old_modes; i++)
{
g_free (old_modes[i].name);
if (old_modes[i].driver_notify)
old_modes[i].driver_notify (&old_modes[i]);
}
g_free (old_modes);
}
static void
meta_monitor_manager_finalize (GObject *object)
{
MetaMonitorManager *manager = META_MONITOR_MANAGER (object);
meta_monitor_manager_free_output_array (manager->outputs, manager->n_outputs);
meta_monitor_manager_free_mode_array (manager->modes, manager->n_modes);
g_free (manager->monitor_infos);
g_free (manager->modes);
g_free (manager->crtcs);
G_OBJECT_CLASS (meta_monitor_manager_parent_class)->finalize (object);
@ -691,60 +614,46 @@ static char *
make_display_name (MetaMonitorManager *manager,
MetaOutput *output)
{
char *inches = NULL;
char *vendor_name = NULL;
char *ret;
if (g_str_has_prefix (output->name, "LVDS") ||
g_str_has_prefix (output->name, "eDP"))
{
ret = g_strdup (_("Built-in display"));
goto out;
}
return g_strdup (_("Built-in display"));
if (output->width_mm > 0 && output->height_mm > 0)
if (output->width_mm != -1 && output->height_mm != -1)
{
double d = sqrt (output->width_mm * output->width_mm +
output->height_mm * output->height_mm);
inches = diagonal_to_str (d / 25.4);
}
char *inches = diagonal_to_str (d / 25.4);
char *vendor_name;
char *ret;
if (g_strcmp0 (output->vendor, "unknown") != 0)
{
if (!manager->pnp_ids)
manager->pnp_ids = gnome_pnp_ids_new ();
if (g_strcmp0 (output->vendor, "unknown") != 0)
{
if (!manager->pnp_ids)
manager->pnp_ids = gnome_pnp_ids_new ();
vendor_name = gnome_pnp_ids_get_pnp_id (manager->pnp_ids,
output->vendor);
vendor_name = gnome_pnp_ids_get_pnp_id (manager->pnp_ids,
output->vendor);
if (!vendor_name)
vendor_name = g_strdup (output->vendor);
}
else
{
if (inches != NULL)
vendor_name = g_strdup (_("Unknown"));
ret = g_strdup_printf ("%s %s", vendor_name, inches);
g_free (vendor_name);
}
else
vendor_name = g_strdup (_("Unknown Display"));
}
{
/* 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"'
*/
ret = g_strdup_printf (_("Unknown %s"), inches);
}
if (inches != NULL)
{
/* TRANSLATORS: this is a monitor vendor name, followed by a
* size in inches, like 'Dell 15"'
*/
ret = g_strdup_printf (_("%s %s"), vendor_name, inches);
g_free (inches);
return ret;
}
else
{
ret = g_strdup (vendor_name);
return g_strdup (output->vendor);
}
out:
g_free (inches);
g_free (vendor_name);
return ret;
}
static gboolean
@ -772,13 +681,13 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&crtc_builder, "(uxiiiiiuaua{sv})",
i, /* ID */
(gint64)crtc->crtc_id,
crtc->crtc_id,
(int)crtc->rect.x,
(int)crtc->rect.y,
(int)crtc->rect.width,
(int)crtc->rect.height,
(int)(crtc->current_mode ? crtc->current_mode - manager->modes : -1),
(guint32)crtc->transform,
crtc->transform,
&transforms,
NULL /* properties */);
}
@ -820,9 +729,6 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_new_take_string (make_display_name (manager, output)));
g_variant_builder_add (&properties, "{sv}", "backlight",
g_variant_new_int32 (output->backlight));
g_variant_builder_add (&properties, "{sv}", "min-backlight-step",
g_variant_new_int32 ((output->backlight_max - output->backlight_min) ?
100 / (output->backlight_max - output->backlight_min) : -1));
g_variant_builder_add (&properties, "{sv}", "primary",
g_variant_new_boolean (output->is_primary));
g_variant_builder_add (&properties, "{sv}", "presentation",
@ -849,7 +755,7 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&output_builder, "(uxiausauaua{sv})",
i, /* ID */
(gint64)output->output_id,
output->output_id,
(int)(output->crtc ? output->crtc - manager->crtcs : -1),
&crtcs,
output->name,
@ -864,9 +770,9 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
g_variant_builder_add (&mode_builder, "(uxuud)",
i, /* ID */
(gint64)mode->mode_id,
(guint32)mode->width,
(guint32)mode->height,
mode->mode_id,
mode->width,
mode->height,
(double)mode->refresh_rate);
}
@ -1455,12 +1361,21 @@ meta_monitor_manager_get_resources (MetaMonitorManager *manager,
MetaOutput **outputs,
unsigned int *n_outputs)
{
*modes = manager->modes;
*n_modes = manager->n_modes;
*crtcs = manager->crtcs;
*n_crtcs = manager->n_crtcs;
*outputs = manager->outputs;
*n_outputs = manager->n_outputs;
if (modes)
{
*modes = manager->modes;
*n_modes = manager->n_modes;
}
if (crtcs)
{
*crtcs = manager->crtcs;
*n_crtcs = manager->n_crtcs;
}
if (outputs)
{
*outputs = manager->outputs;
*n_outputs = manager->n_outputs;
}
}
int

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

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

View File

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

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>
@ -1199,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");
}
}
@ -1274,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;
@ -1340,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;
@ -1906,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.

View File

@ -243,12 +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);
gboolean meta_screen_handle_xevent (MetaScreen *screen,
XEvent *xevent);
#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,6 +45,7 @@
#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>
@ -309,8 +310,6 @@ set_supported_hint (MetaScreen *screen)
#include <meta/atomnames.h>
#undef item
#undef EWMH_ATOMS_ONLY
screen->display->atom__GTK_FRAME_EXTENTS,
};
XChangeProperty (screen->display->xdisplay, screen->xroot,
@ -448,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;
@ -476,9 +476,6 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
CWEventMask|CWOverrideRedirect|CWBackPixel,
&attributes);
/* https://bugzilla.gnome.org/show_bug.cgi?id=710346 */
XStoreName (xdisplay, guard_window, "mutter guard window");
{
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
@ -489,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);
@ -580,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);
@ -675,8 +674,9 @@ meta_screen_new (MetaDisplay *display,
screen->xscreen = ScreenOfDisplay (xdisplay, number);
screen->xroot = xroot;
screen->rect.x = screen->rect.y = 0;
meta_monitor_manager_initialize ();
if (!meta_is_wayland_compositor ())
meta_monitor_manager_initialize ();
manager = meta_monitor_manager_get ();
g_signal_connect (manager, "monitors-changed",
@ -850,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);
@ -859,9 +859,9 @@ meta_screen_free (MetaScreen *screen,
screen->wm_sn_selection_window);
if (screen->work_area_later != 0)
meta_later_remove (screen->work_area_later);
g_source_remove (screen->work_area_later);
if (screen->check_fullscreen_later != 0)
meta_later_remove (screen->check_fullscreen_later);
g_source_remove (screen->check_fullscreen_later);
if (screen->monitor_infos)
g_free (screen->monitor_infos);
@ -880,31 +880,83 @@ meta_screen_free (MetaScreen *screen,
meta_display_ungrab (display);
}
typedef struct
{
Window xwindow;
XWindowAttributes attrs;
} WindowInfo;
static GList *
list_windows (MetaScreen *screen)
{
Window ignored1, ignored2;
Window *children;
guint n_children, i;
GList *result;
XQueryTree (screen->display->xdisplay,
screen->xroot,
&ignored1, &ignored2, &children, &n_children);
result = NULL;
for (i = 0; i < n_children; ++i)
{
WindowInfo *info = g_new0 (WindowInfo, 1);
meta_error_trap_push_with_return (screen->display);
XGetWindowAttributes (screen->display->xdisplay,
children[i], &info->attrs);
if (meta_error_trap_pop_with_return (screen->display))
{
meta_verbose ("Failed to get attributes for window 0x%lx\n",
children[i]);
g_free (info);
}
else
{
info->xwindow = children[i];
}
result = g_list_prepend (result, info);
}
if (children)
XFree (children);
return g_list_reverse (result);
}
void
meta_screen_manage_all_windows (MetaScreen *screen)
{
Window *_children;
Window *children;
int n_children, i;
GList *windows;
GList *list;
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);
meta_stack_freeze (screen->stack);
meta_stack_tracker_get_stack (screen->stack_tracker, &_children, &n_children);
/* Copy the stack as it will be modified as part of the loop */
children = g_memdup (_children, sizeof (Window) * n_children);
for (i = 0; i < n_children; ++i)
for (list = windows; list != NULL; list = list->next)
{
meta_window_new (screen->display, children[i], TRUE,
META_COMP_EFFECT_NONE);
}
WindowInfo *info = list->data;
g_free (children);
meta_window_new_with_attrs (screen->display, info->xwindow, TRUE,
META_COMP_EFFECT_NONE,
&info->attrs);
}
meta_stack_thaw (screen->stack);
g_list_foreach (windows, (GFunc)g_free, NULL);
g_list_free (windows);
meta_display_ungrab (screen->display);
}
/**
@ -1476,7 +1528,7 @@ meta_screen_tab_popup_create (MetaScreen *screen,
if (show_type == META_TAB_SHOW_INSTANTLY ||
!entries[i].hidden ||
!meta_window_get_icon_geometry (window, &r))
meta_window_get_frame_rect (window, &r);
meta_window_get_outer_rect (window, &r);
entries[i].rect = r;
@ -1690,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);
}
@ -1859,7 +1914,7 @@ meta_screen_get_monitor_for_window (MetaScreen *screen,
{
MetaRectangle window_rect;
meta_window_get_frame_rect (window, &window_rect);
meta_window_get_outer_rect (window, &window_rect);
return meta_screen_get_monitor_for_rect (screen, &window_rect);
}
@ -3637,10 +3692,6 @@ gboolean
meta_screen_handle_xevent (MetaScreen *screen,
XEvent *xevent)
{
/* Go through our helpers and see if they want this event.
Currently, only MetaCursorTracker.
*/
if (meta_cursor_tracker_handle_xevent (screen->cursor_tracker, xevent))
return TRUE;

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);
}
@ -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... */
}
@ -1465,7 +1705,7 @@ window_contains_point (MetaWindow *window,
{
MetaRectangle rect;
meta_window_get_frame_rect (window, &rect);
meta_window_get_outer_rect (window, &rect);
return POINT_IN_RECT (root_x, root_y, rect);
}
@ -1484,12 +1724,14 @@ get_default_focus_window (MetaStack *stack,
* or top window in same group as not_this_one.
*/
MetaWindow *topmost_dock;
MetaWindow *transient_parent;
MetaWindow *topmost_in_group;
MetaWindow *topmost_overall;
MetaGroup *not_this_one_group;
GList *link;
topmost_dock = NULL;
transient_parent = NULL;
topmost_in_group = NULL;
topmost_overall = NULL;
@ -1515,6 +1757,10 @@ get_default_focus_window (MetaStack *stack,
(workspace == NULL ||
meta_window_located_on_workspace (window, workspace)))
{
if (topmost_dock == NULL &&
window->type == META_WINDOW_DOCK)
topmost_dock = window;
if (not_this_one != NULL)
{
if (transient_parent == NULL &&
@ -1532,6 +1778,10 @@ get_default_focus_window (MetaStack *stack,
topmost_in_group = window;
}
/* Note that DESKTOP windows can be topmost_overall so
* we prefer focusing desktop or other windows over
* focusing dock, even though docks are stacked higher.
*/
if (topmost_overall == NULL &&
window->type != META_WINDOW_DOCK &&
(!must_be_at_point ||
@ -1553,7 +1803,7 @@ get_default_focus_window (MetaStack *stack,
else if (topmost_overall)
return topmost_overall;
else
return NULL;
return topmost_dock;
}
MetaWindow*
@ -1728,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);
}
@ -1791,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);
@ -411,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);
@ -442,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);
@ -470,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);

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;
@ -355,9 +362,6 @@ struct _MetaWindow
/* the input shape region for picking */
cairo_region_t *input_region;
/* _NET_WM_WINDOW_OPACITY */
guint opacity;
/* if TRUE, the we have the new form of sync request counter which
* also handles application frames */
guint extended_sync_request_counter : 1;
@ -400,6 +404,12 @@ 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;
@ -490,8 +500,16 @@ struct _MetaWindowClass
MetaWindow* meta_window_new (MetaDisplay *display,
Window xwindow,
gboolean must_be_viewable,
MetaCompEffect effect);
gboolean must_be_viewable);
MetaWindow* meta_window_new_with_attrs (MetaDisplay *display,
Window xwindow,
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);
@ -514,7 +532,6 @@ void meta_window_update_fullscreen_monitors (MetaWindow *window,
unsigned long left,
unsigned long right);
/* args to move are window pos, not frame pos */
void meta_window_move (MetaWindow *window,
gboolean user_op,
@ -590,6 +607,11 @@ 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,
@ -656,9 +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_frame_size_changed (MetaWindow *window);
void meta_window_type_changed (MetaWindow *window);
void meta_window_stack_just_below (MetaWindow *window,
MetaWindow *below_this_one);
@ -694,9 +716,21 @@ void meta_window_update_input_region_x11 (MetaWindow *window);
void meta_window_set_shape_region (MetaWindow *window,
cairo_region_t *region);
void meta_window_update_shape_region_x11 (MetaWindow *window);
void meta_window_set_opacity (MetaWindow *window,
guint opacity);
Window meta_window_get_toplevel_xwindow (MetaWindow *window);
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 */
@ -316,9 +317,6 @@ reload_gtk_frame_extents (MetaWindow *window,
{
window->has_custom_frame_extents = FALSE;
}
if (!initial)
meta_window_queue(window, META_QUEUE_MOVE_RESIZE);
}
static void
@ -347,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
{
@ -492,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
@ -878,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",
@ -1537,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)
{
@ -1546,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;
}
@ -1557,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;
@ -1574,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 =
@ -1589,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
@ -1709,20 +1652,6 @@ reload_bypass_compositor (MetaWindow *window,
window->bypass_compositor = requested_value;
}
static void
reload_window_opacity (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
int requested_value = 0xFF;
if (value->type != META_PROP_VALUE_INVALID)
requested_value = (int) value->v.cardinal;
meta_window_set_opacity (window, requested_value);
}
#define RELOAD_STRING(var_name, propname) \
static void \
reload_ ## var_name (MetaWindow *window, \
@ -1825,7 +1754,6 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
{ display->atom__NET_WM_STRUT, META_PROP_VALUE_INVALID, reload_struts, FALSE, FALSE },
{ display->atom__NET_WM_STRUT_PARTIAL, META_PROP_VALUE_INVALID, reload_struts, FALSE, FALSE },
{ display->atom__NET_WM_BYPASS_COMPOSITOR, META_PROP_VALUE_CARDINAL, reload_bypass_compositor, FALSE, FALSE },
{ display->atom__NET_WM_WINDOW_OPACITY, META_PROP_VALUE_CARDINAL, reload_window_opacity, TRUE, TRUE },
{ 0 },
};

File diff suppressed because it is too large Load Diff

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);
@ -536,6 +536,81 @@ meta_prop_get_utf8_list (MetaDisplay *display,
return utf8_list_from_results (&results, str_p, n_str_p);
}
/* this one freakishly returns g_malloc memory */
static gboolean
latin1_list_from_results (GetPropertyResults *results,
char ***str_p,
int *n_str_p)
{
int i;
int n_strings;
char **retval;
const char *p;
*str_p = NULL;
*n_str_p = 0;
if (!validate_or_free_results (results, 8, XA_STRING, FALSE))
return FALSE;
/* I'm not sure this is right, but I'm guessing the
* property is nul-separated
*/
i = 0;
n_strings = 0;
while (i < (int) results->n_items)
{
if (results->prop[i] == '\0')
++n_strings;
++i;
}
if (results->prop[results->n_items - 1] != '\0')
++n_strings;
/* we're guaranteed that results->prop has a nul on the end
* by XGetWindowProperty
*/
retval = g_new0 (char*, n_strings + 1);
p = (char *)results->prop;
i = 0;
while (i < n_strings)
{
retval[i] = g_strdup (p);
p = p + strlen (p) + 1;
++i;
}
*str_p = retval;
*n_str_p = i;
meta_XFree (results->prop);
results->prop = NULL;
return TRUE;
}
gboolean
meta_prop_get_latin1_list (MetaDisplay *display,
Window xwindow,
Atom xatom,
char ***str_p,
int *n_str_p)
{
GetPropertyResults results;
*str_p = NULL;
if (!get_property (display, xwindow, xatom,
XA_STRING, &results))
return FALSE;
return latin1_list_from_results (&results, str_p, n_str_p);
}
void
meta_prop_set_utf8_string_hint (MetaDisplay *display,
Window xwindow,

View File

@ -102,6 +102,11 @@ gboolean meta_prop_get_utf8_list (MetaDisplay *display,
Atom xatom,
char ***str_p,
int *n_str_p);
gboolean meta_prop_get_latin1_list (MetaDisplay *display,
Window xwindow,
Atom xatom,
char ***str_p,
int *n_str_p);
void meta_prop_set_utf8_string_hint
(MetaDisplay *display,
Window xwindow,

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

@ -81,7 +81,7 @@ item(TIMESTAMP)
item(VERSION)
item(ATOM_PAIR)
item(BACKLIGHT)
item(hotplug_mode_update)
item(_XKB_RULES_NAMES)
/* Oddities: These are used, and we need atoms for them,
* but when we need all _NET_WM hints (i.e. when we're making
@ -179,7 +179,6 @@ item(_NET_WM_BYPASS_COMPOSITOR)
item(_NET_WM_OPAQUE_REGION)
item(_NET_WM_FRAME_DRAWN)
item(_NET_WM_FRAME_TIMINGS)
item(_NET_WM_WINDOW_OPACITY)
#if 0
/* We apparently never use: */

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