Compare commits

...

108 Commits

Author SHA1 Message Date
78b41e542b MonitorXrandr: follow the right order in applying the new configuration
First disable CRTCs that should be off in the new configuration,
then resize the framebuffer, then enable the new CRTCs.
If we don't do that, and we're making the screen smaller, X complains
with a BadMatch.

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-17 16:57:33 +02:00
13557b39d0 MonitorXrandr: resize the framebuffer prior to setting the CRTC configuration
Otherwise X11 will trim the new configuration and disable outputs
outside the screen.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-17 16:51:03 +02:00
91d193e5e8 MonitorManager: add support for DPMS levels
To the XRandR and dummy backend (and as usual the dummy backend
has no effect)

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-17 16:50:26 +02:00
f82f3ef67b MonitorManager: inherit directly from DisplayConfig instead of handling signals
This way we can handle properties too.

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

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

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

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

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

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-17 16:36:45 +02:00
355f0258b1 DisplayConfig: add the write side of the API
Implement ApplyConfiguration in terms of XRandR calls.
Error checking is done before actually committing the configuration.

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

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

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

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

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

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

https://bugzilla.gnome.org/show_bug.cgi?id=705670
2013-08-17 16:17:07 +02:00
a413bc106f 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-17 15:56:09 +02:00
b04ac57f02 Strip whitespace in warnings and errors
The old log system did not add a newline at the end, but the new
one does, so don't add another one.
2013-08-14 21:36:34 +02:00
c3a08ee589 main: use glib to handle sigterm
We can remove a lot of code with that
2013-08-14 21:36:34 +02:00
1fdb161f54 main: remove a lot of code to handle wrong theme config
mutter has a hard dependency on gnome-themes-standard, which
provides the Adwaita theme. If that is not satisfied, it is
a distribution problem, so we can just fail (and let the
automatic smoketests notice it)
2013-08-14 21:36:34 +02:00
f3d1653f13 Improve handling of warnings and criticals
Instead of squash everything into "window manager warnings",
let the glib log framework handle Mutter (and other) warnings.
META_USE_LOGFILE support is preserved by rerouting warnings
in our domain.
This way we get process name and PID, nice CRITICAL/WARNING/ERROR
instead of a number, and the ability for plugins to override
the log handler. For example gnome-shell uses this to output
a JS backtrace.
2013-08-14 21:31:45 +02:00
3093b5c95d MetaBackgroundGroup: don't use clutter_actor_get_children()
In C code we can use ClutterActorIter and avoid allocating a GList.
2013-08-14 21:24:11 +02:00
c3e8646af3 Updated POTFILES.in 2013-08-13 21:10:02 +02:00
8c17b670fb keybindings: always acknowledge events to the X server
https://bugzilla.gnome.org/show_bug.cgi?id=666101
2013-08-13 11:18:48 -04:00
12d2e1f600 Support _GTK_FRAME_EXTENTS
https://bugzilla.gnome.org/show_bug.cgi?id=705766
2013-08-13 10:40:15 -04:00
c20b007985 Reintroduce mutter binary
I accidentally deleted one too many things.
2013-08-13 10:16:01 -04:00
ef480e9120 theme: Fix build breakage 2013-08-13 09:50:59 -04:00
8c1c77482d Remove old, deprecated utilities that nobody has used in a million years
https://bugzilla.gnome.org/show_bug.cgi?id=704437
2013-08-13 09:39:02 -04:00
e633606ca9 menu: Remove support for icon items from the window menu
We don't show these by default, and it uses deprecated API.
This also removes our only use of the stock icons, so remove
those as well.

https://bugzilla.gnome.org/show_bug.cgi?id=704437
2013-08-13 09:39:01 -04:00
6fdc23d0b7 Updated Norwegian bokmål translation 2013-08-08 22:14:40 +02:00
4862872c78 window-actor: Fix doc comment
https://bugzilla.gnome.org/show_bug.cgi?id=703332
2013-08-05 16:29:37 +02:00
ae2e4c5114 l10n: Update Japanese translation 2013-08-03 23:38:51 +09:00
06b5be2d13 Bump version to 3.9.5
Update NEWS.
2013-07-30 14:27:06 +02:00
56fb8a81b3 display: Export the timestamp of the event as well
When passing on keybindings, make sure to pass the timestamp
of the event as well as the deviceid and the action.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2
.gitignore vendored
View File

@ -46,7 +46,6 @@ POTFILES
po/*.pot
50-metacity-desktop-key.xml
50-metacity-key.xml
inlinepixbufs.h
libmutter.pc
mutter
mutter-theme-viewer
@ -62,6 +61,7 @@ mutter-message
mutter-window-demo
focus-window
test-attached
test-focus
test-gravity
test-resizing
test-size-hints

73
NEWS
View File

@ -1,3 +1,76 @@
3.9.5
=====
* Don't select for touch events on the stage [Jasper; #697192]
* Don't queue redraws for obscured regions [Adel; #703332]
* Export timestamp of global keybinding events [Bastien; #704858]
* Misc bug fixes and cleanups [Jasper, Rico; #703970]
Contributors:
Adel Gadllah, Bastien Nocera, Jasper St. Pierre, Rico Tzschichholz
3.9.4
=====
* Tweak window shadows [Allan; #702141]
* Ignore our own focus events for focus prediction [Jasper; #701017]
* Add API to query if the stage is focused [Jasper; #700735]
* Add API to query the monitor for a given position [Adel]
* Don't force attached dialogs to be border-only [Florian; #702764]
* Allow slicing of backgrounds to avoid texture size limits [Ray; #702283]
* Miscellaneous bug fixes and cleanups [Adel; #701224, #702564]
Contributors:
Allan Day, Adel Gadllah, Florian Müllner, Jasper St. Pierre, Ray Strode
3.9.3
=====
* Ensure events are always reported to the grab window [Rui; #701219]
* Use new clutter_stage_set_paint_callback() function to prevent dropping
frames with frame synced toolkits [Owen; #698794]
Contributors:
Rui Matos, Owen W. Taylor
3.9.2
=====
* Add meta_window_can_close() function [Jasper; #699269]
* Add support for string-array preferences [Florian; #700223]
* Fix a potential race condition with _NET_WM_MOVERESIZE [Jasper; #699777]
* Fix shade window action [Stef; #693714]
* Remove overlay_group [Giovanni; #700735]
* Improve tracking of the focus window [Dan, Jasper; #647706]
* Add API to freeze/unfreeze the keyboard [Rui; #697001]
* Grab and emit a signal when XK_ISO_Next_Group is pressed [Rui; #697002]
* Misc bug fixes and cleanups [Dieter, Jasper, Rui; #699636, #700735, #697000]
Contributors:
Giovanni Campagna, Rui Matos, Florian Müllner, Jasper St. Pierre,
Dieter Verfaillie, Stef Walter, Dan Winship
Translations:
Kjartan Maraas [nb], Ján Kyselica [sk]
3.9.1
=====
* Fix miscellaneous memory leaks [Pavel; #698710]
* Misc fixes and cleanups [Stef, Simon; #698179, #697758]
Contributors:
Simon McVittie, Pavel Vasin, Stef Walter
3.8.1
=====
* Fix crash when getting default font [Bastien; #696814]
* Fix ungrabbing of keybindings [Rui; #697003]
* Misc fixes and cleanups [Jasper, Simon; #697758]
Contributors:
Jasper Lievisse Adriaanse, Rui Matos, Simon McVittie, Bastien Nocera
Translations:
Guillaume Desmottes [fr], Shankar Prasad [kn], Bruce Cowan [en_GB],
Andika Triwidada [id], Yaron Shahrabani [he], Kjartan Maraas [nb],
Gheyret Kenji [ug]
3.8.0
=====
* Address major memory leak when changing backgrounds [Ray; #696157]

View File

@ -1,8 +1,8 @@
AC_PREREQ(2.50)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [8])
m4_define([mutter_micro_version], [0])
m4_define([mutter_minor_version], [9])
m4_define([mutter_micro_version], [5])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@ -73,8 +73,10 @@ MUTTER_PC_MODULES="
cairo >= 1.10.0
gsettings-desktop-schemas >= 3.7.3
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
$CLUTTER_PACKAGE >= 1.13.5
$CLUTTER_PACKAGE >= 1.14.3
cogl-1.0 >= 1.13.3
upower-glib > 0.9.11
gnome-desktop-3.0
"
GLIB_GSETTINGS
@ -118,9 +120,6 @@ AM_GLIB_GNU_GETTEXT
## here we get the flags we'll actually use
# GRegex requires Glib-2.14.0
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.14.0)
# gtk_window_set_icon_name requires gtk2+-2.6.0
PKG_CHECK_MODULES(MUTTER_MESSAGE, gtk+-3.0)
PKG_CHECK_MODULES(MUTTER_WINDOW_DEMO, gtk+-3.0)
# Unconditionally use this dir to avoid a circular dep with gnomecc
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
@ -307,9 +306,6 @@ if test "x$found_xsync" = "xyes"; then
fi
MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
MUTTER_MESSAGE_LIBS="$MUTTER_MESSAGE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
MUTTER_PROPS_LIBS="$MUTTER_PROPS_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
found_sm=no
case "$MUTTER_LIBS" in
@ -439,10 +435,8 @@ doc/man/Makefile
doc/reference/Makefile
doc/reference/meta-docs.sgml
src/Makefile
src/wm-tester/Makefile
src/libmutter.pc
src/mutter-plugins.pc
src/tools/Makefile
src/compositor/plugins/Makefile
po/Makefile.in
])

View File

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

View File

@ -23,12 +23,9 @@ src/core/xprops.c
src/mutter.desktop.in
src/mutter-wm.desktop.in
src/org.gnome.mutter.gschema.xml.in
src/tools/mutter-message.c
src/ui/frames.c
src/ui/menu.c
src/ui/metaaccellabel.c
src/ui/resizepopup.c
src/ui/theme.c
src/ui/theme-parser.c
src/ui/theme-viewer.c

201
po/he.po
View File

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

View File

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

176
po/nb.po
View File

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

480
po/sk.po

File diff suppressed because it is too large Load Diff

186
po/ug.po
View File

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

View File

@ -3,7 +3,7 @@
lib_LTLIBRARIES = libmutter.la
SUBDIRS=wm-tester tools compositor/plugins
SUBDIRS=compositor/plugins
INCLUDES= \
-DCLUTTER_ENABLE_EXPERIMENTAL_API \
@ -19,7 +19,7 @@ INCLUDES= \
-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" \
-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \
-DMUTTER_DATADIR=\"$(datadir)\" \
-DG_LOG_DOMAIN=\"mutter\" \
-DG_LOG_DOMAIN=\"Mutter\" \
-DSN_API_NOT_YET_FROZEN=1 \
-DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) \
-DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) \
@ -30,6 +30,7 @@ INCLUDES= \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
mutter_built_sources = \
$(dbus_xrandr_built_sources) \
mutter-enum-types.h \
mutter-enum-types.c
@ -94,6 +95,8 @@ libmutter_la_SOURCES = \
ui/draw-workspace.h \
core/edge-resistance.c \
core/edge-resistance.h \
core/edid-parse.c \
core/edid.h \
core/errors.c \
meta/errors.h \
core/frame.c \
@ -110,6 +113,11 @@ libmutter_la_SOURCES = \
core/keybindings.c \
core/keybindings-private.h \
core/main.c \
core/meta-xrandr-shared.h \
core/monitor.c \
core/monitor-config.c \
core/monitor-private.h \
core/monitor-xrandr.c \
core/mutter-Xatomtype.h \
core/place.c \
core/place.h \
@ -139,7 +147,6 @@ libmutter_la_SOURCES = \
meta/common.h \
core/core.h \
ui/ui.h \
inlinepixbufs.h \
ui/frames.c \
ui/frames.h \
ui/menu.c \
@ -157,8 +164,6 @@ libmutter_la_SOURCES = \
meta/theme.h \
ui/theme-private.h \
ui/ui.c \
meta/preview-widget.h \
ui/preview-widget.c \
$(mutter_built_sources)
libmutter_la_LDFLAGS = -no-undefined
@ -196,7 +201,6 @@ libmutterinclude_base_headers = \
# Excluded from scanning for introspection but installed
# atomnames.h: macros cause problems for scanning process
libmutterinclude_extra_headers = \
meta/preview-widget.h \
meta/atomnames.h
libmutterincludedir = $(includedir)/mutter/meta
@ -205,10 +209,7 @@ libmutterinclude_HEADERS = \
$(libmutterinclude_base_headers) \
$(libmutterinclude_extra_headers)
mutter_theme_viewer_SOURCES= \
ui/theme-viewer.c
bin_PROGRAMS=mutter mutter-theme-viewer
bin_PROGRAMS=mutter
mutter_SOURCES = core/mutter.c
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
@ -246,8 +247,6 @@ Meta-$(api_version).gir: libmutter.la
endif
mutter_theme_viewer_LDADD= $(MUTTER_LIBS) libmutter.la
testboxes_SOURCES = core/testboxes.c
testgradient_SOURCES = ui/testgradient.c
testasyncgetprop_SOURCES = core/testasyncgetprop.c
@ -284,14 +283,7 @@ gsettings_SCHEMAS = org.gnome.mutter.gschema.xml
convertdir = $(datadir)/GConf/gsettings
convert_DATA = mutter-schemas.convert
IMAGES=stock_maximize.png stock_minimize.png stock_delete.png
VARIABLES=stock_maximize_data $(srcdir)/stock_maximize.png \
stock_minimize_data $(srcdir)/stock_minimize.png \
stock_delete_data $(srcdir)/stock_delete.png
BUILT_SOURCES = inlinepixbufs.h
CLEANFILES = \
inlinepixbufs.h \
mutter.desktop \
mutter-wm.desktop \
org.gnome.mutter.gschema.xml \
@ -300,9 +292,6 @@ CLEANFILES = \
$(typelib_DATA) \
$(gir_DATA)
inlinepixbufs.h: $(IMAGES)
$(GDK_PIXBUF_CSOURCE) --raw --build-list $(VARIABLES) >$(srcdir)/inlinepixbufs.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmutter.pc mutter-plugins.pc
@ -320,7 +309,7 @@ EXTRA_DIST=$(desktopfiles_files) \
mutter-enum-types.h.in \
mutter-enum-types.c.in
BUILT_SOURCES += $(mutter_built_sources)
BUILT_SOURCES = $(mutter_built_sources)
MUTTER_STAMP_FILES = stamp-mutter-enum-types.h
CLEANFILES += $(MUTTER_STAMP_FILES)
@ -342,3 +331,12 @@ mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
$(libmutterinclude_base_headers) ) >> xgen-tetc && \
cp xgen-tetc mutter-enum-types.c && \
rm -f xgen-tetc
dbus_xrandr_built_sources = meta-dbus-xrandr.c meta-dbus-xrandr.h
$(dbus_xrandr_built_sources) : Makefile.am xrandr.xml
$(AM_V_GEN)gdbus-codegen \
--interface-prefix org.gnome.Mutter \
--c-namespace MetaDBus \
--generate-c-code meta-dbus-xrandr \
xrandr.xml

View File

@ -53,17 +53,15 @@
*
* # Containers #
*
* There's three containers in the stage that can be used to place actors, here
* There's two containers in the stage that are used to place window actors, here
* are listed in the order in which they are painted:
*
* - window group, accessible with meta_get_window_group_for_screen()
* - top window group, accessible with meta_get_top_window_group_for_screen()
* - overlay group, accessible with meta_get_overlay_group_for_screen()
*
* Mutter will place actors representing windows in the window group, except for
* override-redirect windows (ie. popups and menus) which will be placed in the
* top window group. Mutter won't put any actors in the overlay group, but it's
* intended for compositors to place there panel, dashes, status bars, etc.
* top window group.
*/
#include <config.h>
@ -255,23 +253,6 @@ meta_get_stage_for_screen (MetaScreen *screen)
return info->stage;
}
/**
* meta_get_overlay_group_for_screen:
* @screen: a #MetaScreen
*
* Returns: (transfer none): The overlay group corresponding to @screen
*/
ClutterActor *
meta_get_overlay_group_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info)
return NULL;
return info->overlay_group;
}
/**
* meta_get_window_group_for_screen:
* @screen: a #MetaScreen
@ -388,6 +369,46 @@ meta_empty_stage_input_region (MetaScreen *screen)
meta_set_stage_input_region (screen, region);
}
void
meta_focus_stage_window (MetaScreen *screen,
guint32 timestamp)
{
ClutterStage *stage;
Window window;
stage = CLUTTER_STAGE (meta_get_stage_for_screen (screen));
if (!stage)
return;
window = clutter_x11_get_stage_window (stage);
if (window == None)
return;
meta_display_set_input_focus_xwindow (screen->display,
screen,
window,
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);
}
gboolean
meta_begin_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
@ -514,20 +535,20 @@ meta_check_end_modal (MetaScreen *screen)
{
meta_end_modal_for_plugin (screen,
compositor->modal_plugin,
CurrentTime);
CurrentTime);
}
}
static gboolean
after_stage_paint (gpointer data)
static void
after_stage_paint (ClutterStage *stage,
gpointer data)
{
MetaCompScreen *info = (MetaCompScreen*) data;
GList *l;
for (l = info->windows; l; l = l->next)
meta_window_actor_post_paint (l->data);
return TRUE;
}
static void
@ -608,9 +629,10 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
info->stage = clutter_stage_new ();
clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT,
after_stage_paint,
info, NULL);
clutter_stage_set_paint_callback (CLUTTER_STAGE (info->stage),
after_stage_paint,
info,
NULL);
clutter_stage_set_sync_delay (CLUTTER_STAGE (info->stage), META_SYNC_DELAY);
@ -638,6 +660,9 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
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;
@ -649,11 +674,9 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
info->window_group = meta_window_group_new (screen);
info->top_window_group = meta_window_group_new (screen);
info->overlay_group = clutter_actor_new ();
clutter_actor_add_child (info->stage, info->window_group);
clutter_actor_add_child (info->stage, info->top_window_group);
clutter_actor_add_child (info->stage, info->overlay_group);
info->plugin_mgr = meta_plugin_manager_new (screen);
@ -684,8 +707,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
info->pending_input_region = None;
}
clutter_actor_show (info->overlay_group);
/* Map overlay window before redirecting windows offscreen so we catch their
* contents until we show the stage.
*/
@ -1566,8 +1587,10 @@ void
meta_enable_unredirect_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (info != NULL)
info->disable_unredirect_count = MAX(0, info->disable_unredirect_count - 1);
if (info != NULL && info->disable_unredirect_count == 0)
g_warning ("Called enable_unredirect_for_screen while unredirection is enabled.");
if (info != NULL && info->disable_unredirect_count > 0)
info->disable_unredirect_count = info->disable_unredirect_count - 1;
}
#define FLASH_TIME_MS 50

View File

@ -73,13 +73,12 @@ void
meta_background_group_set_visible_region (MetaBackgroundGroup *self,
cairo_region_t *region)
{
GList *children, *l;
ClutterActorIter iter;
ClutterActor *actor;
children = clutter_actor_get_children (CLUTTER_ACTOR (self));
for (l = children; l; l = l->next)
clutter_actor_iter_init (&iter, CLUTTER_ACTOR (self));
while (clutter_actor_iter_next (&iter, &actor))
{
ClutterActor *actor = l->data;
if (META_IS_BACKGROUND_ACTOR (actor))
{
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (actor), region);
@ -96,7 +95,6 @@ meta_background_group_set_visible_region (MetaBackgroundGroup *self,
cairo_region_translate (region, x, y);
}
}
g_list_free (children);
}
ClutterActor *

View File

@ -472,6 +472,17 @@ meta_background_dispose (GObject *object)
G_OBJECT_CLASS (meta_background_parent_class)->dispose (object);
}
static void
meta_background_finalize (GObject *object)
{
MetaBackground *self = META_BACKGROUND (object);
MetaBackgroundPrivate *priv = self->priv;
g_free (priv->filename);
G_OBJECT_CLASS (meta_background_parent_class)->finalize (object);
}
static void
ensure_pipeline (MetaBackground *self)
{
@ -643,6 +654,7 @@ meta_background_class_init (MetaBackgroundClass *klass)
g_type_class_add_private (klass, sizeof (MetaBackgroundPrivate));
object_class->dispose = meta_background_dispose;
object_class->finalize = meta_background_finalize;
object_class->set_property = meta_background_set_property;
object_class->get_property = meta_background_get_property;
@ -1048,7 +1060,7 @@ meta_background_load_file_finish (MetaBackground *self,
texture = cogl_texture_new_from_data (width,
height,
COGL_TEXTURE_NO_SLICING,
COGL_TEXTURE_NO_ATLAS,
has_alpha ?
COGL_PIXEL_FORMAT_RGBA_8888 :
COGL_PIXEL_FORMAT_RGB_888,

View File

@ -85,12 +85,20 @@ meta_plugin_manager_load (const gchar *plugin_name)
g_free (path);
}
static void
on_confirm_display_change (MetaMonitorManager *monitors,
MetaPluginManager *plugin_mgr)
{
meta_plugin_manager_confirm_display_change (plugin_mgr);
}
MetaPluginManager *
meta_plugin_manager_new (MetaScreen *screen)
{
MetaPluginManager *plugin_mgr;
MetaPluginClass *klass;
MetaPlugin *plugin;
MetaMonitorManager *monitors;
plugin_mgr = g_new0 (MetaPluginManager, 1);
plugin_mgr->screen = screen;
@ -101,6 +109,10 @@ meta_plugin_manager_new (MetaScreen *screen)
if (klass->start)
klass->start (plugin);
monitors = meta_monitor_manager_get ();
g_signal_connect (monitors, "confirm-display-change",
G_CALLBACK (on_confirm_display_change), plugin_mgr);
return plugin_mgr;
}
@ -320,3 +332,15 @@ meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
else
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
}
void
meta_plugin_manager_confirm_display_change (MetaPluginManager *plugin_mgr)
{
MetaPlugin *plugin = plugin_mgr->plugin;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (klass->confirm_display_change)
return klass->confirm_display_change (plugin);
else
return meta_plugin_complete_display_change (plugin, TRUE);
}

View File

@ -73,4 +73,6 @@ gboolean meta_plugin_manager_filter_keybinding (MetaPluginManager *mgr,
gboolean meta_plugin_manager_xevent_filter (MetaPluginManager *mgr,
XEvent *xev);
void meta_plugin_manager_confirm_display_change (MetaPluginManager *mgr);
#endif

View File

@ -41,6 +41,7 @@
#include "compositor-private.h"
#include "meta-window-actor-private.h"
#include "monitor-private.h"
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
@ -338,3 +339,13 @@ meta_plugin_get_screen (MetaPlugin *plugin)
return priv->screen;
}
void
meta_plugin_complete_display_change (MetaPlugin *plugin,
gboolean ok)
{
MetaMonitorManager *manager;
manager = meta_monitor_manager_get ();
meta_monitor_manager_confirm_configuration (manager, ok);
}

View File

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

View File

@ -69,9 +69,6 @@ struct _MetaWindowActorPrivate
Damage damage;
guint8 opacity;
guint8 shadow_opacity;
gchar * desc;
/* A region that matches the shape of the window, including frame bounds */
cairo_region_t *shape_region;
@ -130,8 +127,6 @@ struct _MetaWindowActorPrivate
guint no_shadow : 1;
guint no_more_x_calls : 1;
guint unredirected : 1;
/* This is used to detect fullscreen windows that need to be unredirected */
@ -323,9 +318,6 @@ window_decorated_notify (MetaWindow *mw,
priv->damage = None;
}
g_free (priv->desc);
priv->desc = NULL;
priv->xwindow = new_xwindow;
/*
@ -377,10 +369,10 @@ meta_window_actor_constructed (GObject *object)
*/
g_object_ref (priv->actor);
g_signal_connect (window, "notify::decorated",
G_CALLBACK (window_decorated_notify), self);
g_signal_connect (window, "notify::appears-focused",
G_CALLBACK (window_appears_focused_notify), self);
g_signal_connect_object (window, "notify::decorated",
G_CALLBACK (window_decorated_notify), self, 0);
g_signal_connect_object (window, "notify::appears-focused",
G_CALLBACK (window_appears_focused_notify), self, 0);
}
else
{
@ -457,7 +449,6 @@ meta_window_actor_finalize (GObject *object)
MetaWindowActorPrivate *priv = self->priv;
g_list_free_full (priv->frames, (GDestroyNotify) frame_data_free);
g_free (priv->desc);
G_OBJECT_CLASS (meta_window_actor_parent_class)->finalize (object);
}
@ -852,25 +843,6 @@ meta_window_actor_is_override_redirect (MetaWindowActor *self)
return meta_window_is_override_redirect (self->priv->window);
}
const char *meta_window_actor_get_description (MetaWindowActor *self)
{
/*
* For windows managed by the WM, we just defer to the WM for the window
* description. For override-redirect windows, we create the description
* ourselves, but only on demand.
*/
if (self->priv->window)
return meta_window_get_description (self->priv->window);
if (G_UNLIKELY (self->priv->desc == NULL))
{
self->priv->desc = g_strdup_printf ("Override Redirect (0x%x)",
(guint) self->priv->xwindow);
}
return self->priv->desc;
}
/**
* meta_window_actor_get_workspace:
* @self: #MetaWindowActor
@ -1340,14 +1312,6 @@ meta_window_actor_destroy (MetaWindowActor *self)
priv->needs_destroy = TRUE;
/*
* Once the window destruction is initiated we can no longer perform any
* furter X-based operations. For example, if we have a Map effect running,
* we cannot query the window geometry once the effect completes. So, flag
* this.
*/
priv->no_more_x_calls = TRUE;
if (!meta_window_actor_effect_in_progress (self))
clutter_actor_destroy (CLUTTER_ACTOR (self));
}
@ -1645,7 +1609,7 @@ meta_window_actor_get_obscured_region (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
if (priv->back_pixmap && priv->opacity == 0xff)
if (priv->back_pixmap && priv->opacity == 0xff && !priv->window->shaded)
return priv->opaque_region;
else
return NULL;
@ -1748,8 +1712,8 @@ meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
* meta_window_actor_reset_visible_regions:
* @self: a #MetaWindowActor
*
* Unsets the regions set by meta_window_actor_reset_visible_region() and
* meta_window_actor_reset_visible_region_beneath()
* Unsets the regions set by meta_window_actor_set_visible_region() and
* meta_window_actor_set_visible_region_beneath()
*/
void
meta_window_actor_reset_visible_regions (MetaWindowActor *self)
@ -1993,73 +1957,6 @@ meta_window_actor_sync_visibility (MetaWindowActor *self)
}
}
#define TAU (2*M_PI)
static void
install_corners (MetaWindow *window,
MetaFrameBorders *borders,
cairo_t *cr)
{
float top_left, top_right, bottom_left, bottom_right;
int x, y;
MetaRectangle outer;
meta_frame_get_corner_radiuses (window->frame,
&top_left,
&top_right,
&bottom_left,
&bottom_right);
meta_window_get_outer_rect (window, &outer);
/* top left */
x = borders->invisible.left;
y = borders->invisible.top;
cairo_arc (cr,
x + top_left,
y + top_left,
top_left,
2 * TAU / 4,
3 * TAU / 4);
/* top right */
x = borders->invisible.left + outer.width - top_right;
y = borders->invisible.top;
cairo_arc (cr,
x,
y + top_right,
top_right,
3 * TAU / 4,
4 * TAU / 4);
/* bottom right */
x = borders->invisible.left + outer.width - bottom_right;
y = borders->invisible.top + outer.height - bottom_right;
cairo_arc (cr,
x,
y,
bottom_right,
0 * TAU / 4,
1 * TAU / 4);
/* bottom left */
x = borders->invisible.left;
y = borders->invisible.top + outer.height - bottom_left;
cairo_arc (cr,
x + bottom_left,
y,
bottom_left,
1 * TAU / 4,
2 * TAU / 4);
cairo_set_source_rgba (cr, 1, 1, 1, 1);
cairo_fill (cr);
}
static cairo_region_t *
scan_visible_region (guchar *mask_data,
int stride,
@ -2099,7 +1996,6 @@ scan_visible_region (guchar *mask_data,
static void
build_and_scan_frame_mask (MetaWindowActor *self,
MetaFrameBorders *borders,
cairo_rectangle_int_t *client_area,
cairo_region_t *shape_region)
{
@ -2145,7 +2041,7 @@ build_and_scan_frame_mask (MetaWindowActor *self,
gdk_cairo_region (cr, frame_paint_region);
cairo_clip (cr);
install_corners (priv->window, borders, cr);
meta_frame_get_mask (priv->window->frame, cr);
cairo_surface_flush (surface);
scanned_region = scan_visible_region (mask_data, stride, frame_paint_region);
@ -2214,7 +2110,10 @@ check_needs_reshape (MetaWindowActor *self)
client_area.x = borders.total.left;
client_area.y = borders.total.top;
client_area.width = priv->window->rect.width;
client_area.height = priv->window->rect.height;
if (priv->window->shaded)
client_area.height = 0;
else
client_area.height = priv->window->rect.height;
meta_shaped_texture_set_mask_texture (META_SHAPED_TEXTURE (priv->actor), NULL);
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
@ -2308,7 +2207,7 @@ check_needs_reshape (MetaWindowActor *self)
* and scans the mask looking for all opaque pixels,
* adding it to region.
*/
build_and_scan_frame_mask (self, &borders, &client_area, region);
build_and_scan_frame_mask (self, &client_area, region);
}
priv->shape_region = region;

View File

@ -91,8 +91,9 @@ meta_window_group_paint (ClutterActor *actor)
{
cairo_region_t *visible_region;
ClutterActor *stage;
ClutterActorIter iter;
ClutterActor *child;
cairo_rectangle_int_t visible_rect;
GList *children, *l;
int paint_x_origin, paint_y_origin;
int actor_x_origin, actor_y_origin;
int paint_x_offset, paint_y_offset;
@ -123,13 +124,6 @@ meta_window_group_paint (ClutterActor *actor)
paint_x_offset = paint_x_origin - actor_x_origin;
paint_y_offset = paint_y_origin - actor_y_origin;
/* We walk the list from top to bottom (opposite of painting order),
* and subtract the opaque area of each window out of the visible
* region that we pass to the windows below.
*/
children = clutter_actor_get_children (actor);
children = g_list_reverse (children);
/* Get the clipped redraw bounds from Clutter so that we can avoid
* painting shadows on windows that don't need to be painted in this
* frame. In the case of a multihead setup with mismatched monitor
@ -151,12 +145,18 @@ meta_window_group_paint (ClutterActor *actor)
cairo_region_subtract_rectangle (visible_region, &unredirected_rect);
}
for (l = children; l; l = l->next)
/* We walk the list from top to bottom (opposite of painting order),
* and subtract the opaque area of each window out of the visible
* region that we pass to the windows below.
*/
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_prev (&iter, &child))
{
if (!CLUTTER_ACTOR_IS_VISIBLE (l->data))
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
continue;
if (l->data == info->unredirected_window)
if (info->unredirected_window != NULL &&
child == CLUTTER_ACTOR (info->unredirected_window))
continue;
/* If an actor has effects applied, then that can change the area
@ -175,12 +175,12 @@ meta_window_group_paint (ClutterActor *actor)
* as well for the same reason, but omitted for simplicity in the
* hopes that no-one will do that.
*/
if (clutter_actor_has_effects (l->data))
if (clutter_actor_has_effects (child))
continue;
if (META_IS_WINDOW_ACTOR (l->data))
if (META_IS_WINDOW_ACTOR (child))
{
MetaWindowActor *window_actor = l->data;
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
int x, y;
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
@ -204,13 +204,12 @@ meta_window_group_paint (ClutterActor *actor)
meta_window_actor_set_visible_region_beneath (window_actor, visible_region);
cairo_region_translate (visible_region, x, y);
}
else if (META_IS_BACKGROUND_ACTOR (l->data) ||
META_IS_BACKGROUND_GROUP (l->data))
else if (META_IS_BACKGROUND_ACTOR (child) ||
META_IS_BACKGROUND_GROUP (child))
{
ClutterActor *background_actor = l->data;
int x, y;
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (background_actor), &x, &y))
if (!meta_actor_is_untransformed (child, &x, &y))
continue;
x += paint_x_offset;
@ -218,10 +217,10 @@ meta_window_group_paint (ClutterActor *actor)
cairo_region_translate (visible_region, - x, - y);
if (META_IS_BACKGROUND_GROUP (background_actor))
meta_background_group_set_visible_region (META_BACKGROUND_GROUP (background_actor), visible_region);
if (META_IS_BACKGROUND_GROUP (child))
meta_background_group_set_visible_region (META_BACKGROUND_GROUP (child), visible_region);
else
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (background_actor), visible_region);
meta_background_actor_set_visible_region (META_BACKGROUND_ACTOR (child), visible_region);
cairo_region_translate (visible_region, x, y);
}
}
@ -233,21 +232,20 @@ meta_window_group_paint (ClutterActor *actor)
/* Now that we are done painting, unset the visible regions (they will
* mess up painting clones of our actors)
*/
for (l = children; l; l = l->next)
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
{
if (META_IS_WINDOW_ACTOR (l->data))
if (META_IS_WINDOW_ACTOR (child))
{
MetaWindowActor *window_actor = l->data;
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
meta_window_actor_reset_visible_regions (window_actor);
}
else if (META_IS_BACKGROUND_ACTOR (l->data))
else if (META_IS_BACKGROUND_ACTOR (child))
{
MetaBackgroundActor *background_actor = l->data;
MetaBackgroundActor *background_actor = META_BACKGROUND_ACTOR (child);
meta_background_actor_set_visible_region (background_actor, NULL);
}
}
g_list_free (children);
}
static gboolean

View File

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

View File

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

View File

@ -103,19 +103,20 @@ struct _MetaDisplay
#include <meta/atomnames.h>
#undef item
/* This is the actual window from focus events,
* not the one we last set
/* The window and serial of the most recent FocusIn event. */
Window server_focus_window;
gulong server_focus_serial;
/* Our best guess as to the "currently" focused window (that is, the
* window that we expect will be focused at the point when the X
* server processes our next request), and the serial of the request
* or event that caused this.
*/
MetaWindow *focus_window;
/* window we are expecting a FocusIn event for or the current focus
* window if we are not expecting any FocusIn/FocusOut events; not
* perfect because applications can call XSetInputFocus directly.
* (It could also be messed up if a timestamp later than current
* time is sent to meta_display_set_input_focus_window, though that
* would be a programming error). See bug 154598 for more info.
*/
MetaWindow *expected_focus_window;
/* For windows we've focused that don't necessarily have an X window,
* like the no_focus_window or the stage X window. */
Window focus_xwindow;
gulong focus_serial;
/* last timestamp passed to XSetInputFocus */
guint32 last_focus_time;
@ -239,6 +240,8 @@ struct _MetaDisplay
unsigned int meta_mask;
MetaKeyCombo overlay_key_combo;
gboolean overlay_key_only_pressed;
MetaKeyCombo *iso_next_group_combos;
int n_iso_next_group_combos;
/* Monitor cache */
unsigned int monitor_cache_invalidated : 1;
@ -457,7 +460,9 @@ void meta_display_remove_autoraise_callback (MetaDisplay *display);
void meta_display_overlay_key_activate (MetaDisplay *display);
void meta_display_accelerator_activate (MetaDisplay *display,
guint action,
guint deviceid);
guint deviceid,
guint timestamp);
gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display);
/* In above-tab-keycode.c */
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
@ -467,4 +472,9 @@ 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);
#endif

View File

@ -139,6 +139,7 @@ enum
{
OVERLAY_KEY,
ACCELERATOR_ACTIVATED,
MODIFIERS_ACCELERATOR_ACTIVATED,
FOCUS_WINDOW,
WINDOW_CREATED,
WINDOW_DEMANDS_ATTENTION,
@ -253,7 +254,26 @@ meta_display_class_init (MetaDisplayClass *klass)
G_SIGNAL_RUN_LAST,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);
G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
/**
* MetaDisplay::modifiers-accelerator-activated:
* @display: the #MetaDisplay instance
*
* The ::modifiers-accelerator-activated signal will be emitted when
* a special modifiers-only keybinding is activated.
*
* Returns: %TRUE means that the keyboard device should remain
* frozen and %FALSE for the default behavior of unfreezing the
* keyboard.
*/
display_signals[MODIFIERS_ACCELERATOR_ACTIVATED] =
g_signal_new ("modifiers-accelerator-activated",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
g_signal_accumulator_first_wins, NULL, NULL,
G_TYPE_BOOLEAN, 0);
display_signals[WINDOW_CREATED] =
g_signal_new ("window-created",
@ -519,7 +539,9 @@ meta_display_open (void)
the_display->autoraise_timeout_id = 0;
the_display->autoraise_window = NULL;
the_display->focus_window = NULL;
the_display->expected_focus_window = NULL;
the_display->focus_serial = 0;
the_display->server_focus_window = None;
the_display->server_focus_serial = 0;
the_display->grab_old_window_stacking = NULL;
the_display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
@ -1445,6 +1467,17 @@ meta_display_get_current_time (MetaDisplay *display)
return display->current_time;
}
static Bool
find_timestamp_predicate (Display *xdisplay,
XEvent *ev,
XPointer arg)
{
MetaDisplay *display = (MetaDisplay *) arg;
return (ev->type == PropertyNotify &&
ev->xproperty.atom == display->atom__MUTTER_TIMESTAMP_PING);
}
/* Get a timestamp, even if it means a roundtrip */
guint32
meta_display_get_current_time_roundtrip (MetaDisplay *display)
@ -1456,17 +1489,13 @@ meta_display_get_current_time_roundtrip (MetaDisplay *display)
{
XEvent property_event;
/* Using the property XA_PRIMARY because it's safe; nothing
* would use it as a property. The type doesn't matter.
*/
XChangeProperty (display->xdisplay,
display->timestamp_pinging_window,
XA_PRIMARY, XA_STRING, 8,
PropModeAppend, NULL, 0);
XWindowEvent (display->xdisplay,
display->timestamp_pinging_window,
PropertyChangeMask,
&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;
}
@ -1632,12 +1661,12 @@ meta_display_mouse_mode_focus (MetaDisplay *display,
* alternative mechanism works great.
*/
if (meta_prefs_get_focus_mode() == G_DESKTOP_FOCUS_MODE_MOUSE &&
display->expected_focus_window != NULL)
display->focus_window != NULL)
{
meta_topic (META_DEBUG_FOCUS,
"Unsetting focus from %s due to mouse entering "
"the DESKTOP window\n",
display->expected_focus_window->desc);
display->focus_window->desc);
meta_display_focus_the_no_focus_window (display,
window->screen,
timestamp);
@ -1851,6 +1880,246 @@ get_input_event (MetaDisplay *display,
return NULL;
}
static void
update_focus_window (MetaDisplay *display,
MetaWindow *window,
Window xwindow,
gulong serial)
{
display->focus_serial = serial;
if (display->focus_xwindow == xwindow)
return;
if (display->focus_window)
{
MetaWindow *previous;
meta_topic (META_DEBUG_FOCUS,
"%s is now the previous focus window due to being focused out or unmapped\n",
display->focus_window->desc);
/* Make sure that signals handlers invoked by
* meta_window_set_focused_internal() don't see
* display->focus_window->has_focus == FALSE
*/
previous = display->focus_window;
display->focus_window = NULL;
display->focus_xwindow = None;
meta_window_set_focused_internal (previous, FALSE);
}
display->focus_window = window;
display->focus_xwindow = xwindow;
if (display->focus_window)
{
meta_topic (META_DEBUG_FOCUS, "* Focus --> %s with serial %lu\n",
display->focus_window->desc, serial);
meta_window_set_focused_internal (display->focus_window, TRUE);
}
else
meta_topic (META_DEBUG_FOCUS, "* Focus --> NULL with serial %lu\n", serial);
g_object_notify (G_OBJECT (display), "focus-window");
meta_display_update_active_window_hint (display);
}
static gboolean
timestamp_too_old (MetaDisplay *display,
guint32 *timestamp)
{
/* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow
* us to sanity check the timestamp here and ensure it doesn't correspond to
* a future time (though we would want to rename to
* timestamp_too_old_or_in_future).
*/
if (*timestamp == CurrentTime)
{
*timestamp = meta_display_get_current_time_roundtrip (display);
return FALSE;
}
else if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_focus_time))
{
if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_user_time))
return TRUE;
else
{
*timestamp = display->last_focus_time;
return FALSE;
}
}
return FALSE;
}
static void
request_xserver_input_focus_change (MetaDisplay *display,
MetaScreen *screen,
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
* the serial of the "focus request" we made, but if we take the serial
* of the XSetInputFocus request, then there's no way to determine the
* difference between focus events as a result of the SetInputFocus and
* focus events that other clients send around the same time. Ensure that
* we know which is which by making two requests that the server will
* process at the same time.
*/
meta_display_grab (display);
serial = XNextRequest (display->xdisplay);
XSetInputFocus (display->xdisplay,
xwindow,
RevertToPointerRoot,
timestamp);
XChangeProperty (display->xdisplay, display->timestamp_pinging_window,
display->atom__MUTTER_FOCUS_SET,
XA_STRING, 8, PropModeAppend, NULL, 0);
meta_display_ungrab (display);
update_focus_window (display,
meta_window,
xwindow,
serial);
meta_error_trap_pop (display);
display->last_focus_time = timestamp;
display->active_screen = screen;
if (meta_window == NULL || meta_window != display->autoraise_window)
meta_display_remove_autoraise_callback (display);
}
static void
handle_window_focus_event (MetaDisplay *display,
MetaWindow *window,
XIEnterEvent *event,
unsigned long serial)
{
MetaWindow *focus_window;
#ifdef WITH_VERBOSE_MODE
const char *window_type;
/* Note the event can be on either the window or the frame,
* we focus the frame for shaded windows
*/
if (window)
{
if (event->event == window->xwindow)
window_type = "client window";
else if (window->frame && event->event == window->frame->xwindow)
window_type = "frame window";
else
window_type = "unknown client window";
}
else if (meta_display_xwindow_is_a_no_focus_window (display, event->event))
window_type = "no_focus_window";
else if (meta_display_screen_for_root (display, event->event))
window_type = "root window";
else
window_type = "unknown window";
meta_topic (META_DEBUG_FOCUS,
"Focus %s event received on %s 0x%lx (%s) "
"mode %s detail %s serial %lu\n",
event->evtype == XI_FocusIn ? "in" :
event->evtype == XI_FocusOut ? "out" :
"???",
window ? window->desc : "",
event->event, window_type,
meta_event_mode_to_string (event->mode),
meta_event_detail_to_string (event->mode),
event->serial);
#endif
/* FIXME our pointer tracking is broken; see how
* gtk+/gdk/x11/gdkevents-x11.c or XFree86/xc/programs/xterm/misc.c
* for how to handle it the correct way. In brief you need to track
* pointer focus and regular focus, and handle EnterNotify in
* PointerRoot mode with no window manager. However as noted above,
* accurate focus tracking will break things because we want to keep
* windows "focused" when using keybindings on them, and also we
* sometimes "focus" a window by focusing its frame or
* no_focus_window; so this all needs rethinking massively.
*
* My suggestion is to change it so that we clearly separate
* actual keyboard focus tracking using the xterm algorithm,
* and mutter's "pretend" focus window, and go through all
* the code and decide which one should be used in each place;
* a hard bit is deciding on a policy for that.
*
* http://bugzilla.gnome.org/show_bug.cgi?id=90382
*/
/* We ignore grabs, though this is questionable. It may be better to
* increase the intelligence of the focus window tracking.
*
* The problem is that keybindings for windows are done with
* XGrabKey, which means focus_window disappears and the front of
* the MRU list gets confused from what the user expects once a
* keybinding is used.
*/
if (event->mode == XINotifyGrab ||
event->mode == XINotifyUngrab ||
/* From WindowMaker, ignore all funky pointer root events */
event->detail > XINotifyNonlinearVirtual)
{
meta_topic (META_DEBUG_FOCUS,
"Ignoring focus event generated by a grab or other weirdness\n");
return;
}
if (event->evtype == XI_FocusIn)
{
display->server_focus_window = event->event;
display->server_focus_serial = serial;
focus_window = window;
}
else if (event->evtype == XI_FocusOut)
{
if (event->detail == XINotifyInferior)
{
/* This event means the client moved focus to a subwindow */
meta_topic (META_DEBUG_FOCUS,
"Ignoring focus out with NotifyInferior\n");
return;
}
display->server_focus_window = None;
display->server_focus_serial = serial;
focus_window = NULL;
}
else
g_return_if_reached ();
if (display->server_focus_serial > display->focus_serial)
{
update_focus_window (display,
focus_window,
focus_window ? focus_window->xwindow : None,
display->server_focus_serial);
}
}
/**
* event_callback:
* @event: The event that just happened
@ -1877,6 +2146,7 @@ event_callback (XEvent *event,
gboolean bypass_compositor;
gboolean filter_out_event;
XIEvent *input_event;
MetaMonitorManager *monitor;
display = data;
@ -1888,12 +2158,32 @@ event_callback (XEvent *event,
#ifdef HAVE_STARTUP_NOTIFICATION
sn_display_process_event (display->sn_display, event);
#endif
/* Intercept XRandR events early and don't attempt any
processing for them. We still let them through to Gdk though,
so it can update its own internal state.
*/
monitor = meta_monitor_manager_get ();
if (meta_monitor_manager_handle_xevent (monitor, event))
return FALSE;
bypass_compositor = FALSE;
filter_out_event = FALSE;
display->current_time = event_get_time (display, event);
display->monitor_cache_invalidated = TRUE;
if (event->xany.serial > display->focus_serial &&
display->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_display_lookup_x_window (display, display->server_focus_window),
display->server_focus_window,
display->server_focus_serial);
}
modified = event_get_modified_window (display, event);
input_event = get_input_event (display, event);
@ -2213,30 +2503,12 @@ event_callback (XEvent *event,
/* This is from our synchronous grab since
* it has no modifiers and was on the client window
*/
int mode;
/* When clicking a different app in click-to-focus
* in application-based mode, and the different
* app is not a dock or desktop, eat the focus click.
*/
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK &&
meta_prefs_get_application_based () &&
!window->has_focus &&
window->type != META_WINDOW_DOCK &&
window->type != META_WINDOW_DESKTOP &&
(display->focus_window == NULL ||
!meta_window_same_application (window,
display->focus_window)))
mode = XIAsyncDevice; /* eat focus click */
else
mode = XIReplayDevice; /* give event back */
meta_verbose ("Allowing events mode %s time %u\n",
mode == AsyncPointer ? "AsyncPointer" : "ReplayPointer",
meta_verbose ("Allowing events time %u\n",
(unsigned int)device_event->time);
XIAllowEvents (display->xdisplay, device_event->deviceid,
mode, device_event->time);
XIReplayDevice, device_event->time);
}
if (begin_move && window->has_move_func)
@ -2350,40 +2622,19 @@ event_callback (XEvent *event,
break;
case XI_FocusIn:
case XI_FocusOut:
if (window)
{
meta_window_notify_focus (window, enter_event);
}
else if (meta_display_xwindow_is_a_no_focus_window (display,
enter_event->event))
{
meta_topic (META_DEBUG_FOCUS,
"Focus %s event received on no_focus_window 0x%lx "
"mode %s detail %s\n",
enter_event->evtype == XI_FocusIn ? "in" :
enter_event->evtype == XI_FocusOut ? "out" :
"???",
enter_event->event,
meta_event_mode_to_string (enter_event->mode),
meta_event_detail_to_string (enter_event->detail));
}
else
/* libXi does not properly copy the serial to the XIEnterEvent, so pull it
* from the parent XAnyEvent.
* See: https://bugs.freedesktop.org/show_bug.cgi?id=64687
*/
handle_window_focus_event (display, window, enter_event, event->xany.serial);
if (!window)
{
/* Check if the window is a root window. */
MetaScreen *screen =
meta_display_screen_for_root(display,
enter_event->event);
if (screen == NULL)
break;
meta_topic (META_DEBUG_FOCUS,
"Focus %s event received on root window 0x%lx "
"mode %s detail %s\n",
enter_event->evtype == XI_FocusIn ? "in" :
enter_event->evtype == XI_FocusOut ? "out" :
"???",
enter_event->event,
meta_event_mode_to_string (enter_event->mode),
meta_event_detail_to_string (enter_event->detail));
if (enter_event->evtype == XI_FocusIn &&
enter_event->mode == XINotifyDetailNone)
@ -2521,13 +2772,6 @@ event_callback (XEvent *event,
window->unmaps_pending);
}
}
/* Unfocus on UnmapNotify, do this after the possible
* window_free above so that window_free can see if window->has_focus
* and move focus to another window
*/
if (window)
meta_window_lost_focus (window);
}
break;
case MapNotify:
@ -2587,32 +2831,10 @@ event_callback (XEvent *event,
meta_stack_tracker_configure_event (screen->stack_tracker,
&event->xconfigure);
}
if (window && window->override_redirect)
meta_window_configure_notify (window, &event->xconfigure);
else
/* Handle screen resize */
{
MetaScreen *screen;
screen = meta_display_screen_for_root (display,
event->xconfigure.window);
if (screen != NULL)
{
#ifdef HAVE_RANDR
/* do the resize the official way */
XRRUpdateConfiguration (event);
#else
/* poke around in Xlib */
screen->xscreen->width = event->xconfigure.width;
screen->xscreen->height = event->xconfigure.height;
#endif
meta_screen_resize (screen,
event->xconfigure.width,
event->xconfigure.height);
}
}
break;
case ConfigureRequest:
/* This comment and code is found in both twm and fvwm */
@ -2807,27 +3029,6 @@ event_callback (XEvent *event,
meta_workspace_focus_default_window (screen->active_workspace, NULL, timestamp);
}
}
else if (event->xclient.message_type ==
display->atom__MUTTER_RELOAD_THEME_MESSAGE)
{
meta_verbose ("Received reload theme request\n");
meta_ui_set_current_theme (meta_prefs_get_theme (),
TRUE);
meta_display_retheme_all ();
}
else if (event->xclient.message_type ==
display->atom__MUTTER_SET_KEYBINDINGS_MESSAGE)
{
meta_verbose ("Received set keybindings request = %d\n",
(int) event->xclient.data.l[0]);
meta_set_keybindings_disabled (!event->xclient.data.l[0]);
}
else if (event->xclient.message_type ==
display->atom__MUTTER_TOGGLE_VERBOSE)
{
meta_verbose ("Received toggle verbose message\n");
meta_set_verbose (!meta_is_verbose ());
}
else if (event->xclient.message_type ==
display->atom_WM_PROTOCOLS)
{
@ -3537,6 +3738,12 @@ meta_spew_event (MetaDisplay *display,
if (event->type == (display->damage_event_base + XDamageNotify))
return;
if (event->type == (display->xsync_event_base + XSyncAlarmNotify))
return;
if (event->type == PropertyNotify && event->xproperty.atom == display->atom__NET_WM_USER_TIME)
return;
input_event = get_input_event (display, event);
if (input_event)
@ -5561,98 +5768,74 @@ sanity_check_timestamps (MetaDisplay *display,
}
}
static gboolean
timestamp_too_old (MetaDisplay *display,
MetaWindow *window,
guint32 *timestamp)
{
/* FIXME: If Soeren's suggestion in bug 151984 is implemented, it will allow
* us to sanity check the timestamp here and ensure it doesn't correspond to
* a future time (though we would want to rename to
* timestamp_too_old_or_in_future).
*/
if (*timestamp == CurrentTime)
{
meta_warning ("Got a request to focus %s with a timestamp of 0. This "
"shouldn't happen!\n",
window ? window->desc : "the no_focus_window");
*timestamp = meta_display_get_current_time_roundtrip (display);
return FALSE;
}
else if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_focus_time))
{
if (XSERVER_TIME_IS_BEFORE (*timestamp, display->last_user_time))
{
meta_topic (META_DEBUG_FOCUS,
"Ignoring focus request for %s since %u "
"is less than %u and %u.\n",
window ? window->desc : "the no_focus_window",
*timestamp,
display->last_user_time,
display->last_focus_time);
return TRUE;
}
else
{
meta_topic (META_DEBUG_FOCUS,
"Received focus request for %s which is newer than most "
"recent user_time, but less recent than "
"last_focus_time (%u < %u < %u); adjusting "
"accordingly. (See bug 167358)\n",
window ? window->desc : "the no_focus_window",
display->last_user_time,
*timestamp,
display->last_focus_time);
*timestamp = display->last_focus_time;
return FALSE;
}
}
return FALSE;
}
void
meta_display_set_input_focus_window (MetaDisplay *display,
MetaWindow *window,
gboolean focus_frame,
guint32 timestamp)
{
if (timestamp_too_old (display, window, &timestamp))
return;
meta_error_trap_push (display);
XSetInputFocus (display->xdisplay,
focus_frame ? window->frame->xwindow : window->xwindow,
RevertToPointerRoot,
timestamp);
meta_error_trap_pop (display);
display->expected_focus_window = window;
display->last_focus_time = timestamp;
display->active_screen = window->screen;
if (window != display->autoraise_window)
meta_display_remove_autoraise_callback (window->display);
request_xserver_input_focus_change (display,
window->screen,
focus_frame ? window->frame->xwindow : window->xwindow,
timestamp);
}
void
meta_display_focus_the_no_focus_window (MetaDisplay *display,
meta_display_request_take_focus (MetaDisplay *display,
MetaWindow *window,
guint32 timestamp)
{
if (timestamp_too_old (display, &timestamp))
return;
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)
{
request_xserver_input_focus_change (display,
screen,
window,
timestamp);
}
void
meta_display_focus_the_no_focus_window (MetaDisplay *display,
MetaScreen *screen,
guint32 timestamp)
{
if (timestamp_too_old (display, NULL, &timestamp))
return;
XSetInputFocus (display->xdisplay,
screen->no_focus_window,
RevertToPointerRoot,
timestamp);
display->expected_focus_window = NULL;
display->last_focus_time = timestamp;
display->active_screen = screen;
meta_display_remove_autoraise_callback (display);
request_xserver_input_focus_change (display,
screen,
screen->no_focus_window,
timestamp);
}
void
@ -5675,10 +5858,21 @@ meta_display_overlay_key_activate (MetaDisplay *display)
void
meta_display_accelerator_activate (MetaDisplay *display,
guint action,
guint deviceid)
guint deviceid,
guint timestamp)
{
g_signal_emit (display, display_signals[ACCELERATOR_ACTIVATED],
0, action, deviceid);
0, action, deviceid, timestamp);
}
gboolean
meta_display_modifiers_accelerator_activate (MetaDisplay *display)
{
gboolean freeze;
g_signal_emit (display, display_signals[MODIFIERS_ACCELERATOR_ACTIVATED], 0, &freeze);
return freeze;
}
void
@ -5762,11 +5956,9 @@ meta_display_has_shape (MetaDisplay *display)
* meta_display_get_focus_window:
* @display: a #MetaDisplay
*
* Get the window that, according to events received from X server,
* currently has the input focus. We may have already sent a request
* to the X server to move the focus window elsewhere. (The
* expected_focus_window records where we've last set the input
* focus.)
* Get our best guess as to the "currently" focused window (that is,
* the window that we expect will be focused at the point when the X
* server processes our next request).
*
* Return Value: (transfer none): The current focus window
*/

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

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

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

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

View File

@ -332,19 +332,6 @@ meta_frame_calc_borders (MetaFrame *frame,
borders);
}
void
meta_frame_get_corner_radiuses (MetaFrame *frame,
float *top_left,
float *top_right,
float *bottom_left,
float *bottom_right)
{
meta_ui_get_corner_radiuses (frame->window->screen->ui,
frame->xwindow,
top_left, top_right,
bottom_left, bottom_right);
}
gboolean
meta_frame_sync_to_window (MetaFrame *frame,
int resize_gravity,
@ -400,6 +387,14 @@ meta_frame_get_frame_bounds (MetaFrame *frame)
frame->rect.height);
}
void
meta_frame_get_mask (MetaFrame *frame,
cairo_t *cr)
{
meta_ui_get_frame_mask (frame->window->screen->ui, frame->xwindow,
frame->rect.width, frame->rect.height, cr);
}
void
meta_frame_queue_draw (MetaFrame *frame)
{

View File

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

View File

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

View File

@ -56,8 +56,6 @@
#define SCHEMA_COMMON_KEYBINDINGS "org.gnome.desktop.wm.keybindings"
#define SCHEMA_MUTTER_KEYBINDINGS "org.gnome.mutter.keybindings"
static gboolean all_bindings_disabled = FALSE;
static gboolean add_builtin_keybinding (MetaDisplay *display,
const char *name,
GSettings *settings,
@ -147,7 +145,8 @@ static gboolean process_workspace_switch_grab (MetaDisplay *display,
XIDeviceEvent *event,
KeySym keysym);
static void regrab_key_bindings (MetaDisplay *display);
static void grab_key_bindings (MetaDisplay *display);
static void ungrab_key_bindings (MetaDisplay *display);
static GHashTable *key_handlers;
@ -301,6 +300,172 @@ reload_modmap (MetaDisplay *display)
display->meta_mask);
}
/* Original code from gdk_x11_keymap_get_entries_for_keyval() in
* gdkkeys-x11.c */
static int
get_keycodes_for_keysym (MetaDisplay *display,
int keysym,
int **keycodes)
{
GArray *retval;
int n_keycodes;
int keycode;
retval = g_array_new (FALSE, FALSE, sizeof (int));
keycode = display->min_keycode;
while (keycode <= display->max_keycode)
{
const KeySym *syms = display->keymap + (keycode - display->min_keycode) * display->keysyms_per_keycode;
int i = 0;
while (i < display->keysyms_per_keycode)
{
if (syms[i] == (unsigned int)keysym)
g_array_append_val (retval, keycode);
++i;
}
++keycode;
}
n_keycodes = retval->len;
*keycodes = (int*) g_array_free (retval, n_keycodes == 0 ? TRUE : FALSE);
return n_keycodes;
}
static void
reload_iso_next_group_combos (MetaDisplay *display)
{
const char *iso_next_group_option;
MetaKeyCombo *combos;
int *keycodes;
int n_keycodes;
int n_combos;
int i;
g_clear_pointer (&display->iso_next_group_combos, g_free);
display->n_iso_next_group_combos = 0;
iso_next_group_option = meta_prefs_get_iso_next_group_option ();
if (iso_next_group_option == NULL)
return;
n_keycodes = get_keycodes_for_keysym (display, XK_ISO_Next_Group, &keycodes);
if (g_str_equal (iso_next_group_option, "toggle") ||
g_str_equal (iso_next_group_option, "lalt_toggle") ||
g_str_equal (iso_next_group_option, "lwin_toggle") ||
g_str_equal (iso_next_group_option, "rwin_toggle") ||
g_str_equal (iso_next_group_option, "lshift_toggle") ||
g_str_equal (iso_next_group_option, "rshift_toggle") ||
g_str_equal (iso_next_group_option, "lctrl_toggle") ||
g_str_equal (iso_next_group_option, "rctrl_toggle") ||
g_str_equal (iso_next_group_option, "sclk_toggle") ||
g_str_equal (iso_next_group_option, "menu_toggle") ||
g_str_equal (iso_next_group_option, "caps_toggle"))
{
n_combos = n_keycodes;
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XK_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].modifiers = 0;
}
}
else if (g_str_equal (iso_next_group_option, "shift_caps_toggle") ||
g_str_equal (iso_next_group_option, "shifts_toggle"))
{
n_combos = n_keycodes;
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XK_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].modifiers = ShiftMask;
}
}
else if (g_str_equal (iso_next_group_option, "alt_caps_toggle") ||
g_str_equal (iso_next_group_option, "alt_space_toggle"))
{
n_combos = n_keycodes;
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XK_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].modifiers = Mod1Mask;
}
}
else if (g_str_equal (iso_next_group_option, "ctrl_shift_toggle") ||
g_str_equal (iso_next_group_option, "lctrl_lshift_toggle") ||
g_str_equal (iso_next_group_option, "rctrl_rshift_toggle"))
{
n_combos = n_keycodes * 2;
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XK_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].modifiers = ShiftMask;
combos[i + n_keycodes].keysym = XK_ISO_Next_Group;
combos[i + n_keycodes].keycode = keycodes[i];
combos[i + n_keycodes].modifiers = ControlMask;
}
}
else if (g_str_equal (iso_next_group_option, "ctrl_alt_toggle"))
{
n_combos = n_keycodes * 2;
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XK_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].modifiers = Mod1Mask;
combos[i + n_keycodes].keysym = XK_ISO_Next_Group;
combos[i + n_keycodes].keycode = keycodes[i];
combos[i + n_keycodes].modifiers = ControlMask;
}
}
else if (g_str_equal (iso_next_group_option, "alt_shift_toggle") ||
g_str_equal (iso_next_group_option, "lalt_lshift_toggle"))
{
n_combos = n_keycodes * 2;
combos = g_new (MetaKeyCombo, n_combos);
for (i = 0; i < n_keycodes; ++i)
{
combos[i].keysym = XK_ISO_Next_Group;
combos[i].keycode = keycodes[i];
combos[i].modifiers = Mod1Mask;
combos[i + n_keycodes].keysym = XK_ISO_Next_Group;
combos[i + n_keycodes].keycode = keycodes[i];
combos[i + n_keycodes].modifiers = ShiftMask;
}
}
else
{
n_combos = 0;
combos = NULL;
}
g_free (keycodes);
display->n_iso_next_group_combos = n_combos;
display->iso_next_group_combos = combos;
}
static guint
keysym_to_keycode (MetaDisplay *display,
guint keysym)
@ -327,6 +492,8 @@ reload_keycodes (MetaDisplay *display)
display->overlay_key_combo.keycode = 0;
}
reload_iso_next_group_combos (display);
if (display->key_bindings)
{
int i;
@ -531,7 +698,7 @@ rebuild_special_bindings (MetaDisplay *display)
}
static void
regrab_key_bindings (MetaDisplay *display)
ungrab_key_bindings (MetaDisplay *display)
{
GSList *tmp;
GSList *windows;
@ -544,7 +711,6 @@ regrab_key_bindings (MetaDisplay *display)
MetaScreen *screen = tmp->data;
meta_screen_ungrab_keys (screen);
meta_screen_grab_keys (screen);
tmp = tmp->next;
}
@ -556,6 +722,38 @@ regrab_key_bindings (MetaDisplay *display)
MetaWindow *w = tmp->data;
meta_window_ungrab_keys (w);
tmp = tmp->next;
}
meta_error_trap_pop (display);
g_slist_free (windows);
}
static void
grab_key_bindings (MetaDisplay *display)
{
GSList *tmp;
GSList *windows;
meta_error_trap_push (display); /* for efficiency push outer trap */
tmp = display->screens;
while (tmp != NULL)
{
MetaScreen *screen = tmp->data;
meta_screen_grab_keys (screen);
tmp = tmp->next;
}
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
tmp = windows;
while (tmp != NULL)
{
MetaWindow *w = tmp->data;
meta_window_grab_keys (w);
tmp = tmp->next;
@ -796,6 +994,8 @@ meta_display_process_mapping_event (MetaDisplay *display,
if (keymap_changed || modmap_changed)
{
ungrab_key_bindings (display);
if (keymap_changed)
reload_keymap (display);
@ -809,7 +1009,7 @@ meta_display_process_mapping_event (MetaDisplay *display,
reload_modifiers (display);
regrab_key_bindings (display);
grab_key_bindings (display);
}
}
@ -824,11 +1024,12 @@ bindings_changed_callback (MetaPreference pref,
switch (pref)
{
case META_PREF_KEYBINDINGS:
ungrab_key_bindings (display);
rebuild_key_binding_table (display);
rebuild_special_bindings (display);
reload_keycodes (display);
reload_modifiers (display);
regrab_key_bindings (display);
grab_key_bindings (display);
break;
default:
break;
@ -947,21 +1148,12 @@ meta_change_keygrab (MetaDisplay *display,
}
static void
meta_grab_key (MetaDisplay *display,
Window xwindow,
int keysym,
unsigned int keycode,
int modmask)
{
meta_change_keygrab (display, xwindow, TRUE, keysym, keycode, modmask);
}
static void
grab_keys (MetaKeyBinding *bindings,
int n_bindings,
MetaDisplay *display,
Window xwindow,
gboolean binding_per_window)
change_binding_keygrabs (MetaKeyBinding *bindings,
int n_bindings,
MetaDisplay *display,
Window xwindow,
gboolean binding_per_window,
gboolean grab)
{
int i;
@ -976,10 +1168,10 @@ grab_keys (MetaKeyBinding *bindings,
!!(bindings[i].handler->flags & META_KEY_BINDING_PER_WINDOW) &&
bindings[i].keycode != 0)
{
meta_grab_key (display, xwindow,
bindings[i].keysym,
bindings[i].keycode,
bindings[i].mask);
meta_change_keygrab (display, xwindow, grab,
bindings[i].keysym,
bindings[i].keycode,
bindings[i].mask);
}
++i;
@ -989,51 +1181,49 @@ grab_keys (MetaKeyBinding *bindings,
}
static void
ungrab_all_keys (MetaDisplay *display,
Window xwindow)
meta_screen_change_keygrabs (MetaScreen *screen,
gboolean grab)
{
if (meta_is_debugging ())
meta_error_trap_push_with_return (display);
else
meta_error_trap_push (display);
MetaDisplay *display = screen->display;
XUngrabKey (display->xdisplay, AnyKey, AnyModifier,
xwindow);
if (display->overlay_key_combo.keycode != 0)
meta_change_keygrab (display, screen->xroot, grab,
display->overlay_key_combo.keysym,
display->overlay_key_combo.keycode,
display->overlay_key_combo.modifiers);
if (meta_is_debugging ())
if (display->iso_next_group_combos)
{
int result;
result = meta_error_trap_pop_with_return (display);
if (result != Success)
meta_topic (META_DEBUG_KEYBINDINGS,
"Ungrabbing all keys on 0x%lx failed\n", xwindow);
int i = 0;
while (i < display->n_iso_next_group_combos)
{
if (display->iso_next_group_combos[i].keycode != 0)
{
meta_change_keygrab (display, screen->xroot, grab,
display->iso_next_group_combos[i].keysym,
display->iso_next_group_combos[i].keycode,
display->iso_next_group_combos[i].modifiers);
}
++i;
}
}
else
meta_error_trap_pop (display);
change_binding_keygrabs (screen->display->key_bindings,
screen->display->n_key_bindings,
screen->display, screen->xroot,
FALSE, grab);
}
void
meta_screen_grab_keys (MetaScreen *screen)
{
MetaDisplay *display = screen->display;
if (screen->all_keys_grabbed)
return;
if (screen->keys_grabbed)
return;
if (display->overlay_key_combo.keycode != 0)
meta_grab_key (display, screen->xroot,
display->overlay_key_combo.keysym,
display->overlay_key_combo.keycode,
display->overlay_key_combo.modifiers);
grab_keys (screen->display->key_bindings,
screen->display->n_key_bindings,
screen->display, screen->xroot,
FALSE);
meta_screen_change_keygrabs (screen, TRUE);
screen->keys_grabbed = TRUE;
}
@ -1041,11 +1231,23 @@ meta_screen_grab_keys (MetaScreen *screen)
void
meta_screen_ungrab_keys (MetaScreen *screen)
{
if (screen->keys_grabbed)
{
ungrab_all_keys (screen->display, screen->xroot);
screen->keys_grabbed = FALSE;
}
if (!screen->keys_grabbed)
return;
meta_screen_change_keygrabs (screen, FALSE);
screen->keys_grabbed = FALSE;
}
static void
meta_window_change_keygrabs (MetaWindow *window,
Window xwindow,
gboolean grab)
{
change_binding_keygrabs (window->display->key_bindings,
window->display->n_key_bindings,
window->display, xwindow,
TRUE, grab);
}
void
@ -1058,7 +1260,7 @@ meta_window_grab_keys (MetaWindow *window)
|| window->override_redirect)
{
if (window->keys_grabbed)
ungrab_all_keys (window->display, window->xwindow);
meta_window_change_keygrabs (window, window->xwindow, FALSE);
window->keys_grabbed = FALSE;
return;
}
@ -1066,7 +1268,7 @@ meta_window_grab_keys (MetaWindow *window)
if (window->keys_grabbed)
{
if (window->frame && !window->grab_on_frame)
ungrab_all_keys (window->display, window->xwindow);
meta_window_change_keygrabs (window, window->xwindow, FALSE);
else if (window->frame == NULL &&
window->grab_on_frame)
; /* continue to regrab on client window */
@ -1074,11 +1276,9 @@ meta_window_grab_keys (MetaWindow *window)
return; /* already all good */
}
grab_keys (window->display->key_bindings,
window->display->n_key_bindings,
window->display,
window->frame ? window->frame->xwindow : window->xwindow,
TRUE);
meta_window_change_keygrabs (window,
window->frame ? window->frame->xwindow : window->xwindow,
TRUE);
window->keys_grabbed = TRUE;
window->grab_on_frame = window->frame != NULL;
@ -1091,11 +1291,9 @@ meta_window_ungrab_keys (MetaWindow *window)
{
if (window->grab_on_frame &&
window->frame != NULL)
ungrab_all_keys (window->display,
window->frame->xwindow);
meta_window_change_keygrabs (window, window->frame->xwindow, FALSE);
else if (!window->grab_on_frame)
ungrab_all_keys (window->display,
window->xwindow);
meta_window_change_keygrabs (window, window->xwindow, FALSE);
window->keys_grabbed = FALSE;
}
@ -1112,7 +1310,7 @@ handle_external_grab (MetaDisplay *display,
guint action = meta_display_get_keybinding_action (display,
binding->keycode,
binding->mask);
meta_display_accelerator_activate (display, action, event->deviceid);
meta_display_accelerator_activate (display, action, event->deviceid, event->time);
}
@ -1151,7 +1349,7 @@ meta_display_grab_accelerator (MetaDisplay *display,
for (l = display->screens; l; l = l->next)
{
MetaScreen *screen = l->data;
meta_grab_key (display, screen->xroot, keysym, keycode, mask);
meta_change_keygrab (display, screen->xroot, TRUE, keysym, keycode, mask);
}
grab = g_new0 (MetaKeyGrab, 1);
@ -1248,7 +1446,8 @@ grab_status_to_string (int status)
static gboolean
grab_keyboard (MetaDisplay *display,
Window xwindow,
guint32 timestamp)
guint32 timestamp,
int grab_mode)
{
int result;
int grab_status;
@ -1264,13 +1463,22 @@ grab_keyboard (MetaDisplay *display,
*/
meta_error_trap_push_with_return (display);
/* Strictly, we only need to set grab_mode on the keyboard device
* while the pointer should always be XIGrabModeAsync. Unfortunately
* there is a bug in the X server, only fixed (link below) in 1.15,
* which swaps these arguments for keyboard devices. As such, we set
* both the device and the paired device mode which works around
* that bug and also works on fixed X servers.
*
* http://cgit.freedesktop.org/xorg/xserver/commit/?id=9003399708936481083424b4ff8f18a16b88b7b3
*/
grab_status = XIGrabDevice (display->xdisplay,
META_VIRTUAL_CORE_KEYBOARD_ID,
xwindow,
timestamp,
None,
XIGrabModeAsync, XIGrabModeAsync,
True, /* owner_events */
grab_mode, grab_mode,
False, /* owner_events */
&mask);
if (grab_status != Success)
@ -1323,7 +1531,7 @@ meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp)
meta_topic (META_DEBUG_KEYBINDINGS,
"Grabbing all keys on RootWindow\n");
retval = grab_keyboard (screen->display, screen->xroot, timestamp);
retval = grab_keyboard (screen->display, screen->xroot, timestamp, XIGrabModeAsync);
if (retval)
{
screen->all_keys_grabbed = TRUE;
@ -1376,7 +1584,7 @@ meta_window_grab_all_keys (MetaWindow *window,
meta_topic (META_DEBUG_KEYBINDINGS,
"Grabbing all keys on window %s\n", window->desc);
retval = grab_keyboard (window->display, grabwindow, timestamp);
retval = grab_keyboard (window->display, grabwindow, timestamp, XIGrabModeAsync);
if (retval)
{
window->keys_grabbed = FALSE;
@ -1403,6 +1611,32 @@ meta_window_ungrab_all_keys (MetaWindow *window, guint32 timestamp)
}
}
void
meta_display_freeze_keyboard (MetaDisplay *display, Window window, guint32 timestamp)
{
grab_keyboard (display, window, timestamp, XIGrabModeSync);
}
void
meta_display_ungrab_keyboard (MetaDisplay *display, guint32 timestamp)
{
ungrab_keyboard (display, timestamp);
}
void
meta_display_unfreeze_keyboard (MetaDisplay *display, guint32 timestamp)
{
meta_error_trap_push (display);
XIAllowEvents (display->xdisplay, META_VIRTUAL_CORE_KEYBOARD_ID,
XIAsyncDevice, timestamp);
/* We shouldn't need to unfreeze the pointer device here, however we
* have to, due to the workaround we do in grab_keyboard().
*/
XIAllowEvents (display->xdisplay, META_VIRTUAL_CORE_POINTER_ID,
XIAsyncDevice, timestamp);
meta_error_trap_pop (display);
}
static gboolean
is_modifier (MetaDisplay *display,
unsigned int keycode)
@ -1731,6 +1965,23 @@ process_overlay_key (MetaDisplay *display,
return TRUE;
meta_display_overlay_key_activate (display);
}
else
{
/* In some rare race condition, mutter might not receive the Super_L
* KeyRelease event because:
* - the compositor might end the modal mode and call XIUngrabDevice
* while the key is still down
* - passive grabs are only activated on KeyPress and not KeyRelease.
*
* In this case, display->overlay_key_only_pressed might be wrong.
* Mutter still ought to acknowledge events, otherwise the X server
* will not send the next events.
*
* https://bugzilla.gnome.org/show_bug.cgi?id=666101
*/
XIAllowEvents (display->xdisplay, event->deviceid,
XIAsyncDevice, event->time);
}
return TRUE;
}
@ -1749,6 +2000,41 @@ process_overlay_key (MetaDisplay *display,
return FALSE;
}
static gboolean
process_iso_next_group (MetaDisplay *display,
MetaScreen *screen,
XIDeviceEvent *event,
KeySym keysym)
{
gboolean activate;
unsigned int mods;
int i;
if (event->evtype != XI_KeyPress)
return FALSE;
activate = FALSE;
mods = (event->mods.effective & 0xff & ~(display->ignored_modifier_mask));
for (i = 0; i < display->n_iso_next_group_combos; ++i)
{
if (event->detail == (int)display->iso_next_group_combos[i].keycode &&
mods == display->iso_next_group_combos[i].modifiers)
{
/* If the signal handler returns TRUE the keyboard will
remain frozen. It's the signal handler's responsibility
to unfreeze it. */
if (!meta_display_modifiers_accelerator_activate (display))
XIAllowEvents (display->xdisplay, event->deviceid,
XIAsyncDevice, event->time);
activate = TRUE;
break;
}
}
return activate;
}
/* Handle a key event. May be called recursively: some key events cause
* grabs to be ended and then need to be processed again in their own
* right. This cannot cause infinite recursion because we never call
@ -1775,21 +2061,6 @@ meta_display_process_key_event (MetaDisplay *display,
const char *str;
MetaScreen *screen;
if (all_bindings_disabled)
{
/* In this mode, we try to pretend we don't have grabs, so we
* immediately replay events and drop the grab. (This still
* messes up global passive grabs from other clients.) The
* FALSE return here is a little suspect, but we don't really
* know if we'll see the event again or not, and it's pretty
* poorly defined how this mode is supposed to interact with
* plugins.
*/
XIAllowEvents (display->xdisplay, event->deviceid,
XIReplayDevice, event->time);
return FALSE;
}
/* if key event was on root window, we have a shortcut */
screen = meta_display_screen_for_root (display, event->event);
@ -1823,6 +2094,10 @@ meta_display_process_key_event (MetaDisplay *display,
handled = process_overlay_key (display, screen, event, keysym);
if (handled)
return TRUE;
handled = process_iso_next_group (display, screen, event, keysym);
if (handled)
return TRUE;
}
XIAllowEvents (display->xdisplay, event->deviceid,
@ -3823,14 +4098,6 @@ handle_set_spew_mark (MetaDisplay *display,
meta_verbose ("-- MARK MARK MARK MARK --\n");
}
void
meta_set_keybindings_disabled (gboolean setting)
{
all_bindings_disabled = setting;
meta_topic (META_DEBUG_KEYBINDINGS,
"Keybindings %s\n", all_bindings_disabled ? "disabled" : "enabled");
}
/**
* meta_keybindings_set_custom_handler:
* @name: The name of the keybinding to set
@ -4516,6 +4783,12 @@ meta_display_init_keys (MetaDisplay *display)
g_hash_table_insert (key_handlers, g_strdup ("overlay-key"), handler);
handler = g_new0 (MetaKeyHandler, 1);
handler->name = g_strdup ("iso-next-group");
handler->flags = META_KEY_BINDING_BUILTIN;
g_hash_table_insert (key_handlers, g_strdup ("iso-next-group"), handler);
handler = g_new0 (MetaKeyHandler, 1);
handler->name = g_strdup ("external-grab");
handler->func = handle_external_grab;

View File

@ -56,6 +56,7 @@
#include <meta/prefs.h>
#include <meta/compositor.h>
#include <glib-unix.h>
#include <glib-object.h>
#include <gdk/gdkx.h>
@ -93,26 +94,6 @@ static GMainLoop *meta_main_loop = NULL;
static void prefs_changed_callback (MetaPreference pref,
gpointer data);
/**
* log_handler:
* @log_domain: the domain the error occurred in (we ignore this)
* @log_level: the log level so that we can filter out less
* important messages
* @message: the message to log
* @user_data: arbitrary data (we ignore this)
*
* Prints log messages. If Mutter was compiled with backtrace support,
* also prints a backtrace (see meta_print_backtrace()).
*/
static void
log_handler (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data)
{
meta_warning ("Log level %d: %s\n", log_level, message);
}
/**
* meta_print_compilation_info:
*
@ -348,23 +329,8 @@ meta_finalize (void)
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;
}
}
static gboolean
on_sigterm (void)
on_sigterm (gpointer user_data)
{
meta_quit (META_EXIT_SUCCESS);
return FALSE;
@ -381,8 +347,7 @@ meta_init (void)
{
struct sigaction act;
sigset_t empty_mask;
GIOChannel *channel;
sigemptyset (&empty_mask);
act.sa_handler = SIG_IGN;
act.sa_mask = empty_mask;
@ -396,20 +361,9 @@ 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));
g_unix_signal_add (SIGTERM, on_sigterm, NULL);
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));
meta_debug_init ();
if (g_getenv ("MUTTER_VERBOSE"))
meta_set_verbose (TRUE);
@ -496,63 +450,25 @@ meta_register_with_session (void)
int
meta_run (void)
{
const gchar *log_domains[] = {
NULL, G_LOG_DOMAIN, "Gtk", "Gdk", "GLib",
"Pango", "GLib-GObject", "GThread"
};
guint i;
/* Load prefs */
meta_prefs_init ();
meta_prefs_add_listener (prefs_changed_callback, NULL);
for (i=0; i<G_N_ELEMENTS(log_domains); i++)
g_log_set_handler (log_domains[i],
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
log_handler, NULL);
meta_ui_set_current_theme (meta_prefs_get_theme ());
if (g_getenv ("MUTTER_G_FATAL_WARNINGS") != NULL)
g_log_set_always_fatal (G_LOG_LEVEL_MASK);
meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE);
/* Try to find some theme that'll work if the theme preference
* doesn't exist. First try Simple (the default theme) then just
* try anything in the themes directory.
/* If the theme preference does not exists, fallback to
* Adwaita (the default theme), or abort if that doesn't
* exists.
*/
if (!meta_ui_have_a_theme ())
meta_ui_set_current_theme ("Simple", FALSE);
meta_ui_set_current_theme ("Adwaita");
if (!meta_ui_have_a_theme ())
{
const char *dir_entry = NULL;
GError *err = NULL;
GDir *themes_dir = NULL;
if (!(themes_dir = g_dir_open (MUTTER_DATADIR"/themes", 0, &err)))
{
meta_fatal (_("Failed to scan themes directory: %s\n"), err->message);
g_error_free (err);
}
else
{
while (((dir_entry = g_dir_read_name (themes_dir)) != NULL) &&
(!meta_ui_have_a_theme ()))
{
meta_ui_set_current_theme (dir_entry, FALSE);
}
g_dir_close (themes_dir);
}
}
if (!meta_ui_have_a_theme ())
meta_fatal (_("Could not find a theme! Be sure %s exists and contains the usual themes.\n"),
MUTTER_DATADIR"/themes");
meta_fatal ("Adwaita theme missing, please install the gnome-themes-standard package");
if (!meta_display_open ())
meta_exit (META_EXIT_ERROR);
g_main_loop_run (meta_main_loop);
meta_finalize ();
@ -598,7 +514,7 @@ prefs_changed_callback (MetaPreference pref,
{
case META_PREF_THEME:
case META_PREF_DRAGGABLE_BORDER_WIDTH:
meta_ui_set_current_theme (meta_prefs_get_theme (), FALSE);
meta_ui_set_current_theme (meta_prefs_get_theme ());
meta_display_retheme_all ();
break;

View File

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

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

File diff suppressed because it is too large Load Diff

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

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

938
src/core/monitor-xrandr.c Normal file
View File

@ -0,0 +1,938 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2001, 2002 Havoc Pennington
* Copyright (C) 2002, 2003 Red Hat Inc.
* Some ICCCM manager selection code derived from fvwm2,
* Copyright (C) 2001 Dominik Vogt, Matthias Clasen, and fvwm2 team
* Copyright (C) 2003 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
* Copyright (C) 2013 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "config.h"
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <clutter/clutter.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrandr.h>
#include <X11/extensions/dpms.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)
/* Look for DPI_FALLBACK in:
* http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c
* for the reasoning */
#define DPI_FALLBACK 96.0
struct _MetaMonitorManagerXrandr
{
MetaMonitorManager parent_instance;
Display *xdisplay;
XRRScreenResources *resources;
int time;
int rr_event_base;
int rr_error_base;
};
struct _MetaMonitorManagerXrandrClass
{
MetaMonitorManagerClass parent_class;
};
G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER);
static enum wl_output_transform
wl_transform_from_xrandr (Rotation rotation)
{
static const enum wl_output_transform y_reflected_map[4] = {
WL_OUTPUT_TRANSFORM_FLIPPED_180,
WL_OUTPUT_TRANSFORM_FLIPPED_90,
WL_OUTPUT_TRANSFORM_FLIPPED,
WL_OUTPUT_TRANSFORM_FLIPPED_270
};
enum wl_output_transform ret;
switch (rotation & 0x7F)
{
default:
case RR_Rotate_0:
ret = WL_OUTPUT_TRANSFORM_NORMAL;
break;
case RR_Rotate_90:
ret = WL_OUTPUT_TRANSFORM_90;
break;
case RR_Rotate_180:
ret = WL_OUTPUT_TRANSFORM_180;
break;
case RR_Rotate_270:
ret = WL_OUTPUT_TRANSFORM_270;
break;
}
if (rotation & RR_Reflect_X)
return ret + 4;
else if (rotation & RR_Reflect_Y)
return y_reflected_map[ret];
else
return ret;
}
#define ALL_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270)
static unsigned int
wl_transform_from_xrandr_all (Rotation rotation)
{
unsigned ret;
/* Handle the common cases first (none or all) */
if (rotation == 0 || rotation == RR_Rotate_0)
return (1 << WL_OUTPUT_TRANSFORM_NORMAL);
/* All rotations and one reflection -> all of them by composition */
if ((rotation & ALL_ROTATIONS) &&
((rotation & RR_Reflect_X) || (rotation & RR_Reflect_Y)))
return ALL_WL_TRANSFORMS;
ret = 1 << WL_OUTPUT_TRANSFORM_NORMAL;
if (rotation & RR_Rotate_90)
ret |= 1 << WL_OUTPUT_TRANSFORM_90;
if (rotation & RR_Rotate_180)
ret |= 1 << WL_OUTPUT_TRANSFORM_180;
if (rotation & RR_Rotate_270)
ret |= 1 << WL_OUTPUT_TRANSFORM_270;
if (rotation & (RR_Rotate_0 | RR_Reflect_X))
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED;
if (rotation & (RR_Rotate_90 | RR_Reflect_X))
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_90;
if (rotation & (RR_Rotate_180 | RR_Reflect_X))
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_180;
if (rotation & (RR_Rotate_270 | RR_Reflect_X))
ret |= 1 << WL_OUTPUT_TRANSFORM_FLIPPED_270;
return ret;
}
static gboolean
output_get_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
MetaDisplay *display = meta_get_display ();
gboolean value;
Atom actual_type;
int actual_format;
unsigned long nitems, bytes_after;
unsigned char *buffer;
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id,
display->atom__MUTTER_PRESENTATION_OUTPUT,
0, G_MAXLONG, False, False, XA_CARDINAL,
&actual_type, &actual_format,
&nitems, &bytes_after, &buffer);
if (actual_type != XA_CARDINAL || actual_format != 32 ||
nitems < 1)
return FALSE;
value = ((int*)buffer)[0];
XFree (buffer);
return value;
}
static int
normalize_backlight (MetaOutput *output,
int hw_value)
{
return round((double)(hw_value - output->backlight_min) /
(output->backlight_max - output->backlight_min) * 100.0);
}
static int
output_get_backlight_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
MetaDisplay *display = meta_get_display ();
gboolean value;
Atom actual_type;
int actual_format;
unsigned long nitems, bytes_after;
unsigned char *buffer;
XRRGetOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id,
display->atom_BACKLIGHT,
0, G_MAXLONG, False, False, XA_INTEGER,
&actual_type, &actual_format,
&nitems, &bytes_after, &buffer);
if (actual_type != XA_INTEGER || actual_format != 32 ||
nitems < 1)
return -1;
value = ((int*)buffer)[0];
XFree (buffer);
return normalize_backlight (output, value);
}
static void
output_get_backlight_limits_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output)
{
MetaDisplay *display = meta_get_display ();
XRRPropertyInfo *info;
meta_error_trap_push (display);
info = XRRQueryOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id,
display->atom_BACKLIGHT);
meta_error_trap_pop (display);
if (info == NULL)
{
meta_verbose ("could not get output property for %s\n", output->name);
return;
}
if (!info->range || info->num_values != 2)
{
meta_verbose ("backlight %s was not range\n", output->name);
goto out;
}
output->backlight_min = info->values[0];
output->backlight_max = info->values[1];
out:
XFree (info);
}
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 guint8 *
get_edid_property (Display *dpy,
RROutput output,
Atom atom,
gsize *len)
{
unsigned char *prop;
int actual_format;
unsigned long nitems, bytes_after;
Atom actual_type;
guint8 *result;
XRRGetOutputProperty (dpy, output, atom,
0, 100, False, False,
AnyPropertyType,
&actual_type, &actual_format,
&nitems, &bytes_after, &prop);
if (actual_type == XA_INTEGER && actual_format == 8)
{
result = g_memdup (prop, nitems);
if (len)
*len = nitems;
}
else
{
result = NULL;
}
XFree (prop);
return result;
}
static GBytes *
read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
XID output_id)
{
Atom edid_atom;
guint8 *result;
gsize len;
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID", FALSE);
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
if (!result)
{
edid_atom = XInternAtom (manager_xrandr->xdisplay, "EDID_DATA", FALSE);
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
}
if (!result)
{
edid_atom = XInternAtom (manager_xrandr->xdisplay, "XFree86_DDC_EDID1_RAWDATA", FALSE);
result = get_edid_property (manager_xrandr->xdisplay, output_id, edid_atom, &len);
}
if (result)
{
if (len > 0 && len % 128 == 0)
return g_bytes_new_take (result, len);
else
g_free (result);
}
return NULL;
}
static void
meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
XRRScreenResources *resources;
RROutput primary_output;
unsigned int i, j, k;
unsigned int n_actual_outputs;
int min_width, min_height;
Screen *screen;
BOOL dpms_capable, dpms_enabled;
CARD16 dpms_state;
if (manager_xrandr->resources)
XRRFreeScreenResources (manager_xrandr->resources);
manager_xrandr->resources = NULL;
meta_error_trap_push (meta_get_display ());
dpms_capable = DPMSCapable (manager_xrandr->xdisplay);
meta_error_trap_pop (meta_get_display ());
if (dpms_capable &&
DPMSInfo (manager_xrandr->xdisplay, &dpms_state, &dpms_enabled) &&
dpms_enabled)
{
switch (dpms_state)
{
case DPMSModeOn:
manager->power_save_mode = META_POWER_SAVE_ON;
case DPMSModeStandby:
manager->power_save_mode = META_POWER_SAVE_STANDBY;
case DPMSModeSuspend:
manager->power_save_mode = META_POWER_SAVE_SUSPEND;
case DPMSModeOff:
manager->power_save_mode = META_POWER_SAVE_OFF;
default:
manager->power_save_mode = META_POWER_SAVE_UNKNOWN;
}
}
else
{
manager->power_save_mode = META_POWER_SAVE_UNKNOWN;
}
XRRGetScreenSizeRange (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
&min_width,
&min_height,
&manager->max_screen_width,
&manager->max_screen_height);
screen = ScreenOfDisplay (manager_xrandr->xdisplay,
DefaultScreen (manager_xrandr->xdisplay));
/* This is updated because we called RRUpdateConfiguration below */
manager->screen_width = WidthOfScreen (screen);
manager->screen_height = HeightOfScreen (screen);
resources = XRRGetScreenResourcesCurrent (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay));
if (!resources)
return;
manager_xrandr->resources = resources;
manager_xrandr->time = resources->configTimestamp;
manager->n_outputs = resources->noutput;
manager->n_crtcs = resources->ncrtc;
manager->n_modes = resources->nmode;
manager->outputs = g_new0 (MetaOutput, manager->n_outputs);
manager->modes = g_new0 (MetaMonitorMode, manager->n_modes);
manager->crtcs = g_new0 (MetaCRTC, manager->n_crtcs);
for (i = 0; i < (unsigned)resources->nmode; i++)
{
XRRModeInfo *xmode = &resources->modes[i];
MetaMonitorMode *mode;
mode = &manager->modes[i];
mode->mode_id = xmode->id;
mode->width = xmode->width;
mode->height = xmode->height;
mode->refresh_rate = (xmode->dotClock /
((float)xmode->hTotal * xmode->vTotal));
}
for (i = 0; i < (unsigned)resources->ncrtc; i++)
{
XRRCrtcInfo *crtc;
MetaCRTC *meta_crtc;
crtc = XRRGetCrtcInfo (manager_xrandr->xdisplay, resources, resources->crtcs[i]);
meta_crtc = &manager->crtcs[i];
meta_crtc->crtc_id = resources->crtcs[i];
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->dirty = FALSE;
meta_crtc->transform = wl_transform_from_xrandr (crtc->rotation);
meta_crtc->all_transforms = wl_transform_from_xrandr_all (crtc->rotations);
for (j = 0; j < (unsigned)resources->nmode; j++)
{
if (resources->modes[j].id == crtc->mode)
{
meta_crtc->current_mode = &manager->modes[j];
break;
}
}
XRRFreeCrtcInfo (crtc);
}
primary_output = XRRGetOutputPrimary (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay));
n_actual_outputs = 0;
for (i = 0; i < (unsigned)resources->noutput; i++)
{
XRROutputInfo *output;
MetaOutput *meta_output;
output = XRRGetOutputInfo (manager_xrandr->xdisplay, resources, resources->outputs[i]);
meta_output = &manager->outputs[n_actual_outputs];
if (output->connection != RR_Disconnected)
{
GBytes *edid;
MonitorInfo *parsed_edid;
meta_output->output_id = resources->outputs[i];
meta_output->name = g_strdup (output->name);
edid = read_output_edid (manager_xrandr, meta_output->output_id);
if (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");
}
meta_output->width_mm = output->mm_width;
meta_output->height_mm = output->mm_height;
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
meta_output->n_modes = output->nmode;
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
for (j = 0; j < meta_output->n_modes; j++)
{
for (k = 0; k < manager->n_modes; k++)
{
if (output->modes[j] == (XID)manager->modes[k].mode_id)
{
meta_output->modes[j] = &manager->modes[k];
break;
}
}
}
meta_output->preferred_mode = meta_output->modes[0];
meta_output->n_possible_crtcs = output->ncrtc;
meta_output->possible_crtcs = g_new0 (MetaCRTC *, meta_output->n_possible_crtcs);
for (j = 0; j < (unsigned)output->ncrtc; j++)
{
for (k = 0; k < manager->n_crtcs; k++)
{
if ((XID)manager->crtcs[k].crtc_id == output->crtcs[j])
{
meta_output->possible_crtcs[j] = &manager->crtcs[k];
break;
}
}
}
meta_output->crtc = NULL;
for (j = 0; j < manager->n_crtcs; j++)
{
if ((XID)manager->crtcs[j].crtc_id == output->crtc)
{
meta_output->crtc = &manager->crtcs[j];
break;
}
}
meta_output->n_possible_clones = output->nclone;
meta_output->possible_clones = g_new0 (MetaOutput *, meta_output->n_possible_clones);
/* We can build the list of clones now, because we don't have the list of outputs
yet, so temporarily set the pointers to the bare XIDs, and then we'll fix them
in a second pass
*/
for (j = 0; j < (unsigned)output->nclone; j++)
{
meta_output->possible_clones = GINT_TO_POINTER (output->clones[j]);
}
meta_output->is_primary = ((XID)meta_output->output_id == primary_output);
meta_output->is_presentation = output_get_presentation_xrandr (manager_xrandr, meta_output);
output_get_backlight_limits_xrandr (manager_xrandr, meta_output);
if (!(meta_output->backlight_min == 0 && meta_output->backlight_max == 0))
meta_output->backlight = output_get_backlight_xrandr (manager_xrandr, meta_output);
else
meta_output->backlight = -1;
n_actual_outputs++;
}
XRRFreeOutputInfo (output);
}
manager->n_outputs = n_actual_outputs;
/* Sort the outputs for easier handling in MetaMonitorConfig */
qsort (manager->outputs, manager->n_outputs, sizeof (MetaOutput), compare_outputs);
/* Now fix the clones */
for (i = 0; i < manager->n_outputs; i++)
{
MetaOutput *meta_output;
meta_output = &manager->outputs[i];
for (j = 0; j < meta_output->n_possible_clones; j++)
{
RROutput clone = GPOINTER_TO_INT (meta_output->possible_clones[j]);
for (k = 0; k < manager->n_outputs; k++)
{
if (clone == (XID)manager->outputs[k].output_id)
{
meta_output->possible_clones[j] = &manager->outputs[k];
break;
}
}
}
}
}
static GBytes *
meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager,
MetaOutput *output)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
return read_output_edid (manager_xrandr, output->output_id);
}
static void
meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager,
MetaPowerSave mode)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
CARD16 state;
switch (mode) {
case META_POWER_SAVE_ON:
state = DPMSModeOn;
break;
case META_POWER_SAVE_STANDBY:
state = DPMSModeStandby;
break;
case META_POWER_SAVE_SUSPEND:
state = DPMSModeSuspend;
break;
case META_POWER_SAVE_OFF:
state = DPMSModeOff;
break;
default:
return;
}
meta_error_trap_push (meta_get_display ());
DPMSForceLevel (manager_xrandr->xdisplay, state);
DPMSSetTimeouts (manager_xrandr->xdisplay, 0, 0, 0);
meta_error_trap_pop (meta_get_display ());
}
static Rotation
wl_transform_to_xrandr (enum wl_output_transform transform)
{
switch (transform)
{
case WL_OUTPUT_TRANSFORM_NORMAL:
return RR_Rotate_0;
case WL_OUTPUT_TRANSFORM_90:
return RR_Rotate_90;
case WL_OUTPUT_TRANSFORM_180:
return RR_Rotate_180;
case WL_OUTPUT_TRANSFORM_270:
return RR_Rotate_270;
case WL_OUTPUT_TRANSFORM_FLIPPED:
return RR_Reflect_X | RR_Rotate_0;
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
return RR_Reflect_X | RR_Rotate_90;
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
return RR_Reflect_X | RR_Rotate_180;
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
return RR_Reflect_X | RR_Rotate_270;
}
g_assert_not_reached ();
}
static void
output_set_presentation_xrandr (MetaMonitorManagerXrandr *manager_xrandr,
MetaOutput *output,
gboolean presentation)
{
MetaDisplay *display = meta_get_display ();
int value = presentation;
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id,
display->atom__MUTTER_PRESENTATION_OUTPUT,
XA_CARDINAL, 32, PropModeReplace,
(unsigned char*) &value, 1);
}
static void
meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
MetaCRTCInfo **crtcs,
unsigned int n_crtcs,
MetaOutputInfo **outputs,
unsigned int n_outputs)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
unsigned i;
int width, height, width_mm, height_mm;
meta_display_grab (meta_get_display ());
/* First compute the new size of the screen (framebuffer) */
width = 0; height = 0;
for (i = 0; i < n_crtcs; i++)
{
MetaCRTCInfo *crtc_info = crtcs[i];
MetaCRTC *crtc = crtc_info->crtc;
crtc->dirty = TRUE;
if (crtc_info->mode == NULL)
continue;
if (meta_monitor_transform_is_rotated (crtc_info->transform))
{
width = MAX (width, crtc_info->x + crtc_info->mode->height);
height = MAX (height, crtc_info->y + crtc_info->mode->width);
}
else
{
width = MAX (width, crtc_info->x + crtc_info->mode->width);
height = MAX (height, crtc_info->y + crtc_info->mode->height);
}
}
/* Second disable all newly disabled CRTCs, or CRTCs that in the previous
configuration would be outside the new framebuffer (otherwise X complains
loudly when resizing)
CRTC will be enabled again after resizing the FB
*/
for (i = 0; i < n_crtcs; i++)
{
MetaCRTCInfo *crtc_info = crtcs[i];
MetaCRTC *crtc = crtc_info->crtc;
if (crtc_info->mode == NULL ||
crtc->rect.x + crtc->rect.width > width ||
crtc->rect.y + crtc->rect.height > height)
{
XRRSetCrtcConfig (manager_xrandr->xdisplay,
manager_xrandr->resources,
(XID)crtc->crtc_id,
manager_xrandr->time,
0, 0,
None,
RR_Rotate_0,
NULL, 0);
}
}
/* Disable CRTCs not mentioned in the list */
for (i = 0; i < manager->n_crtcs; i++)
{
MetaCRTC *crtc = &manager->crtcs[i];
if (crtc->dirty)
{
crtc->dirty = FALSE;
continue;
}
if (crtc->current_mode == NULL)
continue;
XRRSetCrtcConfig (manager_xrandr->xdisplay,
manager_xrandr->resources,
(XID)crtc->crtc_id,
manager_xrandr->time,
0, 0,
None,
RR_Rotate_0,
NULL, 0);
}
g_assert (width > 0 && height > 0);
/* The 'physical size' of an X screen is meaningless if that screen
* can consist of many monitors. So just pick a size that make the
* dpi 96.
*
* Firefox and Evince apparently believe what X tells them.
*/
width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5;
height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5;
meta_error_trap_push (meta_get_display ());
XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
width, height, width_mm, height_mm);
meta_error_trap_pop (meta_get_display ());
for (i = 0; i < n_crtcs; i++)
{
MetaCRTCInfo *crtc_info = crtcs[i];
MetaCRTC *crtc = crtc_info->crtc;
if (crtc_info->mode != NULL)
{
MetaMonitorMode *mode;
XID *outputs;
int j, n_outputs;
Status ok;
mode = crtc_info->mode;
n_outputs = crtc_info->outputs->len;
outputs = g_new (XID, n_outputs);
for (j = 0; j < n_outputs; j++)
outputs[j] = ((MetaOutput**)crtc_info->outputs->pdata)[j]->output_id;
meta_error_trap_push (meta_get_display ());
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
manager_xrandr->resources,
(XID)crtc->crtc_id,
manager_xrandr->time,
crtc_info->x, crtc_info->y,
(XID)mode->mode_id,
wl_transform_to_xrandr (crtc_info->transform),
outputs, n_outputs);
meta_error_trap_pop (meta_get_display ());
if (ok != Success)
meta_warning ("Configuring CRTC %d with mode %d (%d x %d @ %f) at position %d, %d and transfrom %u failed\n",
(unsigned)(crtc->crtc_id), (unsigned)(mode->mode_id),
mode->width, mode->height, (float)mode->refresh_rate,
crtc_info->x, crtc_info->y, crtc_info->transform);
g_free (outputs);
}
}
for (i = 0; i < n_outputs; i++)
{
MetaOutputInfo *output_info = outputs[i];
if (output_info->is_primary)
{
XRRSetOutputPrimary (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay),
(XID)output_info->output->output_id);
}
output_set_presentation_xrandr (manager_xrandr,
output_info->output,
output_info->is_presentation);
}
meta_display_ungrab (meta_get_display ());
}
static void
meta_monitor_manager_xrandr_change_backlight (MetaMonitorManager *manager,
MetaOutput *output,
gint value)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
MetaDisplay *display = meta_get_display ();
int hw_value;
hw_value = round((double)value / 100.0 * output->backlight_max + output->backlight_min);
meta_error_trap_push (display);
XRRChangeOutputProperty (manager_xrandr->xdisplay,
(XID)output->output_id,
display->atom_BACKLIGHT,
XA_INTEGER, 32, PropModeReplace,
(unsigned char *) &hw_value, 1);
meta_error_trap_pop (display);
/* We're not selecting for property notifies, so update the value immediately */
output->backlight = normalize_backlight (output, hw_value);
}
static void
meta_monitor_manager_xrandr_get_crtc_gamma (MetaMonitorManager *manager,
MetaCRTC *crtc,
gsize *size,
unsigned short **red,
unsigned short **green,
unsigned short **blue)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
XRRCrtcGamma *gamma;
gamma = XRRGetCrtcGamma (manager_xrandr->xdisplay, (XID)crtc->crtc_id);
*size = gamma->size;
*red = g_memdup (gamma->red, sizeof (unsigned short) * gamma->size);
*green = g_memdup (gamma->green, sizeof (unsigned short) * gamma->size);
*blue = g_memdup (gamma->blue, sizeof (unsigned short) * gamma->size);
XRRFreeGamma (gamma);
}
static void
meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
MetaCRTC *crtc,
gsize size,
unsigned short *red,
unsigned short *green,
unsigned short *blue)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
XRRCrtcGamma gamma;
gamma.size = size;
gamma.red = red;
gamma.green = green;
gamma.blue = blue;
XRRSetCrtcGamma (manager_xrandr->xdisplay, (XID)crtc->crtc_id, &gamma);
}
static gboolean
meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
XEvent *event)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
return FALSE;
XRRUpdateConfiguration (event);
return TRUE;
}
static void
meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr)
{
MetaDisplay *display = meta_get_display ();
manager_xrandr->xdisplay = display->xdisplay;
if (!XRRQueryExtension (manager_xrandr->xdisplay,
&manager_xrandr->rr_event_base,
&manager_xrandr->rr_error_base))
{
return;
}
else
{
/* We only use ScreenChangeNotify, but GDK uses the others,
and we don't want to step on its toes */
XRRSelectInput (manager_xrandr->xdisplay,
DefaultRootWindow (manager_xrandr->xdisplay),
RRScreenChangeNotifyMask
| RRCrtcChangeNotifyMask
| RROutputPropertyNotifyMask);
}
}
static void
meta_monitor_manager_xrandr_finalize (GObject *object)
{
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object);
if (manager_xrandr->resources)
XRRFreeScreenResources (manager_xrandr->resources);
manager_xrandr->resources = NULL;
G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object);
}
static void
meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass)
{
MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_monitor_manager_xrandr_finalize;
manager_class->read_current = meta_monitor_manager_xrandr_read_current;
manager_class->read_edid = meta_monitor_manager_xrandr_read_edid;
manager_class->apply_configuration = meta_monitor_manager_xrandr_apply_configuration;
manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode;
manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight;
manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma;
manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma;
manager_class->handle_xevent = meta_monitor_manager_xrandr_handle_xevent;
}

1553
src/core/monitor.c Normal file

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -38,17 +38,7 @@
#include <X11/Xutil.h>
#include "stack-tracker.h"
#include "ui.h"
typedef struct _MetaMonitorInfo MetaMonitorInfo;
struct _MetaMonitorInfo
{
int number;
MetaRectangle rect;
gboolean is_primary;
gboolean in_fullscreen;
XID output; /* The primary or first output for this crtc, None if no xrandr */
};
#include "monitor-private.h"
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
gpointer user_data);
@ -100,10 +90,11 @@ struct _MetaScreen
Window wm_sn_selection_window;
Atom wm_sn_atom;
guint32 wm_sn_timestamp;
MetaMonitorInfo *monitor_infos;
int primary_monitor_index;
int n_monitor_infos;
int primary_monitor_index;
gboolean has_xinerama_indices;
/* Cache the current monitor */
int last_monitor_index;
@ -187,6 +178,9 @@ MetaWindow* meta_screen_get_mouse_window (MetaScreen *scre
MetaWindow *not_this_one);
const MetaMonitorInfo* meta_screen_get_current_monitor_info (MetaScreen *screen);
const MetaMonitorInfo* meta_screen_get_current_monitor_info_for_pos (MetaScreen *screen,
int x,
int y);
const MetaMonitorInfo* meta_screen_get_monitor_for_rect (MetaScreen *screen,
MetaRectangle *rect);
const MetaMonitorInfo* meta_screen_get_monitor_for_window (MetaScreen *screen,
@ -228,10 +222,6 @@ void meta_screen_calc_workspace_layout (MetaScreen *screen,
MetaWorkspaceLayout *layout);
void meta_screen_free_workspace_layout (MetaWorkspaceLayout *layout);
void meta_screen_resize (MetaScreen *screen,
int width,
int height);
void meta_screen_minimize_all_on_active_workspace_except (MetaScreen *screen,
MetaWindow *keep);
@ -254,4 +244,9 @@ void meta_screen_workspace_switched (MetaScreen *screen,
void meta_screen_set_active_workspace_hint (MetaScreen *screen);
int meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
int index);
int meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
int index);
#endif

View File

@ -48,10 +48,6 @@
#include <X11/extensions/Xinerama.h>
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
#endif
#include <X11/Xatom.h>
#include <locale.h>
#include <string.h>
@ -76,6 +72,9 @@ static void meta_screen_sn_event (SnMonitorEvent *event,
void *user_data);
#endif
static void on_monitors_changed (MetaMonitorManager *manager,
MetaScreen *screen);
enum
{
PROP_N_WORKSPACES = 1,
@ -350,250 +349,93 @@ set_wm_icon_size_hint (MetaScreen *screen)
#undef N_VALS
}
/* The list of monitors reported by the windowing system might include
* mirrored monitors with identical bounds. Since mirrored monitors
* shouldn't be treated as separate monitors for most purposes, we
* filter them out here. (We ignore the possibility of partially
* overlapping monitors because they are rare and it's hard to come
* up with any sensible interpretation.)
*/
static void
filter_mirrored_monitors (MetaScreen *screen)
meta_screen_ensure_xinerama_indices (MetaScreen *screen)
{
int i, j;
XineramaScreenInfo *infos;
int n_infos, i, j;
/* Currently always true and simplifies things */
g_assert (screen->primary_monitor_index == 0);
if (screen->has_xinerama_indices)
return;
for (i = 1; i < screen->n_monitor_infos; i++)
screen->has_xinerama_indices = TRUE;
if (!XineramaIsActive (screen->display->xdisplay))
return;
infos = XineramaQueryScreens (screen->display->xdisplay, &n_infos);
if (n_infos <= 0 || infos == NULL)
{
/* In case we've filtered previous monitors */
screen->monitor_infos[i].number = i;
meta_XFree (infos);
return;
}
for (j = 0; j < i; j++)
for (i = 0; i < screen->n_monitor_infos; ++i)
{
for (j = 0; j < n_infos; ++j)
{
if (meta_rectangle_equal (&screen->monitor_infos[i].rect,
&screen->monitor_infos[j].rect))
{
memmove (&screen->monitor_infos[i],
&screen->monitor_infos[i + 1],
(screen->n_monitor_infos - i - 1) * sizeof (MetaMonitorInfo));
screen->n_monitor_infos--;
i--;
continue;
}
if (screen->monitor_infos[i].rect.x == infos[j].x_org &&
screen->monitor_infos[i].rect.y == infos[j].y_org &&
screen->monitor_infos[i].rect.width == infos[j].width &&
screen->monitor_infos[i].rect.height == infos[j].height)
screen->monitor_infos[i].xinerama_index = j;
}
}
meta_XFree (infos);
}
#ifdef HAVE_RANDR
static MetaMonitorInfo *
find_monitor_with_rect (MetaScreen *screen, int x, int y, int w, int h)
int
meta_screen_monitor_index_to_xinerama_index (MetaScreen *screen,
int index)
{
meta_screen_ensure_xinerama_indices (screen);
return screen->monitor_infos[index].xinerama_index;
}
int
meta_screen_xinerama_index_to_monitor_index (MetaScreen *screen,
int index)
{
MetaMonitorInfo *info;
int i;
meta_screen_ensure_xinerama_indices (screen);
for (i = 0; i < screen->n_monitor_infos; i++)
{
info = &screen->monitor_infos[i];
if (x == info->rect.x &&
y == info->rect.y &&
w == info->rect.width &&
h == info->rect.height)
return info;
}
return NULL;
if (screen->monitor_infos[i].xinerama_index == index)
return i;
return -1;
}
/* In the case of multiple outputs of a single crtc (mirroring), we consider one of the
* outputs the "main". This is the one we consider "owning" the windows, so if
* the mirroring is changed to a dual monitor setup then the windows are moved to the
* crtc that now has that main output. If one of the outputs is the primary that is
* always the main, otherwise we just use the first.
*/
static XID
find_main_output_for_crtc (MetaScreen *screen, XRRScreenResources *resources, XRRCrtcInfo *crtc)
{
XRROutputInfo *output;
RROutput primary_output;
int i;
XID res;
primary_output = XRRGetOutputPrimary (screen->display->xdisplay, screen->xroot);
res = None;
for (i = 0; i < crtc->noutput; i++)
{
output = XRRGetOutputInfo (screen->display->xdisplay, resources, crtc->outputs[i]);
if (output->connection != RR_Disconnected &&
(res == None || crtc->outputs[i] == primary_output))
res = crtc->outputs[i];
XRRFreeOutputInfo (output);
}
return res;
}
#endif
static void
reload_monitor_infos (MetaScreen *screen)
{
MetaDisplay *display;
GList *tmp;
MetaMonitorManager *manager;
{
GList *tmp;
tmp = screen->workspaces;
while (tmp != NULL)
{
MetaWorkspace *space = tmp->data;
tmp = screen->workspaces;
while (tmp != NULL)
{
MetaWorkspace *space = tmp->data;
meta_workspace_invalidate_work_area (space);
tmp = tmp->next;
}
meta_workspace_invalidate_work_area (space);
tmp = tmp->next;
}
}
/* Any previous screen->monitor_infos or screen->outputs is freed by the caller */
display = screen->display;
/* Any previous screen->monitor_infos is freed by the caller */
screen->monitor_infos = NULL;
screen->n_monitor_infos = 0;
screen->last_monitor_index = 0;
/* Xinerama doesn't have a concept of primary monitor, however XRandR
* does. However, the XRandR xinerama compat code always sorts the
* primary output first, so we rely on that here. We could use the
* native XRandR calls instead of xinerama, but that would be
* slightly problematic for _NET_WM_FULLSCREEN_MONITORS support, as
* that is defined in terms of xinerama monitor indexes.
* So, since we don't need anything in xrandr except the primary
* we can keep using xinerama and use the first monitor as the
* primary.
*/
screen->primary_monitor_index = 0;
screen->has_xinerama_indices = FALSE;
screen->display->monitor_cache_invalidated = TRUE;
if (g_getenv ("MUTTER_DEBUG_XINERAMA"))
{
meta_topic (META_DEBUG_XINERAMA,
"Pretending a single monitor has two Xinerama screens\n");
manager = meta_monitor_manager_get ();
screen->monitor_infos = g_new0 (MetaMonitorInfo, 2);
screen->n_monitor_infos = 2;
screen->monitor_infos[0].number = 0;
screen->monitor_infos[0].rect = screen->rect;
screen->monitor_infos[0].rect.width = screen->rect.width / 2;
screen->monitor_infos[0].in_fullscreen = -1;
screen->monitor_infos[1].number = 1;
screen->monitor_infos[1].rect = screen->rect;
screen->monitor_infos[1].rect.x = screen->rect.width / 2;
screen->monitor_infos[1].rect.width = screen->rect.width / 2;
screen->monitor_infos[0].in_fullscreen = -1;
}
if (screen->n_monitor_infos == 0 &&
XineramaIsActive (display->xdisplay))
{
XineramaScreenInfo *infos;
int n_infos;
int i;
n_infos = 0;
infos = XineramaQueryScreens (display->xdisplay, &n_infos);
meta_topic (META_DEBUG_XINERAMA,
"Found %d Xinerama screens on display %s\n",
n_infos, display->name);
if (n_infos > 0)
{
screen->monitor_infos = g_new0 (MetaMonitorInfo, n_infos);
screen->n_monitor_infos = n_infos;
i = 0;
while (i < n_infos)
{
screen->monitor_infos[i].number = infos[i].screen_number;
screen->monitor_infos[i].rect.x = infos[i].x_org;
screen->monitor_infos[i].rect.y = infos[i].y_org;
screen->monitor_infos[i].rect.width = infos[i].width;
screen->monitor_infos[i].rect.height = infos[i].height;
screen->monitor_infos[i].in_fullscreen = -1;
meta_topic (META_DEBUG_XINERAMA,
"Monitor %d is %d,%d %d x %d\n",
screen->monitor_infos[i].number,
screen->monitor_infos[i].rect.x,
screen->monitor_infos[i].rect.y,
screen->monitor_infos[i].rect.width,
screen->monitor_infos[i].rect.height);
++i;
}
}
meta_XFree (infos);
#ifdef HAVE_RANDR
{
XRRScreenResources *resources;
resources = XRRGetScreenResourcesCurrent (display->xdisplay, screen->xroot);
if (resources)
{
for (i = 0; i < resources->ncrtc; i++)
{
XRRCrtcInfo *crtc;
MetaMonitorInfo *info;
crtc = XRRGetCrtcInfo (display->xdisplay, resources, resources->crtcs[i]);
info = find_monitor_with_rect (screen, crtc->x, crtc->y, (int)crtc->width, (int)crtc->height);
if (info)
info->output = find_main_output_for_crtc (screen, resources, crtc);
XRRFreeCrtcInfo (crtc);
}
XRRFreeScreenResources (resources);
}
}
#endif
}
else if (screen->n_monitor_infos > 0)
{
meta_topic (META_DEBUG_XINERAMA,
"No Xinerama extension or Xinerama inactive on display %s\n",
display->name);
}
/* If no Xinerama, fill in the single screen info so
* we can use the field unconditionally
*/
if (screen->n_monitor_infos == 0)
{
meta_topic (META_DEBUG_XINERAMA,
"No Xinerama screens, using default screen info\n");
screen->monitor_infos = g_new0 (MetaMonitorInfo, 1);
screen->n_monitor_infos = 1;
screen->monitor_infos[0].number = 0;
screen->monitor_infos[0].rect = screen->rect;
screen->monitor_infos[0].in_fullscreen = -1;
}
filter_mirrored_monitors (screen);
screen->monitor_infos[screen->primary_monitor_index].is_primary = TRUE;
g_assert (screen->n_monitor_infos > 0);
g_assert (screen->monitor_infos != NULL);
screen->monitor_infos = meta_monitor_manager_get_monitor_infos (manager,
(unsigned*)&screen->n_monitor_infos);
screen->primary_monitor_index = meta_monitor_manager_get_primary_index (manager);
}
/* The guard window allows us to leave minimized windows mapped so
@ -668,6 +510,7 @@ meta_screen_new (MetaDisplay *display,
char buf[128];
guint32 manager_timestamp;
gulong current_workspace;
MetaMonitorManager *manager;
replace_current_wm = meta_get_replace_current_wm ();
@ -826,8 +669,17 @@ meta_screen_new (MetaDisplay *display,
screen->xscreen = ScreenOfDisplay (xdisplay, number);
screen->xroot = xroot;
screen->rect.x = screen->rect.y = 0;
screen->rect.width = WidthOfScreen (screen->xscreen);
screen->rect.height = HeightOfScreen (screen->xscreen);
meta_monitor_manager_initialize ();
manager = meta_monitor_manager_get ();
g_signal_connect (manager, "monitors-changed",
G_CALLBACK (on_monitors_changed), screen);
meta_monitor_manager_get_screen_size (manager,
&screen->rect.width,
&screen->rect.height);
screen->current_cursor = -1; /* invalid/unset */
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
@ -852,10 +704,6 @@ meta_screen_new (MetaDisplay *display,
screen->compositor_data = NULL;
screen->guard_window = None;
screen->monitor_infos = NULL;
screen->n_monitor_infos = 0;
screen->last_monitor_index = 0;
reload_monitor_infos (screen);
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
@ -941,7 +789,7 @@ meta_screen_new (MetaDisplay *display,
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
screen->number, screen->screen_name, screen->xroot);
return screen;
}
@ -2216,6 +2064,65 @@ meta_screen_get_current_monitor_info (MetaScreen *screen)
return &screen->monitor_infos[monitor_index];
}
const MetaMonitorInfo*
meta_screen_get_current_monitor_info_for_pos (MetaScreen *screen,
int x,
int y)
{
int monitor_index;
monitor_index = meta_screen_get_current_monitor_for_pos (screen, x, y);
return &screen->monitor_infos[monitor_index];
}
/**
* meta_screen_get_current_monitor_for_pos:
* @screen: a #MetaScreen
* @x: The x coordinate
* @y: The y coordinate
*
* Gets the index of the monitor that contains the passed coordinates.
*
* Return value: a monitor index
*/
int
meta_screen_get_current_monitor_for_pos (MetaScreen *screen,
int x,
int y)
{
if (screen->n_monitor_infos == 1)
return 0;
else if (screen->display->monitor_cache_invalidated)
{
int i;
MetaRectangle pointer_position;
pointer_position.x = x;
pointer_position.y = y;
pointer_position.width = pointer_position.height = 1;
screen->display->monitor_cache_invalidated = FALSE;
screen->last_monitor_index = 0;
for (i = 0; i < screen->n_monitor_infos; i++)
{
if (meta_rectangle_contains_rect (&screen->monitor_infos[i].rect,
&pointer_position))
{
screen->last_monitor_index = i;
break;
}
}
meta_topic (META_DEBUG_XINERAMA,
"Rechecked current monitor, now %d\n",
screen->last_monitor_index);
}
return screen->last_monitor_index;
}
/**
* meta_screen_get_current_monitor:
* @screen: a #MetaScreen
@ -2241,11 +2148,7 @@ meta_screen_get_current_monitor (MetaScreen *screen)
XIButtonState buttons;
XIModifierState mods;
XIGroupState group;
int i;
MetaRectangle pointer_position;
screen->display->monitor_cache_invalidated = FALSE;
XIQueryPointer (screen->display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
screen->xroot,
@ -2260,24 +2163,7 @@ meta_screen_get_current_monitor (MetaScreen *screen)
&group);
free (buttons.mask);
pointer_position.x = root_x_return;
pointer_position.y = root_y_return;
pointer_position.width = pointer_position.height = 1;
screen->last_monitor_index = 0;
for (i = 0; i < screen->n_monitor_infos; i++)
{
if (meta_rectangle_contains_rect (&screen->monitor_infos[i].rect,
&pointer_position))
{
screen->last_monitor_index = i;
break;
}
}
meta_topic (META_DEBUG_XINERAMA,
"Rechecked current monitor, now %d\n",
screen->last_monitor_index);
meta_screen_get_current_monitor_for_pos (screen, root_x_return, root_y_return);
}
return screen->last_monitor_index;
@ -2959,19 +2845,15 @@ meta_screen_resize_func (MetaScreen *screen,
meta_window_recalc_features (window);
}
void
meta_screen_resize (MetaScreen *screen,
int width,
int height)
static void
on_monitors_changed (MetaMonitorManager *manager,
MetaScreen *screen)
{
GSList *windows, *tmp;
MetaMonitorInfo *old_monitor_infos;
GSList *tmp, *windows;
screen->rect.width = width;
screen->rect.height = height;
/* Save the old monitor infos, so they stay valid during the update */
old_monitor_infos = screen->monitor_infos;
meta_monitor_manager_get_screen_size (manager,
&screen->rect.width,
&screen->rect.height);
reload_monitor_infos (screen);
set_desktop_geometry_hint (screen);
@ -2983,8 +2865,8 @@ meta_screen_resize (MetaScreen *screen,
changes.x = 0;
changes.y = 0;
changes.width = width;
changes.height = height;
changes.width = screen->rect.width;
changes.height = screen->rect.height;
XConfigureWindow(screen->display->xdisplay,
screen->guard_window,
@ -2994,14 +2876,15 @@ meta_screen_resize (MetaScreen *screen,
if (screen->display->compositor)
meta_compositor_sync_screen_size (screen->display->compositor,
screen, width, height);
screen,
screen->rect.width, screen->rect.height);
/* Queue a resize on all the windows */
meta_screen_foreach_window (screen, meta_screen_resize_func, 0);
/* Fix up monitor for all windows on this screen */
windows = meta_display_list_windows (screen->display,
META_LIST_DEFAULT);
META_LIST_INCLUDE_OVERRIDE_REDIRECT);
for (tmp = windows; tmp != NULL; tmp = tmp->next)
{
MetaWindow *window = tmp->data;
@ -3010,7 +2893,6 @@ meta_screen_resize (MetaScreen *screen,
meta_window_update_for_monitors_changed (window);
}
g_free (old_monitor_infos);
g_slist_free (windows);
meta_screen_queue_check_fullscreen (screen);

View File

@ -278,7 +278,7 @@ static gboolean
is_focused_foreach (MetaWindow *window,
void *data)
{
if (window == window->display->expected_focus_window)
if (window->has_focus)
{
*((gboolean*) data) = TRUE;
return FALSE;
@ -335,11 +335,11 @@ get_standalone_layer (MetaWindow *window)
layer = META_LAYER_BOTTOM;
else if (window->fullscreen &&
(focused_transient ||
window == window->display->expected_focus_window ||
window->display->expected_focus_window == NULL ||
(window->display->expected_focus_window != NULL &&
window == window->display->focus_window ||
window->display->focus_window == NULL ||
(window->display->focus_window != NULL &&
windows_on_different_monitor (window,
window->display->expected_focus_window))))
window->display->focus_window))))
layer = META_LAYER_FULLSCREEN;
else if (window->wm_state_above && !META_WINDOW_MAXIMIZED (window))
layer = META_LAYER_TOP;

View File

@ -332,6 +332,8 @@ topic_name (MetaDebugTopic topic)
return "COMPOSITOR";
case META_DEBUG_EDGE_RESISTANCE:
return "EDGE_RESISTANCE";
case META_DEBUG_DBUS:
return "DBUS";
case META_DEBUG_VERBOSE:
return "VERBOSE";
}
@ -389,91 +391,100 @@ meta_topic_real (MetaDebugTopic topic,
}
#endif /* WITH_VERBOSE_MODE */
#ifdef WITH_VERBOSE_MODE
static void
logfile_log_handler (const gchar *log_domain,
GLogLevelFlags log_level,
const gchar *message,
gpointer user_data)
{
switch (log_level & G_LOG_LEVEL_MASK) {
case G_LOG_LEVEL_ERROR:
utf8_fputs ("ERROR: ", logfile);
break;
case G_LOG_LEVEL_CRITICAL:
utf8_fputs ("CRITICAL: ", logfile);
break;
case G_LOG_LEVEL_WARNING:
utf8_fputs ("WARNING: ", logfile);
break;
default:
/* the other levels don't go through
g_log, they go directly to the log file */
;
}
utf8_fputs (message, logfile);
}
void
meta_debug_init (void)
{
ensure_logfile ();
if (logfile)
g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK,
logfile_log_handler, NULL);
}
#else
void
meta_debug_init (void)
{
}
#endif
void
meta_bug (const char *format, ...)
{
char *stripped;
va_list args;
gchar *str;
FILE *out;
g_return_if_fail (format != NULL);
stripped = g_strstrip (g_strdup (format));
va_start (args, format);
str = g_strdup_vprintf (format, args);
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, stripped, args);
va_end (args);
#ifdef WITH_VERBOSE_MODE
out = logfile ? logfile : stderr;
#else
out = stderr;
#endif
if (no_prefix == 0)
utf8_fputs (_("Bug in window manager: "), out);
utf8_fputs (str, out);
fflush (out);
g_free (str);
/* stop us in a debugger */
abort ();
g_free (stripped);
}
void
meta_warning (const char *format, ...)
{
char *stripped;
va_list args;
gchar *str;
FILE *out;
g_return_if_fail (format != NULL);
stripped = g_strstrip (g_strdup (format));
va_start (args, format);
str = g_strdup_vprintf (format, args);
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, stripped, args);
va_end (args);
#ifdef WITH_VERBOSE_MODE
out = logfile ? logfile : stderr;
#else
out = stderr;
#endif
if (no_prefix == 0)
utf8_fputs (_("Window manager warning: "), out);
utf8_fputs (str, out);
fflush (out);
g_free (str);
g_free (stripped);
}
void
meta_fatal (const char *format, ...)
{
char *stripped;
va_list args;
gchar *str;
FILE *out;
g_return_if_fail (format != NULL);
stripped = g_strstrip (g_strdup (format));
va_start (args, format);
str = g_strdup_vprintf (format, args);
g_logv (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, stripped, args);
va_end (args);
#ifdef WITH_VERBOSE_MODE
out = logfile ? logfile : stderr;
#else
out = stderr;
#endif
if (no_prefix == 0)
utf8_fputs (_("Window manager error: "), out);
utf8_fputs (str, out);
fflush (out);
g_free (str);
g_free (stripped);
meta_exit (META_EXIT_ERROR);
}
@ -495,7 +506,6 @@ meta_pop_no_msg_prefix (void)
void
meta_exit (MetaExitCode code)
{
exit (code);
}
@ -637,8 +647,13 @@ meta_show_dialog (const char *type,
append_argument (args, "zenity");
append_argument (args, type);
append_argument (args, "--display");
append_argument (args, display);
if (display)
{
append_argument (args, "--display");
append_argument (args, display);
}
append_argument (args, "--class");
append_argument (args, "mutter-dialog");
append_argument (args, "--title");

View File

@ -165,7 +165,7 @@ struct _MetaWindow
* been overridden (via a client message), the window will cover the union of
* these monitors. If not, this is the single monitor which the window's
* origin is on. */
long fullscreen_monitors[4];
gint fullscreen_monitors[4];
/* Whether we're trying to constrain the window to be fully onscreen */
guint require_fully_onscreen : 1;
@ -277,7 +277,7 @@ struct _MetaWindow
/* EWHH demands attention flag */
guint wm_state_demands_attention : 1;
/* this flag tracks receipt of focus_in focus_out */
/* TRUE iff window == window->display->focus_window */
guint has_focus : 1;
/* Have we placed this window? */
@ -394,6 +394,9 @@ struct _MetaWindow
*/
MetaRectangle rect;
gboolean has_custom_frame_extents;
GtkBorder custom_frame_extents;
/* The geometry to restore when we unmaximize. The position is in
* root window coords, even if there's a frame, which contrasts with
* window->rect above. Note that this gives the position and size
@ -590,9 +593,8 @@ gboolean meta_window_property_notify (MetaWindow *window,
XEvent *event);
gboolean meta_window_client_message (MetaWindow *window,
XEvent *event);
gboolean meta_window_notify_focus (MetaWindow *window,
XIEnterEvent *event);
void meta_window_lost_focus (MetaWindow *window);
void meta_window_set_focused_internal (MetaWindow *window,
gboolean focused);
void meta_window_set_current_workspace_hint (MetaWindow *window);

View File

@ -289,6 +289,35 @@ reload_icon_geometry (MetaWindow *window,
}
}
static void
reload_gtk_frame_extents (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
if (value->type != META_PROP_VALUE_INVALID)
{
if (value->v.cardinal_list.n_cardinals != 4)
{
meta_verbose ("_GTK_FRAME_EXTENTS on %s has %d values instead of 4\n",
window->desc, value->v.cardinal_list.n_cardinals);
}
else
{
GtkBorder *extents = &window->custom_frame_extents;
window->has_custom_frame_extents = TRUE;
extents->left = (int)value->v.cardinal_list.cardinals[0];
extents->right = (int)value->v.cardinal_list.cardinals[1];
extents->top = (int)value->v.cardinal_list.cardinals[2];
extents->bottom = (int)value->v.cardinal_list.cardinals[3];
}
}
else
{
window->has_custom_frame_extents = FALSE;
}
}
static void
reload_struts (MetaWindow *window,
MetaPropValue *value,
@ -1766,6 +1795,7 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
{ display->atom__GTK_WINDOW_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_window_object_path, TRUE, FALSE },
{ display->atom__GTK_APP_MENU_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_app_menu_object_path, TRUE, FALSE },
{ display->atom__GTK_MENUBAR_OBJECT_PATH, META_PROP_VALUE_UTF8, reload_gtk_menubar_object_path, TRUE, FALSE },
{ display->atom__GTK_FRAME_EXTENTS, META_PROP_VALUE_CARDINAL_LIST,reload_gtk_frame_extents, TRUE, FALSE },
{ display->atom__NET_WM_USER_TIME_WINDOW, META_PROP_VALUE_WINDOW, reload_net_wm_user_time_window, TRUE, FALSE },
{ display->atom_WM_STATE, META_PROP_VALUE_INVALID, NULL, FALSE, FALSE },
{ display->atom__NET_WM_ICON, META_PROP_VALUE_INVALID, reload_net_wm_icon, FALSE, FALSE },

View File

@ -145,6 +145,8 @@ static void meta_window_move_between_rects (MetaWindow *window,
static void unmaximize_window_before_freeing (MetaWindow *window);
static void unminimize_window_and_all_transient_parents (MetaWindow *window);
static void meta_window_update_monitor (MetaWindow *window);
/* Idle handlers for the three queues (run with meta_later_add()). The
* "data" parameter in each case will be a GINT_TO_POINTER of the
* index into the queue arrays to use.
@ -253,6 +255,8 @@ meta_window_finalize (GObject *object)
g_free (window->gtk_window_object_path);
g_free (window->gtk_app_menu_object_path);
g_free (window->gtk_menubar_object_path);
G_OBJECT_CLASS (meta_window_parent_class)->finalize (object);
}
static void
@ -1752,16 +1756,6 @@ meta_window_unmanage (MetaWindow *window,
window,
timestamp);
}
else if (window->display->expected_focus_window == window)
{
meta_topic (META_DEBUG_FOCUS,
"Focusing default window since expected focus window freed %s\n",
window->desc);
window->display->expected_focus_window = NULL;
meta_workspace_focus_default_window (window->screen->active_workspace,
window,
timestamp);
}
else
{
meta_topic (META_DEBUG_FOCUS,
@ -1769,6 +1763,8 @@ meta_window_unmanage (MetaWindow *window,
window->desc);
}
g_assert (window->display->focus_window != window);
if (window->struts)
{
meta_free_gslist_and_elements (window->struts);
@ -1791,12 +1787,6 @@ meta_window_unmanage (MetaWindow *window,
g_assert (window->display->grab_window != window);
if (window->display->focus_window == window)
{
window->display->focus_window = NULL;
g_object_notify (G_OBJECT (window->display), "focus-window");
}
if (window->maximized_horizontally || window->maximized_vertically)
unmaximize_window_before_freeing (window);
@ -2118,10 +2108,14 @@ set_net_wm_state (MetaWindow *window)
if (window->fullscreen)
{
data[0] = window->fullscreen_monitors[0];
data[1] = window->fullscreen_monitors[1];
data[2] = window->fullscreen_monitors[2];
data[3] = window->fullscreen_monitors[3];
data[0] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[0]);
data[1] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[1]);
data[2] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[2]);
data[3] = meta_screen_monitor_index_to_xinerama_index (window->screen,
window->fullscreen_monitors[3]);
meta_verbose ("Setting _NET_WM_FULLSCREEN_MONITORS\n");
meta_error_trap_push (window->display);
@ -3330,14 +3324,7 @@ meta_window_hide (MetaWindow *window)
invalidate_work_areas (window);
}
/* The check on expected_focus_window is a temporary workaround for
* https://bugzilla.gnome.org/show_bug.cgi?id=597352
* We may have already switched away from this window but not yet
* gotten FocusIn/FocusOut events. A more complete comprehensive
* fix for these type of issues is described in the bug.
*/
if (window->has_focus &&
window == window->display->expected_focus_window)
if (window->has_focus)
{
MetaWindow *not_this_one = NULL;
MetaWorkspace *my_workspace = meta_window_get_workspace (window);
@ -4786,6 +4773,12 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
if (window->type == META_WINDOW_DESKTOP)
return;
if (window->override_redirect)
{
meta_window_update_monitor (window);
return;
}
old = window->monitor;
/* Start on primary */
@ -4796,7 +4789,8 @@ meta_window_update_for_monitors_changed (MetaWindow *window)
{
MetaMonitorInfo *info = &window->screen->monitor_infos[i];
if (info->output == old->output)
if (info->output_id != 0 &&
info->output_id == old->output_id)
{
new = info;
break;
@ -5832,7 +5826,18 @@ meta_window_get_outer_rect (const MetaWindow *window,
rect->height -= borders.invisible.top + borders.invisible.bottom;
}
else
*rect = window->rect;
{
*rect = window->rect;
if (window->has_custom_frame_extents)
{
GtkBorder *extents = &window->custom_frame_extents;
rect->x += extents->left;
rect->y += extents->top;
rect->width -= extents->left + extents->right;
rect->height -= extents->top + extents->bottom;
}
}
}
const char*
@ -5973,10 +5978,10 @@ meta_window_focus (MetaWindow *window,
meta_topic (META_DEBUG_FOCUS,
"Sending WM_TAKE_FOCUS to %s since take_focus = true\n",
window->desc);
meta_window_send_icccm_message (window,
window->display->atom_WM_TAKE_FOCUS,
timestamp);
window->display->expected_focus_window = window;
meta_display_request_take_focus (window->display,
window,
timestamp);
}
}
@ -6516,7 +6521,7 @@ meta_window_configure_request (MetaWindow *window,
if (event->xconfigurerequest.value_mask & CWStackMode)
{
MetaWindow *active_window;
active_window = window->display->expected_focus_window;
active_window = window->display->focus_window;
if (meta_prefs_get_disable_workarounds ())
{
meta_topic (META_DEBUG_STACK,
@ -6624,6 +6629,41 @@ meta_window_change_workspace_by_index (MetaWindow *window,
#define _NET_WM_MOVERESIZE_MOVE_KEYBOARD 10
#define _NET_WM_MOVERESIZE_CANCEL 11
static int
query_pressed_buttons (MetaWindow *window)
{
double x, y, query_root_x, query_root_y;
Window root, child;
XIButtonState buttons;
XIModifierState mods;
XIGroupState group;
int button = 0;
meta_error_trap_push (window->display);
XIQueryPointer (window->display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
window->xwindow,
&root, &child,
&query_root_x, &query_root_y,
&x, &y,
&buttons, &mods, &group);
if (meta_error_trap_pop_with_return (window->display) != Success)
goto out;
if (XIMaskIsSet (buttons.mask, Button1))
button |= 1 << 1;
if (XIMaskIsSet (buttons.mask, Button2))
button |= 1 << 2;
if (XIMaskIsSet (buttons.mask, Button3))
button |= 1 << 3;
free (buttons.mask);
out:
return button;
}
gboolean
meta_window_client_message (MetaWindow *window,
XEvent *event)
@ -6982,56 +7022,58 @@ meta_window_client_message (MetaWindow *window,
(op != META_GRAB_OP_MOVING &&
op != META_GRAB_OP_KEYBOARD_MOVING))))
{
/*
* the button SHOULD already be included in the message
*/
int button_mask;
meta_topic (META_DEBUG_WINDOW_OPS,
"Beginning move/resize with button = %d\n", button);
meta_display_begin_grab_op (window->display,
window->screen,
window,
op,
FALSE,
frame_action,
button, 0,
timestamp,
x_root,
y_root);
button_mask = query_pressed_buttons (window);
if (button == 0)
{
double x, y, query_root_x, query_root_y;
Window root, child;
XIButtonState buttons;
XIModifierState mods;
XIGroupState group;
/* The race conditions in this _NET_WM_MOVERESIZE thing
* are mind-boggling
/*
* the button SHOULD already be included in the message
*/
meta_error_trap_push (window->display);
XIQueryPointer (window->display->xdisplay,
META_VIRTUAL_CORE_POINTER_ID,
window->xwindow,
&root, &child,
&query_root_x, &query_root_y,
&x, &y,
&buttons, &mods, &group);
meta_error_trap_pop (window->display);
if (XIMaskIsSet (buttons.mask, Button1))
if ((button_mask & (1 << 1)) != 0)
button = 1;
else if (XIMaskIsSet (buttons.mask, Button2))
else if ((button_mask & (1 << 2)) != 0)
button = 2;
else if (XIMaskIsSet (buttons.mask, Button3))
else if ((button_mask & (1 << 3)) != 0)
button = 3;
if (button != 0)
window->display->grab_button = button;
else
button = 0;
free (buttons.mask);
meta_display_end_grab_op (window->display,
timestamp);
}
if (button != 0)
else
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Beginning move/resize with button = %d\n", button);
meta_display_begin_grab_op (window->display,
window->screen,
window,
op,
FALSE,
frame_action,
button, 0,
timestamp,
x_root,
y_root);
/* There is a potential race here. If the user presses and
* releases their mouse button very fast, it's possible for
* both the ButtonPress and ButtonRelease to be sent to the
* client before it can get a chance to send _NET_WM_MOVERESIZE
* to us. When that happens, we'll become stuck in a grab
* state, as we haven't received a ButtonRelease to cancel the
* grab.
*
* We can solve this by querying after we take the explicit
* pointer grab -- if the button isn't pressed, we cancel the
* drag immediately.
*/
if ((button_mask & (1 << button)) == 0)
meta_display_end_grab_op (window->display, timestamp);
}
}
@ -7093,10 +7135,14 @@ meta_window_client_message (MetaWindow *window,
meta_verbose ("_NET_WM_FULLSCREEN_MONITORS request for window '%s'\n",
window->desc);
top = event->xclient.data.l[0];
bottom = event->xclient.data.l[1];
left = event->xclient.data.l[2];
right = event->xclient.data.l[3];
top = meta_screen_xinerama_index_to_monitor_index (window->screen,
event->xclient.data.l[0]);
bottom = meta_screen_xinerama_index_to_monitor_index (window->screen,
event->xclient.data.l[1]);
left = meta_screen_xinerama_index_to_monitor_index (window->screen,
event->xclient.data.l[2]);
right = meta_screen_xinerama_index_to_monitor_index (window->screen,
event->xclient.data.l[3]);
/* source_indication = event->xclient.data.l[4]; */
meta_window_update_fullscreen_monitors (window, top, bottom, left, right);
@ -7158,8 +7204,7 @@ meta_window_propagate_focus_appearance (MetaWindow *window,
parent->attached_focus_window = NULL;
}
if (child_focus_state_changed && !parent->has_focus &&
parent != window->display->expected_focus_window)
if (child_focus_state_changed && !parent->has_focus)
{
meta_window_appears_focused_changed (parent);
}
@ -7170,23 +7215,85 @@ meta_window_propagate_focus_appearance (MetaWindow *window,
}
void
meta_window_lost_focus (MetaWindow *window)
meta_window_set_focused_internal (MetaWindow *window,
gboolean focused)
{
if (window == window->display->focus_window)
if (focused)
{
meta_topic (META_DEBUG_FOCUS,
"%s is now the previous focus window due to being focused out or unmapped\n",
window->desc);
window->has_focus = TRUE;
if (window->override_redirect)
return;
meta_topic (META_DEBUG_FOCUS,
"* Focus --> NULL (was %s)\n", window->desc);
/* Move to the front of the focusing workspace's MRU list.
* We should only be "removing" it from the MRU list if it's
* not already there. Note that it's possible that we might
* be processing this FocusIn after we've changed to a
* different workspace; we should therefore update the MRU
* list only if the window is actually on the active
* workspace.
*/
if (window->screen->active_workspace &&
meta_window_located_on_workspace (window,
window->screen->active_workspace))
{
GList* link;
link = g_list_find (window->screen->active_workspace->mru_list,
window);
g_assert (link);
window->screen->active_workspace->mru_list =
g_list_remove_link (window->screen->active_workspace->mru_list,
link);
g_list_free (link);
window->screen->active_workspace->mru_list =
g_list_prepend (window->screen->active_workspace->mru_list,
window);
}
if (window->frame)
meta_frame_queue_draw (window->frame);
meta_error_trap_push (window->display);
XInstallColormap (window->display->xdisplay,
window->colormap);
meta_error_trap_pop (window->display);
/* move into FOCUSED_WINDOW layer */
meta_window_update_layer (window);
/* Ungrab click to focus button since the sync grab can interfere
* with some things you might do inside the focused window, by
* causing the client to get funky enter/leave events.
*
* The reason we usually have a passive grab on the window is
* so that we can intercept clicks and raise the window in
* response. For click-to-focus we don't need that since the
* focused window is already raised. When raise_on_click is
* FALSE we also don't need that since we don't do anything
* when the window is clicked.
*
* There is dicussion in bugs 102209, 115072, and 461577
*/
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
!meta_prefs_get_raise_on_click())
meta_display_ungrab_focus_window_button (window->display, window);
g_signal_emit (window, window_signals[FOCUS], 0);
if (!window->attached_focus_window)
meta_window_appears_focused_changed (window);
meta_window_propagate_focus_appearance (window, TRUE);
}
else
{
window->has_focus = FALSE;
if (window->override_redirect)
return;
meta_window_propagate_focus_appearance (window, FALSE);
window->display->focus_window = NULL;
g_object_notify (G_OBJECT (window->display), "focus-window");
window->has_focus = FALSE;
if (!window->attached_focus_window)
meta_window_appears_focused_changed (window);
@ -7205,176 +7312,6 @@ meta_window_lost_focus (MetaWindow *window)
}
}
gboolean
meta_window_notify_focus (MetaWindow *window,
XIEnterEvent *event)
{
/* note the event can be on either the window or the frame,
* we focus the frame for shaded windows
*/
/* The event can be FocusIn, FocusOut, or UnmapNotify.
* On UnmapNotify we have to pretend it's focus out,
* because we won't get a focus out if it occurs, apparently.
*/
/* We ignore grabs, though this is questionable.
* It may be better to increase the intelligence of
* the focus window tracking.
*
* The problem is that keybindings for windows are done with
* XGrabKey, which means focus_window disappears and the front of
* the MRU list gets confused from what the user expects once a
* keybinding is used.
*/
meta_topic (META_DEBUG_FOCUS,
"Focus %s event received on %s 0x%lx (%s) "
"mode %s detail %s\n",
event->evtype == XI_FocusIn ? "in" :
event->evtype == XI_FocusOut ? "out" :
"???",
window->desc, event->event,
event->event == window->xwindow ?
"client window" :
(window->frame && event->event == window->frame->xwindow) ?
"frame window" :
"unknown window",
meta_event_mode_to_string (event->mode),
meta_event_detail_to_string (event->detail));
/* FIXME our pointer tracking is broken; see how
* gtk+/gdk/x11/gdkevents-x11.c or XFree86/xc/programs/xterm/misc.c
* handle it for the correct way. In brief you need to track
* pointer focus and regular focus, and handle EnterNotify in
* PointerRoot mode with no window manager. However as noted above,
* accurate focus tracking will break things because we want to keep
* windows "focused" when using keybindings on them, and also we
* sometimes "focus" a window by focusing its frame or
* no_focus_window; so this all needs rethinking massively.
*
* My suggestion is to change it so that we clearly separate
* actual keyboard focus tracking using the xterm algorithm,
* and mutter's "pretend" focus window, and go through all
* the code and decide which one should be used in each place;
* a hard bit is deciding on a policy for that.
*
* http://bugzilla.gnome.org/show_bug.cgi?id=90382
*/
if ((event->evtype == XI_FocusIn ||
event->evtype == XI_FocusOut) &&
(event->mode == NotifyGrab ||
event->mode == NotifyUngrab ||
/* From WindowMaker, ignore all funky pointer root events */
event->detail > NotifyNonlinearVirtual))
{
meta_topic (META_DEBUG_FOCUS,
"Ignoring focus event generated by a grab or other weirdness\n");
return TRUE;
}
if (event->evtype == XI_FocusIn)
{
if (window->override_redirect)
{
window->display->focus_window = NULL;
g_object_notify (G_OBJECT (window->display), "focus-window");
return FALSE;
}
if (window != window->display->focus_window)
{
meta_topic (META_DEBUG_FOCUS,
"* Focus --> %s\n", window->desc);
window->display->focus_window = window;
window->has_focus = TRUE;
/* Move to the front of the focusing workspace's MRU list.
* We should only be "removing" it from the MRU list if it's
* not already there. Note that it's possible that we might
* be processing this FocusIn after we've changed to a
* different workspace; we should therefore update the MRU
* list only if the window is actually on the active
* workspace.
*/
if (window->screen->active_workspace &&
meta_window_located_on_workspace (window,
window->screen->active_workspace))
{
GList* link;
link = g_list_find (window->screen->active_workspace->mru_list,
window);
g_assert (link);
window->screen->active_workspace->mru_list =
g_list_remove_link (window->screen->active_workspace->mru_list,
link);
g_list_free (link);
window->screen->active_workspace->mru_list =
g_list_prepend (window->screen->active_workspace->mru_list,
window);
}
if (window->frame)
meta_frame_queue_draw (window->frame);
meta_error_trap_push (window->display);
XInstallColormap (window->display->xdisplay,
window->colormap);
meta_error_trap_pop (window->display);
/* move into FOCUSED_WINDOW layer */
meta_window_update_layer (window);
/* Ungrab click to focus button since the sync grab can interfere
* with some things you might do inside the focused window, by
* causing the client to get funky enter/leave events.
*
* The reason we usually have a passive grab on the window is
* so that we can intercept clicks and raise the window in
* response. For click-to-focus we don't need that since the
* focused window is already raised. When raise_on_click is
* FALSE we also don't need that since we don't do anything
* when the window is clicked.
*
* There is dicussion in bugs 102209, 115072, and 461577
*/
if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
!meta_prefs_get_raise_on_click())
meta_display_ungrab_focus_window_button (window->display, window);
g_signal_emit (window, window_signals[FOCUS], 0);
g_object_notify (G_OBJECT (window->display), "focus-window");
if (!window->attached_focus_window)
meta_window_appears_focused_changed (window);
meta_window_propagate_focus_appearance (window, TRUE);
}
}
else if (event->evtype == XI_FocusOut)
{
if (event->detail == NotifyInferior)
{
/* This event means the client moved focus to a subwindow */
meta_topic (META_DEBUG_FOCUS,
"Ignoring focus out on %s with NotifyInferior\n",
window->desc);
return TRUE;
}
else
{
meta_window_lost_focus (window);
}
}
/* Now set _NET_ACTIVE_WINDOW hint */
meta_display_update_active_window_hint (window->display);
return FALSE;
}
static gboolean
process_property_notify (MetaWindow *window,
XPropertyEvent *event)
@ -8334,9 +8271,6 @@ recalc_window_features (MetaWindow *window)
if (window->type == META_WINDOW_TOOLBAR)
window->decorated = FALSE;
if (meta_window_is_attached_dialog (window))
window->border_only = TRUE;
if (window->type == META_WINDOW_DESKTOP ||
window->type == META_WINDOW_DOCK ||
window->override_redirect)
@ -9007,7 +8941,7 @@ update_move (MetaWindow *window,
* refers to the monitor which contains the largest part of the window,
* the latter to the one where the pointer is located.
*/
monitor = meta_screen_get_current_monitor_info (window->screen);
monitor = meta_screen_get_current_monitor_info_for_pos (window->screen, x, y);
meta_window_get_work_area_for_monitor (window,
monitor->number,
&work_area);
@ -11069,7 +11003,7 @@ meta_window_get_frame_type (MetaWindow *window)
/* can't add border if undecorated */
return META_FRAME_TYPE_LAST;
}
else if ((window->border_only && base_type != META_FRAME_TYPE_ATTACHED) ||
else if (window->border_only ||
(window->hide_titlebar_when_maximized && META_WINDOW_MAXIMIZED (window)) ||
(window->hide_titlebar_when_maximized && META_WINDOW_TILED_SIDE_BY_SIDE (window)))
{
@ -11216,3 +11150,9 @@ meta_window_compute_tile_match (MetaWindow *window)
window->tile_match = match;
}
}
gboolean
meta_window_can_close (MetaWindow *window)
{
return window->has_close_func;
}

View File

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

View File

@ -35,7 +35,6 @@
/* Public compositor API */
ClutterActor *meta_get_stage_for_screen (MetaScreen *screen);
ClutterActor *meta_get_overlay_group_for_screen (MetaScreen *screen);
Window meta_get_overlay_window (MetaScreen *screen);
GList *meta_get_window_actors (MetaScreen *screen);
ClutterActor *meta_get_window_group_for_screen (MetaScreen *screen);
@ -47,5 +46,8 @@ void meta_enable_unredirect_for_screen (MetaScreen *screen);
void meta_set_stage_input_region (MetaScreen *screen,
XserverRegion region);
void meta_empty_stage_input_region (MetaScreen *screen);
void meta_focus_stage_window (MetaScreen *screen,
guint32 timestamp);
gboolean meta_stage_is_focused (MetaScreen *screen);
#endif

View File

@ -165,6 +165,10 @@ void meta_display_set_input_focus_window (MetaDisplay *display,
gboolean focus_frame,
guint32 timestamp);
void meta_display_request_take_focus (MetaDisplay *display,
MetaWindow *window,
guint32 timestamp);
/* meta_display_focus_the_no_focus_window is called when the
* designated no_focus_window should be focused, but is otherwise the
* same as meta_display_set_input_focus_window
@ -187,4 +191,11 @@ void meta_display_unmanage_screen (MetaDisplay *display,
void meta_display_clear_mouse_mode (MetaDisplay *display);
void meta_display_freeze_keyboard (MetaDisplay *display,
Window window,
guint32 timestamp);
void meta_display_ungrab_keyboard (MetaDisplay *display,
guint32 timestamp);
void meta_display_unfreeze_keyboard (MetaDisplay *display,
guint32 timestamp);
#endif

View File

@ -205,6 +205,21 @@ struct _MetaPluginClass
gboolean (*keybinding_filter) (MetaPlugin *plugin,
MetaKeyBinding *binding);
/**
* MetaPluginClass::confirm_display_config:
* @plugin: a #MetaPlugin
*
* Virtual function called when the display configuration changes.
* The common way to implement this function is to show some form
* of modal dialog that should ask the user if everything was ok.
*
* When confirmed by the user, the plugin must call meta_plugin_complete_display_change()
* to make the configuration permanent. If that function is not
* called within the timeout, the previous configuration will be
* reapplied.
*/
void (*confirm_display_change) (MetaPlugin *plugin);
/**
* MetaPluginClass::plugin_info:
* @plugin: a #MetaPlugin
@ -214,6 +229,7 @@ struct _MetaPluginClass
* Returns: a #MetaPluginInfo.
*/
const MetaPluginInfo * (*plugin_info) (MetaPlugin *plugin);
};
/**
@ -360,6 +376,10 @@ void
meta_plugin_destroy_completed (MetaPlugin *plugin,
MetaWindowActor *actor);
void
meta_plugin_complete_display_change (MetaPlugin *plugin,
gboolean ok);
/**
* MetaModalOptions:
* @META_MODAL_POINTER_ALREADY_GRABBED: if set the pointer is already

View File

@ -64,7 +64,6 @@ gint meta_window_actor_get_workspace (MetaWindowActor *self
MetaWindow * meta_window_actor_get_meta_window (MetaWindowActor *self);
ClutterActor * meta_window_actor_get_texture (MetaWindowActor *self);
gboolean meta_window_actor_is_override_redirect (MetaWindowActor *self);
const char * meta_window_actor_get_description (MetaWindowActor *self);
gboolean meta_window_actor_showing_on_its_workspace (MetaWindowActor *self);
gboolean meta_window_actor_is_destroyed (MetaWindowActor *self);

View File

@ -49,7 +49,6 @@
* @META_PREF_TITLEBAR_FONT: title-bar font
* @META_PREF_NUM_WORKSPACES: number of workspaces
* @META_PREF_DYNAMIC_WORKSPACES: dynamic workspaces
* @META_PREF_APPLICATION_BASED: application-based
* @META_PREF_KEYBINDINGS: keybindings
* @META_PREF_DISABLE_WORKAROUNDS: disable workarounds
* @META_PREF_BUTTON_LAYOUT: button layout
@ -88,7 +87,6 @@ typedef enum
META_PREF_TITLEBAR_FONT,
META_PREF_NUM_WORKSPACES,
META_PREF_DYNAMIC_WORKSPACES,
META_PREF_APPLICATION_BASED,
META_PREF_KEYBINDINGS,
META_PREF_DISABLE_WORKAROUNDS,
META_PREF_BUTTON_LAYOUT,
@ -136,7 +134,6 @@ const char* meta_prefs_get_theme (void);
const PangoFontDescription* meta_prefs_get_titlebar_font (void);
int meta_prefs_get_num_workspaces (void);
gboolean meta_prefs_get_dynamic_workspaces (void);
gboolean meta_prefs_get_application_based (void);
gboolean meta_prefs_get_disable_workarounds (void);
gboolean meta_prefs_get_auto_raise (void);
int meta_prefs_get_auto_raise_delay (void);
@ -353,6 +350,7 @@ typedef enum _MetaKeyBindingAction
META_KEYBINDING_ACTION_MOVE_TO_SIDE_W,
META_KEYBINDING_ACTION_MOVE_TO_CENTER,
META_KEYBINDING_ACTION_OVERLAY_KEY,
META_KEYBINDING_ACTION_ISO_NEXT_GROUP,
META_KEYBINDING_ACTION_LAST
} MetaKeyBindingAction;
@ -442,6 +440,7 @@ void meta_prefs_get_window_binding (const char *name,
MetaVirtualModifier *modifiers);
void meta_prefs_get_overlay_binding (MetaKeyCombo *combo);
const char *meta_prefs_get_iso_next_group_option (void);
gboolean meta_prefs_get_visual_bell (void);
gboolean meta_prefs_bell_is_audible (void);

View File

@ -1,87 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Metacity theme preview widget */
/*
* Copyright (C) 2002 Havoc Pennington
*
* 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.
*/
#include <config.h>
#include <meta/common.h>
#include <meta/theme.h>
#include <gtk/gtk.h>
#ifndef META_PREVIEW_WIDGET_H
#define META_PREVIEW_WIDGET_H
#define META_TYPE_PREVIEW (meta_preview_get_type ())
#define META_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_PREVIEW, MetaPreview))
#define META_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_PREVIEW, MetaPreviewClass))
#define META_IS_PREVIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_PREVIEW))
#define META_IS_PREVIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_PREVIEW))
#define META_PREVIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_PREVIEW, MetaPreviewClass))
typedef struct _MetaPreview MetaPreview;
typedef struct _MetaPreviewClass MetaPreviewClass;
struct _MetaPreview
{
GtkBin bin;
GtkStyleContext *style_context;
MetaTheme *theme;
char *title;
MetaFrameType type;
MetaFrameFlags flags;
PangoLayout *layout;
int text_height;
MetaFrameBorders borders;
guint borders_cached : 1;
MetaButtonLayout button_layout;
};
struct _MetaPreviewClass
{
/*< private >*/
GtkBinClass parent_class;
};
GType meta_preview_get_type (void) G_GNUC_CONST;
GtkWidget* meta_preview_new (void);
void meta_preview_set_theme (MetaPreview *preview,
MetaTheme *theme);
void meta_preview_set_title (MetaPreview *preview,
const char *title);
void meta_preview_set_frame_type (MetaPreview *preview,
MetaFrameType type);
void meta_preview_set_frame_flags (MetaPreview *preview,
MetaFrameFlags flags);
void meta_preview_set_button_layout (MetaPreview *preview,
const MetaButtonLayout *button_layout);
GdkPixbuf* meta_preview_get_icon (void);
GdkPixbuf* meta_preview_get_mini_icon (void);
#endif

View File

@ -78,6 +78,9 @@ MetaWorkspace * meta_screen_get_active_workspace (MetaScreen *screen);
int meta_screen_get_n_monitors (MetaScreen *screen);
int meta_screen_get_primary_monitor (MetaScreen *screen);
int meta_screen_get_current_monitor (MetaScreen *screen);
int meta_screen_get_current_monitor_for_pos (MetaScreen *screen,
int x,
int y);
void meta_screen_get_monitor_geometry (MetaScreen *screen,
int monitor,
MetaRectangle *geometry);

View File

@ -33,8 +33,7 @@
typedef struct _MetaTheme MetaTheme;
MetaTheme* meta_theme_get_current (void);
void meta_theme_set_current (const char *name,
gboolean force_reload);
void meta_theme_set_current (const char *name);
MetaTheme* meta_theme_new (void);
void meta_theme_free (MetaTheme *theme);

View File

@ -100,7 +100,8 @@ typedef enum
META_DEBUG_RESIZING = 1 << 18,
META_DEBUG_SHAPES = 1 << 19,
META_DEBUG_COMPOSITOR = 1 << 20,
META_DEBUG_EDGE_RESISTANCE = 1 << 21
META_DEBUG_EDGE_RESISTANCE = 1 << 21,
META_DEBUG_DBUS = 1 << 22
} MetaDebugTopic;
void meta_topic_real (MetaDebugTopic topic,
@ -109,6 +110,8 @@ void meta_topic_real (MetaDebugTopic topic,
void meta_add_verbose_topic (MetaDebugTopic topic);
void meta_remove_verbose_topic (MetaDebugTopic topic);
void meta_debug_init (void);
void meta_push_no_msg_prefix (void);
void meta_pop_no_msg_prefix (void);

View File

@ -237,4 +237,6 @@ void meta_window_begin_grab_op (MetaWindow *window,
gboolean frame_action,
guint32 timestamp);
gboolean meta_window_can_close (MetaWindow *window);
#endif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 B

View File

@ -1,8 +0,0 @@
Makefile
Makefile.in
metacity-grayscale
metacity-message
metacity-mag
metacity-properties
metacity-properties.desktop
metacity-window-demo

View File

@ -1,34 +0,0 @@
@INTLTOOL_DESKTOP_RULE@
icondir=$(pkgdatadir)/icons
icon_DATA=mutter-window-demo.png
INCLUDES=@MUTTER_WINDOW_DEMO_CFLAGS@ @MUTTER_MESSAGE_CFLAGS@ \
-I$(top_srcdir)/src \
-DMUTTER_ICON_DIR=\"$(pkgdatadir)/icons\" \
-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\"
mutter_message_SOURCES= \
mutter-message.c
mutter_window_demo_SOURCES= \
mutter-window-demo.c
mutter_mag_SOURCES= \
mutter-mag.c
mutter_grayscale_SOURCES= \
mutter-grayscale.c
bin_PROGRAMS=mutter-message mutter-window-demo
## cheesy hacks I use, don't really have any business existing. ;-)
noinst_PROGRAMS=mutter-mag mutter-grayscale
mutter_message_LDADD= @MUTTER_MESSAGE_LIBS@
mutter_window_demo_LDADD= @MUTTER_WINDOW_DEMO_LIBS@
mutter_mag_LDADD= @MUTTER_WINDOW_DEMO_LIBS@
mutter_grayscale_LDADD = @MUTTER_WINDOW_DEMO_LIBS@
EXTRA_DIST=$(icon_DATA)

View File

@ -1,107 +0,0 @@
/* Hack for grayscaling an image */
/*
* Copyright (C) 2002 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.
*/
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <unistd.h>
#include <stdlib.h>
#include <math.h>
#define INTENSITY(r, g, b) ((r) * 0.30 + (g) * 0.59 + (b) * 0.11)
static GdkPixbuf*
grayscale_pixbuf (GdkPixbuf *pixbuf)
{
GdkPixbuf *gray;
guchar *pixels;
int rowstride;
int pixstride;
int row;
int n_rows;
int width;
gray = gdk_pixbuf_copy (pixbuf);
rowstride = gdk_pixbuf_get_rowstride (gray);
pixstride = gdk_pixbuf_get_has_alpha (gray) ? 4 : 3;
pixels = gdk_pixbuf_get_pixels (gray);
n_rows = gdk_pixbuf_get_height (gray);
width = gdk_pixbuf_get_width (gray);
row = 0;
while (row < n_rows)
{
guchar *p = pixels + row * rowstride;
guchar *end = p + (pixstride * width);
while (p != end)
{
double v = INTENSITY (p[0], p[1], p[2]);
p[0] = (guchar) v;
p[1] = (guchar) v;
p[2] = (guchar) v;
p += pixstride;
}
++row;
}
return gray;
}
int
main (int argc, char **argv)
{
GdkPixbuf *pixbuf;
GdkPixbuf *gray;
GError *err;
if (argc != 2)
{
g_printerr ("specify a single image on the command line\n");
return 1;
}
err = NULL;
pixbuf = gdk_pixbuf_new_from_file (argv[1], &err);
if (err != NULL)
{
g_printerr ("failed to load image: %s\n", err->message);
g_error_free (err);
return 1;
}
gray = grayscale_pixbuf (pixbuf);
err = NULL;
gdk_pixbuf_save (gray, "grayscale.png", "png", &err, NULL);
if (err != NULL)
{
g_printerr ("failed to save image: %s\n", err->message);
g_error_free (err);
return 1;
}
g_print ("wrote grayscale.png\n");
return 0;
}

View File

@ -1,299 +0,0 @@
/* Hack for use instead of xmag */
/*
* Copyright (C) 2002 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.
*/
#define _GNU_SOURCE
#define _XOPEN_SOURCE 600 /* C99 -- for rint() */
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <gdk/gdkkeysyms.h>
#include <unistd.h>
#include <stdlib.h>
#include <math.h>
static GtkWidget *grab_widget = NULL;
static GtkWidget *display_window = NULL;
static int last_grab_x = 0;
static int last_grab_y = 0;
static int last_grab_width = 150;
static int last_grab_height = 150;
static GtkAllocation last_grab_allocation;
static double width_factor = 4.0;
static double height_factor = 4.0;
static GdkInterpType interp_mode = GDK_INTERP_NEAREST;
static guint regrab_idle_id = 0;
static GdkPixbuf*
get_pixbuf (void)
{
GdkPixbuf *screenshot;
GdkPixbuf *magnified;
#if 0
g_print ("Size %d x %d\n",
last_grab_width, last_grab_height);
#endif
screenshot = gdk_pixbuf_get_from_window (gdk_get_default_root_window (),
last_grab_x, last_grab_y,
last_grab_width, last_grab_height);
if (screenshot == NULL)
{
g_printerr ("Screenshot failed\n");
exit (1);
}
magnified = gdk_pixbuf_scale_simple (screenshot, last_grab_width * width_factor,
last_grab_height * height_factor,
interp_mode);
g_object_unref (G_OBJECT (screenshot));
return magnified;
}
static gboolean
regrab_idle (GtkWidget *image)
{
GtkAllocation allocation;
GdkPixbuf *magnified;
gtk_widget_get_allocation (image, &allocation);
if (allocation.width != last_grab_allocation.width ||
allocation.height != last_grab_allocation.height)
{
last_grab_width = rint (allocation.width / width_factor);
last_grab_height = rint (allocation.height / height_factor);
last_grab_allocation = allocation;
magnified = get_pixbuf ();
gtk_image_set_from_pixbuf (GTK_IMAGE (image), magnified);
g_object_unref (G_OBJECT (magnified));
}
regrab_idle_id = 0;
return FALSE;
}
static void
image_resized (GtkWidget *image)
{
if (regrab_idle_id == 0)
regrab_idle_id = g_idle_add_full (G_PRIORITY_LOW + 100, (GSourceFunc) regrab_idle,
image, NULL);
}
static void
grab_area_at_mouse (GtkWidget *invisible,
int x_root,
int y_root)
{
GdkPixbuf *magnified;
int width, height;
GtkWidget *widget;
width = last_grab_width;
height = last_grab_height;
last_grab_x = x_root;
last_grab_y = y_root;
last_grab_width = width;
last_grab_height = height;
magnified = get_pixbuf ();
display_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (display_window),
last_grab_width, last_grab_height);
widget = gtk_image_new_from_pixbuf (magnified);
gtk_widget_set_size_request (widget, 40, 40);
gtk_container_add (GTK_CONTAINER (display_window), widget);
g_object_unref (G_OBJECT (magnified));
g_object_add_weak_pointer (G_OBJECT (display_window),
(gpointer) &display_window);
g_signal_connect (G_OBJECT (display_window), "destroy",
G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect_after (G_OBJECT (widget), "size_allocate", G_CALLBACK (image_resized), NULL);
gtk_widget_show_all (display_window);
}
static void
shutdown_grab (void)
{
GdkDeviceManager *manager;
GdkDevice *device;
manager = gdk_display_get_device_manager (gdk_display_get_default ());
device = gdk_device_manager_get_client_pointer (manager);
gdk_device_ungrab (device, gtk_get_current_event_time ());
gdk_device_ungrab (gdk_device_get_associated_device (device),
gtk_get_current_event_time ());
gtk_grab_remove (grab_widget);
}
static void
mouse_motion (GtkWidget *invisible,
GdkEventMotion *event,
gpointer data)
{
}
static gboolean
mouse_release (GtkWidget *invisible,
GdkEventButton *event,
gpointer data)
{
if (event->button != 1)
return FALSE;
grab_area_at_mouse (invisible, event->x_root, event->y_root);
shutdown_grab ();
g_signal_handlers_disconnect_by_func (invisible, mouse_motion, NULL);
g_signal_handlers_disconnect_by_func (invisible, mouse_release, NULL);
return TRUE;
}
/* Helper Functions */
static gboolean mouse_press (GtkWidget *invisible,
GdkEventButton *event,
gpointer data);
static gboolean
key_press (GtkWidget *invisible,
GdkEventKey *event,
gpointer data)
{
if (event->keyval == GDK_KEY_Escape)
{
shutdown_grab ();
g_signal_handlers_disconnect_by_func (invisible, mouse_press, NULL);
g_signal_handlers_disconnect_by_func (invisible, key_press, NULL);
gtk_main_quit ();
return TRUE;
}
return FALSE;
}
static gboolean
mouse_press (GtkWidget *invisible,
GdkEventButton *event,
gpointer data)
{
if (event->type == GDK_BUTTON_PRESS &&
event->button == 1)
{
g_signal_connect (invisible, "motion_notify_event",
G_CALLBACK (mouse_motion), NULL);
g_signal_connect (invisible, "button_release_event",
G_CALLBACK (mouse_release), NULL);
g_signal_handlers_disconnect_by_func (invisible, mouse_press, NULL);
g_signal_handlers_disconnect_by_func (invisible, key_press, NULL);
return TRUE;
}
return FALSE;
}
static void
begin_area_grab (void)
{
GdkWindow *window;
GdkDeviceManager *manager;
GdkDevice *device;
if (grab_widget == NULL)
{
grab_widget = gtk_invisible_new ();
gtk_widget_add_events (grab_widget,
GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK);
gtk_widget_show (grab_widget);
}
window = gtk_widget_get_window (grab_widget);
manager = gdk_display_get_device_manager (gdk_display_get_default ());
device = gdk_device_manager_get_client_pointer (manager);
if (gdk_device_grab (device,
window,
GDK_OWNERSHIP_NONE,
FALSE,
GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK,
NULL,
gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS)
{
g_warning ("Failed to grab pointer to do eyedropper");
return;
}
if (gdk_device_grab (gdk_device_get_associated_device (device),
window,
GDK_OWNERSHIP_NONE,
FALSE,
GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
NULL,
gtk_get_current_event_time ()) != GDK_GRAB_SUCCESS)
{
gdk_device_ungrab (device, gtk_get_current_event_time ());
g_warning ("Failed to grab keyboard to do eyedropper");
return;
}
gtk_grab_add (grab_widget);
g_signal_connect (grab_widget, "button_press_event",
G_CALLBACK (mouse_press), NULL);
g_signal_connect (grab_widget, "key_press_event",
G_CALLBACK (key_press), NULL);
}
int
main (int argc, char **argv)
{
gtk_init (&argc, &argv);
begin_area_grab ();
gtk_main ();
return 0;
}

View File

@ -1,160 +0,0 @@
/* Mutter send-magic-messages app */
/*
* Copyright (C) 2002 Havoc Pennington
*
* 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.
*/
#include <config.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <stdlib.h>
#include <string.h>
#include <libintl.h>
#define _(x) dgettext (GETTEXT_PACKAGE, x)
#define N_(x) x
static Display *display;
static void
send_reload_theme (void)
{
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.display = display;
xev.xclient.window = gdk_x11_get_default_root_xwindow ();
xev.xclient.message_type = XInternAtom (display,
"_MUTTER_RELOAD_THEME_MESSAGE",
False);
xev.xclient.format = 32;
xev.xclient.data.l[0] = 0;
xev.xclient.data.l[1] = 0;
xev.xclient.data.l[2] = 0;
XSendEvent (display,
gdk_x11_get_default_root_xwindow (),
False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
XFlush (display);
XSync (display, False);
}
static void
send_set_keybindings (gboolean enabled)
{
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.display = display;
xev.xclient.window = gdk_x11_get_default_root_xwindow ();
xev.xclient.message_type = XInternAtom (display,
"_MUTTER_SET_KEYBINDINGS_MESSAGE",
False);
xev.xclient.format = 32;
xev.xclient.data.l[0] = enabled;
xev.xclient.data.l[1] = 0;
xev.xclient.data.l[2] = 0;
XSendEvent (display,
gdk_x11_get_default_root_xwindow (),
False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
XFlush (display);
XSync (display, False);
}
#ifdef WITH_VERBOSE_MODE
static void
send_toggle_verbose (void)
{
XEvent xev;
xev.xclient.type = ClientMessage;
xev.xclient.serial = 0;
xev.xclient.send_event = True;
xev.xclient.display = display;
xev.xclient.window = gdk_x11_get_default_root_xwindow ();
xev.xclient.message_type = XInternAtom (display,
"_MUTTER_TOGGLE_VERBOSE",
False);
xev.xclient.format = 32;
xev.xclient.data.l[0] = 0;
xev.xclient.data.l[1] = 0;
xev.xclient.data.l[2] = 0;
XSendEvent (display,
gdk_x11_get_default_root_xwindow (),
False,
SubstructureRedirectMask | SubstructureNotifyMask,
&xev);
XFlush (display);
XSync (display, False);
}
#endif
static void
usage (void)
{
g_printerr (_("Usage: %s\n"),
"mutter-message (reload-theme|enable-keybindings|disable-keybindings|toggle-verbose)");
exit (1);
}
int
main (int argc, char **argv)
{
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
gtk_init (&argc, &argv);
if (argc < 2)
usage ();
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
if (strcmp (argv[1], "reload-theme") == 0)
send_reload_theme ();
else if (strcmp (argv[1], "enable-keybindings") == 0)
send_set_keybindings (TRUE);
else if (strcmp (argv[1], "disable-keybindings") == 0)
send_set_keybindings (FALSE);
else if (strcmp (argv[1], "toggle-verbose") == 0)
{
#ifndef WITH_VERBOSE_MODE
g_printerr (_("Mutter was compiled without support for verbose mode\n"));
return 1;
#else
send_toggle_verbose ();
#endif
}
else
usage ();
return 0;
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

View File

@ -664,20 +664,14 @@ meta_frames_lookup_window (MetaFrames *frames,
return frame;
}
void
meta_frames_get_borders (MetaFrames *frames,
Window xwindow,
MetaFrameBorders *borders)
static void
meta_ui_frame_get_borders (MetaFrames *frames,
MetaUIFrame *frame,
MetaFrameBorders *borders)
{
MetaFrameFlags flags;
MetaUIFrame *frame;
MetaFrameType type;
frame = meta_frames_lookup_window (frames, xwindow);
if (frame == NULL)
meta_bug ("No such frame 0x%lx\n", xwindow);
meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow,
META_CORE_GET_FRAME_FLAGS, &flags,
META_CORE_GET_FRAME_TYPE, &type,
@ -700,18 +694,30 @@ meta_frames_get_borders (MetaFrames *frames,
}
void
meta_frames_get_corner_radiuses (MetaFrames *frames,
Window xwindow,
float *top_left,
float *top_right,
float *bottom_left,
float *bottom_right)
meta_frames_get_borders (MetaFrames *frames,
Window xwindow,
MetaFrameBorders *borders)
{
MetaUIFrame *frame;
MetaFrameGeometry fgeom;
frame = meta_frames_lookup_window (frames, xwindow);
if (frame == NULL)
meta_bug ("No such frame 0x%lx\n", xwindow);
meta_ui_frame_get_borders (frames, frame, borders);
}
static void
meta_ui_frame_get_corner_radiuses (MetaFrames *frames,
MetaUIFrame *frame,
float *top_left,
float *top_right,
float *bottom_left,
float *bottom_right)
{
MetaFrameGeometry fgeom;
meta_frames_calc_geometry (frames, frame, &fgeom);
/* For compatibility with the code in get_visible_rect(), there's
@ -1829,6 +1835,102 @@ clip_region_to_visible_frame_border (cairo_region_t *region,
cairo_region_destroy (frame_border);
}
#define TAU (2*M_PI)
/*
* Draw the opaque and semi-opaque pixels of this frame into a mask.
*
* (0,0) in Cairo coordinates is assumed to be the top left corner of the
* invisible border.
*
* The parts of @cr's surface in the clip region are assumed to be
* initialized to fully-transparent, and the clip region is assumed to
* contain the invisible border and the visible parts of the frame, but
* not the client area.
*
* This function uses @cr to draw pixels of arbitrary color (it will
* typically be drawing in a %CAIRO_FORMAT_A8 surface, so the color is
* discarded anyway) with appropriate alpha values to reproduce this
* frame's alpha channel, as a mask to be applied to an opaque pixmap.
*
* @frame: This frame
* @xwindow: The X window for the frame, which has the client window as a child
* @width: The width of the framed window including any invisible borders
* @height: The height of the framed window including any invisible borders
* @cr: Used to draw the resulting mask
*/
void
meta_frames_get_mask (MetaFrames *frames,
Window xwindow,
guint width,
guint height,
cairo_t *cr)
{
MetaUIFrame *frame = meta_frames_lookup_window (frames, xwindow);
float top_left, top_right, bottom_left, bottom_right;
int x, y;
MetaFrameBorders borders;
if (frame == NULL)
meta_bug ("No such frame 0x%lx\n", xwindow);
cairo_save (cr);
meta_ui_frame_get_borders (frames, frame, &borders);
meta_ui_frame_get_corner_radiuses (frames, frame,
&top_left, &top_right,
&bottom_left, &bottom_right);
/* top left */
x = borders.invisible.left;
y = borders.invisible.top;
cairo_arc (cr,
x + top_left,
y + top_left,
top_left,
2 * TAU / 4,
3 * TAU / 4);
/* top right */
x = width - borders.invisible.right - top_right;
y = borders.invisible.top;
cairo_arc (cr,
x,
y + top_right,
top_right,
3 * TAU / 4,
4 * TAU / 4);
/* bottom right */
x = width - borders.invisible.right - bottom_right;
y = height - borders.invisible.bottom - bottom_right;
cairo_arc (cr,
x,
y,
bottom_right,
0 * TAU / 4,
1 * TAU / 4);
/* bottom left */
x = borders.invisible.left;
y = height - borders.invisible.bottom - bottom_left;
cairo_arc (cr,
x + bottom_left,
y,
bottom_left,
1 * TAU / 4,
2 * TAU / 4);
cairo_set_source_rgba (cr, 1, 1, 1, 1);
cairo_fill (cr);
cairo_restore (cr);
}
static gboolean
meta_frames_draw (GtkWidget *widget,
cairo_t *cr)

View File

@ -140,12 +140,11 @@ cairo_region_t *meta_frames_get_frame_bounds (MetaFrames *frames,
int window_width,
int window_height);
void meta_frames_get_corner_radiuses (MetaFrames *frames,
Window xwindow,
float *top_left,
float *top_right,
float *bottom_left,
float *bottom_right);
void meta_frames_get_mask (MetaFrames *frames,
Window xwindow,
guint width,
guint height,
cairo_t *cr);
void meta_frames_move_resize_frame (MetaFrames *frames,
Window xwindow,

View File

@ -40,7 +40,6 @@ typedef enum
{
MENU_ITEM_SEPARATOR = 0,
MENU_ITEM_NORMAL,
MENU_ITEM_IMAGE,
MENU_ITEM_CHECKBOX,
MENU_ITEM_RADIOBUTTON,
MENU_ITEM_WORKSPACE_LIST,
@ -50,7 +49,6 @@ struct _MenuItem
{
MetaMenuOp op;
MetaMenuItemType type;
const char *stock_id;
const gboolean checked;
const char *label;
};
@ -66,42 +64,42 @@ static void activate_cb (GtkWidget *menuitem, gpointer data);
static MenuItem menuitems[] = {
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_MINIMIZE, MENU_ITEM_IMAGE, METACITY_STOCK_MINIMIZE, FALSE, N_("Mi_nimize") },
{ META_MENU_OP_MINIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Mi_nimize") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_MAXIMIZE, MENU_ITEM_IMAGE, METACITY_STOCK_MAXIMIZE, FALSE, N_("Ma_ximize") },
{ META_MENU_OP_MAXIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Ma_ximize") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_UNMAXIMIZE, MENU_ITEM_NORMAL, NULL, FALSE, N_("Unma_ximize") },
{ META_MENU_OP_UNMAXIMIZE, MENU_ITEM_NORMAL, FALSE, N_("Unma_ximize") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_SHADE, MENU_ITEM_NORMAL, NULL, FALSE, N_("Roll _Up") },
{ META_MENU_OP_SHADE, MENU_ITEM_NORMAL, FALSE, N_("Roll _Up") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_UNSHADE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Unroll") },
{ META_MENU_OP_UNSHADE, MENU_ITEM_NORMAL, FALSE, N_("_Unroll") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_MOVE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Move") },
{ META_MENU_OP_MOVE, MENU_ITEM_NORMAL, FALSE, N_("_Move") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_RESIZE, MENU_ITEM_NORMAL, NULL, FALSE, N_("_Resize") },
{ META_MENU_OP_RESIZE, MENU_ITEM_NORMAL, FALSE, N_("_Resize") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_RECOVER, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move Titlebar On_screen") },
{ META_MENU_OP_WORKSPACES, MENU_ITEM_SEPARATOR, NULL, FALSE, NULL }, /* separator */
{ META_MENU_OP_RECOVER, MENU_ITEM_NORMAL, FALSE, N_("Move Titlebar On_screen") },
{ META_MENU_OP_WORKSPACES, MENU_ITEM_SEPARATOR, FALSE, NULL }, /* separator */
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_ABOVE, MENU_ITEM_CHECKBOX, NULL, FALSE, N_("Always on _Top") },
{ META_MENU_OP_ABOVE, MENU_ITEM_CHECKBOX, FALSE, N_("Always on _Top") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_UNABOVE, MENU_ITEM_CHECKBOX, NULL, TRUE, N_("Always on _Top") },
{ META_MENU_OP_UNABOVE, MENU_ITEM_CHECKBOX, TRUE, N_("Always on _Top") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_STICK, MENU_ITEM_RADIOBUTTON, NULL, FALSE, N_("_Always on Visible Workspace") },
{ META_MENU_OP_STICK, MENU_ITEM_RADIOBUTTON, FALSE, N_("_Always on Visible Workspace") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_UNSTICK, MENU_ITEM_RADIOBUTTON, NULL, FALSE, N_("_Only on This Workspace") },
{ META_MENU_OP_UNSTICK, MENU_ITEM_RADIOBUTTON, FALSE, N_("_Only on This Workspace") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_MOVE_LEFT, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace _Left") },
{ META_MENU_OP_MOVE_LEFT, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Left") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_MOVE_RIGHT, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace R_ight") },
{ META_MENU_OP_MOVE_RIGHT, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace R_ight") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_MOVE_UP, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace _Up") },
{ META_MENU_OP_MOVE_UP, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Up") },
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_MOVE_DOWN, MENU_ITEM_NORMAL, NULL, FALSE, N_("Move to Workspace _Down") },
{ 0, MENU_ITEM_WORKSPACE_LIST, NULL, FALSE, NULL },
{ 0, MENU_ITEM_SEPARATOR, NULL, FALSE, NULL }, /* separator */
{ META_MENU_OP_MOVE_DOWN, MENU_ITEM_NORMAL, FALSE, N_("Move to Workspace _Down") },
{ 0, MENU_ITEM_WORKSPACE_LIST, FALSE, NULL },
{ 0, MENU_ITEM_SEPARATOR, FALSE, NULL }, /* separator */
/* Translators: Translate this string the same way as you do in libwnck! */
{ META_MENU_OP_DELETE, MENU_ITEM_IMAGE, METACITY_STOCK_DELETE, FALSE, N_("_Close") }
{ META_MENU_OP_DELETE, MENU_ITEM_NORMAL, FALSE, N_("_Close") }
};
static void
@ -274,16 +272,6 @@ menu_item_new (MenuItem *menuitem, int workspace_id)
{
mi = gtk_menu_item_new ();
}
else if (menuitem->type == MENU_ITEM_IMAGE)
{
GtkWidget *image;
image = gtk_image_new_from_stock (menuitem->stock_id, GTK_ICON_SIZE_MENU);
mi = gtk_image_menu_item_new ();
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (mi), image);
gtk_widget_show (image);
}
else if (menuitem->type == MENU_ITEM_CHECKBOX)
{
mi = gtk_check_menu_item_new ();
@ -392,8 +380,7 @@ meta_window_menu_new (MetaFrames *frames,
int j;
MenuItem to_another_workspace = {
0, MENU_ITEM_NORMAL,
NULL, FALSE,
0, MENU_ITEM_NORMAL, FALSE,
N_("Move to Another _Workspace")
};

View File

@ -27,11 +27,6 @@
#include <gtk/gtk.h>
#include "frames.h"
/* Stock icons */
#define METACITY_STOCK_DELETE "metacity-delete"
#define METACITY_STOCK_MINIMIZE "metacity-minimize"
#define METACITY_STOCK_MAXIMIZE "metacity-maximize"
struct _MetaWindowMenu
{
MetaFrames *frames;

View File

@ -1,496 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2002 Havoc Pennington
*
* 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.
*/
/*
* SECTION:preview-widget
* @title: MetaPreview
* @short_description: Mutter theme preview widget
*/
#define _GNU_SOURCE
#define _XOPEN_SOURCE 600 /* for the maths routines over floats */
#include <math.h>
#include <gtk/gtk.h>
#include <meta/preview-widget.h>
#include "theme-private.h"
static void meta_preview_get_preferred_width (GtkWidget *widget,
gint *minimum,
gint *natural);
static void meta_preview_get_preferred_height (GtkWidget *widget,
gint *minimum,
gint *natural);
static void meta_preview_size_allocate (GtkWidget *widget,
GtkAllocation *allocation);
static gboolean meta_preview_draw (GtkWidget *widget,
cairo_t *cr);
static void meta_preview_realize (GtkWidget *widget);
static void meta_preview_dispose (GObject *object);
static void meta_preview_finalize (GObject *object);
G_DEFINE_TYPE (MetaPreview, meta_preview, GTK_TYPE_BIN);
static void
meta_preview_class_init (MetaPreviewClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
GtkWidgetClass *widget_class;
widget_class = (GtkWidgetClass*) class;
gobject_class->dispose = meta_preview_dispose;
gobject_class->finalize = meta_preview_finalize;
widget_class->realize = meta_preview_realize;
widget_class->draw = meta_preview_draw;
widget_class->get_preferred_width = meta_preview_get_preferred_width;
widget_class->get_preferred_height = meta_preview_get_preferred_height;
widget_class->size_allocate = meta_preview_size_allocate;
gtk_container_class_handle_border_width (GTK_CONTAINER_CLASS (class));
}
static void
meta_preview_init (MetaPreview *preview)
{
int i;
gtk_widget_set_has_window (GTK_WIDGET (preview), FALSE);
i = 0;
while (i < MAX_BUTTONS_PER_CORNER)
{
preview->button_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST;
preview->button_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST;
++i;
}
preview->button_layout.left_buttons[0] = META_BUTTON_FUNCTION_MENU;
preview->button_layout.right_buttons[0] = META_BUTTON_FUNCTION_MINIMIZE;
preview->button_layout.right_buttons[1] = META_BUTTON_FUNCTION_MAXIMIZE;
preview->button_layout.right_buttons[2] = META_BUTTON_FUNCTION_CLOSE;
preview->type = META_FRAME_TYPE_NORMAL;
preview->flags =
META_FRAME_ALLOWS_DELETE |
META_FRAME_ALLOWS_MENU |
META_FRAME_ALLOWS_MINIMIZE |
META_FRAME_ALLOWS_MAXIMIZE |
META_FRAME_ALLOWS_VERTICAL_RESIZE |
META_FRAME_ALLOWS_HORIZONTAL_RESIZE |
META_FRAME_HAS_FOCUS |
META_FRAME_ALLOWS_SHADE |
META_FRAME_ALLOWS_MOVE;
preview->borders_cached = FALSE;
}
GtkWidget*
meta_preview_new (void)
{
MetaPreview *preview;
preview = g_object_new (META_TYPE_PREVIEW, NULL);
return GTK_WIDGET (preview);
}
static void
meta_preview_dispose (GObject *object)
{
MetaPreview *preview = META_PREVIEW (object);
g_clear_object (&preview->style_context);
G_OBJECT_CLASS (meta_preview_parent_class)->dispose (object);
}
static void
meta_preview_finalize (GObject *object)
{
MetaPreview *preview;
preview = META_PREVIEW (object);
g_free (preview->title);
preview->title = NULL;
G_OBJECT_CLASS (meta_preview_parent_class)->finalize (object);
}
static void
ensure_info (MetaPreview *preview)
{
GtkWidget *widget;
widget = GTK_WIDGET (preview);
if (preview->layout == NULL)
{
PangoFontDescription *font_desc;
double scale;
PangoAttrList *attrs;
PangoAttribute *attr;
if (preview->theme)
scale = meta_theme_get_title_scale (preview->theme,
preview->type,
preview->flags);
else
scale = 1.0;
preview->layout = gtk_widget_create_pango_layout (widget,
preview->title);
font_desc = meta_gtk_widget_get_font_desc (widget, scale, NULL);
preview->text_height =
meta_pango_font_desc_get_text_height (font_desc,
gtk_widget_get_pango_context (widget));
attrs = pango_attr_list_new ();
attr = pango_attr_size_new (pango_font_description_get_size (font_desc));
attr->start_index = 0;
attr->end_index = G_MAXINT;
pango_attr_list_insert (attrs, attr);
pango_layout_set_attributes (preview->layout, attrs);
pango_attr_list_unref (attrs);
pango_font_description_free (font_desc);
}
if (!preview->borders_cached)
{
if (preview->theme)
meta_theme_get_frame_borders (preview->theme,
preview->type,
preview->text_height,
preview->flags,
&preview->borders);
else
meta_frame_borders_clear (&preview->borders);
preview->borders_cached = TRUE;
}
}
static gboolean
meta_preview_draw (GtkWidget *widget,
cairo_t *cr)
{
MetaPreview *preview = META_PREVIEW (widget);
GtkAllocation allocation;
gtk_widget_get_allocation (widget, &allocation);
if (preview->theme)
{
int client_width;
int client_height;
MetaButtonState button_states[META_BUTTON_TYPE_LAST] =
{
META_BUTTON_STATE_NORMAL,
META_BUTTON_STATE_NORMAL,
META_BUTTON_STATE_NORMAL,
META_BUTTON_STATE_NORMAL
};
ensure_info (preview);
cairo_save (cr);
client_width = allocation.width - preview->borders.total.left - preview->borders.total.right;
client_height = allocation.height - preview->borders.total.top - preview->borders.total.bottom;
if (client_width < 0)
client_width = 1;
if (client_height < 0)
client_height = 1;
meta_theme_draw_frame (preview->theme,
preview->style_context,
cr,
preview->type,
preview->flags,
client_width, client_height,
preview->layout,
preview->text_height,
&preview->button_layout,
button_states,
meta_preview_get_mini_icon (),
meta_preview_get_icon ());
cairo_restore (cr);
}
/* draw child */
return GTK_WIDGET_CLASS (meta_preview_parent_class)->draw (widget, cr);
}
static void
meta_preview_realize (GtkWidget *widget)
{
MetaPreview *preview = META_PREVIEW (widget);
GTK_WIDGET_CLASS (meta_preview_parent_class)->realize (widget);
preview->style_context = meta_theme_create_style_context (gtk_widget_get_screen (widget),
NULL);
}
#define NO_CHILD_WIDTH 80
#define NO_CHILD_HEIGHT 20
static void
meta_preview_get_preferred_width (GtkWidget *widget,
gint *minimum,
gint *natural)
{
MetaPreview *preview;
GtkWidget *child;
preview = META_PREVIEW (widget);
ensure_info (preview);
*minimum = *natural = preview->borders.total.left + preview->borders.total.right;
child = gtk_bin_get_child (GTK_BIN (preview));
if (child && gtk_widget_get_visible (child))
{
gint child_min, child_nat;
gtk_widget_get_preferred_width (child, &child_min, &child_nat);
*minimum += child_min;
*natural += child_nat;
}
else
{
*minimum += NO_CHILD_WIDTH;
*natural += NO_CHILD_WIDTH;
}
}
static void
meta_preview_get_preferred_height (GtkWidget *widget,
gint *minimum,
gint *natural)
{
MetaPreview *preview;
GtkWidget *child;
preview = META_PREVIEW (widget);
ensure_info (preview);
*minimum = *natural = preview->borders.total.top + preview->borders.total.bottom;
child = gtk_bin_get_child (GTK_BIN (preview));
if (child && gtk_widget_get_visible (child))
{
gint child_min, child_nat;
gtk_widget_get_preferred_height (child, &child_min, &child_nat);
*minimum += child_min;
*natural += child_nat;
}
else
{
*minimum += NO_CHILD_HEIGHT;
*natural += NO_CHILD_HEIGHT;
}
}
static void
meta_preview_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
MetaPreview *preview;
GtkAllocation widget_allocation, child_allocation;
GtkWidget *child;
preview = META_PREVIEW (widget);
ensure_info (preview);
gtk_widget_set_allocation (widget, allocation);
child = gtk_bin_get_child (GTK_BIN (widget));
if (child && gtk_widget_get_visible (child))
{
gtk_widget_get_allocation (widget, &widget_allocation);
child_allocation.x = widget_allocation.x + preview->borders.total.left;
child_allocation.y = widget_allocation.y + preview->borders.total.top;
child_allocation.width = MAX (1, widget_allocation.width - preview->borders.total.left - preview->borders.total.right);
child_allocation.height = MAX (1, widget_allocation.height - preview->borders.total.top - preview->borders.total.bottom);
gtk_widget_size_allocate (child, &child_allocation);
}
}
static void
clear_cache (MetaPreview *preview)
{
if (preview->layout)
{
g_object_unref (G_OBJECT (preview->layout));
preview->layout = NULL;
}
preview->borders_cached = FALSE;
}
void
meta_preview_set_theme (MetaPreview *preview,
MetaTheme *theme)
{
g_return_if_fail (META_IS_PREVIEW (preview));
preview->theme = theme;
clear_cache (preview);
gtk_widget_queue_resize (GTK_WIDGET (preview));
}
void
meta_preview_set_title (MetaPreview *preview,
const char *title)
{
g_return_if_fail (META_IS_PREVIEW (preview));
g_free (preview->title);
preview->title = g_strdup (title);
clear_cache (preview);
gtk_widget_queue_resize (GTK_WIDGET (preview));
}
void
meta_preview_set_frame_type (MetaPreview *preview,
MetaFrameType type)
{
g_return_if_fail (META_IS_PREVIEW (preview));
preview->type = type;
clear_cache (preview);
gtk_widget_queue_resize (GTK_WIDGET (preview));
}
void
meta_preview_set_frame_flags (MetaPreview *preview,
MetaFrameFlags flags)
{
g_return_if_fail (META_IS_PREVIEW (preview));
preview->flags = flags;
clear_cache (preview);
gtk_widget_queue_resize (GTK_WIDGET (preview));
}
void
meta_preview_set_button_layout (MetaPreview *preview,
const MetaButtonLayout *button_layout)
{
g_return_if_fail (META_IS_PREVIEW (preview));
preview->button_layout = *button_layout;
gtk_widget_queue_draw (GTK_WIDGET (preview));
}
GdkPixbuf*
meta_preview_get_icon (void)
{
static GdkPixbuf *default_icon = NULL;
if (default_icon == NULL)
{
GtkIconTheme *theme;
gboolean icon_exists;
theme = gtk_icon_theme_get_default ();
icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME);
if (icon_exists)
default_icon = gtk_icon_theme_load_icon (theme,
META_DEFAULT_ICON_NAME,
META_ICON_WIDTH,
0,
NULL);
else
default_icon = gtk_icon_theme_load_icon (theme,
"gtk-missing-image",
META_ICON_WIDTH,
0,
NULL);
g_assert (default_icon);
}
return default_icon;
}
GdkPixbuf*
meta_preview_get_mini_icon (void)
{
static GdkPixbuf *default_icon = NULL;
if (default_icon == NULL)
{
GtkIconTheme *theme;
gboolean icon_exists;
theme = gtk_icon_theme_get_default ();
icon_exists = gtk_icon_theme_has_icon (theme, META_DEFAULT_ICON_NAME);
if (icon_exists)
default_icon = gtk_icon_theme_load_icon (theme,
META_DEFAULT_ICON_NAME,
META_MINI_ICON_WIDTH,
0,
NULL);
else
default_icon = gtk_icon_theme_load_icon (theme,
"gtk-missing-image",
META_MINI_ICON_WIDTH,
0,
NULL);
g_assert (default_icon);
}
return default_icon;
}

View File

@ -857,10 +857,7 @@ meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
WnckWindowDisplayInfo wnck_window;
wnck_window.icon = window->icon;
wnck_window.mini_icon = window->mini_icon;
wnck_window.is_active = FALSE;
if (window == window->display->expected_focus_window)
wnck_window.is_active = TRUE;
wnck_window.is_active = window->has_focus;
if (window->frame)
{

File diff suppressed because it is too large Load Diff

View File

@ -1880,7 +1880,7 @@ debug_print_tokens (PosToken *tokens,
/**
* pos_tokenize:
* @expr: The expression
* @tokens_p: (out) The resulting tokens
* @tokens_p: (out): The resulting tokens
* @n_tokens_p: (out): The number of resulting tokens
* @err: (out): set to the problem if there was a problem
@ -5063,16 +5063,14 @@ meta_theme_get_current (void)
}
void
meta_theme_set_current (const char *name,
gboolean force_reload)
meta_theme_set_current (const char *name)
{
MetaTheme *new_theme;
GError *err;
meta_topic (META_DEBUG_THEMES, "Setting current theme to \"%s\"\n", name);
if (!force_reload &&
meta_current_theme &&
if (meta_current_theme &&
strcmp (name, meta_current_theme->name) == 0)
return;

View File

@ -4,7 +4,6 @@
/*
* Copyright (C) 2002 Havoc Pennington
* stock icon code Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -31,13 +30,10 @@
#include "core.h"
#include "theme-private.h"
#include "inlinepixbufs.h"
#include <string.h>
#include <stdlib.h>
#include <cairo-xlib.h>
static void meta_stock_icons_init (void);
static void meta_ui_accelerator_parse (const char *accel,
guint *keysym,
guint *keycode,
@ -62,8 +58,6 @@ meta_ui_init (void)
{
if (!gtk_init_check (NULL, NULL))
meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
meta_stock_icons_init ();
}
Display*
@ -324,6 +318,16 @@ meta_ui_free (MetaUI *ui)
g_free (ui);
}
void
meta_ui_get_frame_mask (MetaUI *ui,
Window frame_xwindow,
guint width,
guint height,
cairo_t *cr)
{
meta_frames_get_mask (ui->frames, frame_xwindow, width, height, cr);
}
void
meta_ui_get_frame_borders (MetaUI *ui,
Window frame_xwindow,
@ -333,19 +337,6 @@ meta_ui_get_frame_borders (MetaUI *ui,
borders);
}
void
meta_ui_get_corner_radiuses (MetaUI *ui,
Window xwindow,
float *top_left,
float *top_right,
float *bottom_left,
float *bottom_right)
{
meta_frames_get_corner_radiuses (ui->frames, xwindow,
top_left, top_right,
bottom_left, bottom_right);
}
Window
meta_ui_create_frame_window (MetaUI *ui,
Display *xdisplay,
@ -778,10 +769,9 @@ meta_ui_theme_get_frame_borders (MetaUI *ui,
}
void
meta_ui_set_current_theme (const char *name,
gboolean force_reload)
meta_ui_set_current_theme (const char *name)
{
meta_theme_set_current (name, force_reload);
meta_theme_set_current (name);
meta_invalidate_default_icons ();
}
@ -1001,48 +991,6 @@ meta_ui_window_is_widget (MetaUI *ui,
return FALSE;
}
/* stock icon code Copyright (C) 2002 Jorn Baayen <jorn@nl.linux.org> */
typedef struct
{
char *stock_id;
const guint8 *icon_data;
} MetaStockIcon;
static void
meta_stock_icons_init (void)
{
GtkIconFactory *factory;
int i;
MetaStockIcon items[] =
{
{ METACITY_STOCK_DELETE, stock_delete_data },
{ METACITY_STOCK_MINIMIZE, stock_minimize_data },
{ METACITY_STOCK_MAXIMIZE, stock_maximize_data }
};
factory = gtk_icon_factory_new ();
gtk_icon_factory_add_default (factory);
for (i = 0; i < (gint) G_N_ELEMENTS (items); i++)
{
GtkIconSet *icon_set;
GdkPixbuf *pixbuf;
pixbuf = gdk_pixbuf_new_from_inline (-1, items[i].icon_data,
FALSE,
NULL);
icon_set = gtk_icon_set_new_from_pixbuf (pixbuf);
gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
gtk_icon_set_unref (icon_set);
g_object_unref (G_OBJECT (pixbuf));
}
g_object_unref (G_OBJECT (factory));
}
int
meta_ui_get_drag_threshold (MetaUI *ui)
{

View File

@ -66,6 +66,13 @@ void meta_ui_theme_get_frame_borders (MetaUI *ui,
void meta_ui_get_frame_borders (MetaUI *ui,
Window frame_xwindow,
MetaFrameBorders *borders);
void meta_ui_get_frame_mask (MetaUI *ui,
Window frame_xwindow,
guint width,
guint height,
cairo_t *cr);
Window meta_ui_create_frame_window (MetaUI *ui,
Display *xdisplay,
Visual *xvisual,
@ -102,13 +109,6 @@ cairo_region_t *meta_ui_get_frame_bounds (MetaUI *ui,
int window_width,
int window_height);
void meta_ui_get_corner_radiuses (MetaUI *ui,
Window xwindow,
float *top_left,
float *top_right,
float *bottom_left,
float *bottom_right);
void meta_ui_queue_frame_draw (MetaUI *ui,
Window xwindow);
@ -154,8 +154,7 @@ gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
char* meta_text_property_to_utf8 (Display *xdisplay,
const XTextProperty *prop);
void meta_ui_set_current_theme (const char *name,
gboolean force_reload);
void meta_ui_set_current_theme (const char *name);
gboolean meta_ui_have_a_theme (void);
/* Not a real key symbol but means "key above the tab key"; this is

View File

@ -1,7 +0,0 @@
Makefile
Makefile.in
focus-window
test-gravity
test-resizing
wm-tester
test-size-hints

View File

@ -1,29 +0,0 @@
INCLUDES=@MUTTER_CFLAGS@
wm_tester_SOURCES= \
main.c
test_gravity_SOURCES= \
test-gravity.c
focus_window_SOURCES= \
focus-window.c
test_resizing_SOURCES= \
test-resizing.c
test_size_hints_SOURCES= \
test-size-hints.c
test_attached_SOURCES= \
test-attached.c
noinst_PROGRAMS=wm-tester test-gravity test-resizing focus-window test-size-hints test-attached
wm_tester_LDADD= @MUTTER_LIBS@
test_gravity_LDADD= @MUTTER_LIBS@
test_resizing_LDADD= @MUTTER_LIBS@
test_size_hints_LDADD= @MUTTER_LIBS@
focus_window_LDADD= @MUTTER_LIBS@
test_attached_LDADD= @MUTTER_LIBS@

View File

@ -1,37 +0,0 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
Display *d;
Window w;
const char *w_str;
char *end;
if (argc != 2)
{
fprintf (stderr, "Usage: focus-window WINDOWID\n");
exit (1);
}
d = XOpenDisplay (NULL);
w_str = argv[1];
end = NULL;
w = strtoul (w_str, &end, 16);
if (end == w_str)
{
fprintf (stderr, "Usage: focus-window WINDOWID\n");
exit (1);
}
printf ("Setting input focus to 0x%lx\n", w);
XSetInputFocus (d, w, RevertToPointerRoot, CurrentTime);
XFlush (d);
return 0;
}

View File

@ -1,245 +0,0 @@
/* WM tester main() */
/*
* Copyright (C) 2001 Havoc Pennington
*
* 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.
*/
#include <gtk/gtk.h>
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static void set_up_the_evil (void);
static void set_up_icon_windows (void);
static void
usage (void)
{
g_print ("wm-tester [--evil] [--icon-windows]\n");
exit (0);
}
int
main (int argc, char **argv)
{
int i;
gboolean do_evil;
gboolean do_icon_windows;
gtk_init (&argc, &argv);
do_evil = FALSE;
do_icon_windows = FALSE;
i = 1;
while (i < argc)
{
const char *arg = argv[i];
if (strcmp (arg, "--help") == 0 ||
strcmp (arg, "-h") == 0 ||
strcmp (arg, "-?") == 0)
usage ();
else if (strcmp (arg, "--evil") == 0)
do_evil = TRUE;
else if (strcmp (arg, "--icon-windows") == 0)
do_icon_windows = TRUE;
else
usage ();
++i;
}
/* Be sure some option was provided */
if (! (do_evil || do_icon_windows))
return 1;
if (do_evil)
set_up_the_evil ();
if (do_icon_windows)
set_up_icon_windows ();
gtk_main ();
return 0;
}
static GSList *evil_windows = NULL;
static gint
evil_timeout (gpointer data)
{
int i;
int n_windows;
int len;
int create_count;
int destroy_count;
len = g_slist_length (evil_windows);
if (len > 35)
{
create_count = 2;
destroy_count = 5;
}
else
{
create_count = 5;
destroy_count = 5;
}
/* Create some windows */
n_windows = g_random_int_range (0, create_count);
i = 0;
while (i < n_windows)
{
GtkWidget *w;
GtkWidget *c;
int t;
GtkWidget *parent;
w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_move (GTK_WINDOW (w),
g_random_int_range (0,
gdk_screen_width ()),
g_random_int_range (0,
gdk_screen_height ()));
parent = NULL;
/* set transient for random window (may create all kinds of weird cycles) */
if (len > 0)
{
t = g_random_int_range (- (len / 3), len);
if (t >= 0)
{
parent = g_slist_nth_data (evil_windows, t);
if (parent != NULL)
gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (parent));
}
}
if (parent != NULL)
c = gtk_button_new_with_label ("Evil Transient!");
else
c = gtk_button_new_with_label ("Evil Window!");
gtk_container_add (GTK_CONTAINER (w), c);
gtk_widget_show_all (w);
evil_windows = g_slist_prepend (evil_windows, w);
++i;
}
/* Destroy some windows */
if (len > destroy_count)
{
n_windows = g_random_int_range (0, destroy_count);
i = 0;
while (i < n_windows)
{
GtkWidget *w;
w = g_slist_nth_data (evil_windows,
g_random_int_range (0, len));
if (w)
{
--len;
evil_windows = g_slist_remove (evil_windows, w);
gtk_widget_destroy (w);
}
++i;
}
}
return TRUE;
}
static void
set_up_the_evil (void)
{
g_timeout_add (400, evil_timeout, NULL);
}
static void
set_up_icon_windows (void)
{
int i;
int n_windows;
/* Create some windows */
n_windows = 9;
i = 0;
while (i < n_windows)
{
GtkWidget *w;
GtkWidget *c;
GList *icons;
GdkPixbuf *pix;
w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
c = gtk_button_new_with_label ("Icon window");
gtk_container_add (GTK_CONTAINER (w), c);
icons = NULL;
pix = gtk_widget_render_icon (w,
GTK_STOCK_SAVE,
GTK_ICON_SIZE_LARGE_TOOLBAR,
NULL);
icons = g_list_append (icons, pix);
if (i % 2)
{
pix = gtk_widget_render_icon (w,
GTK_STOCK_SAVE,
GTK_ICON_SIZE_DIALOG,
NULL);
icons = g_list_append (icons, pix);
}
if (i % 3)
{
pix = gtk_widget_render_icon (w,
GTK_STOCK_SAVE,
GTK_ICON_SIZE_MENU,
NULL);
icons = g_list_append (icons, pix);
}
gtk_window_set_icon_list (GTK_WINDOW (w), icons);
g_list_foreach (icons, (GFunc) g_object_unref, NULL);
g_list_free (icons);
gtk_widget_show_all (w);
++i;
}
}

View File

@ -1,100 +0,0 @@
#include <gtk/gtk.h>
enum {
DESTROY_PARENT,
DETACH,
ATTACH_1,
ATTACH_2
};
GtkWidget *window1, *window2;
static void
dialog_response (GtkDialog *dialog, int response, gpointer user_data)
{
if (response == DESTROY_PARENT)
{
GtkWidget *window = GTK_WIDGET (gtk_window_get_transient_for (GTK_WINDOW (dialog)));
if (window == window1)
{
gtk_dialog_set_response_sensitive (dialog, ATTACH_1, FALSE);
window1 = NULL;
}
else
{
gtk_dialog_set_response_sensitive (dialog, ATTACH_2, FALSE);
window2 = NULL;
}
gtk_dialog_set_response_sensitive (dialog, DESTROY_PARENT, FALSE);
gtk_dialog_set_response_sensitive (dialog, DETACH, FALSE);
gtk_widget_destroy (window);
}
else if (response == DETACH)
{
gtk_window_set_transient_for (GTK_WINDOW (dialog), NULL);
gtk_dialog_set_response_sensitive (dialog, DESTROY_PARENT, FALSE);
gtk_dialog_set_response_sensitive (dialog, DETACH, FALSE);
gtk_dialog_set_response_sensitive (dialog, ATTACH_1, window1 != NULL);
gtk_dialog_set_response_sensitive (dialog, ATTACH_2, window2 != NULL);
}
else if (response == ATTACH_1)
{
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window1));
gtk_dialog_set_response_sensitive (dialog, DESTROY_PARENT, TRUE);
gtk_dialog_set_response_sensitive (dialog, DETACH, TRUE);
gtk_dialog_set_response_sensitive (dialog, ATTACH_1, FALSE);
gtk_dialog_set_response_sensitive (dialog, ATTACH_2, window2 != NULL);
}
else if (response == ATTACH_2)
{
gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (window2));
gtk_dialog_set_response_sensitive (dialog, DESTROY_PARENT, TRUE);
gtk_dialog_set_response_sensitive (dialog, DETACH, TRUE);
gtk_dialog_set_response_sensitive (dialog, ATTACH_1, window1 != NULL);
gtk_dialog_set_response_sensitive (dialog, ATTACH_2, FALSE);
}
else if (response == GTK_RESPONSE_CLOSE)
gtk_main_quit ();
}
int
main (int argc, char **argv)
{
GtkWidget *dialog;
gtk_init (&argc, &argv);
window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window1), "Parent 1");
gtk_widget_show (window1);
window2 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window2), "Parent 2");
gtk_widget_show (window2);
dialog = gtk_dialog_new_with_buttons ("Child",
NULL,
GTK_DIALOG_MODAL,
"Destroy Parent",
DESTROY_PARENT,
"Detach",
DETACH,
"Attach to 1",
ATTACH_1,
"Attach to 2",
ATTACH_2,
GTK_STOCK_QUIT,
GTK_RESPONSE_CLOSE,
NULL);
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), DESTROY_PARENT, FALSE);
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), DETACH, FALSE);
g_signal_connect (dialog, "response", G_CALLBACK (dialog_response), NULL);
gtk_widget_show (dialog);
gtk_main ();
return 0;
}

View File

@ -1,308 +0,0 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdio.h>
#include <string.h>
static int gravities[10] = {
NorthWestGravity,
NorthGravity,
NorthEastGravity,
WestGravity,
CenterGravity,
EastGravity,
SouthWestGravity,
SouthGravity,
SouthEastGravity,
StaticGravity
};
typedef struct
{
int x, y, width, height;
} Rectangle;
static Window windows[10];
static int doubled[10] = { 0, };
static Rectangle window_rects[10];
#define WINDOW_WIDTH 100
#define WINDOW_HEIGHT 100
static int x_offset[3] = { 0, - WINDOW_WIDTH/2, -WINDOW_WIDTH };
static int y_offset[3] = { 0, - WINDOW_HEIGHT/2, -WINDOW_HEIGHT };
static double screen_x_fraction[3] = { 0, 0.5, 1.0 };
static double screen_y_fraction[3] = { 0, 0.5, 1.0 };
static int screen_width;
static int screen_height;
static const char*
window_gravity_to_string (int gravity)
{
switch (gravity)
{
case NorthWestGravity:
return "NorthWestGravity";
case NorthGravity:
return "NorthGravity";
case NorthEastGravity:
return "NorthEastGravity";
case WestGravity:
return "WestGravity";
case CenterGravity:
return "CenterGravity";
case EastGravity:
return "EastGravity";
case SouthWestGravity:
return "SouthWestGravity";
case SouthGravity:
return "SouthGravity";
case SouthEastGravity:
return "SouthEastGravity";
case StaticGravity:
return "StaticGravity";
default:
return "NorthWestGravity";
}
}
static void
calculate_position (int i, int doubled, int *x, int *y)
{
if (i == 9)
{
*x = 150;
*y = 150;
}
else
{
int xoff = x_offset[i % 3];
int yoff = y_offset[i / 3];
if (doubled)
{
xoff *= 2;
yoff *= 2;
}
*x = screen_x_fraction[i % 3] * screen_width + xoff;
*y = screen_y_fraction[i / 3] * screen_height + yoff;
}
}
static int
find_window (Window window)
{
int i;
for (i=0; i<10; i++)
{
if (windows[i] == window)
return i;
}
return -1;
}
typedef struct {
unsigned long flags;
unsigned long functions;
unsigned long decorations;
long input_mode;
unsigned long status;
} MotifWmHints, MwmHints;
#define MWM_HINTS_FUNCTIONS (1L << 0)
#define MWM_HINTS_DECORATIONS (1L << 1)
#define MWM_HINTS_INPUT_MODE (1L << 2)
#define MWM_HINTS_STATUS (1L << 3)
int main (int argc, char **argv)
{
Display *d;
Window w;
XSizeHints hints;
int i;
int screen;
XEvent ev;
int noframes;
if (argc > 1 && strcmp (argv[1], "--noframes") == 0)
noframes = 1;
else
noframes = 0;
d = XOpenDisplay (NULL);
screen = DefaultScreen (d);
screen_width = DisplayWidth (d, screen);
screen_height = DisplayHeight (d, screen);
for (i=0; i<10; i++)
{
int x, y;
calculate_position (i, doubled[i], &x, &y);
w = XCreateSimpleWindow (d, RootWindow (d, screen),
x, y, WINDOW_WIDTH, WINDOW_HEIGHT, 0,
WhitePixel (d, screen), WhitePixel (d, screen));
windows[i] = w;
window_rects[i].x = x;
window_rects[i].y = y;
window_rects[i].width = WINDOW_WIDTH;
window_rects[i].height = WINDOW_HEIGHT;
XSelectInput (d, w, ButtonPressMask | ExposureMask | StructureNotifyMask);
hints.flags = USPosition | PMinSize | PMaxSize | PWinGravity;
hints.min_width = WINDOW_WIDTH / 2;
hints.min_height = WINDOW_HEIGHT / 2;
#if 1
/* we constrain max size below the "doubled" size so that
* the WM will have to deal with constraints
* at the same time it's dealing with configure request
*/
hints.max_width = WINDOW_WIDTH * 2 - WINDOW_WIDTH / 2;
hints.max_height = WINDOW_HEIGHT * 2 - WINDOW_HEIGHT / 2;
#else
hints.max_width = WINDOW_WIDTH * 2 + WINDOW_WIDTH / 2;
hints.max_height = WINDOW_HEIGHT * 2 + WINDOW_HEIGHT / 2;
#endif
hints.win_gravity = gravities[i];
XSetWMNormalHints (d, w, &hints);
XStoreName (d, w, window_gravity_to_string (hints.win_gravity));
if (noframes)
{
MotifWmHints mwm;
Atom mwm_atom;
mwm.decorations = 0;
mwm.flags = MWM_HINTS_DECORATIONS;
mwm_atom = XInternAtom (d, "_MOTIF_WM_HINTS", False);
XChangeProperty (d, w, mwm_atom, mwm_atom,
32, PropModeReplace,
(unsigned char *)&mwm,
sizeof (MotifWmHints)/sizeof (long));
}
XMapWindow (d, w);
}
while (1)
{
XNextEvent (d, &ev);
if (ev.xany.type == ConfigureNotify)
{
i = find_window (ev.xconfigure.window);
if (i >= 0)
{
Window ignored;
window_rects[i].width = ev.xconfigure.width;
window_rects[i].height = ev.xconfigure.height;
XClearArea (d, windows[i], 0, 0,
ev.xconfigure.width,
ev.xconfigure.height,
True);
if (!ev.xconfigure.send_event)
XTranslateCoordinates (d, windows[i], DefaultRootWindow (d),
0, 0,
&window_rects[i].x, &window_rects[i].y,
&ignored);
else
{
window_rects[i].x = ev.xconfigure.x;
window_rects[i].y = ev.xconfigure.y;
}
}
}
else if (ev.xany.type == Expose)
{
i = find_window (ev.xexpose.window);
if (i >= 0)
{
GC gc;
XGCValues values;
char buf[256];
values.foreground = BlackPixel (d, screen);
gc = XCreateGC (d, windows[i],
GCForeground, &values);
sprintf (buf,
"%d,%d",
window_rects[i].x,
window_rects[i].y);
XDrawString (d, windows[i], gc, 10, 15,
buf, strlen (buf));
sprintf (buf,
"%dx%d",
window_rects[i].width,
window_rects[i].height);
XDrawString (d, windows[i], gc, 10, 35,
buf, strlen (buf));
XFreeGC (d, gc);
}
}
else if (ev.xany.type == ButtonPress)
{
i = find_window (ev.xbutton.window);
if (i >= 0)
{
/* Button 1 = move, 2 = resize, 3 = both at once */
if (ev.xbutton.button == Button1)
{
int x, y;
calculate_position (i, doubled[i], &x, &y);
XMoveWindow (d, windows[i], x, y);
}
else if (ev.xbutton.button == Button2)
{
if (doubled[i])
XResizeWindow (d, windows[i], WINDOW_WIDTH, WINDOW_HEIGHT);
else
XResizeWindow (d, windows[i], WINDOW_WIDTH*2, WINDOW_HEIGHT*2);
doubled[i] = !doubled[i];
}
else if (ev.xbutton.button == Button3)
{
int x, y;
calculate_position (i, !doubled[i], &x, &y);
if (doubled[i])
XMoveResizeWindow (d, windows[i], x, y, WINDOW_WIDTH, WINDOW_HEIGHT);
else
XMoveResizeWindow (d, windows[i], x, y, WINDOW_WIDTH*2, WINDOW_HEIGHT*2);
doubled[i] = !doubled[i];
}
}
}
}
/* This program has an infinite loop above so a return statement would
* just cause compiler warnings.
*/
}

View File

@ -1,257 +0,0 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <glib.h>
static void
calc_rects (XRectangle *rects, int width, int height)
{
int w = (width - 21) / 3;
int h = (height - 21) / 3;
int i;
i = 0;
while (i < 9)
{
rects[i].width = w;
rects[i].height = h;
++i;
}
/* NW */
rects[0].x = 0;
rects[0].y = 0;
/* N */
rects[1].x = width / 2 - w / 2;
rects[1].y = 0;
/* NE */
rects[2].x = width - w;
rects[2].y = 0;
/* E */
rects[3].x = width - w;
rects[3].y = height / 2 - h / 2;
/* SE */
rects[4].x = width - w;
rects[4].y = height - h;
/* S */
rects[5].x = width / 2 - w / 2;
rects[5].y = height - h;
/* SW */
rects[6].x = 0;
rects[6].y = height - h;
/* W */
rects[7].x = 0;
rects[7].y = height / 2 - h / 2;
/* Center */
rects[8].x = width / 2 - w / 2;
rects[8].y = height / 2 - h / 2;
}
static Bool
all_events (Display *display,
XEvent *event,
XPointer arg)
{
return True;
}
static void
get_size (Display *d, Drawable draw,
int *xp, int *yp, int *widthp, int *heightp)
{
int x, y;
unsigned int width=0, height=0, border=0, depth=0;
Window root;
XGetGeometry (d, draw, &root, &x, &y, &width, &height, &border, &depth);
if (xp)
*xp = x;
if (yp)
*yp = y;
if (widthp)
*widthp = width;
if (heightp)
*heightp = height;
}
int
main (int argc, char **argv)
{
Display *d;
Window w, cw;
XSizeHints hints;
int screen;
XEvent ev;
int x, y, width, height;
Pixmap pix;
GC gc;
XGCValues gc_vals;
XSetWindowAttributes set_attrs;
XWindowChanges changes;
XRectangle rects[9];
gboolean redraw_pending;
unsigned int mask;
d = XOpenDisplay (NULL);
screen = DefaultScreen (d);
/* Print some debug spew to show how StaticGravity works */
w = XCreateSimpleWindow (d, RootWindow (d, screen),
0, 0, 100, 100, 0,
WhitePixel (d, screen),
WhitePixel (d, screen));
cw = XCreateSimpleWindow (d, w,
0, 0, 100, 100, 0,
WhitePixel (d, screen),
WhitePixel (d, screen));
set_attrs.win_gravity = StaticGravity;
XChangeWindowAttributes (d, cw,
CWWinGravity,
&set_attrs);
get_size (d, w, &x, &y, &width, &height);
g_print ("Parent is %d,%d %d x %d before configuring parent\n",
x, y, width, height);
get_size (d, cw, &x, &y, &width, &height);
g_print ("Child is %d,%d %d x %d before configuring parent\n",
x, y, width, height);
changes.x = 10;
changes.y = 10;
changes.width = 110;
changes.height = 110;
/* last mask wins */
mask = CWX | CWY;
mask = CWWidth | CWHeight;
mask = CWX | CWY | CWWidth | CWHeight;
XConfigureWindow (d, w, mask, &changes);
XSync (d, False);
get_size (d, w, &x, &y, &width, &height);
g_print ("Parent is %d,%d %d x %d after configuring parent\n",
x, y, width, height);
get_size (d, cw, &x, &y, &width, &height);
g_print ("Child is %d,%d %d x %d after configuring parent\n",
x, y, width, height);
XDestroyWindow (d, w);
/* The window that gets displayed */
x = 20;
y = 20;
width = 100;
height = 100;
calc_rects (rects, width, height);
w = XCreateSimpleWindow (d, RootWindow (d, screen),
x, y, width, height, 0,
WhitePixel (d, screen),
WhitePixel (d, screen));
set_attrs.bit_gravity = StaticGravity;
XChangeWindowAttributes (d, w,
CWBitGravity,
&set_attrs);
XSelectInput (d, w,
ButtonPressMask | ExposureMask | StructureNotifyMask);
hints.flags = PMinSize;
hints.min_width = 100;
hints.min_height = 100;
XSetWMNormalHints (d, w, &hints);
XMapWindow (d, w);
redraw_pending = FALSE;
while (1)
{
XNextEvent (d, &ev);
switch (ev.xany.type)
{
case ButtonPress:
if (ev.xbutton.button == 3)
{
g_print ("Exiting on button 3 press\n");
exit (0);
}
break;
case ConfigureNotify:
x = ev.xconfigure.x;
y = ev.xconfigure.y;
width = ev.xconfigure.width;
height = ev.xconfigure.height;
redraw_pending = TRUE;
break;
case Expose:
redraw_pending = TRUE;
break;
default:
break;
}
/* Primitive event compression */
if (XCheckIfEvent (d, &ev, all_events, NULL))
{
XPutBackEvent (d, &ev);
}
else if (redraw_pending)
{
calc_rects (rects, width, height);
pix = XCreatePixmap (d, w, width, height,
DefaultDepth (d, screen));
gc_vals.foreground = WhitePixel (d, screen);
gc = XCreateGC (d, pix, GCForeground, &gc_vals);
XFillRectangle (d, pix, gc, 0, 0, width, height);
/* Draw rectangles at each gravity point */
gc_vals.foreground = BlackPixel (d, screen);
XChangeGC (d, gc, GCForeground, &gc_vals);
XFillRectangles (d, pix, gc, rects, G_N_ELEMENTS (rects));
XCopyArea (d, pix, w, gc, 0, 0, width, height, 0, 0);
XFreePixmap (d, pix);
XFreeGC (d, gc);
redraw_pending = FALSE;
}
}
/* This program has an infinite loop above so a return statement would
* just cause compiler warnings.
*/
}

View File

@ -1,136 +0,0 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <stdlib.h>
#include <glib.h>
static Bool
all_events (Display *display,
XEvent *event,
XPointer arg)
{
return True;
}
#if 0
static void
get_size (Display *d, Drawable draw,
int *xp, int *yp, int *widthp, int *heightp)
{
int x, y;
unsigned int width, height, border, depth;
Window root;
XGetGeometry (d, draw, &root, &x, &y, &width, &height, &border, &depth);
if (xp)
*xp = x;
if (yp)
*yp = y;
if (widthp)
*widthp = width;
if (*heightp)
*heightp = height;
}
#endif
int
main (int argc, char **argv)
{
Display *d;
Window zero_min_size;
XSizeHints hints;
int screen;
XEvent ev;
int x, y, width, height;
Pixmap pix;
GC gc;
XGCValues gc_vals;
gboolean redraw_pending;
d = XOpenDisplay (NULL);
screen = DefaultScreen (d);
x = 0;
y = 0;
width = 100;
height = 100;
zero_min_size = XCreateSimpleWindow (d, RootWindow (d, screen),
x, y, width, height, 0,
WhitePixel (d, screen),
WhitePixel (d, screen));
XSelectInput (d, zero_min_size,
ButtonPressMask | ExposureMask | StructureNotifyMask);
hints.flags = PMinSize;
hints.min_width = 0;
hints.min_height = 0;
XSetWMNormalHints (d, zero_min_size, &hints);
XMapWindow (d, zero_min_size);
redraw_pending = FALSE;
while (1)
{
XNextEvent (d, &ev);
switch (ev.xany.type)
{
case ButtonPress:
if (ev.xbutton.button == 1)
{
g_print ("Exiting on button 1 press\n");
exit (0);
}
break;
case ConfigureNotify:
x = ev.xconfigure.x;
y = ev.xconfigure.y;
width = ev.xconfigure.width;
height = ev.xconfigure.height;
redraw_pending = TRUE;
break;
case Expose:
redraw_pending = TRUE;
break;
default:
break;
}
/* Primitive event compression */
if (XCheckIfEvent (d, &ev, all_events, NULL))
{
XPutBackEvent (d, &ev);
}
else if (redraw_pending)
{
pix = XCreatePixmap (d, zero_min_size, width, height,
DefaultDepth (d, screen));
gc_vals.foreground = WhitePixel (d, screen);
gc = XCreateGC (d, pix, GCForeground, &gc_vals);
XFillRectangle (d, pix, gc, 0, 0, width, height);
XCopyArea (d, pix, zero_min_size, gc, 0, 0, width, height, 0, 0);
XFreePixmap (d, pix);
XFreeGC (d, gc);
redraw_pending = FALSE;
}
}
/* This program has an infinite loop above so a return statement would
* just cause compiler warnings.
*/
}

281
src/xrandr.xml Normal file
View File

@ -0,0 +1,281 @@
<!DOCTYPE node PUBLIC
'-//freedesktop//DTD D-BUS Object Introspection 1.0//EN'
'http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd'>
<node>
<!--
org.gnome.Mutter.DisplayConfig:
@short_description: display configuration interface
This interface is used by mutter and gnome-settings-daemon
to apply multiple monitor configuration.
-->
<interface name="org.gnome.Mutter.DisplayConfig">
<!--
GetResources:
@serial: configuration serial
@crtcs: available CRTCs
@outputs: available outputs
@modes: available modes
@max_screen_width:
@max_screen_height:
Retrieves the current layout of the hardware.
@serial is an unique identifier representing the current state
of the screen. It must be passed back to ApplyConfiguration()
and will be increased for every configuration change (so that
mutter can detect that the new configuration is based on old
state).
A CRTC (CRT controller) is a logical monitor, ie a portion
of the compositor coordinate space. It might correspond
to multiple monitors, when in clone mode, but not that
it is possible to implement clone mode also by setting different
CRTCs to the same coordinates.
The number of CRTCs represent the maximum number of monitors
that can be set to expand and it is a HW constraint; if more
monitors are connected, then necessarily some will clone. This
is complementary to the concept of the encoder (not exposed in
the API), which groups outputs that necessarily will show the
same image (again a HW constraint).
A CRTC is represented by a DBus structure with the following
layout:
* u ID: the ID in the API of this CRTC
* x winsys_id: the low-level ID of this CRTC (which might
be a XID, a KMS handle or something entirely
different)
* i x, y, width, height: the geometry of this CRTC
(might be invalid if the CRTC is not in
use)
* i current_mode: the current mode of the CRTC, or -1 if this
CRTC is not used
Note: the size of the mode will always correspond
to the width and height of the CRTC
* u current_transform: the current transform (espressed according
to the wayland protocol)
* au transforms: all possible transforms
* a{sv} properties: other high-level properties that affect this
CRTC; they are not necessarily reflected in
the hardware.
No property is specified in this version of the API.
Note: all geometry information refers to the untransformed
display.
An output represents a physical screen, connected somewhere to
the computer. Floating connectors are not exposed in the API.
An output is a DBus struct with the following fields:
* u ID: the ID in the API
* x winsys_id: the low-level ID of this output (XID or KMS handle)
* i current_crtc: the CRTC that is currently driving this output,
or -1 if the output is disabled
* au possible_crtcs: all CRTCs that can control this output
* s name: the name of the connector to which the output is attached
(like VGA1 or HDMI)
* au modes: valid modes for this output
* au clones: valid clones for this output, ie other outputs that
can be assigned the same CRTC as this one; if you
want to mirror two outputs that don't have each other
in the clone list, you must configure two different
CRTCs for the same geometry
* a{sv} properties: other high-level properties that affect this
output; they are not necessarily reflected in
the hardware.
Known properties:
- "vendor" (s): (readonly) the human readable name
of the manufacturer
- "product" (s): (readonly) the human readable name
of the display model
- "serial" (s): (readonly) the serial number of this
particular hardware part
- "display-name" (s): (readonly) a human readable name
of this output, to be shown in the UI
- "backlight" (i): (readonly, use the specific interface)
the backlight value as a percentage
(-1 if not supported)
- "primary" (b): whether this output is primary
or not
- "presentation" (b): whether this output is
for presentation only
Note: properties might be ignored if not consistenly
applied to all outputs in the same clone group. In
general, it's expected that presentation or primary
outputs will not be cloned.
A mode represents a set of parameters that are applied to
each output, such as resolution and refresh rate. It is a separate
object so that it can be referenced by CRTCs and outputs.
Multiple outputs in the same CRTCs must all have the same mode.
A mode is exposed as:
* u ID: the ID in the API
* x winsys_id: the low-level ID of this mode
* u width, height: the resolution
* d frequency: refresh rate
Output and modes are read-only objects (except for output properties),
they can change only in accordance to HW changes (such as hotplugging
a monitor), while CRTCs can be changed with ApplyConfiguration().
XXX: actually, if you insist enough, you can add new modes
through xrandr command line or the KMS API, overriding what the
kernel driver and the EDID say.
Usually, it only matters with old cards with broken drivers, or
old monitors with broken EDIDs, but it happens more often with
projectors (if for example the kernel driver doesn't add the
640x480 - 800x600 - 1024x768 default modes). Probably something
that we need to handle in mutter anyway.
-->
<method name="GetResources">
<arg name="serial" direction="out" type="u" />
<arg name="crtcs" direction="out" type="a(uxiiiiiuaua{sv})" />
<arg name="outputs" direction="out" type="a(uxiausauaua{sv})" />
<arg name="modes" direction="out" type="a(uxuud)" />
<arg name="max_screen_width" direction="out" type="i" />
<arg name="max_screen_height" direction="out" type="i" />
</method>
<!--
ApplyConfiguration:
@serial: configuration serial
@persistent: whether this configuration should be saved on disk
@crtcs: new data for CRTCs
@outputs: new data for outputs
Applies the requested configuration changes.
@serial must match the serial from the last GetResources() call,
or org.freedesktop.DBus.AccessDenied will be generated.
If @persistent is true, mutter will attempt to replicate this
configuration the next time this HW layout appears.
@crtcs represents the new logical configuration, as a list
of structures containing:
- u ID: the API ID from the corresponding GetResources() call
- i new_mode: the API ID of the new mode to configure the CRTC
with, or -1 if the CRTC should be disabled
- i x, y: the new coordinates of the top left corner
the geometry will be completed with the size information
from @new_mode
- u transform: the desired transform
- au outputs: the API ID of outputs that should be assigned to
this CRTC
- a{sv} properties: properties whose value should be changed
Note: CRTCs not referenced in the array will be disabled.
@outputs represent the output property changes as:
- u ID: the API ID of the output to change
- a{sv} properties: properties whose value should be changed
Note: both for CRTCs and outputs, properties not included in
the dictionary will not be changed.
Note: unrecognized properties will have no effect, but if the
configuration change succeeds the property will be reported
by the next GetResources() call, and if @persistent is true,
it will also be saved to disk.
If the configuration is invalid according to the previous
GetResources() call, for example because a CRTC references
an output it cannot drive, or not all outputs support the
chosen mode, the error org.freedesktop.DBus.InvalidArgs will
be generated.
If the configuration cannot be applied for any other reason
(eg. the screen size would exceed texture limits), the error
org.freedesktop.DBus.Error.LimitsExceeded will be generated.
-->
<method name="ApplyConfiguration">
<arg name="serial" direction="in" type="u" />
<arg name="persistent" direction="in" type="b" />
<arg name="crtcs" direction="in" type="a(uiiiuaua{sv})" />
<arg name="outputs" direction="in" type="a(ua{sv})" />
</method>
<!--
ChangeBacklight:
@serial: configuration serial
@output: the API id of the output
@value: the new backlight value
Changes the backlight of @output to @value, which is
expressed as a percentage and rounded to the HW limits.
-->
<method name="ChangeBacklight">
<arg name="serial" direction="in" type="u" />
<arg name="output" direction="in" type="u" />
<arg name="value" direction="in" type="i" />
</method>
<!--
GetCrtcGamma:
@serial: configuration serial
@crtc: API id of the crtc
@red: red gamma ramp
@green: green gamma ramp
@blue: blue gamma ramp
Requests the current gamma ramps of @crtc.
-->
<method name="GetCrtcGamma">
<arg name="serial" direction="in" type="u" />
<arg name="crtc" direction="in" type="u" />
<arg name="red" direction="out" type="aq" />
<arg name="green" direction="out" type="aq" />
<arg name="blue" direction="out" type="aq" />
</method>
<!--
SetCrtcGamma:
@serial: configuration serial
@crtc: API id of the crtc
@red: red gamma ramp
@green: green gamma ramp
@blue: blue gamma ramp
Changes the gamma ramps of @crtc.
-->
<method name="SetCrtcGamma">
<arg name="serial" direction="in" type="u" />
<arg name="crtc" direction="in" type="u" />
<arg name="red" direction="in" type="aq" />
<arg name="green" direction="in" type="aq" />
<arg name="blue" direction="in" type="aq" />
</method>
<!--
PowerSaveMode:
Contains the current power saving mode for the screen, and
allows changing it.
Possible values:
- 0: on
- 1: standby
- 2: suspend
- 3: off
- -1: unknown (unsupported)
A client should not attempt to change the powersave mode
from -1 (unknown) to any other value, and viceversa.
Note that the actual effects of the different values
depend on the hardware and the kernel driver in use, and
it's perfectly possible that all values different than on
have the same effect.
Also, setting the PowerSaveMode to 3 (off) may or may
not have the same effect as disabling all outputs by
setting no CRTC on them with ApplyConfiguration(), and
may or may not cause a configuration change.
Also note that this property might become out of date
if changed through different means (for example using the
XRandR interface directly).
-->
<property name="PowerSaveMode" type="i" access="readwrite" />
</interface>
</node>