Compare commits

...

294 Commits

Author SHA1 Message Date
bb57a8b6f3 Bump version to 2.91.5 2011-01-11 14:55:19 -05:00
65d0f1a213 [l10n] Updated Estonian translation 2011-01-09 20:42:28 +02:00
4344b7ba69 [l10n] Updated Estonian translation 2011-01-07 10:17:03 +02:00
b0072add05 [l10n] Updated Estonian translation 2011-01-06 19:25:30 +02:00
4ea00e102b Add an "Above_Tab" pseudo-keysym
We want switching between the windows of an application to be an easily
accessible operation. The convenient and memorable keybinding is the
key above the tab key - but the keysym for that key isn't consistent
across different keyboard layouts.

Add code that figures out the key from the XKB geometry and a magic
keysym name "Above_Tab" that refers to this key and switch
the default binding for cycle_group to <Alt>Above_Tab. (This will
have no effect for the normal case of getting the key binding from
GConf until this patch is applied to Metacity as well.)

https://bugzilla.gnome.org/show_bug.cgi?id=635569
2011-01-05 18:58:11 -05:00
ed99d12e8b theme: Add tiled_left/tiled_right frame states
It may be desirable for theme authors to treat side-by-side tiled
windows differently, for instance to give the edge-touching border
a width of 0, so add additional frame states for tiled windows.

https://bugzilla.gnome.org/show_bug.cgi?id=637330
2011-01-05 01:49:58 +01:00
0a2bb1b71c theme: Add background functions for single buttons
With the existing background functions, single buttons can not be
styled separately - on the left side, the style of the left button
is picked, and the right button's style on the right side.

As theme authors may want to add rounded corners to button groups
as a whole, it makes sense to treat the case of a single button in
a group differently.

https://bugzilla.gnome.org/show_bug.cgi?id=635683
2011-01-05 01:49:49 +01:00
4bc8c70c75 theme-parser: Use peek_required_version() for validation
When validating button functions and frame styles, the required
format version of the features used in the theme was compared to
the major version number of the supported format, limiting additions
to major theme format bumps.
Use peek_required_version() instead, so the minor version number
of the supported theme format is taken into account.

https://bugzilla.gnome.org/show_bug.cgi?id=635683
2011-01-04 21:40:38 +01:00
9f2581318a buttons: Fix background functions for non-default layouts
While the configured layout is taken into account for positioning
the buttons, the mapping from button function states to button
position states just assumed the default button layout in LTR
locales.
Do a proper mapping depending on the actual layout instead.

https://bugzilla.gnome.org/show_bug.cgi?id=635686
2011-01-04 19:00:30 +01:00
48b9807c86 Remove option to turn compositing off
This patch removes the ability to disable compositing in mutter.  As
clutter compositing was the reason for the fork from metacity, turning
compositing off does not make sense.

https://bugzilla.gnome.org/show_bug.cgi?id=626875
2011-01-04 11:55:05 -05:00
0a821d2341 Update window->visible_to_compositor before calling into compositor
To deal with reentrancy from compositor plugins doing things like
moving windows between workspaces in an effect callback, update
the visible_to_compositor flag before calling into the compositor.

https://bugzilla.gnome.org/show_bug.cgi?id=613124
2011-01-04 11:46:44 -05:00
78092a404f If enabling a compositor with existing windows, set them visible as necessary
When a compositor is present, we keep the visibility state of the
compositor windows in sync with window->visible_to_compositor. We need
to do the same when enabling the compositor.

https://bugzilla.gnome.org/show_bug.cgi?id=613124
2011-01-04 11:40:41 -05:00
d3df33ecdb Fix errors building for gles-systems (clutter-eglx)
* GL_TEXTURE_RECTANGLE_ARB not avaliable
* clutter_glx_texture_pixmap_using_extension / CLUTTER_GLX_TEXTURE_PIXMAP not avaliable

Signed-off-by: Andreas Mueller <schnitzeltony@gmx.de>
2011-01-04 11:27:16 -05:00
1160744830 ui: Make sure we use the correct atom
We have to use gdk_x11_xatom_to_atom for display to make
it consistent with the surrounding code.
2010-12-24 18:07:03 +01:00
e884fc784e Bump GTK+ required version to 2.91.7 2010-12-23 17:22:16 -05:00
c16788f481 Added UG translation 2010-12-23 19:28:34 +01:00
a1790fb6a8 configure: Increment version
This must have been unpushed after the release.
2010-12-23 11:58:43 -05:00
cbce4fd39d ui: Adapt to GDK API changes
Some API which was only meaningful on X11 was moved to the X11
backend and renamed accordingly, so adapt to those changes.

https://bugzilla.gnome.org/show_bug.cgi?id=637802
2010-12-22 13:39:36 -05:00
93c0620151 po/vi.po: merge translation updates from metacity 2010-12-19 17:58:05 +07:00
2faf56947b Use GdkDeviceManager to get the core pointer
Commit 2c8c1c6df49 in gtk+ removed gdk_display_get_core_pointer().

The equivalent functionality can be achieved by using the
GdkDeviceManager to retrieve the client pointer device.
2010-12-17 17:12:01 +00:00
53777b133b ui: Disable multidevice support in GDK
GDK now uses XI2 by default, which conflicts with the X calls done
in mutter. Enforce the previous behavior.
2010-12-15 18:11:13 +01:00
594a69317a tiling: Reset maximized tile mode when unmaximizing
Maximized tiled windows end up with an inconsistent tile mode when
unmaximized by other means than dragging the window free (e.g.
using the unmaximize button or double clicking the title bar), so
reset the tile mode when unmaximizing.

This is not a problem for side-by-side tiling, as there are no
alternatives to dragging the window free.
2010-12-10 17:30:18 +01:00
3f9c375f1c MetaRegionIterator: avoid reading off end of rectangles array
Fix an off-by-one error in the check for "can we peek ahead to the next
rectangle".

https://bugzilla.gnome.org/show_bug.cgi?id=636491
2010-12-06 12:00:30 -05:00
544c8edd9e theme: Handle new GTK+ states 2010-12-04 17:33:01 -05:00
654bd15319 tiling: Do not restore maximized tile state when unmaximizing
When a tiled window is maximized (e.g. by clicking the title bar
button), unmaximizing the window restores the tiled state. While
this is reasonable for side-by-side tiling, it is confusing for
"maximize" tiled windows, as unmaximization has no visible effect.

Change unmaximize to only restore the tiled state of side-by-side
tiled windows.
2010-12-04 21:35:15 +01:00
b85171007e window: Add a missing break
When adding maximize tiling, the cleaning of the tiled flag was
refactored to use a switch statement - a break was missed in the
process.
2010-12-04 21:35:15 +01:00
f6ec33fa0c Updated Slovenian translation 2010-12-03 20:19:53 +01:00
7d0ff87cbe tiling: Fix "maximize" tile with no chrome at the top
The original patch triggered "maximize" when the window was dragged
to the top, so that the pointer was below or on the monitor edge and
above the work area's top.

If there's no chrome at the top of the monitor, so that monitor edge
and work area top fall together, the pointer cannot be moved above
the work area's top, so tiling was not triggered.
2010-12-03 02:45:41 +01:00
8994e621f7 Replace some GDK X11 calls with future-proof ones
GTK is about to clean up its code and remove duplicate macros and
GdkDrawable usage. To prepare for that landing, we use the future-safe
versions of the same calls.

https://bugzilla.gnome.org/show_bug.cgi?id=636302
2010-12-03 00:17:42 +01:00
d746591894 ui: Port testgradient example to GTK3
https://bugzilla.gnome.org/show_bug.cgi?id=636301
2010-12-03 00:17:42 +01:00
161c1088f9 tiling: disable "shake loose" feature when edge tiling
The old behavior of being able to shake loose a maximized window
overlaps with and is for the most part superceded by top edge tiling.

This commit changes the code to only enable shake loose behavior
when edge tiling is disabled.

https://bugzilla.gnome.org/show_bug.cgi?id=630548
2010-12-02 17:42:14 -05:00
07c0471902 tiling: Add new "maximized" tile
In addition to the existing side-by-side tiling modes, this commit
adds a new "maximize" tiling mode.  It allows the user to maximize
their windows (in other words, tile with the edge panels) by dragging
their window to the top edge of the monitor.

https://bugzilla.gnome.org/show_bug.cgi?id=630548
2010-12-02 17:11:11 -05:00
5f4ee1b6e7 tiling: use META_WINDOW_TILED_SIDE_BY_SIDE in state check
The meta_window_handle_mouse_grab_op_event function ensures
the tile_mode variable is in a consistent state after a drag
op is finished.

The way this is current done is:

if (!window->maximized_vertically &&
    window->tile_mode != META_TILE_NONE)
  window->tile_mode = META_TILE_NONE;

While valid, it doesn't "read" as well as using the
META_WINDOW_TILED_SIDE_BY_SIDE macro, since the macro is specifically
about side-by-side tiling.

This commit just changes things to use the macro and to not bother
checking the tile mode (since if we just reset it anyway, then it doesn't
matter if the value is right or wrong to begin with).

https://bugzilla.gnome.org/show_bug.cgi?id=630548
2010-12-02 16:35:23 -05:00
aa3a4a48e4 tiling: add side_by_side suffix to tile code
The meta_window_can_tile function and META_WINDOW_TILED
macro are pretty side-by-side tiling specific, so
rename them.

https://bugzilla.gnome.org/show_bug.cgi?id=630548
2010-12-02 16:35:23 -05:00
0d27c9600f tiling: rename side-by-side tiling to edge tiling
Currently, the new tiling feature, supports side-by-side, horizontal
tiling when dragging windows to one of the vertical edges of a monitor.

Other types of tiling (on other monitor edges) are potentially useful,
though.

This commit renames the preference from side_by_side_tiling to
edge_tiling.

https://bugzilla.gnome.org/show_bug.cgi?id=630548
2010-12-02 16:35:23 -05:00
1986b20499 Add (out) annotation and documentation to meta_window_get_outer_rectangle()
GObject introspection cannot detect that rect is an (out) parameter.
Also add a meaningful documentation for humans like us.
2010-12-02 00:06:42 +01:00
e7a10b0d6a Bump version to 2.91.3 2010-11-29 16:04:46 -05:00
6b98644c58 workspace: Consider text direction when switching
A direction parameter is passed to meta_compositor_switch_workspace(),
to indicate the direction of the switch depending on the workspace
layout.
In contrast to the switcher popup, this parameter does not take the
text direction of the locale into account. Change this, so that the
workspace switching animations move in the correct direction.

https://bugzilla.gnome.org/show_bug.cgi?id=636083
2010-11-29 21:42:58 +01:00
5397335ae8 Fix builds with clutter < 1.5.2 2010-11-22 22:00:02 -06:00
0b6d6e517d configure.in: it's git, not Subversion
Bug #635493
2010-11-22 20:04:22 -05:00
b031543f5a Fix updating overlay key keycode when keymap changes
overlay_key_combo needs the same treatment as other keycodes on a
change - we should always recompute it if we have a keysym not
a keycode, and not only if the keycode hasn't already been
computed.
2010-11-22 16:10:34 -05:00
c6be05f9d7 Unify keymap-reloading code branches
Simplify the keymap loading logic by unifying the different
branches; in the reorganization this patch fixes a bug where when
we got a MappingKeyboard event we wouldn't update virtual modifiers
correctly.

Based on a patch by Thomas Thurman <tthurman@gnome.org>

https://bugzilla.gnome.org/show_bug.cgi?id=565540
2010-11-22 16:02:03 -05:00
cb88e0d052 Update keybindings when XKB keyboard layout changes
* Select for XKB keyboard notification events explicitly; since GTK+
  has selected for XKB events, delivery of old-school MappingNotify
  events is disabled.

* Fix a bug where once a keycode was loaded for a key binding,
  it would never be reassigned; we want to laod new keycodes for
  all bindings that have a key symbol rather than a fixed
  keycode.

[ With fixes from Owen W. Taylor <otaylor@fishsoup.net> ]

https://bugzilla.gnome.org/show_bug.cgi?id=565540
2010-11-22 16:02:03 -05:00
54e82daae2 configure.ac: move CFLAGS modifications after all tests
-Werror in CFLAGS was causing the check for GNU gettext in
AM_GNU_GLIB_GETTEXT to fail, resulting in .mo files in $libdir.

https://bugzilla.gnome.org/show_bug.cgi?id=635528
2010-11-22 10:49:55 -05:00
1394c566eb [MetaWindowActor] Fix crash in shadow shape creation
Protect against shape_region or bounding_region being NULL in check_needs_shadow.

This can happen for short lived windows and result into a crash.

https://bugzilla.gnome.org/show_bug.cgi?id=635421
2010-11-21 19:57:42 +01:00
3183d954a0 Updated Hebrew translation. 2010-11-21 12:58:12 +02:00
67b89e5c86 Updated Norwegian bokmål translation 2010-11-20 18:40:39 +01:00
c88c94886b Added UG translation 2010-11-20 12:06:01 +01:00
c1f6902cb9 Updated Galician translations 2010-11-20 01:24:44 +01:00
8817e68926 Use COGL_MATERIAL_WRAP_MODE_* defines not COGL_PIPELINE_*
Since we aren't depending on Clutter 1.5 or using the new
CoglPipeline name elsewhere, we need to stick to the old
COGL_MATERIAL_WRAP_MODE_* names, which are provided with
compatibility defines in Clutter 1.4.

Pointed out by Rico Tzschichholz
2010-11-19 14:41:44 -05:00
b1868fb213 Updated Spanish translation 2010-11-19 13:46:08 +01:00
6260814285 Turn off background repeats for a full-size image
If we have repeats on for a full-sized image, then if the background
is displayed scaled (for example, in a desktop preview mode) then we
can get artifacts along the edge of the background where the repeat
of the opposite edge is blended in by bilinear scaling. So turn off
repeats when the screen and background image sizes match.

https://bugzilla.gnome.org/show_bug.cgi?id=634833
2010-11-18 13:58:37 -05:00
07e6c5aac2 Draw the root window background
Add code to track and draw the root window background. The advantage of doing
it here as compared to in a plugin is that we can use the visiblity smarts
of MetaWindowGroup to optimize out drawing the background when obscured.

If handling other than tracking the _XROOTPMAP_ID property is desired in the
future, more functionality like setting the background from a file or doing
cross-fades can be added.

The new background actor is exposed to plugins via meta_plugin_get_background_actor()
similar to other exposed actors to allow cloning the background for use in
other displays. The actual class is not installed for public consumption at
the moment since it has no useful methods.

https://bugzilla.gnome.org/show_bug.cgi?id=634833
2010-11-18 13:58:37 -05:00
0477a3066d Refactor "texture material" creation from MetaShadowFactory
Create new cogl-utils.[ch] and move a helper function from
MetaShadowFactory there as meta_create_texture_material(); this
allows us to create single-layer materials from different parts of
Mutter and have them share the same template material.

Also expose a function for creating a 1x1 texture of a given
color meta_create_color_texture_4ub().

https://bugzilla.gnome.org/show_bug.cgi?id=634833
2010-11-18 13:58:37 -05:00
59639909b1 MetaWindowGroup: further optimize paints by using current scissor
When in a partial stage paint, we can combine that with the visibility
information in MetaWindowGroup to further eliminate unneeded drawing.

Since there is no current Clutter API to access the current clip,
drop to using GL directly.

https://bugzilla.gnome.org/show_bug.cgi?id=634779
2010-11-18 13:58:36 -05:00
64c37852b1 meta-actor-window: Use G_UNLIKELY for TFP check
This is just a microptimization, as we pretty much always use
TFP (and do the check every time we set a pixmap),
we can let gcc generate better code here.

https://bugzilla.gnome.org/show_bug.cgi?id=633002
2010-11-18 18:51:04 +01:00
bac668d287 Optimize out restacks that don't change actor order
For various reasons (mostly the stack tracker correctly predicting the
stacking order before getting events, but also because of the processing
that the compositor does to get the actor stacking order) the compositor
can be told to sync the stack when it has nothing to do. Detect this
at the last moment before actually telling Clutter to restack to avoid
triggering unnecessary redraws.

https://bugzilla.gnome.org/show_bug.cgi?id=634771
2010-11-18 10:07:38 -05:00
f372fa29b2 MetaStackTracker: Avoid queueing resync for obvious no-ops
Since we can't distinguish a ConfigureEvent that indicates a raise
from a ConfigureEvent that indicates a move, we get lots of
STACK_OP_RAISE_ABOVE events for windows that are already in the
right place in the stacking order. Avoid queueing a restack in that
case.

https://bugzilla.gnome.org/show_bug.cgi?id=634771
2010-11-18 09:54:44 -05:00
8b24711bba Omit shadows for fullscreen and maximized windows
Fullscreen and maximized windows never have visible shadows - the only
case where we would ever see them is if they bleed onto an adjacent
monitor and that looks bad.

It's small performance win to avoid computing them, and this also avoids
painting the top shadow for all maximized windows in GNOME Shell - since
the top panel isn't a X window, it doesn't factor into the computation
of what parts of windows are visible and maximized windows are computed
as having a top shadow.

https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:58 -05:00
d4c28fc5f5 Add meta_window_get_maximized() and meta_window_is_fullscreen()
These functions duplicate existing properties; they are added for
convenience and to avoid the GObject property code on some
performance critical painting paths.

https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:58 -05:00
ca5f2ac3ec Implement more accurate clipping of obscured shadows
Instead of making optimizing obscured shadows an all-or-none operation,
pass the clip region to meta_shadow_paint() and only paint the 9-slices
that are at least partially visible.

https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:58 -05:00
15f9590427 Report a correct paint volume for shadowed windows
Since we paint shadows directly now rather than using a child actor
in the ClutterGroup, we need to implement get_paint_volume() for
Clutter 1.5.

https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:58 -05:00
21a246eb42 Use a template material for shadows
To avoid unnecessary shader recompilation, use a root template material
for all shadows.

https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:58 -05:00
1bbaec81ce Make window shadows globally configurable
Instead of setting shadow parameters on individual windows, add the
idea of a "shadow class". Windows have default shadow classes based
on their frame and window type, which can be overriden by setting
the shadow-class property.

Each shadow class has separably configurable parameters for the
focused and unfocused state. New shadow classes can be defined with
arbitrary names.

https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:58 -05:00
7952feb48b Export meta_frame_type_to_string()
Frame types will form the bases of shadow classes, which are strings,
so export the to-string function so that we can do the conversion
uniformly.

https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:57 -05:00
52aebdf223 Add meta_window_get_frame_type()
Add a public function to get the frame type for a window; the
code is refactored from existing code in core.c.

https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:57 -05:00
6b16604c26 Export meta_window_appears_focused()
Move meta_window_appears_focused() into the public window.h so
we can use it to change the shadow type.

https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:57 -05:00
3c4d52732e Make MetaShadowFactory public
The basic MetaShadowFactory type is moved to a public header, while
the functions to fetch and paint shadows are kept private.
The public object will be used for configuration of shadows by
plugins.

https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:57 -05:00
d56d267f7d MetaShadowFactory: convert to a GObject
https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:57 -05:00
8eb31944a5 MetaShadowFactory: Add the ability to top-fade a shadow
For attached modal dialogs, we want the shadow to fade out at the top
as if the window was glued to the parent at the top. Add a
shadow-top-fade property to MetaWindowActor and the corresponding
parameter to meta_shadow_factory_get_shadow().

The internal implementation of MetaShadow is adjusted to work
in terms of an "inner border" and "outer border" instead of doing
the calculations in terms of an aggregate border and the spread
of the shadow. The old way of doing things gets clumsy when the
top_fade distance is added in as well.

https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:57 -05:00
ed2fbcd13a Add frame type for attached modal dialogs
Add a new frame type META_FRAME_TYPE_ATTACHED which is used for
attached modal dialogs.

The theme format version is bumped to 3.2, and attached windows
can have borders defined in a metacity-theme-3.xml as:

 <window version=">= 3.2" type="attached" style_set="[name]"/>

If no style is defined for "attached", drawing will fall back
to the "border" type.

https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:57 -05:00
9f4942e9a7 Make shadows pretty and configurable
The current shadow code just uses a single fixed texture (the Gaussian
blur of a rectangle with a fixed blur radius) for drawing all window
shadows. This patch adds the ability

* Implement efficient blurring of arbitrary regions by approximating
  a Gaussian blur with multiple box blurs.

* Detect when multiple windows can use the same shadow texture by
  converting their shape into a size-invariant MetaWindowShape.

* Add properties shadow-radius, shadow-x-offset, shadow-y-offset,
  shadow-opacity to allow the shadow for a window to be configured.

* Add meta_window_actor_paint() and draw the shadow directly
  from there rather than using a child actor.

* Remove TidyTextureFrame, which is no longer used

https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:56 -05:00
982a10ac44 Added UG translation 2010-11-14 00:06:42 +01:00
e59a9872b4 Added UG translation 2010-11-13 22:49:22 +01:00
9aedd32e01 Use gtk_button_box_new() instead gtk_[h|v]button_box_new() 2010-11-11 01:25:35 +01:00
dd0ca4dd60 Updated Arabic translation 2010-11-09 03:40:15 +02:00
3e7d2df6f3 Bump version to 2.91.2 2010-11-08 10:34:56 -05:00
02e709e89e Prepare for the demise of size_request
The size_request vfunc is going to be dropped in GTK3; replace
the usage in MetaAccelLabel and MetaPreview with
get_preferred_width/get_preferred_height vfuncs.

https://bugzilla.gnome.org/show_bug.cgi?id=633352
2010-11-03 19:06:08 -04:00
1114e5effa Update Czech translation 2010-10-31 11:48:40 +01:00
c40fab214d Fix warning from synthesized events with GdkDevice
In GTK+ 3, it's mandatory to have a GdkDevice in a synthesized event,
so fill in the pointer device for the events we synthesize and forward
to GTK+. Since gdk_event_set_device() only works for allocated events,
we need to switch to gdk_event_new() rather than using stack allocated
events.

https://bugzilla.gnome.org/show_bug.cgi?id=633401
2010-10-28 17:27:14 -04:00
441c050808 Fix check for events on UI widgets
Now that we create MetaWindow objects for override-redirect windows, we need
to check all key press events to see if they are on GTK+ widgets, not just
events that don't match a MetaWindow. This fixes a problem with alt-Tab stealing
grabs away from the window menu.

https://bugzilla.gnome.org/show_bug.cgi?id=633398
2010-10-28 16:33:28 -04:00
85425f64a5 Stop confusing GDK's grab tracking
With client side windows, mixing GDK event delivery with explicit calls
to XUngrabPointer() can result in GDK losing button release events
it expects to get. This means that GDK thinks there is an implicit
grab in effect when there is none and send events to the wrong window.

Avoid this by bypassing GDK's event handling for most mouse events.
We do a simplified conversion of the X event into a GdkEvent and send
it to directly to libgtk for delivery.

We make an exception when a GDK grab is already in effect - this is
needed for the correct operation of menus.

http://bugzilla.gnome.org/show_bug.cgi?id=599181
2010-10-28 15:48:54 -04:00
b445ee3763 Remove compatibility for GTK+-2.0
While the Meego developers agreed to switching mutter to GTK+-3.0
unconditionally a while ago, Canonical used a GTK+-2.0 build for their
Unity project. As Canonical now announced a switch to compiz as their
window manager, there is no longer a reason to maintain GTK+-2.0
compatibility.

https://bugzilla.gnome.org/show_bug.cgi?id=633133
2010-10-28 12:16:14 +02:00
95a7f0269a Bump version to 2.91.1 2010-10-27 17:02:04 -04:00
db63764e22 Updated Galician translations 2010-10-26 16:46:11 +02:00
03578b69f3 meta_display_get_keybinding_action: remove keysym parameter
meta_display_process_key_event() always looks up events based on the
"default" keysym for the keycode, so we should do the same here. This
fixes, eg, the lookup of Shift-Alt-Tab (which would otherwise be
unrecognized because the keysym would be XK_ISO_Left_Tab rather than
XK_Tab).

https://bugzilla.gnome.org/show_bug.cgi?id=632155
2010-10-25 16:37:52 -04:00
8cbaee47a0 Use correct signature and connection function for ::draw
In ui/fixedtip.c, use g_signal_connect instead of g_signal_connect_swapped
since we're not using the data pointer (and for clarity).
At the same time, ensure that both the GTK2 and the GTK3 code paths
have the correct signature for the handler.

https://bugzilla.gnome.org/show_bug.cgi?id=633051
2010-10-25 18:24:22 +02:00
bcded5ae25 Update Simplified Chinese translation. 2010-10-25 16:12:14 +08:00
7227b636c6 Fix typo 2010-10-24 12:00:57 +02:00
af715f71e7 Make color constants work without warnings
The code for defining a color as a constant had broken logic: it
would try to parse the color first as an double, then as an integer;
the second attempt would produce an error about overwriting the
already-set-GError. Then it would clear the error and store the constant
as a color.

Use the fact that colors have to start with a letter or #, divide the
space of constants into:

 - Integers
 - Doubles
 - Colors

so we get good error messages. Based on a patch by
William Jon McCann <jmccann@redhat.com>.

Note that this breaks the ability to specify an integer constant as
identical to another integer constant (the same didn't work for doubles.)
I think this was an accidental side effect of the code and not something
that was intentional or people were relying on

https://bugzilla.gnome.org/show_bug.cgi?id=632116
2010-10-23 16:11:06 -04:00
52bc675fcb introspection: remove --allow-unprefixed
Remove --allow-unprefixed option to the scanner, and fix resulting
problems:

 * theme.h and boxes.h are split into a main -header and a private
   header that includes stuff that is not generally useful and
   hard to introspect. Merge theme-parser.h into theme.h.

 * meta_display_get_atom() and meta_window_get_window_type_atom()
   are marked as (skip)

 * Fix annotation: (element-type Strut) => (element-type Meta.Strut)

https://bugzilla.gnome.org/show_bug.cgi?id=632494
2010-10-23 15:58:16 -04:00
1920f211b0 Remove Mutter namespace prefix
Move all objects and functions namespaced with Mutter into the Meta namespace
to get a single consistent namespace. Changes that aren't simply changing mutter
to meta:

 MutterWindow              => MetaWindowActor
 mutter_get_windows        => meta_get_window_actors
 mutter_plugin_get_windows => meta_plugin_get_window_actors

https://bugzilla.gnome.org/show_bug.cgi?id=628520
2010-10-23 15:48:29 -04:00
804117c456 Remove MetaRegion
In many places, MetaRegion was being used entirely internally, rather
than for gtk2/gtk3 compatibility. In these cases, it's simpler to just
depend on cairo-1.10 (for both gtk2 and gtk3) and use cairo_region_t.

The few places where we did need GDK compatibility (GdkEvent.region and
gdk_window_shape_combine_mask) are replaced with a combination of
converting GdkRegion to cairo_region_t and conditional code.

https://bugzilla.gnome.org/show_bug.cgi?id=632474
2010-10-23 15:48:29 -04:00
9a4d1686a6 Fill in missing MetaKeyBindingAction values
Also, add an assertion to init_bindings() to keep it from getting out
of sync again in the future.

https://bugzilla.gnome.org/show_bug.cgi?id=632149
2010-10-20 14:00:06 -04:00
e8dda03441 Fix drawing of <arc> elements
This patch fixes the drawing of <arc> theme elements to appear in the desired orientation

https://bugzilla.gnome.org/show_bug.cgi?id=631487
2010-10-11 17:46:29 -04:00
4b214b4710 Clean up antialiasing fixes
Simplify the code by noting that when we have square end-caps, the
results of generic line path give the right pixel-aligned rectangle
for horizontal/vertical lines.

Add comments and remove some extra braces.

https://bugzilla.gnome.org/show_bug.cgi?id=630426
2010-10-06 13:01:54 -04:00
6ed34976c9 Patch to fix theme breakage in 2.30.2; see bug 630426 2010-10-06 12:40:30 -04:00
069092eb9d configure: Flip default to GTK3
This is the primary target for GNOME 3, so it makes sense to have
it be the default.
2010-10-05 12:07:53 -04:00
dc7d323295 configure: Check for new enough libcanberra
The GNOME Shell jhbuild doesn't include libcanberra atm, so
if we find an old one (as is in F14) it will fail with a newer
GTK3.
2010-10-05 12:03:08 -04:00
cbedfd680f Bump version to 2.91.0 2010-10-04 13:38:24 -04:00
a1e2e2a13d Fix builddir != srcdir builds
An accidental removal of $$pwd was causing Meta-<version>.gir to
be generated in srcdir.
2010-10-04 13:38:24 -04:00
a53a40c43e Use the correct image missing icon name from the icon naming spec
Fixes an assertion when the wrong icon can't be found.
2010-10-02 16:35:19 -04:00
33489c8cb8 Adapt to GTK API changes
This code adapts mutter to the latest changes to GTK in
http://git.gnome.org/browse/gtk+/commit/?id=872ef111ecabf6cd4453590b1e17afd3c9757f28
that remove the dest argument from gdk_pixbuf_get_from_window() and
gdk_pixbuf_get_from_surface().

It also removes the dest argument from meta_gdk_pixbuf_get_from_pixmap()
to match. The function is internal and the argument wasn't used.

https://bugzilla.gnome.org/show_bug.cgi?id=631147
2010-10-02 04:27:05 +02:00
c382d8f7ea Remove unused variable 2010-09-30 18:49:21 +02:00
f2ccf70f8d mutter-window: Don't track the window type twice
Currently mutter-window has its own type field, even though the same
information is already present in meta_window.

And while at it get rid of MetaCompWindowType, it is equally redundant.

https://bugzilla.gnome.org/show_bug.cgi?id=630363
2010-09-30 18:35:12 +02:00
ff04e38326 Replace gtk_window_set_visual() with gtk_widget_set_visual()
gtk_window_set_visual() was changed back to work on a widget level
for more compatibility with 2.x.

https://bugzilla.gnome.org/show_bug.cgi?id=630843
2010-09-28 15:37:53 -04:00
1123fca3f2 mutter-window: Add error traps check_needs_reshape
A window might change its shape and close immediately and thus causing
XShapeGetRectangles to produce a BadWindow, use an error trap
to avoid that.
2010-09-27 20:11:53 +02:00
33e2d15495 Adapt to GtkObject removal in GTK3
The destroy signal has been moved to GtkWidget, so change the class_init
functions of MetaFrames and MetaAccelLabel to match.

https://bugzilla.gnome.org/show_bug.cgi?id=630671
2010-09-27 13:58:36 -04:00
b265e8099a theme: Get rid of x/y_offset usage when drawing frames
Commit aa65f94c67 that started passing
cairo_t around broke offsets. Since passing cairo_t makes them
unnecessary, this patches removes them rather than fixing them.

This patch changes API.

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-27 17:07:23 +02:00
a2b3f9aeb0 frames.c: Clip the client area correctly
The code switched the x and y variables. Oops.

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-27 17:07:23 +02:00
d19295a68e Updated Hebrew translation. 2010-09-26 23:55:12 +02:00
9f5d8d1a2a Fix compilation against latest GTK3 changes
With the newest changes to GTK3, some things were changed. This patch
now uses the features introduced in gtk3-compat.h in previous patches.

This patch also introduces a macro named USE_GTK3 that is used to
differentiate between GTK3 and GTK2. Its main use is differenting
between expose and draw handlers for GtkWidget subclasses.

The draw vs expose handlers question is usually handled by using ifdefs
at the beginning and end to set up/tear down a cairo_t and then use it.

However, when the function is too different and too many ifdefs would be
necessary, two versions of the function are written. This is currently
the case for:
- MetaAccelLabel
- MetaFrames

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-26 17:09:20 +02:00
e75abacec6 frames.c: Make cached_pixels_draw() take a cairo_t
This basically just moves the creation of the cairo_t out of the
function. It is done in preparation for GTK3.

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-26 17:09:20 +02:00
1c31e8ffc2 ui: Port draw_workspace() to take a cairo_t
https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-26 17:09:20 +02:00
1083a4c0b7 Introduce MetaPixmap compatibility wrapper
Similar to the region compatibility shim, we will soon need a
compatibility shim around GdkPixmap/cairo_surface_t. For now, the patch
just introduces the compatibility layer.

This patch also does not include the function
meta_gdk_pixbuf_get_from_pixmap() as that function will need special
treatment in GTK3 anyway.

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-26 17:09:20 +02:00
d212be799a frames.c: Merge clear_backing() function into its only user
Avoids creating a cairo_t twice. And without the code to create a
cairo_t, there was not a lot left to warrant a separate function.

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-26 17:09:20 +02:00
84986c7695 frames.c: Change meta_frames_paint() to take a cairo_t
Rename meta_frames_paint_to_drawable() to meta_frames_paint() and make
it take a cairo_t as an argument instead of creating the cairo_t itself.

This patch refactors code for GTK3 changes where code needs to handle
cairo_t and not GdkDrawable arguments.

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-26 17:09:20 +02:00
aa65f94c67 theme: Upgrade to use Cairo for painting (changes API)
This commit is in preparation for the work happening in GTK3, which will
use Cairo for drawing exclusively. So it is necessary to move all
drawing code to Cairo. In this commit the "gtk2" code is used for both
gtk2 and gtk3; compatibility with newer versions of gtk3 where different
code is needed will be added subsequently.
For compatibility with older GTK versions, the file gdk2-drawing-utils.h
provides a compatibility layer.

The commit changes the API of libmutter-private.

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-26 17:09:20 +02:00
dc80242e51 build: Only install libmutter-private for GTK3 builds
Define INSTALL_LIBMUTTER_PRIVATE with AM_CONDITIONAL and use it to build
an installed or uninstalled libmutter-private.so

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-26 17:09:20 +02:00
f2c63e5eec ui: Remove unused meta_gdk_pixbuf_get_from_window()
https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-26 17:09:20 +02:00
1fc91dc459 Updated Norwegian bokmål translation 2010-09-26 11:44:57 +02:00
a2e4789b3e tiling: Limit tiling to landscape orientation
Tiling is arguably only useful for monitors in landscape orientation,
so disable it when the current monitor is in portrait orientation.
2010-09-24 17:46:57 +02:00
7d58524185 Fix use of (closure) annotation
For functions (but not callback types), '(closure)' is used on the
callback parameter, and takes the name of the parameter which is
the closure/user data.
2010-09-24 11:28:26 -04:00
635e20d057 Allow breaking out from tiling during a mouse resize
Extend the code which allows resizing maximized windows using
alt-middle-drag, so that it applies to tiled windows as well.

https://bugzilla.gnome.org/show_bug.cgi?id=629931
2010-09-23 13:32:35 +02:00
1c3f7c4088 Allow breaking out from maximization during a mouse resize
A maximized window can't be resized from the screen edges (preserves
Fitts law goodness for the application), but it's still possible
to start a resize drag with alt-middle-button. Currently we just
don't let the user resize the window, while showing drag feedback;
it's more useful to let the user "break" out from the resize.

This provides a fast way to get a window partially aligned with
the screen edges - maximize, then alt-drag it out from one edge.

Behavior choices in this patch:

 - You can drag out a window out of maximization in both directions -
   smaller and larger. This can be potentilaly useful in multihead.

 - Dragging a window in only one direction unmaximizes the window
   fully, rather than leaving it in a horizontally/vertically
   maximized state. This is done because the horizontally/vertically
   maximzed states don't have clear visual representation and can
   be confusing to the user.

 - If you drag back to the maximized state after breaking out,
   maximization is restored, but you can't maximize a window by
   dragging to the full size if it didn't start out that way.

A new internal function meta_window_unmaximize_with_gravity() is
added for implementing this; it's a hybrid of
meta_window_unmaximize() and meta_window_resize_with_gravity().

Port of the metacity patch from Owen Taylor in bug 622517.

https://bugzilla.gnome.org/show_bug.cgi?id=629931
2010-09-23 13:32:35 +02:00
5c3b0cda2e ui: gtk_widget_show() the MetaFrames object
The widget needs to be visible and mapped for GTK3 to deliver expose
events to the widget. This is achieved by making the map function a
no-op and calling gtk_widget_show() instead of just calling
gtk_widget_realize().
Apart from making GTK think the widget is drawable, the effect is the
same.

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:54:14 +02:00
a3c6486e52 Remove MetaImageWindow
The code isn't used anymore.

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:54:14 +02:00
741d2b761a frames.c: Simplify cached area subtraction code
Because we store the affected rectangle in the piece, we can just
subtract it and don't need any complicated computations.

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:54:14 +02:00
a0ffe71db3 Change the cached rectangle ares to a GdkRectangle
Simplifies the code as the rectangle is mainly interacting with GDK
APIs.

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:54:14 +02:00
ecf812db83 frames.c: Do not create pixmaps when there's nothing to draw
https://bugzilla.gnome.org/show_bug.cgi?id=630203

Take advantage of existing handling for CachedFramePiece.piece == NULL
to avoid generating pixmaps when width/height are 0
2010-09-23 12:54:14 +02:00
afd3b96e2e Simplify code: Use cairo_paint() to paint the whole pixmap
Also, gdk_drawable_get_size() is going away soon

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:54:14 +02:00
b79e6c0b3e Remove unused code
https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:54:14 +02:00
c6f8ad24bd Remove MetaArea widget
It's unused.

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:54:14 +02:00
d4d05e496a Remove meta_ui_get_pixbuf_from_pixmap() function
https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:54:14 +02:00
0a88329526 Move begin_paint() handling to expose handler
This way, we can remove the special casing in
meta_frames_paint_to_drawable().
Since the setup in meta_frames_paint_to_drawable() is relatively cheap,
doing it once per rectangle in the expose area should be fine.

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:54:00 +02:00
b4344b5ab5 Remove NULL checks in meta_frame_layout_get_borders()
This function actually handles NULL. (And I'm going to pass some NULLs
soon).

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:31:02 +02:00
4ac836fde4 Remove client area from region in expose event
https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:31:02 +02:00
7897448a5b frames.c: Remove workaround now that clip_to_screen() works properly
This code seems to be basically broken. It looks like it tried to clip
the expose area to the screen, but used screen coordinates for the
screen area but frame coordinates for the frame area. So someone tried
to work around this by adding a border around the screen, which made the
broken clipping work most of the time (see bugs below for examples where
it didn't).
Anyway, all of this is gone now.

https://bugzilla.gnome.org/show_bug.cgi?id=399529
https://bugzilla.redhat.com/show_bug.cgi?id=557402
https://bugzilla.gnome.org/show_bug.cgi?id=538438
https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:31:01 +02:00
94f4011844 frames.c: Make clip_to_screen() actually clip to the screen
https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:31:01 +02:00
3f8e6020f7 ui: Clip the region once, not every rectangle manually
https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:31:01 +02:00
beb65f011d tile-preview: Fix crash when falling back to default style
gtk_rc_get_style_by_paths() returns NULL if no matching style was
found and the default style should be used. Actually use the default
style in this case.

https://bugzilla.gnome.org/show_bug.cgi?id=630003
2010-09-22 00:11:14 +02:00
c2f894963a Use GDK error trapping straight-up
The hacks we were playing by calling gdk_error_trap_push() and then
resetting the error handler are incompatible with the rewrite of
GDK error traps.

Since the new error code has some features that simplify what we
are doing (like automatically figuring out whether a XSync() is needed)
and because our custom error handler didn't have a lot of a point,
use a separate code path for GTK+ 3.0 builds that just uses the
GDK error traps straight-up without a custom error handler.

https://bugzilla.gnome.org/show_bug.cgi?id=630195
2010-09-20 18:41:21 -04:00
dacea8edf9 Fix behavior of the window resize popup to only appear when resizing
This patch reverts part of commit 94f6479, which accidentally removed
a section of code and introduced this bug.

https://bugzilla.gnome.org/show_bug.cgi?id=598603
2010-09-20 11:14:45 -04:00
3fed2ab64d [mutter-shaped-texture] Use a base material for all instances
Use a base material for all textures rather than recreating it for every instance,
this should allow Cogl to optimize the program generation.

Idea 'stolen' from:

http://git.clutter-project.org/clutter/commit/?id=7e56a98413817479d0501ce8af9fad3e6411104d

https://bugzilla.gnome.org/show_bug.cgi?id=629350
2010-09-19 16:17:36 +02:00
476652da0a [i18n] Updated German translation 2010-09-19 13:52:05 +02:00
35289050e4 Updated French translation 2010-09-19 00:22:14 +02:00
ed9d7f18a6 Avoid confusion when _NET_WM_USER_TIME_WINDOW is in the window stack
Wine sets _NET_WM_USER_TIME_WINDOW to point to an unmapped toplevel;
this was causing much confusion because both the real window and
the unmapped window were in the window stack and mapped back to the
same MetaWindow.

Debugged by Alban Browaeys
https://bugzilla.gnome.org/show_bug.cgi?id=593887
2010-09-17 14:23:33 -04:00
a7d1053ff5 Updated Spanish translation 2010-09-17 19:47:59 +02:00
97e2b4666b Implement side-by-side tiling
When dragging a window over a screen edge and dropping it there,
maximize it vertically and scale it horizontally to cover the
corresponding half of the current monitor.

Whenever a "hot area" which triggers this behavior is entered, an
indication of window's target size is displayed after a short delay
to avoid distraction when moving a window between monitors.

https://bugzilla.gnome.org/show_bug.cgi?id=606260
2010-09-17 16:00:03 +02:00
7d8cc4f940 Fix build error introduced in the last commit 2010-09-15 03:15:46 +02:00
ee2f995fc7 introspection: Fix annotations
The scanner got stricter again - some annotations need fixing.
2010-09-15 02:31:47 +02:00
7e852f8c14 Updated Hungarian translation 2010-09-14 12:07:08 +02:00
b4c1692d14 Updated Slovenian translation 2010-09-11 20:29:06 +02:00
c0858b247f Updated Tamil translation 2010-09-11 15:16:58 +05:30
0a956f56aa update for Punjabi 2010-09-11 08:35:26 +05:30
66105c6e7e Optionally attach modal dialogs
Add a preference /apps/mutter/general/attach_modal_dialogs. When true, instead
of having independent titlebars, modal dialogs appear attached to the titlebar
of the parent window and are moved together with the parent window.
https://bugzilla.gnome.org/show_bug.cgi?id=612726
2010-09-11 05:36:12 +04:00
bb1ab0afd9 Lower a window and all its transients as a unit
It's strange to leave transients windows around, after ancestor window was
lowered and unfocused.
https://bugzilla.gnome.org/show_bug.cgi?id=612726
2010-09-11 05:36:02 +04:00
0d51d9e4cf Remove usage of 'gdk_display', a removed symbol in gtk3.
https://bugzilla.gnome.org/show_bug.cgi?id=629232
2010-09-10 15:18:06 -04:00
e3789e31ef introspection: Remove workaround MetaMutter comment
The scanner should understand this better now.
2010-09-09 11:45:08 -04:00
8a6b583cdc Adjust for API break in gdkkeysyms.h
The key symbols were renamed to avoid namespace conflicts with
gobject-introspection.
2010-09-09 17:37:48 +02:00
86b8b9051f Updated Polish translation 2010-09-07 18:17:25 +02:00
4c0763792d introspection: Build with --warn-fatal, drop fix-meta-rectangle.py hack
Cleanly build with --warn-fatal.  Implementation:

* Liberally apply (skip) where the API is clearly C only, e.g. uses
  XLib.  The theming code and MutterPlugin are skipped too.
* Add missing (transfer) and (element-type) annotations

For a few functions that had a comment, I turned it into gtk-doc, but
I didn't (with a few exceptions) try to write new documentation in
this pass.
2010-09-07 10:48:07 -04:00
599eb5e3e4 Updated Portuguese translation 2010-09-04 23:06:24 +01:00
31fe25aa78 Unfuzzy translations 2010-09-02 22:58:12 +02:00
252657905f Updated Italian translation 2010-09-02 22:56:20 +02:00
77a5e817a5 introspection: Use new --accept-unprefixed
Also depend on an introspection version which has this.
2010-09-01 13:20:39 -04:00
2521e8103d l10n: Updated Greek translation for mutter 2010-09-01 11:50:37 +03:00
47fcb998f5 introspection: Enable warnings
Also depend on Makefile to ensure we rerun on build changes.
2010-08-31 19:50:43 -04:00
455c40677b Update British English translation 2010-08-31 09:56:30 +01:00
9ae8e4c006 Updated Hungarian translation 2010-08-31 01:19:09 +02:00
d514516543 Updated Brazilian Portuguese translation 2010-08-30 15:11:24 -03:00
1024eae742 Really install region.h as private header
Libmutter-private's preview-widget.h depends on region.h, so that one
needs to be installed as well in order to keep dependees build.

Signed-off-by: Tomas Frydrych <tf@linux.intel.com>
2010-08-27 10:59:21 +01:00
dad1f01c5b Fixed incorrect location of regin.h in the previous commit
region.h lives in include, not ui
2010-08-27 10:06:37 +01:00
ce53f35974 Added region.h to installed headers
region.h is explicictely included by the installed preview-widget.h
2010-08-27 09:59:08 +01:00
3d19e800ab Updated Bulgarian translation 2010-08-24 15:45:58 +03:00
2a54baf60e Trap xerrors in mutter_window_pre_paint
XDamageSubstract can create a BadDamage
(when the window goes away before XDamageSubstract is called)
and thus resulting into a crash.

Fix it by protecting the call with an error trap.

https://bugzilla.gnome.org/show_bug.cgi?id=623235
2010-08-23 22:31:51 +02:00
4544fe7571 Fix build against gtk+ older than 2.21.6.
The gdk_window_get_background_pattern() function copied from GDK and
introduced in commit 0839c10 has a small syntax error and uses a private
API (_gdk_drawable_ref_cairo_surface()). This patch imports the missing
API and fixes the syntax error.

https://bugzilla.gnome.org/show_bug.cgi?id=626583
2010-08-23 11:11:50 +01:00
a125b0179a Do not cancel Alt+Tab grab due to modifier key events
If the user just presses a modifier (e.g., shift) during Alt+Tab grab, we need
to keep the grab in place to allow the custom Alt+Tab handler to deal with what
might simply be a change of tabbing direction.

https://bugzilla.gnome.org/show_bug.cgi?id=613126
2010-08-23 10:35:10 +01:00
6b69acdf8b Updated Serbian translation 2010-08-22 15:47:20 +02:00
8c11a2e5a3 Updated Danish translation 2010-08-22 13:36:05 +02:00
693c2bc175 Updated Traditional Chinese translation(Hong Kong and Taiwan) 2010-08-21 21:01:55 +08:00
8b34b4bd0b MutterShapedWindow: drop all indirect references to textures
We don't get correct notifications for the ::cogl-texture property of
ClutterTexture in the case when we are unsetting the pixmap before calling
XFreePixmap. (This is because ClutterX11TexturePixmap is a hack on top
of ClutterTexture and we're a hack on top of that.) So we need to manually
clear everything out.

For consistency we also make sure that we drop all references to dead
textures:

 - When the shape changes
 - If the window pixmap texture changes without first being cleared
   (this is not expected to happen)

https://bugzilla.gnome.org/show_bug.cgi?id=627210
2010-08-19 16:12:11 -04:00
8cce57ba44 Updated Serbian translation 2010-08-19 14:48:31 +02:00
63f81ed027 Fix meta_window_set_user_time: assertion `!window->override_redirect' failed error messages
This patch adds a check in event_callback () to check whether the
window is override-redirect or not, and avoids unnecessarily calling
meta_window_set_user_time () if it is.

https://bugzilla.gnome.org/show_bug.cgi?id=606158
2010-08-18 17:22:01 -04:00
c9ebc0ea25 Always use mipmap emulation
Rather than trying to find out from Clutter whether mipmap generation
can be used together with texture_from_pixmap, just always assume
it can't and use the MutterTextureTower emulation code.

This fixes a problem with our previous hack for doing the query
no longer working. In the rare cases where mipmap generation
is supported, it is unlikely to produce significantly more efficient
or better looking results than the emulation. (In terms of efficiency,
we have better knowledge of when we need to update the lower mipmaps
and when we don't than CoglTexturePixmapX11.)

Some care is taken so mutter_shaped_texture_set_create_mipmaps() works
when changed on the fly and properly discards the old mipmap levels.
This isn't necesary currently, since it can only be controlled via
envvar, but is easier than future-proofing through documentation.

https://bugzilla.gnome.org/show_bug.cgi?id=627087
2010-08-18 14:02:32 -04:00
15a214e435 Fix order of pixmap = None and XFreePixmap() in last commit
The last commit set MutterWindow->priv->back_pixmap to None before
calling XFreePixmap on it. Fix.
2010-08-17 19:07:49 -04:00
0b3327f04d Unset window pixmaps from MutterShapedWindow before freeing them
At least with the Mesa/DRI implementation of GLX, calling XFreePixmap()
on a pixmap before glxDestroyPixmap() on the corresponding GLX pixmap
causes an X error. To avoid triggering this with the new
ClutterTexturePixmapX11 code, we need to move our XFreePixmap after
unsetting the pixmap from the actor.

https://bugzilla.gnome.org/show_bug.cgi?id=627210
2010-08-17 18:42:02 -04:00
0839c100c0 Use gdk_window_get_background_pattern() to clear the background
gdk_window_get_back_pixmap() and gdk_window_get_background() have
been removed/deprecated. Use gdk_window_get_background_pattern()
as replacement.

https://bugzilla.gnome.org/show_bug.cgi?id=626583
2010-08-17 20:57:47 +02:00
08cfdcd802 Replace GDK drawing API with cairo
The GDK drawing API was deprecated/removed.

https://bugzilla.gnome.org/show_bug.cgi?id=626583
2010-08-17 20:42:05 +02:00
a1bb3835cc [mutter-shaped-texture] Remove material_workaround
It is no longer needed as the workaround has been removed in
452025e984,
but the material is still around and unused.

https://bugzilla.gnome.org/show_bug.cgi?id=625712
2010-08-16 23:06:46 +02:00
e590cd2b99 Don't screw up the event mask when "managing" our own windows
When we do pseudo-management on an override-redirect window, we have to be
careful to augment the existing event mask, not replace it, or
delivery of pointer events will be disrupted.

When we unmanage a window, we shouldn't try to unselect events at all,
since that will interfere with event selection done by GDK.

http://bugzilla.gnome.org/show_bug.cgi?id=597763
2010-08-09 12:57:57 -04:00
77b620e50e Updated LowGerman translation 2010-08-08 15:45:58 +02:00
9bc723d256 Updated Tamil translation 2010-08-05 11:51:01 +05:30
b9f9a230e6 update Translation in master for Punjabi by A S Alam 2010-08-04 15:17:03 +05:30
ce1ffa4624 Check for TFP usage after actually setting the pixmap
Starting with clutter 1.4 clutter / cogl only knows whether TFP is in use after
setting the pixmap, so doing the check before setting the pixmap will just
lead to a wrong message.

https://bugzilla.gnome.org/show_bug.cgi?id=624757
2010-07-30 16:16:55 +02:00
17aa36d343 Update Simplified Chinese translation. 2010-07-24 18:36:51 +08:00
cc0965f9f9 Updated Galician translations 2010-07-21 14:36:14 +02:00
0e728d7751 Updated Traditional Chinese translation(Hong Kong and Taiwan) 2010-07-20 19:28:28 +08:00
3e6cf75d73 Updated French translation 2010-07-19 17:50:22 +02:00
bbedba8b18 Update Simplified Chinese translation. 2010-07-18 11:10:55 +08:00
c8d756dde3 [i18n] Updated German translation 2010-07-16 21:23:23 +02:00
97a8dbb71e Updated Slovenian translation 2010-07-14 15:03:24 +02:00
6835804dab Updated Norwegian bokmål translation 2010-07-13 18:54:08 +02:00
1a2a374380 Bump version to 2.31.5 2010-07-12 11:44:09 -04:00
2b84afc1e3 src/core/util.c: Fix warning in case WITH_VERBOSE_MODE is not set
Signed-off-by: Andreas Mueller <schnitzeltony@gmx.de>

https://bugzilla.gnome.org/show_bug.cgi?id=624166
2010-07-12 11:07:26 -04:00
bb3d23f7f6 Add --enable-compile-warnings option to configure script.
This patch adds the option to disable or enable compiler warnings
to maintain compatibility with gnome standard configure options, and
allow users to work around warnings from compiler incompatibility.

--enable-compile-warnings=no disables compile warnings completely,
while --enable-compile-warnings=yes turns on non-fatal warnings.
The default --enable-compile-warnings=error gives the previous behavior.

Dead code for enabling '-ansi -pendantic' is removed, and the
default enabling of -ansi is removed as well. Blanket disabling
GCC extensions and C99 features causes various problems; we're
better off enforcing the dialect we want to use at code review
time.

https://bugzilla.gnome.org/show_bug.cgi?id=616275
2010-07-12 11:07:26 -04:00
7511ea27e2 Update Czech translation 2010-07-11 22:05:46 +02:00
adbe3a2312 Fix gtk+ dependency in libmutter-private pkg-config file 2010-07-09 18:05:02 +02:00
eda50a91df Updated Galician translations 2010-07-07 18:05:50 +02:00
7853bb8042 Work around g-ir-scanner problem with Gdk.Rectangle
g-ir-scanner is currently buggy and confuses the Gdk.Rectangle alias
with MetaRectangle. Since this is moderately hard to fix in
gobject-introspection and the fix would conflict with in-progress
changes, work around by doing a 'sed job' on the generated Meta.gir.

https://bugzilla.gnome.org/show_bug.cgi?id=623639
2010-07-06 15:11:13 -04:00
37de1b2d25 Updated Slovenian translation 2010-07-06 15:14:58 +02:00
0c4ac0b48a Updated Spanish translation 2010-07-03 12:35:52 +02:00
c24cf44c6a Updated Hebrew translation. 2010-07-03 02:05:52 +03:00
11a8ab47fa Make MetaRectangle a boxed type
Export a boxed type for MetaRectangle; this is mostly of interest
because GdkRectangle has been turned into a typedef for
cairo_rectangle_int_t which causes massive problems for using it from
gobject-introspection based language bindings.

https://bugzilla.gnome.org/show_bug.cgi?id=623335
2010-07-02 13:14:39 -04:00
7feeb72721 Use cairo_region_t when building with gtk+-3.0
GdkRegion has been removed from Gtk+. The replacement is a
yet-unreleased cairo API, so use it only when building with
Gtk+-3.0.

https://bugzilla.gnome.org/show_bug.cgi?id=587991
2010-07-02 04:36:28 +02:00
01447d94d1 Allow building with Gtk+-3.0
Add a configure switch to select the Gtk+ version to build with. The
default is to build against Gtk+-2.0 >= 2.18.

https://bugzilla.gnome.org/show_bug.cgi?id=622303
2010-07-02 04:36:27 +02:00
e267a63330 Add compatibility with GTK+ 2.18
In order to replace calls to deprecated GDK code, the current
development version of GTK+ is required. Add some basic compatibility
code to allow building mutter with GTK+ 2.18.

https://bugzilla.gnome.org/show_bug.cgi?id=587991
2010-07-01 20:55:12 +02:00
c65a24486d Replace deprecated GDK symbols
The fix depends on new API added in this cycle, so the required
GTK+ version is bumped to 2.21.1.

https://bugzilla.gnome.org/show_bug.cgi?id=587991
2010-07-01 20:55:11 +02:00
42e786b15b Remove deprecated Gtk+ symbols
This patch removes all uses of deprecated Gtk+ symbols from mutter.

https://bugzilla.gnome.org/show_bug.cgi?id=587991
2010-07-01 20:55:11 +02:00
7a04673dd7 Don't use deprecated GtkTooltips type unnecessarily
Bug 622800.
2010-06-30 01:35:42 +03:00
c47d2da0cb Don't incĺude internal gdk headers directly
Bug 622800.
2010-06-30 01:35:35 +03:00
fd12eddb5d Use g_signal_connect_data() instead of deprecated gtk_signal_connect_full()
Bug 622800.
2010-06-30 01:35:26 +03:00
0b56599d28 Don't use gtk_type_unique()
Replace usage of deprecated gtk_type_unique() by switching to defining
types with G_DEFINE_TYPE.

Bug 622800.
2010-06-30 01:34:54 +03:00
27de94b915 Bump version to 2.31.4 2010-06-25 16:18:39 -04:00
9e31f2b1de Added Norwegian bokmål translation 2010-06-20 11:41:52 +02:00
13ad103823 Clean up MutterPlugin effect interface
The current effect API passes an unnecessary list of windows to
switch_workspace() and forces a window to be passed in when killing
the switch_workspace() effect.

We can simplify the interface to correspond more closely to how
it is actually used and fix these problems:

Remove the actors parameter to plugin->switch_workspace
Remove the events parameter to plugin->kill_effect and rename it to kill_window_effects
Add plugin->kill_switch_workspace

Remove mutter_plugin_manager_kill_effect
Add mutter_plugin_manager_kill_window_effects
Add mutter_plugin_manager_kill_switch_workspace

Remove mutter_plugin_effect_completed
Add mutter_plugin_[minimize/map/destroy/maximize/unmaximize]_completed
https://bugzilla.gnome.org/show_bug.cgi?id=621082
2010-06-17 01:40:43 +04:00
ff5a73de49 Fix problem with window unmaximization
A mismerge of the Metacity commit "4943d79 Prevent window self-maximisation"
caused the window's user set size and position to be saved *before*
actually resizing the window to the unmaximized position rather than after.

This meant that after unmaximization the window was in an inconsistent
state and anything that caused a resize to be queued (like a change in
window properties by the application) would cause it to pop back to
the maximized size and position.

https://bugzilla.gnome.org/show_bug.cgi?id=621413
2010-06-14 16:44:28 -04:00
275a6ec63f update Punjabi Translation 2010-06-14 08:09:49 +05:30
604da0f6ea Add _XOPEN_SOURCE display.c for gethostname()
We shouldn't need _GNU_SOURCE in delete.c anymore either.

https://bugzilla.gnome.org/show_bug.cgi?id=620860
2010-06-07 14:26:45 -04:00
72a19dd448 [display] Include unistd.h for gethostname
https://bugzilla.gnome.org/show_bug.cgi?id=620860
2010-06-07 12:32:56 -04:00
3a73f6b8ec Add meta_window_is_remote
It's useful for plugins to be able to easily detect whether
or not a window is from a remote host.  Also, make use of this
in the window delete codepath, instead of looking up the hostname
each time.

https://bugzilla.gnome.org/show_bug.cgi?id=620585
2010-06-07 09:44:14 -04:00
343474a570 Allow logging only specific debug topics
While debugging a focus problem, I noticed that Mutter had exactly
the debug statements I wanted under the META_DEBUG_FOCUS topic.
However, calling meta_set_verbose (true) results in enormous amounts
of other messages, and it's inconvenient to filter after having
started mutter.

This patch allows one to call Meta.add_debug_topic(Meta.DebugTopic.FOCUS)
from a console, and get just what one wants.

https://bugzilla.gnome.org/show_bug.cgi?id=620359
2010-06-04 11:27:48 -04:00
91d82bf8c7 mutter-window: request DamageReportBoundingBox report level
In commit d34ae764769 I switched mutter-window to ask for Raw rectangles
from the X server. This avoided 2 non synchronous and 2 synchronous X
requests per window with damage, per frame; 2 (non-sync) to
create/destroy a temporary region to copy the damage region into, 1 to
request the server to copy the damage region into a our given region and
another to fetch that region back into the client. The problem with raw
events though is that it's possible to DOS the compositor with them.

Instead of receiving an event for every bit of damage this patch instead
asks the server to only report BoundingBox changes to the damage region.

https://bugzilla.gnome.org/show_bug.cgi?id=611838
2010-06-04 00:36:08 +01:00
ed19060074 Updated Galician translations 2010-06-03 23:46:58 +02:00
f230a67b94 Updated Hebrew translation. 2010-06-03 14:33:17 +03:00
849f101feb Bump version to 2.31.2 2010-05-25 14:16:40 -04:00
f45083ce82 Fix crash with --sync option
If the display hasn't been initialized yet, just change the
start variable and don't update the display.

https://bugzilla.gnome.org/show_bug.cgi?id=618613
2010-05-25 13:24:42 -04:00
4c143ae9af Updated French translation 2010-05-17 20:39:44 +02:00
cd1a1d5778 Updated Arabic translation 2010-05-15 23:55:34 +03:00
e28e7a72aa [MetaDisplay] meta_display_get_leader_window()
This function returns xid of the WM leader window (as defined by the
_NET_SUPPORTING_WM_CHECK mechanism of EWMH). For use by plugins that wish to
attach custom properties to this window.

https://bugzilla.gnome.org/show_bug.cgi?id=613125
2010-05-14 12:44:38 +01:00
fc9488211f [MetaScreen] Keep num_workspaces key in sync with the actual workspace number
Changing the number of workspaces via an external pager relies on the gconf
key; if a plugin adds or removes workspaces on the fly, we can get into a
situation when the stale number stored by the preferences matches the new
number requested by the pager, in which case the pager request becomes a nop.

This commit ensures that when the meta_screen_append_new_workspace() or
meta_screen_remove_workspace() functions are called, the stored value is
updated accordingly.

https://bugzilla.gnome.org/show_bug.cgi?id=613127
2010-05-14 12:31:38 +01:00
28767c4d34 _MUTTER_HINTS
A per-window _MUTTER_HINTS property allowing plugins to use custom hints. The
property holds a colon separated list of key=value pairs; plugin-specific keys
must be suitably namespaced, while 'mutter-' prefix is reserved for internal
Mutter use only.

This commit adds MetaWindow::mutter-hints property, and
meta_window_get_mutter_hints() accessor, as well as the internal machinery for
reading and updating of the hints.

https://bugzilla.gnome.org/show_bug.cgi?id=613123
2010-05-14 12:20:56 +01:00
c6c7b05d7b Add compatibility with GTK+ 2.18
To replace all calls to deprecated code, GTK+ 2.20 is required - add
some basic compatibility code, so that it is still possible to build
mutter with GTK+ 2.18 when not using -DGSEAL_ENABLE.

https://bugzilla.gnome.org/show_bug.cgi?id=595496
2010-05-12 11:02:52 +02:00
5526e91b6e Replace left-over accesses of struct members
When replacing direct accesses with accessor functions, two snippets
were left out. Mutter now builds with GSEAL_ENABLE.

https://bugzilla.gnome.org/show_bug.cgi?id=595496
2010-05-12 11:02:52 +02:00
9e123695d0 Use accessor functions instead direct access.
GTK+ 2.20 is now the required version

Still missing:
GTK_MENU_SHELL ()->have_xgrab

https://bugzilla.gnome.org/show_bug.cgi?id=595496
2010-05-12 11:02:45 +02:00
092cc47afc Work around COGL bug causing flash for new windows
COGL bug http://bugzilla.openedhand.com/show_bug.cgi?id=2110 results
in pending drawing at the time of cogl_offscreen_new_to_texture() going
to the newly created framebuffer rather than the stage.

This would result in most windows being missing for the first frame
when a new window is mapped.

Work around this by calling cogl_flush() before
cogl_offscreen_new_to_texture().

https://bugzilla.gnome.org/show_bug.cgi?id=618138
2010-05-09 14:30:18 -04:00
fd20059f68 Add public function to sort windows by stacking
https://bugzilla.gnome.org/show_bug.cgi?id=616050
2010-05-05 17:18:22 -04:00
609aae684f Export functions to iterate over window transients
https://bugzilla.gnome.org/show_bug.cgi?id=616050
2010-05-05 17:17:41 -04:00
49940877d1 Export meta_window_raise and meta_window_lower
For plugins that want fine grained control over window stacking.

https://bugzilla.gnome.org/show_bug.cgi?id=616050
2010-05-05 17:13:08 -04:00
22ae86104b Updated German translation 2010-05-02 12:26:41 +02:00
f8dd4c160b Fix crash when right-clicking on window frame
This is a regression added in 333446ab.

https://bugzilla.gnome.org/show_bug.cgi?id=614592
2010-04-26 17:04:07 -04:00
11061a23b1 Fix build with gcc 4.5
Based on patch by Dominique Leuenberger
<dominique-gnomezilla@leuenberger.net>

https://bugzilla.gnome.org/show_bug.cgi?id=606719
2010-04-26 17:02:23 -04:00
d8b0f213b2 Fix accounting of frozen with maximize/unmaximize
The beginning maximization/unmaximization don't go through
start_effect_simple(), so we need to freeze the window
separately.

Change MutterWindow.freeze_count to a signed integer for
consistency with other counts, and so the logic for
checking for errors works properly.

https://bugzilla.gnome.org/show_bug.cgi?id=616546
2010-04-26 16:57:06 -04:00
e9fbe4b2c1 Export the functions to control demands_attention
Plugins can want a finer grained control over this.

https://bugzilla.gnome.org/show_bug.cgi?id=616050
2010-04-24 13:13:54 -04:00
edcb351107 Export methods interact with user_time
This is useful when calling some of the lower level mutter functions,
e.g. controlling window stacking.

https://bugzilla.gnome.org/show_bug.cgi?id=616050
2010-04-24 13:13:54 -04:00
0c14640352 mutter-window: stream raw updates to ClutterX11TexturePixmap
This changes the way we handle Damage events so instead of getting an
event when the damage region of a pixmap becomes non-empty we now get
sent all damage rectangles and stream those all though to
ClutterX11TexturePixmap using clutter_x11_texture_pixmap_update_area()

For Clutter 1.2, ClutterGLXTexturePixmap was updated so that calls to
clutter_x11_texture_pixmap_update_area are now cheap (glXBindTexImageEXT
calls are now deferred until just before painting) and since
ClutterGLXTexturePixmap is now capable of queueing clipped redraws that
can result in only updating a sub-region of the stage during a repaint
cycle (and using glXCopySubBufferMESA to present the sub-region redraw
to the front buffer) this should improve performance and reduced power
consumption for a range of use cases. (For example viewing a website
that has animated adverts doesn't force the whole screen to be redrawn
for each frame of the advert)

Besides being able to take advantage of glXCopySubBuffer to only update
a small region of the stage the fact that this patch makes Mutter now
request RawRectangles from the X server means we no longer do a
synchronous X request for a complete Damage Region for every window
damaged each frame. This should also improve performance.

CLUTTER_PAINT=redraws can be used to visualize what parts of the stage
are redrawn and with this patch applied I can open a terminal and as I
type I see that only the damaged areas of the terminal are being
redrawn.
2010-04-21 16:40:46 +01:00
cfa30f9876 make sure we create a pixmap for all new mutter windows
In the case where a mutter window is created for an X Window that is
already mapped then we weren't calling mutter_window_mark_for_repair and
so we weren't calling XCompositeNameWindowPixmap e.g. for menu windows.

This doesn't get noticed because as soon as some damage gets delivered
for such windows the pixmap will be named anyway, but if we were to
change how damage is handled this would result in broken menus.

We now call mutter_window_mark_for_repair in mutter_window_new when the
given Window is already mapped.
2010-04-21 16:40:34 +01:00
af60dd3634 Add a missing space 2010-04-21 14:09:12 +02:00
ccabce1b34 Updated Slovenian translation 2010-04-17 19:39:08 +02:00
9915a18810 Avoid triggering strict-aliasing checks when iterating preferences
Rewrite the code to iterate generically over Meta*Preference
arrays to avoid running into GCC's strict-aliasing warnings.

https://bugzilla.gnome.org/show_bug.cgi?id=615672
2010-04-14 22:18:45 -04:00
a78373f324 Updated Spanish translation 2010-04-14 19:53:44 +02:00
1d7476a725 Allow a theme to specify ellipsize width for a title
It's nice to indicate when a title is truncated with an ellipsis.
Because themes may draw a title multiple times to draw a shadow, or
may include the window icon within the title area, we can't determine
the proper ellipsization width automatically, so add an optional
attribute to the <title/> element "ellipsize_width" which, if set,
is the width to ellipsize at.

This is only enabled if a theme version of 3.1 is required.

When it's not set, we keep the old behavior of just letting the
title be clipped with a hard edge.

https://bugzilla.gnome.org/show_bug.cgi?id=591842
2010-04-13 14:10:54 -04:00
e8e78ebfdd Add frame_x_center/frame_y_center variables for themes
Sometimes you want to position something (usually the title) to be centered
with respect to the entire frame instead of centered with respect to the
individual piece currently being drawn.

This patch adds frame_x_center and frame_y_center variables that represent
the X/Y centers of the frame in the coordinate system of the piece being
drawn.

The theme version is bumped from 3.0 to 3.1 (3.0 is just the new version
system, 3.1 will have all the features we add for Mutter-2.28.)
position expressions

https://bugzilla.gnome.org/show_bug.cgi?id=591842
2010-04-13 14:07:50 -04:00
b77b0a3d81 Load one copy of plugins early
Although multi-screen support has not been tested and probably
doesn't fully work, the basic setup for multi-screen is that
we have the same list of plugins for all screens, but a different
instance of the plugins for each screen.

To allow plugins to do setup that is screen independent and needs
to occur early in the setup process, we identify a "default plugin
manager" and load (but not start) that plugin manager's plugins
immediately after we know our list of plugins.

That plugin manager is then reused for the first screen we open
and the plugins are started at that time. Separate plugin managers
are loaded and started for any other screens we open.

(A plugin could keep track of whether the screen-independent
setup has been done in a static variable, or it could do everything
in a way that is safe to do repeatedly.)

https://bugzilla.gnome.org/show_bug.cgi?id=615586
2010-04-13 13:53:55 -04:00
95b260f3a9 Add meta_prefs_override_preference_location()
Allow a plugin to redirect preferences from one GConf location
to another GConf location. This is useful for keys that need to be
set differently in a plugin-managed environment (like GNOME Shell)
as compared to in standalone Metacity.

Overriding is implemented by overwriting the keys in the arrays
of preferences; a list of the current overrides is stored to allow
proper memory management when an override is itself overriden.
(we need to know whether to free the old keys or not)

This patch cleans up the comments in prefs.c a bit as well; some ideas
about less-exciting potential improvements were removed to make the
comments explaining the structure easier to figure out.

https://bugzilla.gnome.org/show_bug.cgi?id=615586
2010-04-13 13:52:39 -04:00
97a9726845 Add an explicit start() method for plugins
Rather than using the plugin objects constructed() method for doing
setup that requires the MetaScreen, add an explicit start() method
that is called after the screen is set.

The reason for this is that this allows plugin objects to be created
early before the bulk of Metacity setup, which then allows plugins
to affect how the setup happens. (For example, to change the way
that preferences are loaded.)

This is an incompatible change, since 'screen' is now not set in the
constructed method, so the plugin API version is bumped.

https://bugzilla.gnome.org/show_bug.cgi?id=615586
2010-04-13 13:40:16 -04:00
020aea033c metacity-theme-3.xml: Add a flexible version mechanism
The current mechanism of metacity-theme-1.xml and metacity-theme-2.xml
is not flexible for allowing small-scale additions. With this patch
we bump the major version version once more to metacity-theme-3.xml
and add a single feature:

Any element in the DTD can have an attribute:

 version="[<|<=|=>|>] MAJOR.MINOR"

And it will be ignored unless the predicate is met. (< and > should
be to be entity escaped as &lt; and &gt;)

This allows having alternate sections of the theme file for older and
newer version.

* Required GLib version is bumped to 2.14 so we can parse versions
  with a regular expression.

* We switch internal version numbers to be "1000 * major + minor"

* We keep a stack of the maximum required version for the current portion
  the XML tree so that the "cannot use versions you don't require" stricture
  of the old code can be made local to a subpart of the tree.

* A version on the top metacity_theme element causes the entire file to
  be ignored; this allows having one metacity-theme-3.xml for version 3.2
  and newer (say) and a metacity-1.xml for everything old.

Actual new features will be added starting with 3.1 - 3.0 is just the
version="" feature.

http://bugzilla.gnome.org/show_bug.cgi?id=592503
2010-04-13 13:40:16 -04:00
0ac46316af Clean up code to find themes
Simplify code to find the right theme to load and loading it by moving
all the loading code into a load_theme() helper function, and making
meta_load_theme() use that as it searches through the directories.

Look for old-version themes even when loading relative to the working
in debug mode.

Don't unnecessarily duplicate and then free info->theme_file and
info->theme_dir.

http://bugzilla.gnome.org/show_bug.cgi?id=592503
2010-04-13 11:15:10 -04:00
94d47dc25e Make sure all workspaces have a non-empty, non-null name
The change to using gconf_client_all_entries() in commit 2d57b1b4
meant that workspaces without a GConf key for their name were not
getting a name at all. Fix this by doing a post-processing loop
to set workspace names that were not otherwise set.

Alternate to patch from Tomas Frydrych
https://bugzilla.gnome.org/show_bug.cgi?id=613136
2010-04-13 08:51:06 -04:00
debf08cac0 Fix handling of grabbed key events
https://bugzilla.gnome.org/show_bug.cgi?id=596659
2010-04-12 17:52:19 -04:00
ce1393d2d4 Fix missing comma in previous commit 2010-04-11 19:59:29 +02:00
fac482c442 Stop using gtk_widget_set_uposition
Replace with non-deprecated gtk_window_move()

http://bugzilla.gnome.org/show_bug.cgi?id=587991
2010-04-11 18:35:22 +02:00
ee35540b6e Remove compositor-internal window lookup code
Since all windows are now MetaWindows as well as compositor
windows, there's no reason to keep a compositor-specific hash table
mapping from XID to MutterWindow.

This reduces complexity and removes a call to XQueryTree that could
potentially produce a BadWindow error if not error-trapped.

https://bugzilla.gnome.org/show_bug.cgi?id=613398
2010-04-07 10:22:30 -04:00
f77507e825 Don't trap XErrors in meta_compositor_process_event
meta_compositor_process_event uses meta_error_trap_push/pop for
every event processed by meta_compositor_process_event which isn't needed
and can cause performance problems.

https://bugzilla.gnome.org/show_bug.cgi?id=613398
2010-04-07 13:28:19 +02:00
0021efd593 Updated Italian translation 2010-04-06 22:53:15 +02:00
0d955bb873 Updated asturian translation 2010-03-30 06:03:10 +02:00
7fa2e8d2d3 Updated Slovak translation 2010-03-27 16:48:20 +01:00
713d94d881 Updated Lithuanian translation. 2010-03-27 12:06:07 +02:00
4ecf8964b8 Update Czech translation 2010-03-20 02:54:09 +01:00
11d044fa6e Updated Basque language 2010-03-19 17:28:47 +01:00
a2104c5404 Bump version to 2.29.1 2010-03-18 18:29:48 -04:00
1abed05413 meta_display_get_keybinding_action: strip out uninteresting modifiers
That is, don't consider the state of num lock, xkb group number, etc,
when looking up keybindings.

https://bugzilla.gnome.org/show_bug.cgi?id=613278
2010-03-18 17:57:47 -04:00
1465895ff7 Updated French translation 2010-03-17 21:39:21 +01:00
452025e984 Remove the workaround for multi-texturing with old intel drivers
The 2009 Q2 release of the drivers includes the relevent bug fix.

https://bugzilla.gnome.org/show_bug.cgi?id=613121
2010-03-17 16:13:24 +00:00
d537dd93d5 [MetaWindow] Accessor for the instance part of WM_CLASS property
https://bugzilla.gnome.org/show_bug.cgi?id=613128
2010-03-17 16:10:03 +00:00
650a1e807c [MetaDisplay] Expose meta_display_get_keybinding_action
This can be used when a plugin has control of input to determine
what action would be done, and thus filter to a subset of them.

https://bugzilla.gnome.org/show_bug.cgi?id=613100
2010-03-17 07:22:04 -04:00
67f8a33cad Include <sys/wait.h> for WIFEXITSTATUS/WIFEXITED
Exit status macros are specified by POSIX to be in <sys/wait.h>.
Fixes compilation on Solaris.

Reported by Brian Cameron
https://bugzilla.gnome.org/show_bug.cgi?id=612506
2010-03-15 11:09:49 -04:00
ff4f096f1d Support and require Clutter 1.2
- Specify a minimum version of Clutter-1.2.0
- Remove conditionalizatin and always use Clutter-1.1 framebuffer
  API rather than raw GL fbos
- Replace deprecated cogl_material/texture_unref() with
  cogl_handle_unref()

https://bugzilla.gnome.org/show_bug.cgi?id=610862
2010-03-11 15:06:06 -05:00
b5cb353ab5 Added Bulgarian translation 2010-02-27 10:50:32 +02:00
17a38dfbed Updated LowGerman translation 2010-02-25 16:59:48 +01:00
f773683601 Updated Polish translation 2010-02-24 19:29:54 +01:00
abeaf828a3 Update Simplified Chinese translation. 2010-02-24 18:58:13 +08:00
23a8a4201a Updated German translation 2010-02-21 17:00:06 +01:00
2d409e5c09 Remove executable bit from mutter-shaped-texture.c 2010-02-21 21:23:17 +07:00
148 changed files with 38221 additions and 38379 deletions

View File

@ -1,13 +1,13 @@
AC_PREREQ(2.50)
m4_define([mutter_major_version], [2])
m4_define([mutter_minor_version], [29])
m4_define([mutter_micro_version], [0])
m4_define([mutter_minor_version], [91])
m4_define([mutter_micro_version], [5])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
m4_define([mutter_plugin_api_version], [2])
m4_define([mutter_plugin_api_version], [3])
AC_INIT([mutter], [mutter_version],
[http://bugzilla.gnome.org/enter_bug.cgi?product=mutter])
@ -61,70 +61,11 @@ AC_CHECK_SIZEOF(__int64)
## byte order
AC_C_BIGENDIAN
#### Warnings
GTK_MIN_VERSION=2.91.7
CANBERRA_GTK=libcanberra-gtk3
CANBERRA_GTK_VERSION=0.26
changequote(,)dnl
if test "x$GCC" = "xyes"; then
case " $CFLAGS " in
*[\ \ ]-Wall[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wall" ;;
esac
# case " $CFLAGS " in
# *[\ \ ]-Wshadow[\ \ ]*) ;;
# *) CFLAGS="$CFLAGS -Wshadow" ;;
# esac
case " $CFLAGS " in
*[\ \ ]-Wchar-subscripts[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wmissing-declarations[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wnested-externs[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wnested-externs" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wpointer-arith[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wpointer-arith" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wcast-align[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wcast-align" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wsign-compare[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wsign-compare" ;;
esac
if test "x$enable_ansi" = "xyes"; then
case " $CFLAGS " in
*[\ \ ]-ansi[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -ansi" ;;
esac
case " $CFLAGS " in
*[\ \ ]-pedantic[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -pedantic" ;;
esac
fi
fi
changequote([,])dnl
MUTTER_PC_MODULES='gtk+-2.0 >= 2.10.0 pango >= 1.2.0'
MUTTER_PC_MODULES="gtk+-3.0 >= $GTK_MIN_VERSION pango >= 1.2.0 cairo >= 1.10.0"
AC_ARG_ENABLE(gconf,
AC_HELP_STRING([--disable-gconf],
@ -181,11 +122,11 @@ AC_CHECK_HEADERS(execinfo.h, [AC_CHECK_FUNCS(backtrace)])
AM_GLIB_GNU_GETTEXT
## here we get the flags we'll actually use
# GOptionEntry requires glib-2.6.0
PKG_CHECK_MODULES(ALL, glib-2.0 >= 2.6.0)
# 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+-2.0 >= 2.6.0)
PKG_CHECK_MODULES(MUTTER_WINDOW_DEMO, gtk+-2.0 >= 2.6.0)
PKG_CHECK_MODULES(MUTTER_MESSAGE, gtk+-3.0 >= $GTK_MIN_VERSION)
PKG_CHECK_MODULES(MUTTER_WINDOW_DEMO, gtk+-3.0 >= $GTK_MIN_VERSION)
# Unconditionally use this dir to avoid a circular dep with gnomecc
GNOME_KEYBINDINGS_KEYSDIR="${datadir}/gnome-control-center/keybindings"
@ -222,10 +163,10 @@ AC_MSG_CHECKING([libcanberra-gtk])
if test x$with_libcanberra = xno ; then
AC_MSG_RESULT([disabled])
else
if $PKG_CONFIG --exists libcanberra-gtk; then
if $PKG_CONFIG --exists $CANBERRA_GTK '>=' $CANBERRA_GTK_VERSION; then
have_libcanberra=yes
AC_MSG_RESULT(yes)
MUTTER_PC_MODULES="$MUTTER_PC_MODULES libcanberra-gtk"
MUTTER_PC_MODULES="$MUTTER_PC_MODULES $CANBERRA_GTK"
AC_DEFINE([HAVE_LIBCANBERRA], 1, [Building with libcanberra for playing sounds])
else
AC_MSG_RESULT(no)
@ -249,7 +190,7 @@ else
AC_MSG_ERROR([no. Mutter requires the Xcomposite extension to build.])
fi
CLUTTER_VERSION=1.0.0
CLUTTER_VERSION=1.2.0
CLUTTER_PACKAGE=clutter-1.0
AC_SUBST(CLUTTER_PACKAGE)
if $PKG_CONFIG --atleast-version $CLUTTER_VERSION $CLUTTER_PACKAGE ; then
@ -274,7 +215,7 @@ else
fi
if test x$with_introspection != xno; then
PKG_CHECK_MODULES(INTROSPECTION, gobject-introspection-1.0, have_introspection=yes, have_introspection=no)
PKG_CHECK_MODULES(INTROSPECTION, gobject-introspection-1.0 >= 0.9.5, have_introspection=yes, have_introspection=no)
if test x$have_introspection=xyes; then
MUTTER_PC_MODULES="$MUTTER_PC_MODULES gobject-introspection-1.0"
AC_DEFINE(HAVE_INTROSPECTION, 1, [Define if GObject introspection is available])
@ -505,14 +446,78 @@ if test "x$enable_debug" = "xyes"; then
CFLAGS="$CFLAGS -g -O"
fi
# Warnings are there for a reason
if test "x$GCC" = "xyes"; then
CFLAGS="$CFLAGS -Wall -Werror -ansi"
fi
# For fix-meta-rectangle.py
AM_PATH_PYTHON([2.5])
# Use gnome-doc-utils:
GNOME_DOC_INIT([0.8.0])
#### Warnings (last since -Werror can disturb other tests)
# Stay command-line compatible with the gnome-common configure option. Here
# minimum/yes/maximum are the same, however.
AC_ARG_ENABLE(compile_warnings,
AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),,
enable_compile_warnings=error)
changequote(,)dnl
if test "$enable_compile_warnings" != no ; then
if test "x$GCC" = "xyes"; then
case " $CFLAGS " in
*[\ \ ]-Wall[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wall" ;;
esac
# case " $CFLAGS " in
# *[\ \ ]-Wshadow[\ \ ]*) ;;
# *) CFLAGS="$CFLAGS -Wshadow" ;;
# esac
case " $CFLAGS " in
*[\ \ ]-Wchar-subscripts[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wmissing-declarations[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wnested-externs[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wnested-externs" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wpointer-arith[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wpointer-arith" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wcast-align[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wcast-align" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wsign-compare[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wsign-compare" ;;
esac
if test "$enable_compile_warnings" = error; then
case " $CFLAGS " in
*[\ \ ]-Werror[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Werror" ;;
esac
fi
fi
fi
changequote([,])dnl
AC_CONFIG_FILES([
Makefile
doc/Makefile
@ -545,7 +550,7 @@ fi
dnl ==========================================================================
echo "
mutter-$VERSION:
mutter-$VERSION
prefix: ${prefix}
source code location: ${srcdir}
@ -569,7 +574,7 @@ if expr $MUTTER_MINOR_VERSION % 2 > /dev/null ; then
stable_version=`expr $MUTTER_MINOR_VERSION - 1`
echo "This is the UNSTABLE branch of mutter"
echo -n "Use 2.$stable_version.x for stable "
echo "(gnome-2-$stable_version branch in Subversion)"
echo "(gnome-2-$stable_version branch in git)"
else
echo "This is the stable branch of mutter"
fi

View File

@ -4,6 +4,7 @@ of the theme format, and a given theme can support more than one format.
Version 1: THEMEDIR/metacity-1/metacity-theme-1.xml
(original metacity format)
Version 2: THEMEDIR/metacity-1/metacity-theme-2.xml
Version 3: THEMEDIR/metacity-1/metacity-theme-3.xml
The subdirectory name is "metacity-1" in all versions.
@ -21,6 +22,59 @@ This document has separate sections for each format version. You may
want to read the document in reverse order, since the base features
are discussed under version 1.
New Features in Theme Format Version 3.3
========================================
Add two additional button background functions - left_single_background and
right_single_background - for button groups with just a single button.
There are now additional frame states to style left/right tiled windows
differently ("tiled_left", "tiled_right", "tiled_left_and_shaded",
"tiled_right_and_shaded").
New Features in Theme Format Version 3.2
========================================
A new window type 'attached' is added for modal dialogs which are
attached to their parent window. (When the attach_modal_dialogs preference
is turned on.) If no style is defined for the 'attached' window type,
the 'border' window type will be used instead.
New Features in Theme Format Version 3.1
========================================
Additional predefined variables are added for positioning expressions:
frame_x_center: the X center of the entire frame, with respect to the
piece currently being drawn.
frame_y_center: the Y center of the entire frame, with respect to the
piece currently being drawn.
The <title/> element now supports an "ellipsize_width" attribute. When
specified, this gives a width at which to ellipsize the title. If not
specified, the title will simply be clipped to the title area.
New Features in Theme Format Version 3
======================================
Format version 3 has exactly one new feature; any element in the file
can now have a version attribute:
version="[<|<=|=>|>] MAJOR.MINOR"
(< and > should be to be entity escaped as &lt; and &gt;). If this
version check is not met, then the element and its children will be
ignored. This allows having alternate sections of the theme file for
older and newer version of the Metacity theme format.
When placed on the toplevel <metacity_theme> element, an unsatisfied
version check will not just cause the contents of the file to be
ignored, it will also cause the lookup of a theme file to proceed on
and look for an older format 2 or format 1 file. This allows making a
metacity-theme-3.xml file that is only used the format version 3.2 or
newer is supported, and using metacity-theme-1.xml for older window
managers.
New Features in Theme Format Version 2
======================================

View File

@ -82,6 +82,7 @@ te
th
tk
tr
ug
uk
vi
wa

794
po/ar.po

File diff suppressed because it is too large Load Diff

1815
po/ast.po

File diff suppressed because it is too large Load Diff

1483
po/bg.po

File diff suppressed because it is too large Load Diff

1269
po/cs.po

File diff suppressed because it is too large Load Diff

1859
po/da.po

File diff suppressed because it is too large Load Diff

2183
po/de.po

File diff suppressed because it is too large Load Diff

1485
po/el.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1121
po/es.po

File diff suppressed because it is too large Load Diff

2432
po/et.po

File diff suppressed because it is too large Load Diff

336
po/eu.po
View File

@ -3,14 +3,14 @@
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER.
#
# Hizkuntza Politikarako Sailburuordetza <hizpol@ej-gv.es>, 2004.
# Iñaki Larrañaga Murgoitio <dooteo@euskalgnu.org>, 2004, 2005, 2006, 2008, 2009.
# Iñaki Larrañaga Murgoitio <dooteo@euskalgnu.org>, 2004, 2005, 2006, 2008, 2009, 2010.
# Iñaki Larrañaga Murgoitio <dooteo@zundan.com>, 2007.
msgid ""
msgstr ""
"Project-Id-Version: eu\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2009-09-04 11:40+0200\n"
"PO-Revision-Date: 2009-09-04 11:56+0200\n"
"POT-Creation-Date: 2010-03-19 17:23+0100\n"
"PO-Revision-Date: 2010-03-19 17:27+0100\n"
"Last-Translator: Iñaki Larrañaga Murgoitio <dooteo@euskalgnu.org>\n"
"Language-Team: Basque <itzulpena@euskalgnu.org>\n"
"MIME-Version: 1.0\n"
@ -20,48 +20,53 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"\n"
#: ../src/core/bell.c:302
msgid "Bell event"
msgstr "Soinuaren gertaera"
#: ../src/core/core.c:213
#, c-format
msgid "Unknown window information request: %d"
msgstr "Leihoaren informazio eskaera ezezaguna: %d"
#: ../src/core/delete.c:105
#. Translators: %s is a window title
#: ../src/core/delete.c:95
#, c-format
msgid ""
"<big><b><tt>%s</tt> is not responding.</b></big>\n"
"\n"
"<i>You may choose to wait a short while for it to continue or force the "
"application to quit entirely.</i>"
msgstr ""
"<big><b><tt>%s</tt>(e)k ez du erantzuten.</b></big>\n"
"\n"
"<i>Aukeratu piskatean zai egotea aplikazioak jarraitzeko edo derrigortu "
"aplikazioa erabat ixtea.</i>"
msgid "<tt>%s</tt> is not responding."
msgstr "<tt>%s</tt>(e)k ez du erantzuten."
#: ../src/core/delete.c:116
#: ../src/core/delete.c:100
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
msgstr ""
"Aukeratu piskatean zai egotea aplikazioak jarraitzeko edo derrigortu "
"aplikazioa erabat ixtea."
#: ../src/core/delete.c:109
msgid "_Wait"
msgstr "_Itxaron"
#: ../src/core/delete.c:116
#: ../src/core/delete.c:109
msgid "_Force Quit"
msgstr "_Behartu ixtera"
#: ../src/core/delete.c:217
#: ../src/core/delete.c:207
#, c-format
msgid "Failed to get hostname: %s\n"
msgstr "Huts egin du ostalari-izena hartzean: %s\n"
#: ../src/core/display.c:329
#: ../src/core/display.c:362
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Konposaketa lantzeko beharrezkoa den %s hedapena falta da"
#: ../src/core/display.c:414
#: ../src/core/display.c:447
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Huts egin du X Window sistemaren '%s' pantaila irekitzean\n"
#: ../src/core/errors.c:236
#: ../src/core/errors.c:233
#, c-format
msgid ""
"Lost connection to the display '%s';\n"
@ -72,12 +77,12 @@ msgstr ""
"seguru asko X zerbitzaria itzalita egongo da edo leiho-kudeatzailea \n"
"hilko/hondatuko zenuen.\n"
#: ../src/core/errors.c:243
#: ../src/core/errors.c:240
#, c-format
msgid "Fatal IO error %d (%s) on display '%s'.\n"
msgstr "S/Iko %d (%s) errore konponezina '%s' pantailan.\n"
#: ../src/core/keybindings.c:697
#: ../src/core/keybindings.c:708
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -89,7 +94,7 @@ msgstr ""
#. Displayed when a keybinding which is
#. * supposed to launch a program fails.
#.
#: ../src/core/keybindings.c:2392
#: ../src/core/keybindings.c:2399
#, c-format
msgid ""
"There was an error running <tt>%s</tt>:\n"
@ -100,92 +105,96 @@ msgstr ""
"\n"
"%s"
#: ../src/core/keybindings.c:2482
#: ../src/core/keybindings.c:2489
#, c-format
msgid "No command %d has been defined.\n"
msgstr "%d komandoa ez dago definituta.\n"
#: ../src/core/keybindings.c:3495
#: ../src/core/keybindings.c:3502
#, c-format
msgid "No terminal command has been defined.\n"
msgstr "Ez da terminalaren komandoa definitu.\n"
#: ../src/core/main.c:127
#: ../src/core/main.c:130
#, c-format
msgid ""
"mutter %s\n"
"Copyright (C) 2001-2008 Havoc Pennington, Red Hat, Inc., and others\n"
"Copyright (C) 2001-%d Havoc Pennington, Red Hat, Inc., and others\n"
"This is free software; see the source for copying conditions.\n"
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A "
"PARTICULAR PURPOSE.\n"
msgstr ""
"mutter %s\n"
"Copyright-a (C) 2001-2008 Havoc Pennington, Red Hat, Inc., eta beste batzuk\n"
"Copyright-a (C) 2001-%d Havoc Pennington, Red Hat, Inc., eta beste batzuk\n"
"Hau software librea da; ikus kopiatzeko baldintzak iturburu-kodean.\n"
"EZ du bermerik; ezta MERKATURATZEKO edo XEDE JAKIN BATERAKO EGOKITASUNAREN "
"BERMERIK ERE.\n"
#: ../src/core/main.c:257
#: ../src/core/main.c:261
msgid "Disable connection to session manager"
msgstr "Desgaitu saio-kudeatzailearen konexioa"
#: ../src/core/main.c:263
#: ../src/core/main.c:267
msgid "Replace the running window manager with Mutter"
msgstr "Ordeztu exekutatzen dagoen leiho-kudeatzailea Mutter-rekin"
#: ../src/core/main.c:269
#: ../src/core/main.c:273
msgid "Specify session management ID"
msgstr "Zehaztu saio-kudeatzailearen IDa"
#: ../src/core/main.c:274
#: ../src/core/main.c:278
msgid "X Display to use"
msgstr "X pantaila erabiltzeko"
#: ../src/core/main.c:280
#: ../src/core/main.c:284
msgid "Initialize session from savefile"
msgstr "Hasieratu saioa babes-fitxategitik"
#: ../src/core/main.c:286
#: ../src/core/main.c:290
msgid "Print version"
msgstr "Erakutsi bertsioa"
#: ../src/core/main.c:292
#: ../src/core/main.c:296
msgid "Make X calls synchronous"
msgstr "Egin X deiak sinkronoak izatea"
#: ../src/core/main.c:298
#: ../src/core/main.c:302
msgid "Turn compositing on"
msgstr "Aktibatu konposaketa"
#: ../src/core/main.c:304
#: ../src/core/main.c:308
msgid "Turn compositing off"
msgstr "Desaktibatu konposaketa"
#: ../src/core/main.c:310
#: ../src/core/main.c:314
msgid "Don't make fullscreen windows that are maximized and have no decorations"
msgstr "Ez jarri pantaila osoan maximizatuta dauden eta dekoraziorik ez duten leihoak"
#: ../src/core/main.c:320
msgid "Comma-separated list of compositor plugins"
msgstr "Konpositoreen pluginen komaz bereiztutako zerrenda"
#: ../src/core/main.c:316
#: ../src/core/main.c:326
msgid "Whether window popup/frame should be shown when cycling windows."
msgstr "Leihoak begiztan sartzean laster-leihoak/-markoak erakutsiko diren edo ez."
#: ../src/core/main.c:323
#: ../src/core/main.c:333
msgid "Internal argument for GObject introspection"
msgstr "Barneko argumentua GObject objektua aztertzeko"
#: ../src/core/main.c:668
#: ../src/core/main.c:663
#, c-format
msgid "Failed to scan themes directory: %s\n"
msgstr "Huts egin du gaien direktorioa aztertzean: %s\n"
#: ../src/core/main.c:684
#: ../src/core/main.c:679
#, c-format
msgid "Could not find a theme! Be sure %s exists and contains the usual themes.\n"
msgstr ""
"Gai bat ezin izan da aurkitu. Ziurtatu %s badagoela eta ohiko gaiak "
"dituela.\n"
#: ../src/core/main.c:745
#: ../src/core/main.c:743
#, c-format
msgid "Failed to restart: %s\n"
msgstr "Ezin izan da berrabiarazi: %s\n"
@ -201,24 +210,24 @@ msgstr "Ezin izan da berrabiarazi: %s\n"
#. * (Empty comment follows so the translators don't see this.)
#.
#.
#: ../src/core/prefs.c:522 ../src/core/prefs.c:683
#: ../src/core/prefs.c:529 ../src/core/prefs.c:690
#, c-format
msgid "GConf key '%s' is set to an invalid value\n"
msgstr "\"%s\" GConf gakoa balio baliogabean ezarrita dago\n"
#: ../src/core/prefs.c:609 ../src/core/prefs.c:852
#: ../src/core/prefs.c:616 ../src/core/prefs.c:859
#, c-format
msgid "%d stored in GConf key %s is out of range %d to %d\n"
msgstr "%2$s GConf gakoko %1$d balioa %3$d - %4$d barrutitik kanpo dago\n"
#: ../src/core/prefs.c:653 ../src/core/prefs.c:730 ../src/core/prefs.c:778
#: ../src/core/prefs.c:842 ../src/core/prefs.c:1142 ../src/core/prefs.c:1158
#: ../src/core/prefs.c:1175 ../src/core/prefs.c:1191
#: ../src/core/prefs.c:660 ../src/core/prefs.c:737 ../src/core/prefs.c:785
#: ../src/core/prefs.c:849 ../src/core/prefs.c:1149 ../src/core/prefs.c:1165
#: ../src/core/prefs.c:1182 ../src/core/prefs.c:1198
#, c-format
msgid "GConf key \"%s\" is set to an invalid type\n"
msgstr "\"%s\" GConf gakoa mota baliogabean ezarrita dago\n"
#: ../src/core/prefs.c:1282
#: ../src/core/prefs.c:1289
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -226,12 +235,12 @@ msgstr ""
"Aplikazio hautsien konponbidea desgaituta. Aplikazio batzuk ez dira behar "
"den bezala ibiliko.\n"
#: ../src/core/prefs.c:1353
#: ../src/core/prefs.c:1360
#, c-format
msgid "Could not parse font description \"%s\" from GConf key %s\n"
msgstr "Ezin izan da analizatu \"%s\" letra-tipoaren deskribapena %s GConf gakoan\n"
#: ../src/core/prefs.c:1415
#: ../src/core/prefs.c:1422
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -240,17 +249,17 @@ msgstr ""
"Konfigurazioaren datu-basean aurkitutako \"%s\" balioa ez da baliozkoa sagu-"
"botoiaren aldatzailearentzat\n"
#: ../src/core/prefs.c:1839
#: ../src/core/prefs.c:1849
#, c-format
msgid "Error setting number of workspaces to %d: %s\n"
msgstr "Errorea laneko %d area ezartzean: %s\n"
#: ../src/core/prefs.c:2023 ../src/core/prefs.c:2529
#: ../src/core/prefs.c:2028 ../src/core/prefs.c:2531
#, c-format
msgid "Workspace %d"
msgstr "%d. laneko area"
#: ../src/core/prefs.c:2056 ../src/core/prefs.c:2234
#: ../src/core/prefs.c:2061 ../src/core/prefs.c:2239
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@ -259,37 +268,37 @@ msgstr ""
"Konfigurazioaren datu-basean aurkitutako \"%s\" balioa ez da baliozkoa \"%s"
"\" laster-teklarentzat.\n"
#: ../src/core/prefs.c:2610
#: ../src/core/prefs.c:2612
#, c-format
msgid "Error setting name for workspace %d to \"%s\": %s\n"
msgstr "Errorea %d. laneko areari \"%s\" izena ezartzean: %s\n"
#: ../src/core/prefs.c:2808
#: ../src/core/prefs.c:2816
#, c-format
msgid "Error setting compositor status: %s\n"
msgstr "Errorea konposaketaren egoera ezartzean: %s\n"
#: ../src/core/prefs.c:2836
#: ../src/core/prefs.c:2845
#, c-format
msgid "Error setting clutter plugin list: %s\n"
msgstr "Errorea 'clutter' pluginen zerrenda ezartzean: %s\n"
#: ../src/core/prefs.c:2879
#: ../src/core/prefs.c:2889
#, c-format
msgid "Error setting live hidden windows status status: %s\n"
msgstr "Errorea ezkutuko leihoen bizitzen egoera ezartzean: %s\n"
#: ../src/core/prefs.c:2907
#: ../src/core/prefs.c:2917
#, c-format
msgid "Error setting no tab popup status: %s\n"
msgstr "Errorea fitxarik gabeko laster-leihoen egoera ezartzean: %s\n"
#: ../src/core/screen.c:561
#: ../src/core/screen.c:577
#, c-format
msgid "Screen %d on display '%s' is invalid\n"
msgstr "'%2$s' bistaratzeko %1$d pantaila ez da baliozkoa\n"
#: ../src/core/screen.c:577
#: ../src/core/screen.c:593
#, c-format
msgid ""
"Screen %d on display \"%s\" already has a window manager; try using the --"
@ -298,77 +307,71 @@ msgstr ""
"\"%2$s\" bistaratzeko %1$d pantailak badu leiho-kudeatzailea; leiho-"
"kudeatzaile hori ordeztu nahi baduzu, saiatu --replace aukerarekin.\n"
#: ../src/core/screen.c:604
#: ../src/core/screen.c:620
#, c-format
msgid "Could not acquire window manager selection on screen %d display \"%s\"\n"
msgstr ""
"Ezin izan da eskuratu leiho-kudeatzailearen hautapena \"%2$s\" bistaratzeko %"
"1$d pantailan\n"
#: ../src/core/screen.c:659
#: ../src/core/screen.c:675
#, c-format
msgid "Screen %d on display \"%s\" already has a window manager\n"
msgstr "\"%2$s\" bistaratzeko %1$d pantailak badu leiho-kudeatzailea\n"
#: ../src/core/screen.c:871
#: ../src/core/screen.c:857
#, c-format
msgid "Could not release screen %d on display \"%s\"\n"
msgstr "Ezin izan da askatu \"%2$s\" bistaratzeko %1$d pantaila\n"
#: ../src/core/session.c:851 ../src/core/session.c:858
#: ../src/core/session.c:856 ../src/core/session.c:863
#, c-format
msgid "Could not create directory '%s': %s\n"
msgstr "Ezin izan da '%s' direktorioa sortu: %s\n"
#: ../src/core/session.c:868
#: ../src/core/session.c:873
#, c-format
msgid "Could not open session file '%s' for writing: %s\n"
msgstr "Ezin izan da '%s' saio-fitxategia idazteko ireki: %s\n"
#: ../src/core/session.c:1009
#: ../src/core/session.c:1014
#, c-format
msgid "Error writing session file '%s': %s\n"
msgstr "Errorea '%s' saio-fitxategia idaztean: %s\n"
#: ../src/core/session.c:1014
#: ../src/core/session.c:1019
#, c-format
msgid "Error closing session file '%s': %s\n"
msgstr "Errorea '%s' saio-fitxategia ixtean: %s\n"
#. oh, just give up
#: ../src/core/session.c:1107
#, c-format
msgid "Failed to read saved session file %s: %s\n"
msgstr "Huts egin du gordetako %s saio-fitxategia irakurtzean: %s\n"
#: ../src/core/session.c:1146
#: ../src/core/session.c:1149
#, c-format
msgid "Failed to parse saved session file: %s\n"
msgstr "Huts egin du gordetako saio-fitxategia analizatzean: %s\n"
#: ../src/core/session.c:1195
#: ../src/core/session.c:1198
#, c-format
msgid "<mutter_session> attribute seen but we already have the session ID"
msgstr "<mutter_session> atributua ikusi da baina dagoeneko badugu saio-IDa"
#: ../src/core/session.c:1208 ../src/core/session.c:1283
#: ../src/core/session.c:1315 ../src/core/session.c:1387
#: ../src/core/session.c:1447
#: ../src/core/session.c:1211 ../src/core/session.c:1286
#: ../src/core/session.c:1318 ../src/core/session.c:1390
#: ../src/core/session.c:1450
#, c-format
msgid "Unknown attribute %s on <%s> element"
msgstr "%s atributu ezezaguna <%s> elementuan"
#: ../src/core/session.c:1225
#: ../src/core/session.c:1228
#, c-format
msgid "nested <window> tag"
msgstr "<window> etiketa habiaratua"
#: ../src/core/session.c:1467
#: ../src/core/session.c:1470
#, c-format
msgid "Unknown element %s"
msgstr "%s elementu ezezaguna"
#: ../src/core/session.c:1818
#: ../src/core/session.c:1822
msgid ""
"These windows do not support &quot;save current setup&quot; and will have to "
"be restarted manually next time you log in."
@ -376,51 +379,51 @@ msgstr ""
"Leiho hauek ez dute onartzen &quot;gorde uneko konfigurazioa&quot; eta eskuz "
"berrabiarazi beharko dituzu hurrengo saioa hasten duzunean."
#: ../src/core/util.c:103
#: ../src/core/util.c:104
#, c-format
msgid "Failed to open debug log: %s\n"
msgstr "Huts egin du arazketako egunkaria irekitzean: %s\n"
#: ../src/core/util.c:113
#: ../src/core/util.c:114
#, c-format
msgid "Failed to fdopen() log file %s: %s\n"
msgstr "Huts egin du %s egunkari-fitxategian fdopen() egitean: %s\n"
#: ../src/core/util.c:119
#: ../src/core/util.c:120
#, c-format
msgid "Opened log file %s\n"
msgstr "%s egunkari-fitxategia irekita\n"
#: ../src/core/util.c:138 ../src/tools/mutter-message.c:176
#: ../src/core/util.c:139 ../src/tools/mutter-message.c:176
#, c-format
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter modu xehatuaren euskarririk gabe konpilatu da\n"
#: ../src/core/util.c:238
#: ../src/core/util.c:239
msgid "Window manager: "
msgstr "Leiho-kudeatzailea: "
#: ../src/core/util.c:390
#: ../src/core/util.c:391
msgid "Bug in window manager: "
msgstr "Akatsa leiho-kudeatzailean: "
#: ../src/core/util.c:423
#: ../src/core/util.c:424
msgid "Window manager warning: "
msgstr "Leiho-kudeatzailearen abisua: "
#: ../src/core/util.c:451
#: ../src/core/util.c:452
msgid "Window manager error: "
msgstr "Leiho-kudeatzailearen errorea: "
#. Translators: This is the title used on dialog boxes
#. eof all-keybindings.h
#: ../src/core/util.c:570 ../src/mutter.desktop.in.h:1
#: ../src/core/util.c:573 ../src/mutter.desktop.in.h:1
#: ../src/mutter-wm.desktop.in.h:1
msgid "Mutter"
msgstr "Mutter"
#. first time through
#: ../src/core/window.c:6086
#: ../src/core/window.c:6217
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -436,7 +439,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:6749
#: ../src/core/window.c:6880
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size %"
@ -456,7 +459,7 @@ msgstr "Aplikazioak _NET_WM_PID %lu faltsua ezarri du\n"
msgid "%s (on %s)"
msgstr "%s (%s)"
#: ../src/core/window-props.c:1419
#: ../src/core/window-props.c:1435
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "%2$s(e)n baliogabeko WM_TRANSIENT_FOR 0x%1$lx leihoa zehaztu da.\n"
@ -476,12 +479,12 @@ msgstr ""
"Gehiago ematen du aplikazioaren akatsa leiho-kudeatzailearena baino.\n"
"Leihoak title=\"%s\" class=\"%s\" name=\"%s\" du\n"
#: ../src/core/xprops.c:401
#: ../src/core/xprops.c:411
#, c-format
msgid "Property %s on window 0x%lx contained invalid UTF-8\n"
msgstr "0x%2$lx leihoko %1$s propietateak UTF-8 baliogabea du\n"
#: ../src/core/xprops.c:484
#: ../src/core/xprops.c:494
#, c-format
msgid "Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n"
msgstr ""
@ -804,7 +807,9 @@ msgstr "Clutter pluginak"
msgid ""
"Determines whether hidden windows (i.e., minimized windows and windows on "
"other workspaces than the current one) should be kept alive."
msgstr "Ezkutuko leihoak (adib. ikonotutakoak, beste laneko arekoak) bizirik iraungo diren edo ez zehazten du."
msgstr ""
"Ezkutuko leihoak (adib. ikonotutakoak, beste laneko arekoak) bizirik iraungo "
"diren edo ez zehazten du."
#: ../src/mutter.schemas.in.h:3
msgid "Live Hidden Windows"
@ -816,7 +821,9 @@ msgstr "Aldatzailea leihoak kudeatzeko eragiketa hedatuetan erabiltzeko"
#: ../src/mutter.schemas.in.h:5
msgid "Plugins to load for the Clutter-based compositing manager."
msgstr "Kargatuko diren puginak Clutter-en oinarritutako konposaketa-kudeatzailearentzako"
msgstr ""
"Kargatuko diren puginak Clutter-en oinarritutako konposaketa-"
"kudeatzailearentzako"
#: ../src/mutter.schemas.in.h:6
msgid ""
@ -825,8 +832,8 @@ msgid ""
"\"Windows key\" on PC hardware. It's expected that this binding either the "
"default or set to the empty string."
msgstr ""
"Gako honek \"overlay\" (gainjarria) hasieratuko du: hau leihoaren "
"ikuspegi orokorraren eta aplikazioa abiarazteko sistemaren arteko konbinazioa da. "
"Gako honek \"overlay\" (gainjarria) hasieratuko du: hau leihoaren ikuspegi "
"orokorraren eta aplikazioa abiarazteko sistemaren arteko konbinazioa da. "
"Lehenetsi gisa, PC ordenagailuko \"Windows tekla\" da. Tekla konbinazio hau "
"lehenetsia izatea edo kate hutz gisa ezartzea da."
@ -1289,7 +1296,7 @@ msgstr "Koordenatuen adierazpenak ez dirudi eragilerik edo eragigairik duenik"
msgid "Theme contained an expression that resulted in an error: %s\n"
msgstr "Gaiak errorea ematen duen adierazpen bat dauka: %s\n"
#: ../src/ui/theme.c:4187
#: ../src/ui/theme.c:4203
#, c-format
msgid ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
@ -1298,23 +1305,23 @@ msgstr ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> zehaztu behar "
"da marko-estilo honetan"
#: ../src/ui/theme.c:4695 ../src/ui/theme.c:4720
#: ../src/ui/theme.c:4711 ../src/ui/theme.c:4736
#, c-format
msgid "Missing <frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/>"
msgstr "<frame state=\"%s\" resize=\"%s\" focus=\"%s\" style=\"whatever\"/> falta da"
#: ../src/ui/theme.c:4764
#: ../src/ui/theme.c:4780
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr "Huts egin du \"%s\" gaia kargatzean: %s\n"
#: ../src/ui/theme.c:4894 ../src/ui/theme.c:4901 ../src/ui/theme.c:4908
#: ../src/ui/theme.c:4915 ../src/ui/theme.c:4922
#: ../src/ui/theme.c:4910 ../src/ui/theme.c:4917 ../src/ui/theme.c:4924
#: ../src/ui/theme.c:4931 ../src/ui/theme.c:4938
#, c-format
msgid "No <%s> set for theme \"%s\""
msgstr "<%s> ez da ezarri \"%s\" gaian"
#: ../src/ui/theme.c:4930
#: ../src/ui/theme.c:4946
#, c-format
msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
@ -1323,14 +1330,14 @@ msgstr ""
"Ez da marko-estilorik ezarri set \"%s\" leiho-motarentzat \"%s\" gaian, "
"gehitu <window type=\"%s\" style_set=\"whatever\"/> elementu bat"
#: ../src/ui/theme.c:5383 ../src/ui/theme.c:5445 ../src/ui/theme.c:5508
#: ../src/ui/theme.c:5389 ../src/ui/theme.c:5451 ../src/ui/theme.c:5514
#, c-format
msgid "User-defined constants must begin with a capital letter; \"%s\" does not"
msgstr ""
"Erabiltzaileak definitutako konstanteak maiuskulaz hasi behar du; \"%s\" ez "
"da maiuskulaz hasten"
#: ../src/ui/theme.c:5391 ../src/ui/theme.c:5453 ../src/ui/theme.c:5516
#: ../src/ui/theme.c:5397 ../src/ui/theme.c:5459 ../src/ui/theme.c:5522
#, c-format
msgid "Constant \"%s\" has already been defined"
msgstr "\"%s\" konstantea lehendik definituta dago"
@ -1449,10 +1456,10 @@ msgid "Window type \"%s\" has already been assigned a style set"
msgstr "\"%s\" leiho-motak dagoeneko esleituta du estilo-multzoa"
#: ../src/ui/theme-parser.c:1229 ../src/ui/theme-parser.c:1293
#: ../src/ui/theme-parser.c:1519 ../src/ui/theme-parser.c:2732
#: ../src/ui/theme-parser.c:2778 ../src/ui/theme-parser.c:2926
#: ../src/ui/theme-parser.c:3118 ../src/ui/theme-parser.c:3156
#: ../src/ui/theme-parser.c:3194 ../src/ui/theme-parser.c:3232
#: ../src/ui/theme-parser.c:1519 ../src/ui/theme-parser.c:2740
#: ../src/ui/theme-parser.c:2786 ../src/ui/theme-parser.c:2934
#: ../src/ui/theme-parser.c:3126 ../src/ui/theme-parser.c:3164
#: ../src/ui/theme-parser.c:3202 ../src/ui/theme-parser.c:3240
#, c-format
msgid "Element <%s> is not allowed below <%s>"
msgstr "Ez da onartzen <%s> elementua <%s>(r)en azpian jartzea"
@ -1481,108 +1488,108 @@ msgstr "\"%s\" aspektu-erlazioa ezezaguna da"
msgid "Border \"%s\" is unknown"
msgstr "\"%s\" ertza ezezaguna da"
#: ../src/ui/theme-parser.c:1776
#: ../src/ui/theme-parser.c:1784
#, c-format
msgid "No \"start_angle\" or \"from\" attribute on element <%s>"
msgstr "Ez dago \"start_angle\" edo \"from\" atributurik <%s> elementuan"
#: ../src/ui/theme-parser.c:1783
#: ../src/ui/theme-parser.c:1791
#, c-format
msgid "No \"extent_angle\" or \"to\" attribute on element <%s>"
msgstr "Ez dago \"extent_angle\" edo \"to\" atributurik <%s> elementuan"
#: ../src/ui/theme-parser.c:2023
#: ../src/ui/theme-parser.c:2031
#, c-format
msgid "Did not understand value \"%s\" for type of gradient"
msgstr "Gradiente-motan ez da ulertu \"%s\" balioa"
#: ../src/ui/theme-parser.c:2101 ../src/ui/theme-parser.c:2476
#: ../src/ui/theme-parser.c:2109 ../src/ui/theme-parser.c:2484
#, c-format
msgid "Did not understand fill type \"%s\" for <%s> element"
msgstr "Ez da ulertu \"%s\" betetze-mota <%s> elementuan"
#: ../src/ui/theme-parser.c:2268 ../src/ui/theme-parser.c:2351
#: ../src/ui/theme-parser.c:2414
#: ../src/ui/theme-parser.c:2276 ../src/ui/theme-parser.c:2359
#: ../src/ui/theme-parser.c:2422
#, c-format
msgid "Did not understand state \"%s\" for <%s> element"
msgstr "Ez da ulertu \"%s\" egoera <%s> elementuan"
#: ../src/ui/theme-parser.c:2278 ../src/ui/theme-parser.c:2361
#: ../src/ui/theme-parser.c:2286 ../src/ui/theme-parser.c:2369
#, c-format
msgid "Did not understand shadow \"%s\" for <%s> element"
msgstr "Ez da ulertu \"%s\" itzala <%s> elementuan"
#: ../src/ui/theme-parser.c:2288
#: ../src/ui/theme-parser.c:2296
#, c-format
msgid "Did not understand arrow \"%s\" for <%s> element"
msgstr "Ez da ulertu \"%s\" gezia <%s> elementuan"
#: ../src/ui/theme-parser.c:2588 ../src/ui/theme-parser.c:2684
#: ../src/ui/theme-parser.c:2596 ../src/ui/theme-parser.c:2692
#, c-format
msgid "No <draw_ops> called \"%s\" has been defined"
msgstr "Ez da \"%s\" izeneko <draw_ops> bat ere definitu"
#: ../src/ui/theme-parser.c:2600 ../src/ui/theme-parser.c:2696
#: ../src/ui/theme-parser.c:2608 ../src/ui/theme-parser.c:2704
#, c-format
msgid "Including draw_ops \"%s\" here would create a circular reference"
msgstr "Hemen \"%s\" draw_ops sartzen bada, erreferentzia zirkularra sortuko da"
#: ../src/ui/theme-parser.c:2811
#: ../src/ui/theme-parser.c:2819
#, c-format
msgid "Unknown position \"%s\" for frame piece"
msgstr "\"%s\" kokaleku ezezaguna markoarentzat"
#: ../src/ui/theme-parser.c:2819
#: ../src/ui/theme-parser.c:2827
#, c-format
msgid "Frame style already has a piece at position %s"
msgstr "Marko-estiloak badu zati bat %s posizioan"
#: ../src/ui/theme-parser.c:2836 ../src/ui/theme-parser.c:2911
#: ../src/ui/theme-parser.c:2844 ../src/ui/theme-parser.c:2919
#, c-format
msgid "No <draw_ops> with the name \"%s\" has been defined"
msgstr "Ez da \"%s\" izeneko <draw_ops> bat ere definitu"
#: ../src/ui/theme-parser.c:2865
#: ../src/ui/theme-parser.c:2873
#, c-format
msgid "Unknown function \"%s\" for button"
msgstr "\"%s\" funtzioa ezezaguna botoiarentzat"
#: ../src/ui/theme-parser.c:2874
#: ../src/ui/theme-parser.c:2882
#, c-format
msgid "Button function \"%s\" does not exist in this version (%d, need %d)"
msgstr "\"%s\" botoi-funtzioa ez da existitzen bertsio honetan (%d, %d behar du)"
#: ../src/ui/theme-parser.c:2886
#: ../src/ui/theme-parser.c:2894
#, c-format
msgid "Unknown state \"%s\" for button"
msgstr "\"%s\" egoera ezezaguna botoiarentzat"
#: ../src/ui/theme-parser.c:2894
#: ../src/ui/theme-parser.c:2902
#, c-format
msgid "Frame style already has a button for function %s state %s"
msgstr "Marko-estiloak badu botoi bat %s funtzioan %s egoeran"
#: ../src/ui/theme-parser.c:2965
#: ../src/ui/theme-parser.c:2973
#, c-format
msgid "\"%s\" is not a valid value for focus attribute"
msgstr "\"%s\" ez da baliozko balioa foku-atributuarentzat"
#: ../src/ui/theme-parser.c:2974
#: ../src/ui/theme-parser.c:2982
#, c-format
msgid "\"%s\" is not a valid value for state attribute"
msgstr "\"%s\" ez da baliozko balioa egoera-atributuarentzat"
#: ../src/ui/theme-parser.c:2984
#: ../src/ui/theme-parser.c:2992
#, c-format
msgid "A style called \"%s\" has not been defined"
msgstr "\"%s\" izeneko estiloa ez da definitu"
#: ../src/ui/theme-parser.c:3005 ../src/ui/theme-parser.c:3028
#: ../src/ui/theme-parser.c:3013 ../src/ui/theme-parser.c:3036
#, c-format
msgid "\"%s\" is not a valid value for resize attribute"
msgstr "\"%s\" ez da baliozko balioa tamainaz aldatzeko atributuarentzat"
#: ../src/ui/theme-parser.c:3039
#: ../src/ui/theme-parser.c:3047
#, c-format
msgid ""
"Should not have \"resize\" attribute on <%s> element for maximized/shaded "
@ -1591,24 +1598,24 @@ msgstr ""
"Ez luke izan behar \"resize\" atributurik <%s> elementuan maximizatutako/"
"bildutako egoerentzat"
#: ../src/ui/theme-parser.c:3053
#: ../src/ui/theme-parser.c:3061
#, c-format
msgid "Should not have \"resize\" attribute on <%s> element for maximized states"
msgstr ""
"Ez luke izan behar \"resize\" atributurik <%s> elementuan maximizatutako "
"egoerentzat"
#: ../src/ui/theme-parser.c:3067 ../src/ui/theme-parser.c:3089
#: ../src/ui/theme-parser.c:3075 ../src/ui/theme-parser.c:3097
#, c-format
msgid "Style has already been specified for state %s resize %s focus %s"
msgstr "Estiloa dagoeneko zehaztu da %s egoeran %s tamaina-aldatzean %s fokuan"
#: ../src/ui/theme-parser.c:3078 ../src/ui/theme-parser.c:3100
#: ../src/ui/theme-parser.c:3086 ../src/ui/theme-parser.c:3108
#, c-format
msgid "Style has already been specified for state %s focus %s"
msgstr "Estiloa dagoeneko zehaztu da %s egoeran %s fokuan"
#: ../src/ui/theme-parser.c:3139
#: ../src/ui/theme-parser.c:3147
msgid ""
"Can't have a two draw_ops for a <piece> element (theme specified a draw_ops "
"attribute and also a <draw_ops> element, or specified two elements)"
@ -1616,7 +1623,7 @@ msgstr ""
"Ezin dira bi draw_ops izan <piece> elementu batean (gaiak draw_ops atributu "
"bat eta <draw_ops> elementu bat zehaztu ditu, edo bi elementu zehaztu ditu)"
#: ../src/ui/theme-parser.c:3177
#: ../src/ui/theme-parser.c:3185
msgid ""
"Can't have a two draw_ops for a <button> element (theme specified a draw_ops "
"attribute and also a <draw_ops> element, or specified two elements)"
@ -1624,7 +1631,7 @@ msgstr ""
"Ezin dira bi draw_ops izan <button> elementu batean (gaiak draw_ops atributu "
"bat eta <draw_ops> elementu bat zehaztu ditu, edo bi elementu zehaztu ditu)"
#: ../src/ui/theme-parser.c:3215
#: ../src/ui/theme-parser.c:3223
msgid ""
"Can't have a two draw_ops for a <menu_icon> element (theme specified a "
"draw_ops attribute and also a <draw_ops> element, or specified two elements)"
@ -1633,76 +1640,63 @@ msgstr ""
"atributu bat eta <draw_ops> elementu bat zehaztu ditu, edo bi elementu "
"zehaztu ditu)"
#: ../src/ui/theme-parser.c:3263
#: ../src/ui/theme-parser.c:3271
#, c-format
msgid "Outermost element in theme must be <metacity_theme> not <%s>"
msgstr "Gaian kanporen dagoen elementuak <metacity_theme> izan behar du, ez <%s>"
#: ../src/ui/theme-parser.c:3283
#: ../src/ui/theme-parser.c:3291
#, c-format
msgid "Element <%s> is not allowed inside a name/author/date/description element"
msgstr "<%s> elementua ez da onartzen name/author/date/description elementuan"
#: ../src/ui/theme-parser.c:3288
#: ../src/ui/theme-parser.c:3296
#, c-format
msgid "Element <%s> is not allowed inside a <constant> element"
msgstr "<%s> elementua ez da onartzen <constant> elementuaren barnean"
#: ../src/ui/theme-parser.c:3300
#: ../src/ui/theme-parser.c:3308
#, c-format
msgid "Element <%s> is not allowed inside a distance/border/aspect_ratio element"
msgstr "<%s> elementua ez da onartzen distance/border/aspect_ratio elementuan"
#: ../src/ui/theme-parser.c:3322
#: ../src/ui/theme-parser.c:3330
#, c-format
msgid "Element <%s> is not allowed inside a draw operation element"
msgstr "<%s> elementua ez da onartzen marrazteko eragiketaren elementuaren barnean"
#: ../src/ui/theme-parser.c:3332 ../src/ui/theme-parser.c:3362
#: ../src/ui/theme-parser.c:3367 ../src/ui/theme-parser.c:3372
#: ../src/ui/theme-parser.c:3340 ../src/ui/theme-parser.c:3370
#: ../src/ui/theme-parser.c:3375 ../src/ui/theme-parser.c:3380
#, c-format
msgid "Element <%s> is not allowed inside a <%s> element"
msgstr "<%s> elementua ez da onartzen <%s> elementuaren barnean"
#: ../src/ui/theme-parser.c:3594
#: ../src/ui/theme-parser.c:3602
msgid "No draw_ops provided for frame piece"
msgstr "Ez da draw_ops-ik eman marko-zatiarentzat"
#: ../src/ui/theme-parser.c:3609
#: ../src/ui/theme-parser.c:3617
msgid "No draw_ops provided for button"
msgstr "Ez da draw_ops-ik eman botoiarentzat"
#: ../src/ui/theme-parser.c:3661
#: ../src/ui/theme-parser.c:3669
#, c-format
msgid "No text is allowed inside element <%s>"
msgstr "Ez da testurik onartzen <%s> elementuaren barnean"
#: ../src/ui/theme-parser.c:3716
msgid "<name> specified twice for this theme"
msgstr "<izena> birritan zehaztu da gai honetan"
#: ../src/ui/theme-parser.c:3724 ../src/ui/theme-parser.c:3736
#: ../src/ui/theme-parser.c:3748 ../src/ui/theme-parser.c:3760
#: ../src/ui/theme-parser.c:3772
#, c-format
msgid "<%s> specified twice for this theme"
msgstr "<%s> birritan zehaztu da gai honetan"
#: ../src/ui/theme-parser.c:3727
msgid "<author> specified twice for this theme"
msgstr "<egilea> birritan zehaztu da gai honetan"
#: ../src/ui/theme-parser.c:3738
msgid "<copyright> specified twice for this theme"
msgstr "<copyright-a> birritan zehaztu da gai honetan"
#: ../src/ui/theme-parser.c:3749
msgid "<date> specified twice for this theme"
msgstr "<data> birritan zehaztu da gai honetan"
#: ../src/ui/theme-parser.c:3760
msgid "<description> specified twice for this theme"
msgstr "<azalpena> birritan zehaztu da gai honetan"
#: ../src/ui/theme-parser.c:4027
#: ../src/ui/theme-parser.c:4040
#, c-format
msgid "Failed to find a valid file for theme %s\n"
msgstr "Huts egin du %s gaiaren fitxategi egokia bilatzean\n"
#: ../src/ui/theme-parser.c:4083
#: ../src/ui/theme-parser.c:4096
#, c-format
msgid "Theme file %s did not contain a root <metacity_theme> element"
msgstr "%s gai-fitxategiak ez du erroko <metacity_theme> elementurik"

823
po/fr.po

File diff suppressed because it is too large Load Diff

3064
po/gl.po

File diff suppressed because it is too large Load Diff

2863
po/he.po

File diff suppressed because it is too large Load Diff

634
po/hu.po

File diff suppressed because it is too large Load Diff

2181
po/it.po

File diff suppressed because it is too large Load Diff

1667
po/lt.po

File diff suppressed because it is too large Load Diff

716
po/nb.po

File diff suppressed because it is too large Load Diff

View File

@ -1,15 +1,15 @@
# Low German translation for mutter.
# Copyright (C) 2009 mutter's COPYRIGHT HOLDER
# This file is distributed under the same license as the mutter package.
# Nils-Christoph Fiedler <fiedler@medienkompanie.de>, 2009.
# Nils-Christoph Fiedler <ncfiedler@gnome.org>, 2009.
#
msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=mutter&component=general\n"
"POT-Creation-Date: 2009-11-24 21:04+0000\n"
"PO-Revision-Date: 2009-11-26 21:39+0100\n"
"Last-Translator: Nils-Christoph Fiedler <fiedler@medienkompanie.de>\n"
"PO-Revision-Date: 2010-08-08 15:45+0100\n"
"Last-Translator: Nils-Christoph Fiedler <ncfiedler@gnome.org>\n"
"Language-Team: Low German <nds-lowgerman@lists.sourceforge.net>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@ -163,7 +163,7 @@ msgstr ""
#: ../src/core/main.c:704
#, c-format
msgid "Failed to restart: %s\n"
msgstr ""
msgstr "Künn nich nej starten: %s\n"
#.
#. * We found it, but it was invalid. Complain.
@ -335,7 +335,7 @@ msgstr ""
#: ../src/core/session.c:1468
#, c-format
msgid "Unknown element %s"
msgstr ""
msgstr "Unbekanntes Element %s"
#: ../src/core/session.c:1820
msgid "These windows do not support &quot;save current setup&quot; and will have to be restarted manually next time you log in."
@ -364,7 +364,7 @@ msgstr ""
#: ../src/core/util.c:239
msgid "Window manager: "
msgstr ""
msgstr "Finsteroppasser:"
#: ../src/core/util.c:391
msgid "Bug in window manager: "
@ -376,7 +376,7 @@ msgstr ""
#: ../src/core/util.c:452
msgid "Window manager error: "
msgstr ""
msgstr "Finsteroppasserfehler:"
#. Translators: This is the title used on dialog boxes
#. eof all-keybindings.h
@ -384,7 +384,7 @@ msgstr ""
#: ../src/mutter.desktop.in.h:1
#: ../src/mutter-wm.desktop.in.h:1
msgid "Mutter"
msgstr ""
msgstr "Mutter"
#. first time through
#: ../src/core/window.c:6161
@ -412,7 +412,7 @@ msgstr ""
#: ../src/core/window-props.c:426
#, c-format
msgid "%s (on %s)"
msgstr ""
msgstr "%s (op %s)"
#: ../src/core/window-props.c:1440
#, c-format
@ -441,51 +441,51 @@ msgstr ""
#: ../src/include/all-keybindings.h:88
msgid "Switch to workspace 1"
msgstr ""
msgstr "Nah Schrievdisk 1 wesseln"
#: ../src/include/all-keybindings.h:90
msgid "Switch to workspace 2"
msgstr ""
msgstr "Nah Schrievdisk 2 wesseln"
#: ../src/include/all-keybindings.h:92
msgid "Switch to workspace 3"
msgstr ""
msgstr "Nah Schrievdisk 3 wesseln"
#: ../src/include/all-keybindings.h:94
msgid "Switch to workspace 4"
msgstr ""
msgstr "Nah Schrievdisk 4 wesseln"
#: ../src/include/all-keybindings.h:96
msgid "Switch to workspace 5"
msgstr ""
msgstr "Nah Schrievdisk 5 wesseln"
#: ../src/include/all-keybindings.h:98
msgid "Switch to workspace 6"
msgstr ""
msgstr "Nah Schrievdisk 6 wesseln"
#: ../src/include/all-keybindings.h:100
msgid "Switch to workspace 7"
msgstr ""
msgstr "Nah Schrievdisk 7 wesseln"
#: ../src/include/all-keybindings.h:102
msgid "Switch to workspace 8"
msgstr ""
msgstr "Nah Schrievdisk 8 wesseln"
#: ../src/include/all-keybindings.h:104
msgid "Switch to workspace 9"
msgstr ""
msgstr "Nah Schrievdisk 9 wesseln"
#: ../src/include/all-keybindings.h:106
msgid "Switch to workspace 10"
msgstr ""
msgstr "Nah Schrievdisk 10 wesseln"
#: ../src/include/all-keybindings.h:108
msgid "Switch to workspace 11"
msgstr ""
msgstr "Nah Schrievdisk 11 wesseln"
#: ../src/include/all-keybindings.h:110
msgid "Switch to workspace 12"
msgstr ""
msgstr "Nah Schrievdisk 12 wesseln"
#: ../src/include/all-keybindings.h:122
msgid "Switch to workspace on the left of the current workspace"
@ -569,19 +569,19 @@ msgstr ""
#: ../src/include/all-keybindings.h:252
msgid "Take a screenshot"
msgstr ""
msgstr "Billschirmbill scheten"
#: ../src/include/all-keybindings.h:254
msgid "Take a screenshot of a window"
msgstr ""
msgstr "Billschirmbill vun ee'm Finster scheten"
#: ../src/include/all-keybindings.h:256
msgid "Run a terminal"
msgstr ""
msgstr "Een Terminal lööpen laten"
#: ../src/include/all-keybindings.h:271
msgid "Activate the window menu"
msgstr ""
msgstr "Finstermenü aktiveren"
#: ../src/include/all-keybindings.h:274
msgid "Toggle fullscreen mode"
@ -814,7 +814,7 @@ msgstr ""
#: ../src/ui/frames.c:1145
msgid "Always On Visible Workspace"
msgstr ""
msgstr "Jümmers op opwiestem Schrievdisk"
#: ../src/ui/frames.c:1148
msgid "Put Window On Only One Workspace"
@ -1220,7 +1220,7 @@ msgstr ""
#: ../src/ui/theme.c:4764
#, c-format
msgid "Failed to load theme \"%s\": %s\n"
msgstr ""
msgstr "Künn Thema nich laden \"%s\": %s\n"
#: ../src/ui/theme.c:4894
#: ../src/ui/theme.c:4901

2016
po/pa.po

File diff suppressed because it is too large Load Diff

3030
po/pl.po

File diff suppressed because it is too large Load Diff

1999
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2118
po/sk.po

File diff suppressed because it is too large Load Diff

1131
po/sl.po

File diff suppressed because it is too large Load Diff

1984
po/sr.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2076
po/ta.po

File diff suppressed because it is too large Load Diff

1841
po/ug.po Normal file

File diff suppressed because it is too large Load Diff

1384
po/vi.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -19,30 +19,39 @@ mutter_SOURCES= \
core/bell.c \
core/bell.h \
core/boxes.c \
core/boxes-private.h \
include/boxes.h \
compositor/cogl-utils.c \
compositor/cogl-utils.h \
compositor/compositor.c \
compositor/compositor-private.h \
compositor/mutter-module.c \
compositor/mutter-module.h \
compositor/mutter-plugin.c \
compositor/mutter-plugin-manager.c \
compositor/mutter-plugin-manager.h \
compositor/mutter-shaped-texture.c \
compositor/mutter-texture-tower.c \
compositor/mutter-texture-tower.h \
compositor/mutter-window.c \
compositor/mutter-window-private.h \
compositor/mutter-window-group.c \
compositor/mutter-window-group.h \
compositor/shadow.c \
compositor/shadow.h \
compositor/mutter-shaped-texture.h \
compositor/tidy/tidy-texture-frame.c \
compositor/tidy/tidy-texture-frame.h \
compositor/meta-background-actor.c \
compositor/meta-background-actor.h \
compositor/meta-module.c \
compositor/meta-module.h \
compositor/meta-plugin.c \
compositor/meta-plugin-manager.c \
compositor/meta-plugin-manager.h \
compositor/meta-shadow-factory.c \
compositor/meta-shadow-factory-private.h \
compositor/meta-shaped-texture.c \
compositor/meta-shaped-texture.h \
compositor/meta-texture-tower.c \
compositor/meta-texture-tower.h \
compositor/meta-window-actor.c \
compositor/meta-window-actor-private.h \
compositor/meta-window-group.c \
compositor/meta-window-group.h \
compositor/meta-window-shape.c \
compositor/meta-window-shape.h \
compositor/region-utils.c \
compositor/region-utils.h \
include/compositor.h \
include/mutter-plugin.h \
include/mutter-window.h \
include/meta-plugin.h \
include/meta-shadow-factory.h \
include/meta-window-actor.h \
include/compositor-mutter.h \
core/above-tab-keycode.c \
core/constraints.c \
core/constraints.h \
core/core.c \
@ -73,7 +82,7 @@ mutter_SOURCES= \
core/keybindings.c \
core/keybindings-private.h \
core/main.c \
core/mutter-Xatomtype.h \
core/mutter-Xatomtype.h \
core/place.c \
core/place.h \
core/prefs.c \
@ -115,12 +124,12 @@ mutter_SOURCES= \
include/resizepopup.h \
ui/tabpopup.c \
include/tabpopup.h \
ui/tile-preview.c \
include/tile-preview.h \
ui/theme-parser.c \
ui/theme-parser.h \
ui/theme.c \
ui/theme.h \
ui/themewidget.c \
ui/themewidget.h \
ui/theme-private.h \
ui/ui.c \
include/all-keybindings.h \
$(mutter_built_sources)
@ -139,15 +148,12 @@ libmutter_private_la_SOURCES= \
ui/preview-widget.c \
ui/preview-widget.h \
ui/theme-parser.c \
ui/theme-parser.h \
ui/theme.c \
ui/theme.h
libmutter_private_la_LDFLAGS = -no-undefined
libmutter_private_la_LIBADD = @MUTTER_LIBS@
libmutterincludedir = $(includedir)/mutter/mutter-private
# Headers installed for plugins; introspected information will
# be extracted into Mutter-<version>.gir
libmutterinclude_base_headers = \
@ -156,7 +162,6 @@ libmutterinclude_base_headers = \
include/main.h \
include/util.h \
include/common.h \
ui/theme-parser.h \
ui/theme.h \
include/prefs.h \
include/window.h \
@ -169,8 +174,9 @@ libmutterinclude_base_headers = \
include/display.h \
include/group.h \
include/keybindings.h \
include/mutter-plugin.h \
include/mutter-window.h
include/meta-plugin.h \
include/meta-shadow-factory.h \
include/meta-window-actor.h
# Excluded from scanning for introspection but installed
# preview-widget.h: only part of libmutter-private
@ -179,6 +185,8 @@ libmutterinclude_extra_headers = \
ui/preview-widget.h \
include/atomnames.h
libmutterincludedir = $(includedir)/mutter/mutter-private
libmutterinclude_HEADERS = \
$(libmutterinclude_base_headers) \
$(libmutterinclude_extra_headers)
@ -202,21 +210,24 @@ typelib_DATA = Meta-$(api_version).typelib
# We need to strip out the attribute that would point back to libmutter-introspect
# so that libgirepository looks for symbols in the executable instead
Meta-$(api_version).gir: $(G_IR_SCANNER) mutter $(libmutterinclude_HEADERS) $(mutter_SOURCES)
Meta-$(api_version).gir: $(G_IR_SCANNER) mutter $(libmutterinclude_HEADERS) $(mutter_SOURCES) Makefile
$(AM_V_GEN) pwd=`pwd` ; \
cd $(srcdir) && \
$(G_IR_SCANNER) \
--namespace=Meta \
--nsversion=$(api_version) \
--warn-all \
--warn-error \
--include=GObject-2.0 \
--include=Gdk-2.0 \
--include=Gtk-2.0 \
--include=Gdk-3.0 \
--include=Gtk-3.0 \
--include=Clutter-1.0 \
--pkg=clutter-1.0 \
--pkg=gtk+-2.0 \
--pkg=gtk+-3.0 \
--include=xlib-2.0 \
--include=xfixes-4.0 \
--program=$$pwd/mutter \
mutter-enum-types.h \
$(filter %.c,$(mutter_SOURCES)) \
$(libmutterinclude_base_headers) \
$(INCLUDES) \

104
src/compositor/cogl-utils.c Normal file
View File

@ -0,0 +1,104 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Utilities for use with Cogl
*
* Copyright 2010 Red Hat, Inc.
* Copyright 2010 Intel Corporation
*
* 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 "cogl-utils.h"
/**
* meta_create_color_texture_4ub:
* @red:
* @green:
* @blue:
* @alpha:
*
* Creates a texture that is a single pixel with the specified
* unpremultiplied color components.
*
* Return value: (transfer full): a newly created Cogl texture
*/
CoglHandle
meta_create_color_texture_4ub (guint8 red,
guint8 green,
guint8 blue,
guint8 alpha)
{
CoglColor color;
guint8 pixel[4];
cogl_color_set_from_4ub (&color, red, green, blue, alpha);
cogl_color_premultiply (&color);
pixel[0] = cogl_color_get_red_byte (&color);
pixel[1] = cogl_color_get_green_byte (&color);
pixel[2] = cogl_color_get_blue_byte (&color);
pixel[3] = cogl_color_get_alpha_byte (&color);
return cogl_texture_new_from_data (1, 1,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
COGL_PIXEL_FORMAT_ANY,
4, pixel);
}
/* Based on gnome-shell/src/st/st-private.c:_st_create_texture_material.c */
/**
* meta_create_texture_material:
* @src_texture: (allow-none): texture to use initially for the layer
*
* Creates a material with a single layer. Using a common template
* allows sharing a shader for different uses in Mutter. To share the same
* shader with all other materials that are just texture plus opacity
* would require Cogl fixes.
* (See http://bugzilla.clutter-project.org/show_bug.cgi?id=2425)
*
* Return value: (transfer full): a newly created Cogl material
*/
CoglHandle
meta_create_texture_material (CoglHandle src_texture)
{
static CoglHandle texture_material_template = COGL_INVALID_HANDLE;
CoglHandle material;
/* We use a material that has a dummy texture as a base for all
texture materials. The idea is that only the Cogl texture object
would be different in the children so it is likely that Cogl will
be able to share GL programs between all the textures. */
if (G_UNLIKELY (texture_material_template == COGL_INVALID_HANDLE))
{
CoglHandle dummy_texture;
dummy_texture = meta_create_color_texture_4ub (0xff, 0xff, 0xff, 0xff);
texture_material_template = cogl_material_new ();
cogl_material_set_layer (texture_material_template, 0, dummy_texture);
cogl_handle_unref (dummy_texture);
}
material = cogl_material_copy (texture_material_template);
if (src_texture != COGL_INVALID_HANDLE)
cogl_material_set_layer (material, 0, src_texture);
return material;
}

View File

@ -1,10 +1,9 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Metacity theme parsing */
/*
* Copyright (C) 2001 Havoc Pennington
*
/*
* Utilities for use with Cogl
*
* Copyright 2010 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
@ -14,19 +13,22 @@
* 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 "theme.h"
#ifndef __META_COGL_UTILS_H__
#define __META_COGL_UTILS_H__
#ifndef META_THEME_PARSER_H
#define META_THEME_PARSER_H
#include <cogl/cogl.h>
MetaTheme* meta_theme_load (const char *theme_name,
GError **err);
CoglHandle meta_create_color_texture_4ub (guint8 red,
guint8 green,
guint8 blue,
guint8 alpha);
CoglHandle meta_create_texture_material (CoglHandle src_texture);
#endif
#endif /* __META_COGL_UTILS_H__ */

View File

@ -7,7 +7,7 @@
#include "compositor.h"
#include "display.h"
#include "mutter-plugin-manager.h"
#include "meta-plugin-manager.h"
#include <clutter/clutter.h>
typedef struct _MetaCompScreen MetaCompScreen;
@ -23,7 +23,7 @@ struct _MetaCompositor
ClutterActor *shadow_src;
MutterPlugin *modal_plugin;
MetaPlugin *modal_plugin;
gboolean show_redraw : 1;
gboolean debug : 1;
@ -35,6 +35,7 @@ struct _MetaCompScreen
MetaScreen *screen;
ClutterActor *stage, *window_group, *overlay_group;
ClutterActor *background_actor;
ClutterActor *hidden_group;
GList *windows;
GHashTable *windows_by_xid;
@ -45,24 +46,24 @@ struct _MetaCompScreen
gint switch_workspace_in_progress;
MutterPluginManager *plugin_mgr;
MetaPluginManager *plugin_mgr;
};
void mutter_switch_workspace_completed (MetaScreen *screen);
void mutter_set_stage_input_region (MetaScreen *screen,
XserverRegion region);
void mutter_empty_stage_input_region (MetaScreen *screen);
void meta_switch_workspace_completed (MetaScreen *screen);
void meta_set_stage_input_region (MetaScreen *screen,
XserverRegion region);
void meta_empty_stage_input_region (MetaScreen *screen);
gboolean mutter_begin_modal_for_plugin (MetaScreen *screen,
MutterPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp);
void mutter_end_modal_for_plugin (MetaScreen *screen,
MutterPlugin *plugin,
guint32 timestamp);
gboolean meta_begin_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp);
void meta_end_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
guint32 timestamp);
void mutter_check_end_modal (MetaScreen *screen);
void meta_check_end_modal (MetaScreen *screen);
#endif /* META_COMPOSITOR_PRIVATE_H */

View File

@ -11,8 +11,10 @@
#include "compositor-mutter.h"
#include "xprops.h"
#include "prefs.h"
#include "mutter-window-private.h"
#include "mutter-window-group.h"
#include "meta-shadow-factory.h"
#include "meta-window-actor-private.h"
#include "meta-window-group.h"
#include "meta-background-actor.h"
#include "../core/window-private.h" /* to check window->hidden */
#include "../core/display-private.h" /* for meta_display_lookup_x_window() */
#include <X11/extensions/shape.h>
@ -33,81 +35,28 @@ composite_at_least_version (MetaDisplay *display, int maj, int min)
return (major > maj || (major == maj && minor >= min));
}
static MutterWindow*
find_window_for_screen (MetaScreen *screen, Window xwindow)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (info == NULL)
return NULL;
return g_hash_table_lookup (info->windows_by_xid,
(gpointer) xwindow);
}
static MutterWindow *
find_window_in_display (MetaDisplay *display, Window xwindow)
{
GSList *index;
MetaWindow *window = meta_display_lookup_x_window (display, xwindow);
if (window)
{
void *priv = meta_window_get_compositor_private (window);
if (priv)
return priv;
}
for (index = meta_display_get_screens (display);
index;
index = index->next)
{
MutterWindow *cw = find_window_for_screen (index->data, xwindow);
if (cw != NULL)
return cw;
}
return NULL;
}
static MutterWindow *
find_window_for_child_window_in_display (MetaDisplay *display, Window xwindow)
{
Window ignored1, *ignored2, parent;
guint ignored_children;
XQueryTree (meta_display_get_xdisplay (display), xwindow, &ignored1,
&parent, &ignored2, &ignored_children);
if (parent != None)
return find_window_in_display (display, parent);
return NULL;
}
static void sync_actor_stacking (GList *windows);
static void sync_actor_stacking (MetaCompScreen *info);
static void
mutter_finish_workspace_switch (MetaCompScreen *info)
meta_finish_workspace_switch (MetaCompScreen *info)
{
GList *l;
/* Finish hiding and showing actors for the new workspace */
for (l = info->windows; l; l = l->next)
mutter_window_sync_visibility (l->data);
meta_window_actor_sync_visibility (l->data);
/*
* Fix up stacking order in case the plugin messed it up.
*/
sync_actor_stacking (info->windows);
sync_actor_stacking (info);
/* printf ("... FINISHED DESKTOP SWITCH\n"); */
}
void
mutter_switch_workspace_completed (MetaScreen *screen)
meta_switch_workspace_completed (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
@ -120,7 +69,7 @@ mutter_switch_workspace_completed (MetaScreen *screen)
}
if (!info->switch_workspace_in_progress)
mutter_finish_workspace_switch (info);
meta_finish_workspace_switch (info);
}
void
@ -137,82 +86,88 @@ add_win (MetaWindow *window)
g_return_if_fail (info != NULL);
mutter_window_new (window);
meta_window_actor_new (window);
sync_actor_stacking (info->windows);
sync_actor_stacking (info);
}
static void
process_damage (MetaCompositor *compositor,
XDamageNotifyEvent *event)
XDamageNotifyEvent *event,
MetaWindow *window)
{
MutterWindow *cw = find_window_in_display (compositor->display, event->drawable);
if (cw == NULL)
MetaWindowActor *window_actor;
if (window == NULL)
return;
mutter_window_process_damage (cw, event);
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (window_actor == NULL)
return;
meta_window_actor_process_damage (window_actor, event);
}
#ifdef HAVE_SHAPE
static void
process_shape (MetaCompositor *compositor,
XShapeEvent *event)
XShapeEvent *event,
MetaWindow *window)
{
MutterWindow *cw = find_window_in_display (compositor->display,
event->window);
if (cw == NULL)
MetaWindowActor *window_actor;
if (window == NULL)
return;
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (window_actor == NULL)
return;
if (event->kind == ShapeBounding)
{
mutter_window_update_shape (cw, event->shaped);
meta_window_actor_update_shape (window_actor, event->shaped);
}
}
#endif
static void
process_property_notify (MetaCompositor *compositor,
XPropertyEvent *event)
XPropertyEvent *event,
MetaWindow *window)
{
MetaDisplay *display = compositor->display;
MetaWindowActor *window_actor;
if (event->atom == compositor->atom_x_root_pixmap)
{
GSList *l;
for (l = meta_display_get_screens (compositor->display); l; l = l->next)
{
MetaScreen *screen = l->data;
if (event->window == meta_screen_get_xroot (screen))
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
meta_background_actor_update (META_BACKGROUND_ACTOR (info->background_actor));
return;
}
}
}
if (window == NULL)
return;
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (window_actor == NULL)
return;
/* Check for the opacity changing */
if (event->atom == compositor->atom_net_wm_window_opacity)
{
MutterWindow *cw = find_window_in_display (display, event->window);
if (!cw)
{
/* Applications can set this for their toplevel windows, so
* this must be propagated to the window managed by the compositor
*/
cw = find_window_for_child_window_in_display (display,
event->window);
}
if (!cw)
{
DEBUG_TRACE ("process_property_notify: opacity, early exit\n");
return;
}
mutter_window_update_opacity (cw);
}
else if (event->atom == meta_display_get_atom (display,
META_ATOM__NET_WM_WINDOW_TYPE))
{
MutterWindow *cw = find_window_in_display (display, event->window);
if (!cw)
{
DEBUG_TRACE ("process_property_notify: net_wm_type, early exit\n");
return;
}
mutter_window_update_window_type (cw);
DEBUG_TRACE ("process_property_notify: net_wm_type\n");
meta_window_actor_update_opacity (window_actor);
DEBUG_TRACE ("process_property_notify: net_wm_window_opacity\n");
return;
}
DEBUG_TRACE ("process_property_notify: unknown\n");
}
@ -247,8 +202,14 @@ get_output_window (MetaScreen *screen)
return output;
}
/**
* meta_get_stage_for_screen:
* @screen: a #MetaScreen
*
* Returns: (transfer none): The #ClutterStage for the screen
*/
ClutterActor *
mutter_get_stage_for_screen (MetaScreen *screen)
meta_get_stage_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
@ -258,8 +219,14 @@ mutter_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 *
mutter_get_overlay_group_for_screen (MetaScreen *screen)
meta_get_overlay_group_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
@ -269,8 +236,14 @@ mutter_get_overlay_group_for_screen (MetaScreen *screen)
return info->overlay_group;
}
/**
* meta_get_window_group_for_screen:
* @screen: a #MetaScreen
*
* Returns: (transfer none): The window group corresponding to @screen
*/
ClutterActor *
mutter_get_window_group_for_screen (MetaScreen *screen)
meta_get_window_group_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
@ -280,8 +253,35 @@ mutter_get_window_group_for_screen (MetaScreen *screen)
return info->window_group;
}
/**
* meta_get_background_actor_for_screen:
* @screen: a #MetaScreen
*
* Gets the actor that draws the root window background under the windows.
* The root window background automatically tracks the image or color set
* by the environment.
*
* Returns: (transfer none): The background actor corresponding to @screen
*/
ClutterActor *
meta_get_background_actor_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info)
return NULL;
return info->background_actor;
}
/**
* meta_get_window_actors:
* @screen: a #MetaScreen
*
* Returns: (transfer none) (element-type Clutter.Actor): The set of #MetaWindowActor on @screen
*/
GList *
mutter_get_windows (MetaScreen *screen)
meta_get_window_actors (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
@ -292,7 +292,7 @@ mutter_get_windows (MetaScreen *screen)
}
static void
do_set_stage_input_region (MetaScreen *screen,
do_set_stage_input_region (MetaScreen *screen,
XserverRegion region)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
@ -305,8 +305,8 @@ do_set_stage_input_region (MetaScreen *screen,
}
void
mutter_set_stage_input_region (MetaScreen *screen,
XserverRegion region)
meta_set_stage_input_region (MetaScreen *screen,
XserverRegion region)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaDisplay *display = meta_screen_get_display (screen);
@ -334,7 +334,7 @@ mutter_set_stage_input_region (MetaScreen *screen,
}
void
mutter_empty_stage_input_region (MetaScreen *screen)
meta_empty_stage_input_region (MetaScreen *screen)
{
/* Using a static region here is a bit hacky, but Metacity never opens more than
* one XDisplay, so it works fine. */
@ -347,16 +347,16 @@ mutter_empty_stage_input_region (MetaScreen *screen)
region = XFixesCreateRegion (xdpy, NULL, 0);
}
mutter_set_stage_input_region (screen, region);
meta_set_stage_input_region (screen, region);
}
gboolean
mutter_begin_modal_for_plugin (MetaScreen *screen,
MutterPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp)
meta_begin_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp)
{
/* To some extent this duplicates code in meta_display_begin_grab_op(), but there
* are significant differences in how we handle grabs that make it difficult to
@ -421,9 +421,9 @@ mutter_begin_modal_for_plugin (MetaScreen *screen,
}
void
mutter_end_modal_for_plugin (MetaScreen *screen,
MutterPlugin *plugin,
guint32 timestamp)
meta_end_modal_for_plugin (MetaScreen *screen,
MetaPlugin *plugin,
guint32 timestamp)
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
@ -447,15 +447,15 @@ mutter_end_modal_for_plugin (MetaScreen *screen,
* a left-over modal grab for this screen.
*/
void
mutter_check_end_modal (MetaScreen *screen)
meta_check_end_modal (MetaScreen *screen)
{
MetaDisplay *display = meta_screen_get_display (screen);
MetaCompositor *compositor = display->compositor;
if (compositor->modal_plugin &&
mutter_plugin_get_screen (compositor->modal_plugin) == screen)
meta_plugin_get_screen (compositor->modal_plugin) == screen)
{
mutter_end_modal_for_plugin (screen,
meta_end_modal_for_plugin (screen,
compositor->modal_plugin,
CurrentTime);
}
@ -483,7 +483,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
XSync (xdisplay, FALSE);
if (meta_error_trap_pop_with_return (display, FALSE))
if (meta_error_trap_pop_with_return (display))
{
g_warning ("Another compositing manager is running on screen %i",
screen_number);
@ -505,7 +505,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
info->output = None;
info->windows = NULL;
info->windows_by_xid = g_hash_table_new (g_direct_hash, g_direct_equal);
meta_screen_set_cm_selection (screen);
@ -532,10 +531,15 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
XSelectInput (xdisplay, xwin, event_mask);
info->window_group = mutter_window_group_new (screen);
info->window_group = meta_window_group_new (screen);
info->background_actor = meta_background_actor_new (screen);
info->overlay_group = clutter_group_new ();
info->hidden_group = clutter_group_new ();
clutter_container_add (CLUTTER_CONTAINER (info->window_group),
info->background_actor,
NULL);
clutter_container_add (CLUTTER_CONTAINER (info->stage),
info->window_group,
info->overlay_group,
@ -545,10 +549,18 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
clutter_actor_hide (info->hidden_group);
info->plugin_mgr =
mutter_plugin_manager_new (screen);
if (!mutter_plugin_manager_load (info->plugin_mgr))
g_critical ("failed to load plugins");
if (!mutter_plugin_manager_initialize (info->plugin_mgr))
meta_plugin_manager_get (screen);
if (info->plugin_mgr != meta_plugin_manager_get_default ())
{
/* The default plugin manager has been initialized during
* global preferences load.
*/
if (!meta_plugin_manager_load (info->plugin_mgr))
g_critical ("failed to load plugins");
}
if (!meta_plugin_manager_initialize (info->plugin_mgr))
g_critical ("failed to initialize plugins");
/*
@ -600,21 +612,21 @@ meta_compositor_add_window (MetaCompositor *compositor,
add_win (window);
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
void
meta_compositor_remove_window (MetaCompositor *compositor,
MetaWindow *window)
{
MutterWindow *cw = NULL;
MetaWindowActor *window_actor = NULL;
DEBUG_TRACE ("meta_compositor_remove_window\n");
cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
if (!cw)
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
if (!window_actor)
return;
mutter_window_destroy (cw);
meta_window_actor_destroy (window_actor);
}
void
@ -634,14 +646,17 @@ is_grabbed_event (XEvent *event)
case EnterNotify:
case LeaveNotify:
case MotionNotify:
case KeyPressMask:
case KeyReleaseMask:
case KeyPress:
case KeyRelease:
return TRUE;
}
return FALSE;
}
/**
* meta_compositor_process_event: (skip)
*
*/
gboolean
meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event,
@ -649,7 +664,7 @@ meta_compositor_process_event (MetaCompositor *compositor,
{
if (compositor->modal_plugin && is_grabbed_event (event))
{
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (compositor->modal_plugin);
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (compositor->modal_plugin);
if (klass->xevent_filter)
klass->xevent_filter (compositor->modal_plugin, event);
@ -667,7 +682,7 @@ meta_compositor_process_event (MetaCompositor *compositor,
screen = meta_window_get_screen (window);
info = meta_screen_get_compositor_data (screen);
if (mutter_plugin_manager_xevent_filter (info->plugin_mgr, event))
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
{
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
return TRUE;
@ -686,7 +701,7 @@ meta_compositor_process_event (MetaCompositor *compositor,
info = meta_screen_get_compositor_data (screen);
if (mutter_plugin_manager_xevent_filter (info->plugin_mgr, event))
if (meta_plugin_manager_xevent_filter (info->plugin_mgr, event))
{
DEBUG_TRACE ("meta_compositor_process_event (filtered,window==NULL)\n");
return TRUE;
@ -696,38 +711,37 @@ meta_compositor_process_event (MetaCompositor *compositor,
}
}
/*
* This trap is so that none of the compositor functions cause
* X errors. This is really a hack, but I'm afraid I don't understand
* enough about Metacity/X to know how else you are supposed to do it
*/
meta_error_trap_push (compositor->display);
switch (event->type)
{
case PropertyNotify:
process_property_notify (compositor, (XPropertyEvent *) event);
process_property_notify (compositor, (XPropertyEvent *) event, window);
break;
default:
if (event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
{
/* Core code doesn't handle damage events, so we need to extract the MetaWindow
* ourselves
*/
if (window == NULL)
{
Window xwin = ((XDamageNotifyEvent *) event)->drawable;
window = meta_display_lookup_x_window (compositor->display, xwin);
}
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
process_damage (compositor, (XDamageNotifyEvent *) event);
process_damage (compositor, (XDamageNotifyEvent *) event, window);
}
#ifdef HAVE_SHAPE
else if (event->type == meta_display_get_shape_event_base (compositor->display) + ShapeNotify)
{
DEBUG_TRACE ("meta_compositor_process_event (process_shape)\n");
process_shape (compositor, (XShapeEvent *) event);
process_shape (compositor, (XShapeEvent *) event, window);
}
#endif /* HAVE_SHAPE */
break;
}
meta_error_trap_pop (compositor->display, FALSE);
/* Clutter needs to know about MapNotify events otherwise it will
think the stage is invisible */
if (event->type == MapNotify)
@ -745,12 +759,12 @@ meta_compositor_show_window (MetaCompositor *compositor,
MetaWindow *window,
MetaCompEffect effect)
{
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
DEBUG_TRACE ("meta_compositor_show_window\n");
if (!cw)
if (!window_actor)
return;
mutter_window_show (cw, effect);
meta_window_actor_show (window_actor, effect);
}
void
@ -758,12 +772,12 @@ meta_compositor_hide_window (MetaCompositor *compositor,
MetaWindow *window,
MetaCompEffect effect)
{
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
DEBUG_TRACE ("meta_compositor_hide_window\n");
if (!cw)
if (!window_actor)
return;
mutter_window_hide (cw, effect);
meta_window_actor_hide (window_actor, effect);
}
void
@ -772,12 +786,12 @@ meta_compositor_maximize_window (MetaCompositor *compositor,
MetaRectangle *old_rect,
MetaRectangle *new_rect)
{
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
DEBUG_TRACE ("meta_compositor_maximize_window\n");
if (!cw)
if (!window_actor)
return;
mutter_window_maximize (cw, old_rect, new_rect);
meta_window_actor_maximize (window_actor, old_rect, new_rect);
}
void
@ -786,12 +800,12 @@ meta_compositor_unmaximize_window (MetaCompositor *compositor,
MetaRectangle *old_rect,
MetaRectangle *new_rect)
{
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
DEBUG_TRACE ("meta_compositor_unmaximize_window\n");
if (!cw)
if (!window_actor)
return;
mutter_window_unmaximize (cw, old_rect, new_rect);
meta_window_actor_unmaximize (window_actor, old_rect, new_rect);
}
void
@ -804,7 +818,7 @@ meta_compositor_update_workspace_geometry (MetaCompositor *compositor,
*/
MetaScreen *screen = meta_workspace_get_screen (workspace);
MetaCompScreen *info;
MutterPluginManager *mgr;
MetaPluginManager *mgr;
DEBUG_TRACE ("meta_compositor_update_workspace_geometry\n");
info = meta_screen_get_compositor_data (screen);
@ -813,7 +827,7 @@ meta_compositor_update_workspace_geometry (MetaCompositor *compositor,
if (!mgr || !workspace)
return;
mutter_plugin_manager_update_workspace (mgr, workspace);
meta_plugin_manager_update_workspace (mgr, workspace);
#endif
}
@ -839,8 +853,7 @@ meta_compositor_switch_workspace (MetaCompositor *compositor,
info->switch_workspace_in_progress++;
if (!info->plugin_mgr ||
!mutter_plugin_manager_switch_workspace (info->plugin_mgr,
(const GList **)&info->windows,
!meta_plugin_manager_switch_workspace (info->plugin_mgr,
from_indx,
to_indx,
direction))
@ -852,23 +865,78 @@ meta_compositor_switch_workspace (MetaCompositor *compositor,
* necessarily change during the window hiding/unhiding, only their
* relative position toward the destkop window.
*/
mutter_finish_workspace_switch (info);
meta_finish_workspace_switch (info);
}
}
static void
sync_actor_stacking (GList *windows)
sync_actor_stacking (MetaCompScreen *info)
{
GList *children;
GList *tmp;
GList *old;
gboolean reordered;
/* NB: The first entry in the list is stacked the lowest */
/* NB: The first entries in the lists are stacked the lowest */
for (tmp = g_list_last (windows); tmp != NULL; tmp = tmp->prev)
/* Restacking will trigger full screen redraws, so it's worth a
* little effort to make sure we actually need to restack before
* we go ahead and do it */
children = clutter_container_get_children (CLUTTER_CONTAINER (info->window_group));
reordered = FALSE;
old = children;
/* We allow for actors in the window group other than the actors we
* know about, but it's up to a plugin to try and keep them stacked correctly
* (we really need extra API to make that reliable.)
*/
/* Of the actors we know, the bottom actor should be the background actor */
while (old && old->data != info->background_actor && !META_IS_WINDOW_ACTOR (old->data))
old = old->next;
if (old == NULL || old->data != info->background_actor)
{
MutterWindow *cw = tmp->data;
clutter_actor_lower_bottom (CLUTTER_ACTOR (cw));
reordered = TRUE;
goto done_with_check;
}
/* Then the window actors should follow in sequence */
old = old->next;
for (tmp = info->windows; tmp != NULL; tmp = tmp->next)
{
while (old && !META_IS_WINDOW_ACTOR (old->data))
old = old->next;
/* old == NULL: someone reparented a window out of the window group,
* order undefined, always restack */
if (old == NULL || old->data != tmp->data)
{
reordered = TRUE;
goto done_with_check;
}
old = old->next;
}
done_with_check:
g_list_free (children);
if (!reordered)
return;
for (tmp = g_list_last (info->windows); tmp != NULL; tmp = tmp->prev)
{
MetaWindowActor *window_actor = tmp->data;
clutter_actor_lower_bottom (CLUTTER_ACTOR (window_actor));
}
clutter_actor_lower_bottom (info->background_actor);
}
void
@ -889,12 +957,12 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
/* Sources: first window is the highest */
stack = g_list_copy (stack); /* The new stack of MetaWindow */
old_stack = g_list_reverse (info->windows); /* The old stack of MutterWindow */
old_stack = g_list_reverse (info->windows); /* The old stack of MetaWindowActor */
info->windows = NULL;
while (TRUE)
{
MutterWindow *old_actor = NULL, *stack_actor = NULL, *actor;
MetaWindowActor *old_actor = NULL, *stack_actor = NULL, *actor;
MetaWindow *old_window = NULL, *stack_window = NULL, *window;
/* Find the remaining top actor in our existing stack (ignoring
@ -902,10 +970,10 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
while (old_stack)
{
old_actor = old_stack->data;
old_window = mutter_window_get_meta_window (old_actor);
old_window = meta_window_actor_get_meta_window (old_actor);
if (old_window->hidden &&
!mutter_window_effect_in_progress (old_actor))
!meta_window_actor_effect_in_progress (old_actor))
old_stack = g_list_delete_link (old_stack, old_stack);
else
break;
@ -915,10 +983,10 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
while (stack)
{
stack_window = stack->data;
stack_actor = MUTTER_WINDOW (meta_window_get_compositor_private (stack_window));
stack_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (stack_window));
if (!stack_actor)
{
meta_verbose ("Failed to find corresponding MutterWindow "
meta_verbose ("Failed to find corresponding MetaWindowActor "
"for window %s\n", meta_window_get_description (stack_window));
stack = g_list_delete_link (stack, stack);
}
@ -957,48 +1025,48 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
old_stack = g_list_remove (old_stack, actor);
}
sync_actor_stacking (info->windows);
sync_actor_stacking (info);
}
void
meta_compositor_window_mapped (MetaCompositor *compositor,
MetaWindow *window)
{
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
DEBUG_TRACE ("meta_compositor_window_mapped\n");
if (!cw)
if (!window_actor)
return;
mutter_window_mapped (cw);
meta_window_actor_mapped (window_actor);
}
void
meta_compositor_window_unmapped (MetaCompositor *compositor,
MetaWindow *window)
{
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
DEBUG_TRACE ("meta_compositor_window_unmapped\n");
if (!cw)
if (!window_actor)
return;
mutter_window_unmapped (cw);
meta_window_actor_unmapped (window_actor);
}
void
meta_compositor_sync_window_geometry (MetaCompositor *compositor,
MetaWindow *window)
{
MutterWindow *cw = MUTTER_WINDOW (meta_window_get_compositor_private (window));
MetaScreen *screen = meta_window_get_screen (window);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
MetaScreen *screen = meta_window_get_screen (window);
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
DEBUG_TRACE ("meta_compositor_sync_window_geometry\n");
g_return_if_fail (info);
if (!cw)
if (!window_actor)
return;
mutter_window_sync_actor_position (cw);
meta_window_actor_sync_actor_position (window_actor);
}
void
@ -1014,6 +1082,8 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
clutter_actor_set_size (info->stage, width, height);
meta_background_actor_screen_size_changed (META_BACKGROUND_ACTOR (info->background_actor));
meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
meta_screen_get_screen_number (screen),
width, height);
@ -1025,11 +1095,11 @@ pre_paint_windows (MetaCompScreen *info)
GList *l;
for (l = info->windows; l; l = l->next)
mutter_window_pre_paint (l->data);
meta_window_actor_pre_paint (l->data);
}
static gboolean
mutter_repaint_func (gpointer data)
meta_repaint_func (gpointer data)
{
MetaCompositor *compositor = data;
GSList *screens = meta_display_get_screens (compositor->display);
@ -1048,6 +1118,30 @@ mutter_repaint_func (gpointer data)
return TRUE;
}
static void
on_shadow_factory_changed (MetaShadowFactory *factory,
MetaCompositor *compositor)
{
GSList *screens = meta_display_get_screens (compositor->display);
GList *l;
GSList *sl;
for (sl = screens; sl; sl = sl->next)
{
MetaScreen *screen = sl->data;
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info)
continue;
for (l = info->windows; l; l = l->next)
meta_window_actor_invalidate_shadow (l->data);
}
}
/**
* meta_compositor_new: (skip)
*
*/
MetaCompositor *
meta_compositor_new (MetaDisplay *display)
{
@ -1067,26 +1161,35 @@ meta_compositor_new (MetaDisplay *display)
compositor->display = display;
if (g_getenv("MUTTER_DISABLE_MIPMAPS"))
if (g_getenv("META_DISABLE_MIPMAPS"))
compositor->no_mipmaps = TRUE;
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
False, atoms);
g_signal_connect (meta_shadow_factory_get_default (),
"changed",
G_CALLBACK (on_shadow_factory_changed),
compositor);
compositor->atom_x_root_pixmap = atoms[0];
compositor->atom_x_set_root = atoms[1];
compositor->atom_net_wm_window_opacity = atoms[2];
compositor->repaint_func_id = clutter_threads_add_repaint_func (mutter_repaint_func,
compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
compositor,
NULL);
return compositor;
}
/**
* meta_get_overlay_window: (skip)
*
*/
Window
mutter_get_overlay_window (MetaScreen *screen)
meta_get_overlay_window (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);

View File

@ -0,0 +1,414 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* meta-background-actor.c: Actor for painting the root window background
*
* Copyright 2009 Sander Dijkhuis
* Copyright 2010 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.
*
* Portions adapted from gnome-shell/src/shell-global.c
*/
#include <config.h>
#define COGL_ENABLE_EXPERIMENTAL_API
#include <cogl/cogl-texture-pixmap-x11.h>
#include <X11/Xatom.h>
#include "cogl-utils.h"
#include "compositor-private.h"
#include "errors.h"
#include "meta-background-actor.h"
struct _MetaBackgroundActorClass
{
ClutterActorClass parent_class;
};
struct _MetaBackgroundActor
{
ClutterActor parent;
CoglHandle material;
MetaScreen *screen;
cairo_region_t *visible_region;
float texture_width;
float texture_height;
guint have_pixmap : 1;
};
G_DEFINE_TYPE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR);
static void
update_wrap_mode (MetaBackgroundActor *self)
{
int width, height;
CoglMaterialWrapMode wrap_mode;
meta_screen_get_size (self->screen, &width, &height);
/* We turn off repeating when we have a full-screen pixmap to keep from
* getting artifacts from one side of the image sneaking into the other
* side of the image via bilinear filtering.
*/
if (width == self->texture_width && height == self->texture_height)
wrap_mode = COGL_MATERIAL_WRAP_MODE_CLAMP_TO_EDGE;
else
wrap_mode = COGL_MATERIAL_WRAP_MODE_REPEAT;
cogl_material_set_layer_wrap_mode (self->material, 0, wrap_mode);
}
static void
set_texture (MetaBackgroundActor *self,
CoglHandle texture)
{
MetaDisplay *display;
display = meta_screen_get_display (self->screen);
/* This may trigger destruction of an old texture pixmap, which, if
* the underlying X pixmap is already gone has the tendency to trigger
* X errors inside DRI. For safety, trap errors */
meta_error_trap_push (display);
cogl_material_set_layer (self->material, 0, texture);
meta_error_trap_pop (display);
self->texture_width = cogl_texture_get_width (texture);
self->texture_height = cogl_texture_get_height (texture);
update_wrap_mode (self);
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
}
/* Sets our material to paint with a 1x1 texture of the stage's background
* color; doing this when we have no pixmap allows the application to turn
* off painting the stage. There might be a performance benefit to
* painting in this case with a solid color, but the normal solid color
* case is a 1x1 root pixmap, so we'd have to reverse-engineer that to
* actually pick up the (small?) performance win. This is just a fallback.
*/
static void
set_texture_to_stage_color (MetaBackgroundActor *self)
{
ClutterActor *stage = meta_get_stage_for_screen (self->screen);
ClutterColor color;
CoglHandle texture;
clutter_stage_get_color (CLUTTER_STAGE (stage), &color);
texture = meta_create_color_texture_4ub (color.red, color.green,
color.blue, 0xff);
set_texture (self, texture);
cogl_handle_unref (texture);
}
static void
on_notify_stage_color (GObject *stage,
GParamSpec *pspec,
MetaBackgroundActor *self)
{
if (!self->have_pixmap)
set_texture_to_stage_color (self);
}
static void
meta_background_actor_dispose (GObject *object)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
meta_background_actor_set_visible_region (self, NULL);
if (self->material != COGL_INVALID_HANDLE)
{
cogl_handle_unref (self->material);
self->material = COGL_INVALID_HANDLE;
}
if (self->screen != NULL)
{
ClutterActor *stage = meta_get_stage_for_screen (self->screen);
g_signal_handlers_disconnect_by_func (stage,
(gpointer) on_notify_stage_color,
self);
self->screen = NULL;
}
}
static void
meta_background_actor_get_preferred_width (ClutterActor *actor,
gfloat for_height,
gfloat *min_width_p,
gfloat *natural_width_p)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
int width, height;
meta_screen_get_size (self->screen, &width, &height);
if (min_width_p)
*min_width_p = width;
if (natural_width_p)
*natural_width_p = height;
}
static void
meta_background_actor_get_preferred_height (ClutterActor *actor,
gfloat for_width,
gfloat *min_height_p,
gfloat *natural_height_p)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
int width, height;
meta_screen_get_size (self->screen, &width, &height);
if (min_height_p)
*min_height_p = height;
if (natural_height_p)
*natural_height_p = height;
}
static void
meta_background_actor_paint (ClutterActor *actor)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
int width, height;
meta_screen_get_size (self->screen, &width, &height);
cogl_set_source (self->material);
if (self->visible_region)
{
int n_rectangles = cairo_region_num_rectangles (self->visible_region);
int i;
for (i = 0; i < n_rectangles; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (self->visible_region, i, &rect);
cogl_rectangle_with_texture_coords (rect.x, rect.y,
rect.x + rect.width, rect.y + rect.height,
rect.x / self->texture_width,
rect.y / self->texture_height,
(rect.x + rect.width) / self->texture_width,
(rect.y + rect.height) / self->texture_height);
}
}
else
{
cogl_rectangle_with_texture_coords (0.0f, 0.0f,
width, height,
0.0f, 0.0f,
width / self->texture_width,
height / self->texture_height);
}
}
#if CLUTTER_CHECK_VERSION(1, 5, 2)
static gboolean
meta_background_actor_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (actor);
int width, height;
meta_screen_get_size (self->screen, &width, &height);
clutter_paint_volume_set_width (volume, width);
clutter_paint_volume_set_height (volume, height);
return TRUE;
}
#endif
static void
meta_background_actor_class_init (MetaBackgroundActorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
object_class->dispose = meta_background_actor_dispose;
actor_class->get_preferred_width = meta_background_actor_get_preferred_width;
actor_class->get_preferred_height = meta_background_actor_get_preferred_height;
actor_class->paint = meta_background_actor_paint;
#if CLUTTER_CHECK_VERSION(1, 5, 2)
actor_class->get_paint_volume = meta_background_actor_get_paint_volume;
#endif
}
static void
meta_background_actor_init (MetaBackgroundActor *background_actor)
{
}
/**
* @screen: the #MetaScreen
* meta_background_actor_new:
*
* Creates a new actor to draw the background for the given screen.
*
* Return value: (transfer none): the newly created background actor
*/
ClutterActor *
meta_background_actor_new (MetaScreen *screen)
{
MetaBackgroundActor *self;
ClutterActor *stage;
g_return_val_if_fail (META_IS_SCREEN (screen), NULL);
self = g_object_new (META_TYPE_BACKGROUND_ACTOR, NULL);
self->screen = screen;
self->material = meta_create_texture_material (NULL);
cogl_material_set_layer_wrap_mode (self->material, 0,
COGL_MATERIAL_WRAP_MODE_REPEAT);
stage = meta_get_stage_for_screen (self->screen);
g_signal_connect (stage, "notify::color",
G_CALLBACK (on_notify_stage_color), self);
meta_background_actor_update (self);
return CLUTTER_ACTOR (self);
}
/**
* meta_background_actor_update:
* @self: a #MetaBackgroundActor
*
* Refetches the _XROOTPMAP_ID property for the root window and updates
* the contents of the background actor based on that. There's no attempt
* to optimize out pixmap values that don't change (since a root pixmap
* could be replaced by with another pixmap with the same ID under some
* circumstances), so this should only be called when we actually receive
* a PropertyNotify event for the property.
*/
void
meta_background_actor_update (MetaBackgroundActor *self)
{
MetaDisplay *display;
MetaCompositor *compositor;
Atom type;
int format;
gulong nitems;
gulong bytes_after;
guchar *data;
Pixmap root_pixmap_id;
g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
display = meta_screen_get_display (self->screen);
compositor = meta_display_get_compositor (display);
root_pixmap_id = None;
if (!XGetWindowProperty (meta_display_get_xdisplay (display),
meta_screen_get_xroot (self->screen),
compositor->atom_x_root_pixmap,
0, LONG_MAX,
False,
AnyPropertyType,
&type, &format, &nitems, &bytes_after, &data) &&
type != None)
{
/* Got a property. */
if (type == XA_PIXMAP && format == 32 && nitems == 1)
{
/* Was what we expected. */
root_pixmap_id = *(Pixmap *)data;
}
XFree(data);
}
if (root_pixmap_id != None)
{
CoglHandle texture;
meta_error_trap_push (display);
texture = cogl_texture_pixmap_x11_new (root_pixmap_id, FALSE);
meta_error_trap_pop (display);
if (texture != COGL_INVALID_HANDLE)
{
set_texture (self, texture);
cogl_handle_unref (texture);
self->have_pixmap = True;
return;
}
}
self->have_pixmap = False;
set_texture_to_stage_color (self);
}
/**
* meta_background_actor_set_visible_region:
* @self: a #MetaBackgroundActor
* @visible_region: (allow-none): the area of the actor (in allocate-relative
* coordinates) that is visible.
*
* Sets the area of the background that is unobscured by overlapping windows.
* This is used to optimize and only paint the visible portions.
*/
void
meta_background_actor_set_visible_region (MetaBackgroundActor *self,
cairo_region_t *visible_region)
{
g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
if (self->visible_region)
{
cairo_region_destroy (self->visible_region);
self->visible_region = NULL;
}
if (visible_region)
{
cairo_rectangle_int_t screen_rect = { 0 };
meta_screen_get_size (self->screen, &screen_rect.width, &screen_rect.height);
/* Doing the intersection here is probably unnecessary - MetaWindowGroup
* should never compute a visible area that's larger than the root screen!
* but it's not that expensive and adds some extra robustness.
*/
self->visible_region = cairo_region_create_rectangle (&screen_rect);
cairo_region_intersect (self->visible_region, visible_region);
}
}
/**
* meta_background_actor_screen_size_changed:
* @self: a #MetaBackgroundActor
*
* Called by the compositor when the size of the #MetaScreen changes
*/
void
meta_background_actor_screen_size_changed (MetaBackgroundActor *self)
{
update_wrap_mode (self);
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
}

View File

@ -0,0 +1,58 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* meta-background-actor.h: Actor for painting the root window background
*
* Copyright 2010 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_BACKGROUND_ACTOR_H
#define META_BACKGROUND_ACTOR_H
#include <clutter/clutter.h>
#include "screen.h"
/**
* MetaBackgroundActor:
*
* This class handles tracking and painting the root window background.
* By integrating with #MetaWindowGroup we can avoid painting parts of
* the background that are obscured by other windows.
*/
#define META_TYPE_BACKGROUND_ACTOR (meta_background_actor_get_type ())
#define META_BACKGROUND_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKGROUND_ACTOR, MetaBackgroundActor))
#define META_BACKGROUND_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BACKGROUND_ACTOR, MetaBackgroundActorClass))
#define META_IS_BACKGROUND_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKGROUND_ACTOR))
#define META_IS_BACKGROUND_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BACKGROUND_ACTOR))
#define META_BACKGROUND_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BACKGROUND_ACTOR, MetaBackgroundActorClass))
typedef struct _MetaBackgroundActor MetaBackgroundActor;
typedef struct _MetaBackgroundActorClass MetaBackgroundActorClass;
typedef struct _MetaBackgroundActorPrivate MetaBackgroundActorPrivate;
GType meta_background_actor_get_type (void);
ClutterActor *meta_background_actor_new (MetaScreen *screen);
void meta_background_actor_update (MetaBackgroundActor *actor);
void meta_background_actor_set_visible_region (MetaBackgroundActor *self,
cairo_region_t *visible_region);
void meta_background_actor_screen_size_changed (MetaBackgroundActor *self);
#endif /* META_BACKGROUND_ACTOR_H */

View File

@ -21,8 +21,8 @@
* 02111-1307, USA.
*/
#include "mutter-plugin.h"
#include "mutter-module.h"
#include "meta-plugin.h"
#include "meta-module.h"
#include <gmodule.h>
@ -32,23 +32,23 @@ enum
PROP_PATH,
};
struct _MutterModulePrivate
struct _MetaModulePrivate
{
GModule *lib;
gchar *path;
GType plugin_type;
};
#define MUTTER_MODULE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_MODULE, MutterModulePrivate))
#define META_MODULE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_MODULE, MetaModulePrivate))
G_DEFINE_TYPE (MutterModule, mutter_module, G_TYPE_TYPE_MODULE);
G_DEFINE_TYPE (MetaModule, meta_module, G_TYPE_TYPE_MODULE);
static gboolean
mutter_module_load (GTypeModule *gmodule)
meta_module_load (GTypeModule *gmodule)
{
MutterModulePrivate *priv = MUTTER_MODULE (gmodule)->priv;
MutterPluginVersion *info = NULL;
MetaModulePrivate *priv = META_MODULE (gmodule)->priv;
MetaPluginVersion *info = NULL;
GType (*register_type) (GTypeModule *) = NULL;
if (priv->lib && priv->plugin_type)
@ -64,9 +64,9 @@ mutter_module_load (GTypeModule *gmodule)
return FALSE;
}
if (g_module_symbol (priv->lib, "mutter_plugin_version",
if (g_module_symbol (priv->lib, "meta_plugin_version",
(gpointer *)(void *)&info) &&
g_module_symbol (priv->lib, "mutter_plugin_register_type",
g_module_symbol (priv->lib, "meta_plugin_register_type",
(gpointer *)(void *)&register_type) &&
info && register_type)
{
@ -97,9 +97,9 @@ mutter_module_load (GTypeModule *gmodule)
}
static void
mutter_module_unload (GTypeModule *gmodule)
meta_module_unload (GTypeModule *gmodule)
{
MutterModulePrivate *priv = MUTTER_MODULE (gmodule)->priv;
MetaModulePrivate *priv = META_MODULE (gmodule)->priv;
g_module_close (priv->lib);
@ -108,29 +108,29 @@ mutter_module_unload (GTypeModule *gmodule)
}
static void
mutter_module_dispose (GObject *object)
meta_module_dispose (GObject *object)
{
G_OBJECT_CLASS (mutter_module_parent_class)->dispose (object);
G_OBJECT_CLASS (meta_module_parent_class)->dispose (object);
}
static void
mutter_module_finalize (GObject *object)
meta_module_finalize (GObject *object)
{
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
MetaModulePrivate *priv = META_MODULE (object)->priv;
g_free (priv->path);
priv->path = NULL;
G_OBJECT_CLASS (mutter_module_parent_class)->finalize (object);
G_OBJECT_CLASS (meta_module_parent_class)->finalize (object);
}
static void
mutter_module_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
meta_module_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
MetaModulePrivate *priv = META_MODULE (object)->priv;
switch (prop_id)
{
@ -145,12 +145,12 @@ mutter_module_set_property (GObject *object,
}
static void
mutter_module_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
meta_module_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MutterModulePrivate *priv = MUTTER_MODULE (object)->priv;
MetaModulePrivate *priv = META_MODULE (object)->priv;
switch (prop_id)
{
@ -164,18 +164,18 @@ mutter_module_get_property (GObject *object,
}
static void
mutter_module_class_init (MutterModuleClass *klass)
meta_module_class_init (MetaModuleClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
GTypeModuleClass *gmodule_class = G_TYPE_MODULE_CLASS (klass);
gobject_class->finalize = mutter_module_finalize;
gobject_class->dispose = mutter_module_dispose;
gobject_class->set_property = mutter_module_set_property;
gobject_class->get_property = mutter_module_get_property;
gobject_class->finalize = meta_module_finalize;
gobject_class->dispose = meta_module_dispose;
gobject_class->set_property = meta_module_set_property;
gobject_class->get_property = meta_module_get_property;
gmodule_class->load = mutter_module_load;
gmodule_class->unload = mutter_module_unload;
gmodule_class->load = meta_module_load;
gmodule_class->unload = meta_module_unload;
g_object_class_install_property (gobject_class,
PROP_PATH,
@ -186,22 +186,22 @@ mutter_module_class_init (MutterModuleClass *klass)
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_type_class_add_private (gobject_class, sizeof (MutterModulePrivate));
g_type_class_add_private (gobject_class, sizeof (MetaModulePrivate));
}
static void
mutter_module_init (MutterModule *self)
meta_module_init (MetaModule *self)
{
MutterModulePrivate *priv;
MetaModulePrivate *priv;
self->priv = priv = MUTTER_MODULE_GET_PRIVATE (self);
self->priv = priv = META_MODULE_GET_PRIVATE (self);
}
GType
mutter_module_get_plugin_type (MutterModule *module)
meta_module_get_plugin_type (MetaModule *module)
{
MutterModulePrivate *priv = MUTTER_MODULE (module)->priv;
MetaModulePrivate *priv = META_MODULE (module)->priv;
return priv->plugin_type;
}

View File

@ -21,37 +21,37 @@
* 02111-1307, USA.
*/
#ifndef MUTTER_MODULE_H_
#define MUTTER_MODULE_H_
#ifndef META_MODULE_H_
#define META_MODULE_H_
#include <glib-object.h>
#define MUTTER_TYPE_MODULE (mutter_module_get_type ())
#define MUTTER_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_MODULE, MutterModule))
#define MUTTER_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_MODULE, MutterModuleClass))
#define MUTTER_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_MODULE_TYPE))
#define MUTTER_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_MODULE))
#define MUTTER_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_MODULE, MutterModuleClass))
#define META_TYPE_MODULE (meta_module_get_type ())
#define META_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_MODULE, MetaModule))
#define META_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_MODULE, MetaModuleClass))
#define META_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_MODULE_TYPE))
#define META_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_MODULE))
#define META_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_MODULE, MetaModuleClass))
typedef struct _MutterModule MutterModule;
typedef struct _MutterModuleClass MutterModuleClass;
typedef struct _MutterModulePrivate MutterModulePrivate;
typedef struct _MetaModule MetaModule;
typedef struct _MetaModuleClass MetaModuleClass;
typedef struct _MetaModulePrivate MetaModulePrivate;
struct _MutterModule
struct _MetaModule
{
GTypeModule parent;
MutterModulePrivate *priv;
MetaModulePrivate *priv;
};
struct _MutterModuleClass
struct _MetaModuleClass
{
GTypeModuleClass parent_class;
};
GType mutter_module_get_type (void);
GType meta_module_get_type (void);
GType mutter_module_get_plugin_type (MutterModule *module);
GType meta_module_get_plugin_type (MetaModule *module);
#endif

View File

@ -23,11 +23,11 @@
#include "config.h"
#include "compositor-private.h"
#include "mutter-plugin-manager.h"
#include "meta-plugin-manager.h"
#include "prefs.h"
#include "errors.h"
#include "workspace.h"
#include "mutter-module.h"
#include "meta-module.h"
#include "../core/window-private.h"
#include <string.h>
@ -39,37 +39,38 @@
*/
static GHashTable *plugin_modules = NULL;
static gboolean mutter_plugin_manager_reload (MutterPluginManager *plugin_mgr);
/*
* We have one "default plugin manager" that acts for the first screen,
* but also can be used before we open any screens, and additional
* plugin managers for each screen. (This is ugly. Probably we should
* have one plugin manager and only make the plugins per-screen.)
*/
struct MutterPluginManager
static MetaPluginManager *default_plugin_manager;
static gboolean meta_plugin_manager_reload (MetaPluginManager *plugin_mgr);
struct MetaPluginManager
{
MetaScreen *screen;
GList /* MutterPluginPending */ *pending_plugin_modules; /* Plugins not yet fully loaded */
GList /* MutterPlugin */ *plugins; /* TODO -- maybe use hash table */
GList *unload; /* Plugins that are disabled and pending unload */
GList /* MetaPlugin */ *plugins; /* TODO -- maybe use hash table */
GList *unload; /* Plugins that are disabled and pending unload */
guint idle_unload_id;
};
typedef struct MutterPluginPending
{
MutterModule *module;
char *path;
char *params;
} MutterPluginPending;
/*
* Checks that the plugin is compatible with the WM and sets up the plugin
* struct.
*/
static MutterPlugin *
mutter_plugin_load (MutterPluginManager *mgr,
MutterModule *module,
const gchar *params)
static MetaPlugin *
meta_plugin_load (MetaPluginManager *mgr,
MetaModule *module,
const gchar *params)
{
MutterPlugin *plugin = NULL;
GType plugin_type = mutter_module_get_plugin_type (module);
MetaPlugin *plugin = NULL;
GType plugin_type = meta_module_get_plugin_type (module);
if (!plugin_type)
{
@ -78,7 +79,6 @@ mutter_plugin_load (MutterPluginManager *mgr,
}
plugin = g_object_new (plugin_type,
"screen", mgr->screen,
"params", params,
NULL);
@ -91,9 +91,9 @@ mutter_plugin_load (MutterPluginManager *mgr,
* removal later.
*/
static gboolean
mutter_plugin_unload (MutterPlugin *plugin)
meta_plugin_unload (MetaPlugin *plugin)
{
if (mutter_plugin_running (plugin))
if (meta_plugin_running (plugin))
{
g_object_set (plugin, "disabled", TRUE, NULL);
return FALSE;
@ -109,16 +109,16 @@ mutter_plugin_unload (MutterPlugin *plugin)
* pending for removal.
*/
static gboolean
mutter_plugin_manager_idle_unload (MutterPluginManager *plugin_mgr)
meta_plugin_manager_idle_unload (MetaPluginManager *plugin_mgr)
{
GList *l = plugin_mgr->unload;
gboolean dont_remove = TRUE;
while (l)
{
MutterPlugin *plugin = l->data;
MetaPlugin *plugin = l->data;
if (mutter_plugin_unload (plugin))
if (meta_plugin_unload (plugin))
{
/* Remove from list */
GList *p = l->prev;
@ -154,23 +154,23 @@ mutter_plugin_manager_idle_unload (MutterPluginManager *plugin_mgr)
* Unloads all plugins
*/
static void
mutter_plugin_manager_unload (MutterPluginManager *plugin_mgr)
meta_plugin_manager_unload (MetaPluginManager *plugin_mgr)
{
GList *plugins = plugin_mgr->plugins;
while (plugins)
{
MutterPlugin *plugin = plugins->data;
MetaPlugin *plugin = plugins->data;
/* If the plugin could not be removed, move it to the unload list */
if (!mutter_plugin_unload (plugin))
if (!meta_plugin_unload (plugin))
{
plugin_mgr->unload = g_list_prepend (plugin_mgr->unload, plugin);
if (!plugin_mgr->idle_unload_id)
{
plugin_mgr->idle_unload_id = g_idle_add ((GSourceFunc)
mutter_plugin_manager_idle_unload,
meta_plugin_manager_idle_unload,
plugin_mgr);
}
}
@ -186,21 +186,21 @@ static void
prefs_changed_callback (MetaPreference pref,
void *data)
{
MutterPluginManager *plugin_mgr = data;
MetaPluginManager *plugin_mgr = data;
if (pref == META_PREF_CLUTTER_PLUGINS)
{
mutter_plugin_manager_reload (plugin_mgr);
meta_plugin_manager_reload (plugin_mgr);
}
}
static MutterModule *
mutter_plugin_manager_get_module (const gchar *path)
static MetaModule *
meta_plugin_manager_get_module (const gchar *path)
{
MutterModule *module = g_hash_table_lookup (plugin_modules, path);
MetaModule *module = g_hash_table_lookup (plugin_modules, path);
if (!module &&
(module = g_object_new (MUTTER_TYPE_MODULE, "path", path, NULL)))
(module = g_object_new (META_TYPE_MODULE, "path", path, NULL)))
{
g_hash_table_insert (plugin_modules, g_strdup (path), module);
}
@ -212,7 +212,7 @@ mutter_plugin_manager_get_module (const gchar *path)
* Loads all plugins listed in gconf registry.
*/
gboolean
mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
meta_plugin_manager_load (MetaPluginManager *plugin_mgr)
{
const gchar *dpath = MUTTER_PLUGIN_DIR "/";
GSList *plugins, *fallback = NULL;
@ -237,7 +237,7 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
if (plugin_string)
{
MutterModule *module;
MetaModule *module;
gchar *path;
params = strchr (plugin_string, ':');
@ -253,7 +253,7 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
else
path = g_strconcat (dpath, plugin_string, ".so", NULL);
module = mutter_plugin_manager_get_module (path);
module = meta_plugin_manager_get_module (path);
if (module)
{
@ -270,12 +270,14 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
if (use_succeeded)
{
MutterPluginPending *pending = g_new0 (MutterPluginPending, 1);
pending->module = module;
pending->path = g_strdup (path);
pending->params = g_strdup (params);
plugin_mgr->pending_plugin_modules =
g_list_prepend (plugin_mgr->pending_plugin_modules, pending);
MetaPlugin *plugin = meta_plugin_load (plugin_mgr, module, params);
if (plugin)
plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, plugin);
else
g_warning ("Plugin load for [%s] failed", path);
g_type_module_unuse (G_TYPE_MODULE (module));
}
}
else
@ -293,7 +295,7 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
if (fallback)
g_slist_free (fallback);
if (plugin_mgr->pending_plugin_modules != NULL)
if (plugin_mgr->plugins != NULL)
{
meta_prefs_add_listener (prefs_changed_callback, plugin_mgr);
return TRUE;
@ -303,31 +305,23 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
}
gboolean
mutter_plugin_manager_initialize (MutterPluginManager *plugin_mgr)
meta_plugin_manager_initialize (MetaPluginManager *plugin_mgr)
{
GList *iter;
for (iter = plugin_mgr->pending_plugin_modules; iter; iter = iter->next)
for (iter = plugin_mgr->plugins; iter; iter = iter->next)
{
MutterPluginPending *pending = (MutterPluginPending*) iter->data;
MutterPlugin *p;
MetaPlugin *plugin = (MetaPlugin*) iter->data;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if ((p = mutter_plugin_load (plugin_mgr, pending->module, pending->params)))
{
plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, p);
}
else
{
g_warning ("Plugin load for [%s] failed", pending->path);
}
g_object_set (plugin,
"screen", plugin_mgr->screen,
NULL);
g_type_module_unuse (G_TYPE_MODULE (pending->module));
g_free (pending->path);
g_free (pending->params);
g_free (pending);
if (klass->start)
klass->start (plugin);
}
g_list_free (plugin_mgr->pending_plugin_modules);
plugin_mgr->pending_plugin_modules = NULL;
return TRUE;
}
@ -335,7 +329,7 @@ mutter_plugin_manager_initialize (MutterPluginManager *plugin_mgr)
* Reloads all plugins
*/
static gboolean
mutter_plugin_manager_reload (MutterPluginManager *plugin_mgr)
meta_plugin_manager_reload (MetaPluginManager *plugin_mgr)
{
/* TODO -- brute force; should we build a list of plugins to load and list of
* plugins to unload? We are probably not going to have large numbers of
@ -343,16 +337,16 @@ mutter_plugin_manager_reload (MutterPluginManager *plugin_mgr)
*/
/* Prevent stale grabs on unloaded plugins */
mutter_check_end_modal (plugin_mgr->screen);
meta_check_end_modal (plugin_mgr->screen);
mutter_plugin_manager_unload (plugin_mgr);
return mutter_plugin_manager_load (plugin_mgr);
meta_plugin_manager_unload (plugin_mgr);
return meta_plugin_manager_load (plugin_mgr);
}
MutterPluginManager *
mutter_plugin_manager_new (MetaScreen *screen)
static MetaPluginManager *
meta_plugin_manager_new (MetaScreen *screen)
{
MutterPluginManager *plugin_mgr;
MetaPluginManager *plugin_mgr;
if (!plugin_modules)
{
@ -360,37 +354,91 @@ mutter_plugin_manager_new (MetaScreen *screen)
NULL);
}
plugin_mgr = g_new0 (MutterPluginManager, 1);
plugin_mgr = g_new0 (MetaPluginManager, 1);
plugin_mgr->screen = screen;
if (screen)
g_object_set_data (G_OBJECT (screen), "meta-plugin-manager", plugin_mgr);
return plugin_mgr;
}
MetaPluginManager *
meta_plugin_manager_get_default (void)
{
if (!default_plugin_manager)
{
default_plugin_manager = meta_plugin_manager_new (NULL);
}
return default_plugin_manager;
}
MetaPluginManager *
meta_plugin_manager_get (MetaScreen *screen)
{
MetaPluginManager *plugin_mgr;
plugin_mgr = g_object_get_data (G_OBJECT (screen), "meta-plugin-manager");
if (plugin_mgr)
return plugin_mgr;
if (!default_plugin_manager)
meta_plugin_manager_get_default ();
if (!default_plugin_manager->screen)
{
/* The default plugin manager is so far unused, we can recycle it */
default_plugin_manager->screen = screen;
g_object_set_data (G_OBJECT (screen), "meta-plugin-manager", default_plugin_manager);
return default_plugin_manager;
}
else
{
return meta_plugin_manager_new (screen);
}
}
static void
mutter_plugin_manager_kill_effect (MutterPluginManager *plugin_mgr,
MutterWindow *actor,
unsigned long events)
meta_plugin_manager_kill_window_effects (MetaPluginManager *plugin_mgr,
MetaWindowActor *actor)
{
GList *l = plugin_mgr->plugins;
while (l)
{
MutterPlugin *plugin = l->data;
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
MetaPlugin *plugin = l->data;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (!mutter_plugin_disabled (plugin)
&& (mutter_plugin_features (plugin) & events)
&& klass->kill_effect)
klass->kill_effect (plugin, actor, events);
if (!meta_plugin_disabled (plugin)
&& klass->kill_window_effects)
klass->kill_window_effects (plugin, actor);
l = l->next;
}
}
static void
meta_plugin_manager_kill_switch_workspace (MetaPluginManager *plugin_mgr)
{
GList *l = plugin_mgr->plugins;
while (l)
{
MetaPlugin *plugin = l->data;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (!meta_plugin_disabled (plugin)
&& (meta_plugin_features (plugin) & META_PLUGIN_SWITCH_WORKSPACE)
&& klass->kill_switch_workspace)
klass->kill_switch_workspace (plugin);
l = l->next;
}
}
#define ALL_BUT_SWITCH \
MUTTER_PLUGIN_ALL_EFFECTS & \
~MUTTER_PLUGIN_SWITCH_WORKSPACE
/*
* Public method that the compositor hooks into for events that require
* no additional parameters.
@ -401,9 +449,9 @@ mutter_plugin_manager_kill_effect (MutterPluginManager *plugin_mgr,
* appropriate post-effect cleanup is carried out.
*/
gboolean
mutter_plugin_manager_event_simple (MutterPluginManager *plugin_mgr,
MutterWindow *actor,
unsigned long event)
meta_plugin_manager_event_simple (MetaPluginManager *plugin_mgr,
MetaWindowActor *actor,
unsigned long event)
{
GList *l = plugin_mgr->plugins;
gboolean retval = FALSE;
@ -414,44 +462,42 @@ mutter_plugin_manager_event_simple (MutterPluginManager *plugin_mgr,
while (l)
{
MutterPlugin *plugin = l->data;
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
MetaPlugin *plugin = l->data;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (!mutter_plugin_disabled (plugin) &&
(mutter_plugin_features (plugin) & event))
if (!meta_plugin_disabled (plugin) &&
(meta_plugin_features (plugin) & event))
{
retval = TRUE;
switch (event)
{
case MUTTER_PLUGIN_MINIMIZE:
case META_PLUGIN_MINIMIZE:
if (klass->minimize)
{
mutter_plugin_manager_kill_effect (
meta_plugin_manager_kill_window_effects (
plugin_mgr,
actor,
ALL_BUT_SWITCH);
actor);
_mutter_plugin_effect_started (plugin);
_meta_plugin_effect_started (plugin);
klass->minimize (plugin, actor);
}
break;
case MUTTER_PLUGIN_MAP:
case META_PLUGIN_MAP:
if (klass->map)
{
mutter_plugin_manager_kill_effect (
meta_plugin_manager_kill_window_effects (
plugin_mgr,
actor,
ALL_BUT_SWITCH);
actor);
_mutter_plugin_effect_started (plugin);
_meta_plugin_effect_started (plugin);
klass->map (plugin, actor);
}
break;
case MUTTER_PLUGIN_DESTROY:
case META_PLUGIN_DESTROY:
if (klass->destroy)
{
_mutter_plugin_effect_started (plugin);
_meta_plugin_effect_started (plugin);
klass->destroy (plugin, actor);
}
break;
@ -476,13 +522,13 @@ mutter_plugin_manager_event_simple (MutterPluginManager *plugin_mgr,
* appropriate post-effect cleanup is carried out.
*/
gboolean
mutter_plugin_manager_event_maximize (MutterPluginManager *plugin_mgr,
MutterWindow *actor,
unsigned long event,
gint target_x,
gint target_y,
gint target_width,
gint target_height)
meta_plugin_manager_event_maximize (MetaPluginManager *plugin_mgr,
MetaWindowActor *actor,
unsigned long event,
gint target_x,
gint target_y,
gint target_width,
gint target_height)
{
GList *l = plugin_mgr->plugins;
gboolean retval = FALSE;
@ -493,39 +539,37 @@ mutter_plugin_manager_event_maximize (MutterPluginManager *plugin_mgr,
while (l)
{
MutterPlugin *plugin = l->data;
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
MetaPlugin *plugin = l->data;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (!mutter_plugin_disabled (plugin) &&
(mutter_plugin_features (plugin) & event))
if (!meta_plugin_disabled (plugin) &&
(meta_plugin_features (plugin) & event))
{
retval = TRUE;
switch (event)
{
case MUTTER_PLUGIN_MAXIMIZE:
case META_PLUGIN_MAXIMIZE:
if (klass->maximize)
{
mutter_plugin_manager_kill_effect (
meta_plugin_manager_kill_window_effects (
plugin_mgr,
actor,
ALL_BUT_SWITCH);
actor);
_mutter_plugin_effect_started (plugin);
_meta_plugin_effect_started (plugin);
klass->maximize (plugin, actor,
target_x, target_y,
target_width, target_height);
}
break;
case MUTTER_PLUGIN_UNMAXIMIZE:
case META_PLUGIN_UNMAXIMIZE:
if (klass->unmaximize)
{
mutter_plugin_manager_kill_effect (
meta_plugin_manager_kill_window_effects (
plugin_mgr,
actor,
ALL_BUT_SWITCH);
actor);
_mutter_plugin_effect_started (plugin);
_meta_plugin_effect_started (plugin);
klass->unmaximize (plugin, actor,
target_x, target_y,
target_width, target_height);
@ -551,11 +595,10 @@ mutter_plugin_manager_event_maximize (MutterPluginManager *plugin_mgr,
* appropriate post-effect cleanup is carried out.
*/
gboolean
mutter_plugin_manager_switch_workspace (MutterPluginManager *plugin_mgr,
const GList **actors,
gint from,
gint to,
MetaMotionDirection direction)
meta_plugin_manager_switch_workspace (MetaPluginManager *plugin_mgr,
gint from,
gint to,
MetaMotionDirection direction)
{
GList *l = plugin_mgr->plugins;
gboolean retval = FALSE;
@ -566,23 +609,19 @@ mutter_plugin_manager_switch_workspace (MutterPluginManager *plugin_mgr,
while (l)
{
MutterPlugin *plugin = l->data;
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
MetaPlugin *plugin = l->data;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (!mutter_plugin_disabled (plugin) &&
(mutter_plugin_features (plugin) & MUTTER_PLUGIN_SWITCH_WORKSPACE) &&
(actors && *actors))
if (!meta_plugin_disabled (plugin) &&
(meta_plugin_features (plugin) & META_PLUGIN_SWITCH_WORKSPACE))
{
if (klass->switch_workspace)
{
retval = TRUE;
mutter_plugin_manager_kill_effect (
plugin_mgr,
MUTTER_WINDOW ((*actors)->data),
MUTTER_PLUGIN_SWITCH_WORKSPACE);
meta_plugin_manager_kill_switch_workspace (plugin_mgr);
_mutter_plugin_effect_started (plugin);
klass->switch_workspace (plugin, actors, from, to, direction);
_meta_plugin_effect_started (plugin);
klass->switch_workspace (plugin, from, to, direction);
}
}
@ -601,8 +640,8 @@ mutter_plugin_manager_switch_workspace (MutterPluginManager *plugin_mgr,
* appropriate post-effect cleanup is carried out.
*/
gboolean
mutter_plugin_manager_xevent_filter (MutterPluginManager *plugin_mgr,
XEvent *xev)
meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
XEvent *xev)
{
GList *l;
gboolean have_plugin_xevent_func;
@ -632,8 +671,8 @@ mutter_plugin_manager_xevent_filter (MutterPluginManager *plugin_mgr,
while (l)
{
MutterPlugin *plugin = l->data;
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
MetaPlugin *plugin = l->data;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (klass->xevent_filter)
{

View File

@ -0,0 +1,78 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (c) 2008 Intel Corp.
*
* Author: Tomas Frydrych <tf@linux.intel.com>
*
* 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_PLUGIN_MANAGER_H_
#define META_PLUGIN_MANAGER_H_
#include "types.h"
#include "screen.h"
#define META_PLUGIN_FROM_MANAGER_
#include "meta-plugin.h"
#undef META_PLUGIN_FROM_MANAGER_
#define META_PLUGIN_MINIMIZE (1<<0)
#define META_PLUGIN_MAXIMIZE (1<<1)
#define META_PLUGIN_UNMAXIMIZE (1<<2)
#define META_PLUGIN_MAP (1<<3)
#define META_PLUGIN_DESTROY (1<<4)
#define META_PLUGIN_SWITCH_WORKSPACE (1<<5)
#define META_PLUGIN_ALL_EFFECTS (~0)
/**
* MetaPluginManager: (skip)
*
*/
typedef struct MetaPluginManager MetaPluginManager;
MetaPluginManager * meta_plugin_manager_get (MetaScreen *screen);
MetaPluginManager * meta_plugin_manager_get_default (void);
gboolean meta_plugin_manager_load (MetaPluginManager *mgr);
gboolean meta_plugin_manager_initialize (MetaPluginManager *plugin_mgr);
gboolean meta_plugin_manager_event_simple (MetaPluginManager *mgr,
MetaWindowActor *actor,
unsigned long event);
gboolean meta_plugin_manager_event_maximize (MetaPluginManager *mgr,
MetaWindowActor *actor,
unsigned long event,
gint target_x,
gint target_y,
gint target_width,
gint target_height);
void meta_plugin_manager_update_workspaces (MetaPluginManager *mgr);
void meta_plugin_manager_update_workspace (MetaPluginManager *mgr,
MetaWorkspace *w);
gboolean meta_plugin_manager_switch_workspace (MetaPluginManager *mgr,
gint from,
gint to,
MetaMotionDirection direction);
gboolean meta_plugin_manager_xevent_filter (MetaPluginManager *mgr,
XEvent *xev);
#endif

View File

@ -21,7 +21,7 @@
* 02111-1307, USA.
*/
#include "mutter-plugin.h"
#include "meta-plugin.h"
#include "screen.h"
#include "display.h"
@ -32,12 +32,12 @@
#include <clutter/x11/clutter-x11.h>
#include "compositor-private.h"
#include "mutter-window-private.h"
#include "meta-window-actor-private.h"
G_DEFINE_ABSTRACT_TYPE (MutterPlugin, mutter_plugin, G_TYPE_OBJECT);
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
#define MUTTER_PLUGIN_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_PLUGIN, MutterPluginPrivate))
#define META_PLUGIN_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_PLUGIN, MetaPluginPrivate))
enum
{
@ -49,7 +49,7 @@ enum
PROP_DEBUG_MODE,
};
struct _MutterPluginPrivate
struct _MetaPluginPrivate
{
MetaScreen *screen;
gchar *params;
@ -62,51 +62,51 @@ struct _MutterPluginPrivate
};
static void
mutter_plugin_dispose (GObject *object)
meta_plugin_dispose (GObject *object)
{
G_OBJECT_CLASS (mutter_plugin_parent_class)->dispose (object);
G_OBJECT_CLASS (meta_plugin_parent_class)->dispose (object);
}
static void
mutter_plugin_finalize (GObject *object)
meta_plugin_finalize (GObject *object)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
g_free (priv->params);
priv->params = NULL;
G_OBJECT_CLASS (mutter_plugin_parent_class)->finalize (object);
G_OBJECT_CLASS (meta_plugin_parent_class)->finalize (object);
}
static void
mutter_plugin_parse_params (MutterPlugin *plugin)
meta_plugin_parse_params (MetaPlugin *plugin)
{
char *p;
gulong features = 0;
MutterPluginPrivate *priv = plugin->priv;
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
MetaPluginPrivate *priv = plugin->priv;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
/*
* Feature flags: identify events that the plugin can handle; a plugin can
* handle one or more events.
*/
if (klass->minimize)
features |= MUTTER_PLUGIN_MINIMIZE;
features |= META_PLUGIN_MINIMIZE;
if (klass->maximize)
features |= MUTTER_PLUGIN_MAXIMIZE;
features |= META_PLUGIN_MAXIMIZE;
if (klass->unmaximize)
features |= MUTTER_PLUGIN_UNMAXIMIZE;
features |= META_PLUGIN_UNMAXIMIZE;
if (klass->map)
features |= MUTTER_PLUGIN_MAP;
features |= META_PLUGIN_MAP;
if (klass->destroy)
features |= MUTTER_PLUGIN_DESTROY;
features |= META_PLUGIN_DESTROY;
if (klass->switch_workspace)
features |= MUTTER_PLUGIN_SWITCH_WORKSPACE;
features |= META_PLUGIN_SWITCH_WORKSPACE;
if (priv->params)
{
@ -122,22 +122,22 @@ mutter_plugin_parse_params (MutterPlugin *plugin)
*p = 0;
if (strstr (d, "minimize"))
features &= ~ MUTTER_PLUGIN_MINIMIZE;
features &= ~ META_PLUGIN_MINIMIZE;
if (strstr (d, "maximize"))
features &= ~ MUTTER_PLUGIN_MAXIMIZE;
features &= ~ META_PLUGIN_MAXIMIZE;
if (strstr (d, "unmaximize"))
features &= ~ MUTTER_PLUGIN_UNMAXIMIZE;
features &= ~ META_PLUGIN_UNMAXIMIZE;
if (strstr (d, "map"))
features &= ~ MUTTER_PLUGIN_MAP;
features &= ~ META_PLUGIN_MAP;
if (strstr (d, "destroy"))
features &= ~ MUTTER_PLUGIN_DESTROY;
features &= ~ META_PLUGIN_DESTROY;
if (strstr (d, "switch-workspace"))
features &= ~MUTTER_PLUGIN_SWITCH_WORKSPACE;
features &= ~META_PLUGIN_SWITCH_WORKSPACE;
g_free (d);
}
@ -162,12 +162,12 @@ mutter_plugin_parse_params (MutterPlugin *plugin)
}
static void
mutter_plugin_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
meta_plugin_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
switch (prop_id)
{
@ -176,7 +176,7 @@ mutter_plugin_set_property (GObject *object,
break;
case PROP_PARAMS:
priv->params = g_value_dup_string (value);
mutter_plugin_parse_params (MUTTER_PLUGIN (object));
meta_plugin_parse_params (META_PLUGIN (object));
break;
case PROP_DISABLED:
priv->disabled = g_value_get_boolean (value);
@ -191,12 +191,12 @@ mutter_plugin_set_property (GObject *object,
}
static void
mutter_plugin_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
meta_plugin_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
switch (prop_id)
{
@ -223,14 +223,14 @@ mutter_plugin_get_property (GObject *object,
static void
mutter_plugin_class_init (MutterPluginClass *klass)
meta_plugin_class_init (MetaPluginClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->finalize = mutter_plugin_finalize;
gobject_class->dispose = mutter_plugin_dispose;
gobject_class->set_property = mutter_plugin_set_property;
gobject_class->get_property = mutter_plugin_get_property;
gobject_class->finalize = meta_plugin_finalize;
gobject_class->dispose = meta_plugin_dispose;
gobject_class->set_property = meta_plugin_set_property;
gobject_class->get_property = meta_plugin_get_property;
g_object_class_install_property (gobject_class,
PROP_SCREEN,
@ -238,8 +238,7 @@ mutter_plugin_class_init (MutterPluginClass *klass)
"MetaScreen",
"MetaScreen",
META_TYPE_SCREEN,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_PARAMS,
@ -274,53 +273,53 @@ mutter_plugin_class_init (MutterPluginClass *klass)
FALSE,
G_PARAM_READABLE));
g_type_class_add_private (gobject_class, sizeof (MutterPluginPrivate));
g_type_class_add_private (gobject_class, sizeof (MetaPluginPrivate));
}
static void
mutter_plugin_init (MutterPlugin *self)
meta_plugin_init (MetaPlugin *self)
{
MutterPluginPrivate *priv;
MetaPluginPrivate *priv;
self->priv = priv = MUTTER_PLUGIN_GET_PRIVATE (self);
self->priv = priv = META_PLUGIN_GET_PRIVATE (self);
}
gulong
mutter_plugin_features (MutterPlugin *plugin)
meta_plugin_features (MetaPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return priv->features;
}
gboolean
mutter_plugin_disabled (MutterPlugin *plugin)
meta_plugin_disabled (MetaPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return priv->disabled;
}
gboolean
mutter_plugin_running (MutterPlugin *plugin)
meta_plugin_running (MetaPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return (priv->running > 0);
}
gboolean
mutter_plugin_debug_mode (MutterPlugin *plugin)
meta_plugin_debug_mode (MetaPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return priv->debug;
}
const MutterPluginInfo *
mutter_plugin_get_info (MutterPlugin *plugin)
const MetaPluginInfo *
meta_plugin_get_info (MetaPlugin *plugin)
{
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (klass && klass->plugin_info)
return klass->plugin_info (plugin);
@ -329,50 +328,74 @@ mutter_plugin_get_info (MutterPlugin *plugin)
}
ClutterActor *
mutter_plugin_get_overlay_group (MutterPlugin *plugin)
meta_plugin_get_overlay_group (MetaPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return mutter_get_overlay_group_for_screen (priv->screen);
return meta_get_overlay_group_for_screen (priv->screen);
}
ClutterActor *
mutter_plugin_get_stage (MutterPlugin *plugin)
meta_plugin_get_stage (MetaPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return mutter_get_stage_for_screen (priv->screen);
return meta_get_stage_for_screen (priv->screen);
}
ClutterActor *
mutter_plugin_get_window_group (MutterPlugin *plugin)
meta_plugin_get_window_group (MetaPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return mutter_get_window_group_for_screen (priv->screen);
return meta_get_window_group_for_screen (priv->screen);
}
ClutterActor *
meta_plugin_get_background_actor (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return meta_get_background_actor_for_screen (priv->screen);
}
/**
* _mutter_plugin_effect_started:
* _meta_plugin_effect_started:
* @plugin: the plugin
*
* Mark that an effect has started for the plugin. This is called
* internally by MutterPluginManager.
* internally by MetaPluginManager.
*/
void
_mutter_plugin_effect_started (MutterPlugin *plugin)
_meta_plugin_effect_started (MetaPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
priv->running++;
}
void
mutter_plugin_effect_completed (MutterPlugin *plugin,
MutterWindow *actor,
unsigned long event)
meta_plugin_switch_workspace_completed (MetaPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
MetaScreen *screen = meta_plugin_get_screen (plugin);
if (priv->running-- < 0)
{
g_warning ("Error in running effect accounting, adjusting.");
priv->running = 0;
}
meta_switch_workspace_completed (screen);
}
static void
meta_plugin_window_effect_completed (MetaPlugin *plugin,
MetaWindowActor *actor,
unsigned long event)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
if (priv->running-- < 0)
{
@ -382,57 +405,82 @@ mutter_plugin_effect_completed (MutterPlugin *plugin,
if (!actor)
{
const MutterPluginInfo *info;
const MetaPluginInfo *info;
const gchar *name = NULL;
if (plugin && (info = mutter_plugin_get_info (plugin)))
if (plugin && (info = meta_plugin_get_info (plugin)))
name = info->name;
g_warning ("Plugin [%s] passed NULL for actor!",
name ? name : "unknown");
}
if (event == MUTTER_PLUGIN_SWITCH_WORKSPACE)
{
/* The window is just used to identify the screen */
MetaWindow *window = mutter_window_get_meta_window (actor);
MetaScreen *screen = meta_window_get_screen (window);
mutter_switch_workspace_completed (screen);
}
else
{
mutter_window_effect_completed (actor, event);
}
meta_window_actor_effect_completed (actor, event);
}
void
mutter_plugin_query_screen_size (MutterPlugin *plugin,
int *width,
int *height)
meta_plugin_minimize_completed (MetaPlugin *plugin,
MetaWindowActor *actor)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MINIMIZE);
}
void
meta_plugin_maximize_completed (MetaPlugin *plugin,
MetaWindowActor *actor)
{
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MAXIMIZE);
}
void
meta_plugin_unmaximize_completed (MetaPlugin *plugin,
MetaWindowActor *actor)
{
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_UNMAXIMIZE);
}
void
meta_plugin_map_completed (MetaPlugin *plugin,
MetaWindowActor *actor)
{
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_MAP);
}
void
meta_plugin_destroy_completed (MetaPlugin *plugin,
MetaWindowActor *actor)
{
meta_plugin_window_effect_completed (plugin, actor, META_PLUGIN_DESTROY);
}
void
meta_plugin_query_screen_size (MetaPlugin *plugin,
int *width,
int *height)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
meta_screen_get_size (priv->screen, width, height);
}
void
mutter_plugin_set_stage_reactive (MutterPlugin *plugin,
gboolean reactive)
meta_plugin_set_stage_reactive (MetaPlugin *plugin,
gboolean reactive)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
if (reactive)
mutter_set_stage_input_region (screen, None);
meta_set_stage_input_region (screen, None);
else
mutter_empty_stage_input_region (screen);
meta_empty_stage_input_region (screen);
}
void
mutter_plugin_set_stage_input_area (MutterPlugin *plugin,
gint x, gint y, gint width, gint height)
meta_plugin_set_stage_input_area (MetaPlugin *plugin,
gint x, gint y, gint width, gint height)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
@ -445,43 +493,43 @@ mutter_plugin_set_stage_input_area (MutterPlugin *plugin,
rect.height = height;
region = XFixesCreateRegion (xdpy, &rect, 1);
mutter_set_stage_input_region (screen, region);
meta_set_stage_input_region (screen, region);
XFixesDestroyRegion (xdpy, region);
}
void
mutter_plugin_set_stage_input_region (MutterPlugin *plugin,
XserverRegion region)
meta_plugin_set_stage_input_region (MetaPlugin *plugin,
XserverRegion region)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
mutter_set_stage_input_region (screen, region);
meta_set_stage_input_region (screen, region);
}
/**
* mutter_plugin_get_windows:
* @plugin: A #MutterPlugin
* meta_plugin_get_window_actors:
* @plugin: A #MetaPlugin
*
* This function returns all of the #MutterWindow objects referenced by Mutter, including
* This function returns all of the #MetaWindowActor objects referenced by Mutter, including
* override-redirect windows. The returned list is a snapshot of Mutter's current
* stacking order, with the topmost window last.
*
* The 'restacked' signal of #MetaScreen signals when this value has changed.
*
* Returns: (transfer none) (element-type MutterWindow): Windows in stacking order, topmost last
* Returns: (transfer none) (element-type MetaWindowActor): Windows in stacking order, topmost last
*/
GList *
mutter_plugin_get_windows (MutterPlugin *plugin)
meta_plugin_get_window_actors (MetaPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return mutter_get_windows (priv->screen);
return meta_get_window_actors (priv->screen);
}
/**
* mutter_plugin_begin_modal:
* @plugin: a #MutterPlugin
* meta_plugin_begin_modal:
* @plugin: a #MetaPlugin
* @grab_window: the X window to grab the keyboard and mouse on
* @cursor: the cursor to use for the pointer grab, or None,
* to use the normal cursor for the grab window and
@ -492,7 +540,7 @@ mutter_plugin_get_windows (MutterPlugin *plugin)
* This function is used to grab the keyboard and mouse for the exclusive
* use of the plugin. Correct operation requires that both the keyboard
* and mouse are grabbed, or thing will break. (In particular, other
* passive X grabs in Mutter can trigger but not be handled by the normal
* passive X grabs in Meta can trigger but not be handled by the normal
* keybinding handling code.) However, the plugin can establish the keyboard
* and/or mouse grabs ahead of time and pass in the
* %META_MODAL_POINTER_ALREADY_GRABBED and/or %META_MODAL_KEYBOARD_ALREADY_GRABBED
@ -505,21 +553,21 @@ mutter_plugin_get_windows (MutterPlugin *plugin)
* mouse and made the plugin modal.
*/
gboolean
mutter_plugin_begin_modal (MutterPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp)
meta_plugin_begin_modal (MetaPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return mutter_begin_modal_for_plugin (priv->screen, plugin,
grab_window, cursor, options, timestamp);
return meta_begin_modal_for_plugin (priv->screen, plugin,
grab_window, cursor, options, timestamp);
}
/**
* mutter_plugin_end_modal
* @plugin: a #MutterPlugin
* meta_plugin_end_modal
* @plugin: a #MetaPlugin
* @timestamp: the time used for releasing grabs
*
* Ends the modal operation begun with meta_plugin_begin_modal(). This
@ -529,27 +577,27 @@ mutter_plugin_begin_modal (MutterPlugin *plugin,
* when beginnning the modal operation.
*/
void
mutter_plugin_end_modal (MutterPlugin *plugin,
guint32 timestamp)
meta_plugin_end_modal (MetaPlugin *plugin,
guint32 timestamp)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
mutter_end_modal_for_plugin (priv->screen, plugin, timestamp);
meta_end_modal_for_plugin (priv->screen, plugin, timestamp);
}
Display *
mutter_plugin_get_xdisplay (MutterPlugin *plugin)
meta_plugin_get_xdisplay (MetaPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaDisplay *display = meta_screen_get_display (priv->screen);
Display *xdpy = meta_display_get_xdisplay (display);
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
MetaDisplay *display = meta_screen_get_display (priv->screen);
Display *xdpy = meta_display_get_xdisplay (display);
return xdpy;
}
/**
* mutter_plugin_get_screen:
* @plugin: a #MutterPlugin
* meta_plugin_get_screen:
* @plugin: a #MetaPlugin
*
* Gets the #MetaScreen corresponding to a plugin. Each plugin instance
* is associated with exactly one screen; if Metacity is managing
@ -558,9 +606,9 @@ mutter_plugin_get_xdisplay (MutterPlugin *plugin)
* Return value: (transfer none): the #MetaScreen for the plugin
*/
MetaScreen *
mutter_plugin_get_screen (MutterPlugin *plugin)
meta_plugin_get_screen (MetaPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return priv->screen;
}

View File

@ -0,0 +1,67 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MetaShadowFactory:
*
* Create and cache shadow textures for arbitrary window shapes
*
* Copyright (C) 2010 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_SHADOW_FACTORY_PRIVATE_H__
#define __META_SHADOW_FACTORY_PRIVATE_H__
#include <cairo.h>
#include <clutter/clutter.h>
#include "meta-window-shape.h"
#include "meta-shadow-factory.h"
/**
* MetaShadow:
* #MetaShadow holds a shadow texture along with information about how to
* apply that texture to draw a window texture. (E.g., it knows how big the
* unscaled borders are on each side of the shadow texture.)
*/
typedef struct _MetaShadow MetaShadow;
MetaShadow *meta_shadow_ref (MetaShadow *shadow);
void meta_shadow_unref (MetaShadow *shadow);
CoglHandle meta_shadow_get_texture (MetaShadow *shadow);
void meta_shadow_paint (MetaShadow *shadow,
int window_x,
int window_y,
int window_width,
int window_height,
guint8 opacity,
cairo_region_t *clip);
void meta_shadow_get_bounds (MetaShadow *shadow,
int window_x,
int window_y,
int window_width,
int window_height,
cairo_rectangle_int_t *bounds);
MetaShadowFactory *meta_shadow_factory_new (void);
MetaShadow *meta_shadow_factory_get_shadow (MetaShadowFactory *factory,
MetaWindowShape *shape,
int width,
int height,
const char *class_name,
gboolean focused);
#endif /* __META_SHADOW_FACTORY_PRIVATE_H__ */

View File

@ -0,0 +1,989 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MetaShadowFactory:
*
* Create and cache shadow textures for abritrary window shapes
*
* Copyright 2010 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 <math.h>
#include <string.h>
#include "cogl-utils.h"
#include "meta-shadow-factory-private.h"
#include "region-utils.h"
/* This file implements blurring the shape of a window to produce a
* shadow texture. The details are discussed below; a quick summary
* of the optimizations we use:
*
* - If the window shape is along the lines of a rounded rectangle -
* a rectangular center portion with stuff at the corners - then
* the blur of this - the shadow - can also be represented as a
* 9-sliced texture and the same texture can be used for different
* size.
*
* - We use the fact that a Gaussian blur is separable to do a
* 2D blur as 1D blur of the rows followed by a 1D blur of the
* columns.
*
* - For better cache efficiency, we blur rows, transpose the image
* in blocks, blur rows again, and then transpose back.
*
* - We approximate the 1D gaussian blur as 3 successive box filters.
*/
typedef struct _MetaShadowCacheKey MetaShadowCacheKey;
typedef struct _MetaShadowClassInfo MetaShadowClassInfo;
struct _MetaShadowCacheKey
{
MetaWindowShape *shape;
int radius;
int top_fade;
};
struct _MetaShadow
{
int ref_count;
MetaShadowFactory *factory;
MetaShadowCacheKey key;
CoglHandle texture;
CoglHandle material;
/* The outer order is the distance the shadow extends outside the window
* shape; the inner border is the unscaled portion inside the window
* shape */
int outer_border_top;
int inner_border_top;
int outer_border_right;
int inner_border_right;
int outer_border_bottom;
int inner_border_bottom;
int outer_border_left;
int inner_border_left;
guint scale_width : 1;
guint scale_height : 1;
};
struct _MetaShadowClassInfo
{
const char *name; /* const so we can reuse for static definitions */
MetaShadowParams focused;
MetaShadowParams unfocused;
};
struct _MetaShadowFactory
{
GObject parent_instance;
/* MetaShadowCacheKey => MetaShadow; the shadows are not referenced
* by the factory, they are simply removed from the table when freed */
GHashTable *shadows;
/* class name => MetaShadowClassInfo */
GHashTable *shadow_classes;
};
struct _MetaShadowFactoryClass
{
GObjectClass parent_class;
};
enum
{
CHANGED,
LAST_SIGNAL
};
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", { 12, -1, 0, 8, 255 }, { 6, -1, 0, 4, 255 } },
{ "dialog", { 12, -1, 0, 8, 255 }, { 6, -1, 0, 4, 255 } },
{ "modal_dialog", { 12, -1, 0, 8, 255 }, { 6, -1, 0, 4, 255 } },
{ "utility", { 12, -1, 0, 8, 255 }, { 6, -1, 0, 4, 255 } },
{ "border", { 12, -1, 0, 8, 255 }, { 6, -1, 0, 4, 255 } },
{ "menu", { 12, -1, 0, 8, 255 }, { 6, -1, 0, 4, 255 } },
{ "popup-menu", { 6, -1, 0, 4, 255 }, { 6, -1, 0, 4, 255 } },
{ "dropdown-menu", { 6, 25, 0, 4, 255 }, { 6, 100, 0, 4, 255 } },
{ "attached", { 6, 25, 0, 4, 255 }, { 6, 100, 0, 4, 255 } }
};
G_DEFINE_TYPE (MetaShadowFactory, meta_shadow_factory, G_TYPE_OBJECT);
static guint
meta_shadow_cache_key_hash (gconstpointer val)
{
const MetaShadowCacheKey *key = val;
return 59 * key->radius + 67 * key->top_fade + 73 * meta_window_shape_hash (key->shape);
}
static gboolean
meta_shadow_cache_key_equal (gconstpointer a,
gconstpointer b)
{
const MetaShadowCacheKey *key_a = a;
const MetaShadowCacheKey *key_b = b;
return (key_a->radius == key_b->radius && key_a->top_fade == key_b->top_fade &&
meta_window_shape_equal (key_a->shape, key_b->shape));
}
MetaShadow *
meta_shadow_ref (MetaShadow *shadow)
{
shadow->ref_count++;
return shadow;
}
void
meta_shadow_unref (MetaShadow *shadow)
{
shadow->ref_count--;
if (shadow->ref_count == 0)
{
if (shadow->factory)
{
g_hash_table_remove (shadow->factory->shadows,
&shadow->key);
}
meta_window_shape_unref (shadow->key.shape);
cogl_handle_unref (shadow->texture);
cogl_handle_unref (shadow->material);
g_slice_free (MetaShadow, shadow);
}
}
/**
* meta_shadow_paint:
* @window_x: x position of the region to paint a shadow for
* @window_y: y position of the region to paint a shadow for
* @window_width: actual width of the region to paint a shadow for
* @window_height: actual height of the region to paint a shadow for
* @clip: (allow-none): if non-%NULL specifies the visible portion
* of the shadow. Drawing won't be strictly clipped to this region
* but it will be used to optimize what is drawn.
*
* Paints the shadow at the given position, for the specified actual
* size of the region. (Since a #MetaShadow can be shared between
* different sizes with the same extracted #MetaWindowShape the
* size needs to be passed in here.)
*/
void
meta_shadow_paint (MetaShadow *shadow,
int window_x,
int window_y,
int window_width,
int window_height,
guint8 opacity,
cairo_region_t *clip)
{
float texture_width = cogl_texture_get_width (shadow->texture);
float texture_height = cogl_texture_get_height (shadow->texture);
int i, j;
float src_x[4];
float src_y[4];
int dest_x[4];
int dest_y[4];
int n_x, n_y;
cogl_material_set_color4ub (shadow->material,
opacity, opacity, opacity, opacity);
cogl_set_source (shadow->material);
if (shadow->scale_width)
{
n_x = 3;
src_x[0] = 0.0;
src_x[1] = (shadow->inner_border_left + shadow->outer_border_left) / texture_width;
src_x[2] = (texture_width - (shadow->inner_border_right + shadow->outer_border_right)) / texture_width;
src_x[3] = 1.0;
dest_x[0] = window_x - shadow->outer_border_left;
dest_x[1] = window_x + shadow->inner_border_left;
dest_x[2] = window_x + window_width - shadow->inner_border_right;
dest_x[3] = window_x + window_width + shadow->outer_border_right;
}
else
{
n_x = 1;
src_x[0] = 0.0;
src_x[1] = 1.0;
dest_x[0] = window_x - shadow->outer_border_left;
dest_x[1] = window_x + window_width + shadow->outer_border_right;
}
if (shadow->scale_height)
{
n_y = 3;
src_y[0] = 0.0;
src_y[1] = (shadow->inner_border_top + shadow->outer_border_top) / texture_height;
src_y[2] = (texture_height - (shadow->inner_border_bottom + shadow->outer_border_bottom)) / texture_height;
src_y[3] = 1.0;
dest_y[0] = window_y - shadow->outer_border_top;
dest_y[1] = window_y + shadow->inner_border_top;
dest_y[2] = window_y + window_height - shadow->inner_border_bottom;
dest_y[3] = window_y + window_height + shadow->outer_border_bottom;
}
else
{
n_y = 1;
src_y[0] = 0.0;
src_y[1] = 1.0;
dest_y[0] = window_y - shadow->outer_border_top;
dest_y[1] = window_y + window_height + shadow->outer_border_bottom;
}
for (j = 0; j < n_y; j++)
{
cairo_rectangle_int_t dest_rect;
dest_rect.y = dest_y[j];
dest_rect.height = dest_y[j + 1] - dest_y[j];
for (i = 0; i < n_x; i++)
{
cairo_region_overlap_t overlap;
dest_rect.x = dest_x[i];
dest_rect.width = dest_x[i + 1] - dest_x[i];
if (clip)
overlap = cairo_region_contains_rectangle (clip, &dest_rect);
else
overlap = CAIRO_REGION_OVERLAP_PART;
if (overlap != CAIRO_REGION_OVERLAP_OUT)
cogl_rectangle_with_texture_coords (dest_x[i], dest_y[j],
dest_x[i + 1], dest_y[j + 1],
src_x[i], src_y[j],
src_x[i + 1], src_y[j + 1]);
}
}
}
/**
* meta_shadow_get_bounds:
* @shadow: a #MetaShadow
* @window_x: x position of the region to paint a shadow for
* @window_y: y position of the region to paint a shadow for
* @window_width: actual width of the region to paint a shadow for
* @window_height: actual height of the region to paint a shadow for
*
* Computes the bounds of the pixels that will be affected by
* meta_shadow_paints()
*/
void
meta_shadow_get_bounds (MetaShadow *shadow,
int window_x,
int window_y,
int window_width,
int window_height,
cairo_rectangle_int_t *bounds)
{
bounds->x = window_x - shadow->outer_border_left;
bounds->y = window_x - shadow->outer_border_top;
bounds->width = window_width + shadow->outer_border_left + shadow->outer_border_right;
bounds->height = window_height + shadow->outer_border_top + shadow->outer_border_bottom;
}
static void
meta_shadow_class_info_free (MetaShadowClassInfo *class_info)
{
g_free ((char *)class_info->name);
g_slice_free (MetaShadowClassInfo, class_info);
}
static void
meta_shadow_factory_init (MetaShadowFactory *factory)
{
guint i;
factory->shadows = g_hash_table_new (meta_shadow_cache_key_hash,
meta_shadow_cache_key_equal);
factory->shadow_classes = g_hash_table_new_full (g_str_hash,
g_str_equal,
NULL,
(GDestroyNotify)meta_shadow_class_info_free);
for (i = 0; i < G_N_ELEMENTS (default_shadow_classes); i++)
{
MetaShadowClassInfo *class_info = g_slice_new (MetaShadowClassInfo);
*class_info = default_shadow_classes[i];
class_info->name = g_strdup (class_info->name);
g_hash_table_insert (factory->shadow_classes,
(char *)class_info->name, class_info);
}
}
static void
meta_shadow_factory_finalize (GObject *object)
{
MetaShadowFactory *factory = META_SHADOW_FACTORY (object);
GHashTableIter iter;
gpointer key, value;
/* Detach from the shadows in the table so we won't try to
* remove them when they're freed. */
g_hash_table_iter_init (&iter, factory->shadows);
while (g_hash_table_iter_next (&iter, &key, &value))
{
MetaShadow *shadow = key;
shadow->factory = NULL;
}
g_hash_table_destroy (factory->shadows);
g_hash_table_destroy (factory->shadow_classes);
G_OBJECT_CLASS (meta_shadow_factory_parent_class)->finalize (object);
}
static void
meta_shadow_factory_class_init (MetaShadowFactoryClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = meta_shadow_factory_finalize;
signals[CHANGED] =
g_signal_new ("changed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
MetaShadowFactory *
meta_shadow_factory_new (void)
{
return g_object_new (META_TYPE_SHADOW_FACTORY, NULL);
}
/**
* meta_shadow_factory_get_default:
*
* Return value: (transfer none): the global singleton shadow factory
*/
MetaShadowFactory *
meta_shadow_factory_get_default (void)
{
static MetaShadowFactory *factory;
if (factory == NULL)
factory = meta_shadow_factory_new ();
return factory;
}
/* We emulate a 1D Gaussian blur by using 3 consecutive box blurs;
* this produces a result that's within 3% of the original and can be
* implemented much faster for large filter sizes because of the
* efficiency of implementation of a box blur. Idea and formula
* for choosing the box blur size come from:
*
* http://www.w3.org/TR/SVG/filters.html#feGaussianBlurElement
*
* The 2D blur is then done by blurring the rows, flipping the
* image and blurring the columns. (This is possible because the
* Gaussian kernel is separable - it's the product of a horizontal
* blur and a vertical blur.)
*/
static int
get_box_filter_size (int radius)
{
return (int)(0.5 + radius * (0.75 * sqrt(2*M_PI)));
}
/* The "spread" of the filter is the number of pixels from an original
* pixel that it's blurred image extends. (A no-op blur that doesn't
* blur would have a spread of 0.) See comment in blur_rows() for why the
* odd and even cases are different
*/
static int
get_shadow_spread (int radius)
{
int d = get_box_filter_size (radius);
if (d % 2 == 1)
return 3 * (d / 2);
else
return 3 * (d / 2) - 1;
}
/* This applies a single box blur pass to a horizontal range of pixels;
* since the box blur has the same weight for all pixels, we can
* implement an efficient sliding window algorithm where we add
* in pixels coming into the window from the right and remove
* them when they leave the windw to the left.
*
* d is the filter width; for even d shift indicates how the blurred
* result is aligned with the original - does ' x ' go to ' yy' (shift=1)
* or 'yy ' (shift=-1)
*/
static void
blur_xspan (guchar *row,
guchar *tmp_buffer,
int row_width,
int x0,
int x1,
int d,
int shift)
{
int offset;
int sum = 0;
int i;
if (d % 2 == 1)
offset = d / 2;
else
offset = (d - shift) / 2;
/* All the conditionals in here look slow, but the branches will
* be well predicted and there are enough different possibilities
* that trying to write this as a series of unconditional loops
* is hard and not an obvious win. The main slow down here seems
* to be the integer division for pixel; one possible optimization
* would be to accumulate into two 16-bit integer buffers and
* only divide down after all three passes. (SSE parallel implementation
* of the divide step is possible.)
*/
for (i = x0 - d + offset; i < x1 + offset; i++)
{
if (i >= 0 && i < row_width)
sum += row[i];
if (i >= x0 + offset)
{
if (i >= d)
sum -= row[i - d];
tmp_buffer[i - offset] = (sum + d / 2) / d;
}
}
memcpy(row + x0, tmp_buffer + x0, x1 - x0);
}
static void
blur_rows (cairo_region_t *convolve_region,
int x_offset,
int y_offset,
guchar *buffer,
int buffer_width,
int buffer_height,
int d)
{
int i, j;
int n_rectangles;
guchar *tmp_buffer;
tmp_buffer = g_malloc (buffer_width);
n_rectangles = cairo_region_num_rectangles (convolve_region);
for (i = 0; i < n_rectangles; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (convolve_region, i, &rect);
for (j = y_offset + rect.y; j < y_offset + rect.y + rect.height; j++)
{
guchar *row = buffer + j * buffer_width;
int x0 = x_offset + rect.x;
int x1 = x0 + rect.width;
/* We want to produce a symmetric blur that spreads a pixel
* equally far to the left and right. If d is odd that happens
* naturally, but for d even, we approximate by using a blur
* on either side and then a centered blur of size d + 1.
* (techique also from the SVG specification)
*/
if (d % 2 == 1)
{
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 0);
}
else
{
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, 1);
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d, -1);
blur_xspan (row, tmp_buffer, buffer_width, x0, x1, d + 1, 0);
}
}
}
g_free (tmp_buffer);
}
static void
fade_bytes (guchar *bytes,
int width,
int distance,
int total)
{
guint32 multiplier = (distance * 0x10000 + 0x8000) / total;
int i;
for (i = 0; i < width; i++)
bytes[i] = (bytes[i] * multiplier) >> 16;
}
/* Swaps width and height. Either swaps in-place and returns the original
* buffer or allocates a new buffer, frees the original buffer and returns
* the new buffer.
*/
static guchar *
flip_buffer (guchar *buffer,
int width,
int height)
{
/* Working in blocks increases cache efficiency, compared to reading
* or writing an entire column at once */
#define BLOCK_SIZE 16
if (width == height)
{
int i0, j0;
for (j0 = 0; j0 < height; j0 += BLOCK_SIZE)
for (i0 = 0; i0 <= j0; i0 += BLOCK_SIZE)
{
int max_j = MIN(j0 + BLOCK_SIZE, height);
int max_i = MIN(i0 + BLOCK_SIZE, width);
int i, j;
if (i0 == j0)
{
for (j = j0; j < max_j; j++)
for (i = i0; i < j; i++)
{
guchar tmp = buffer[j * width + i];
buffer[j * width + i] = buffer[i * width + j];
buffer[i * width + j] = tmp;
}
}
else
{
for (j = j0; j < max_j; j++)
for (i = i0; i < max_i; i++)
{
guchar tmp = buffer[j * width + i];
buffer[j * width + i] = buffer[i * width + j];
buffer[i * width + j] = tmp;
}
}
}
return buffer;
}
else
{
guchar *new_buffer = g_malloc (height * width);
int i0, j0;
for (i0 = 0; i0 < width; i0 += BLOCK_SIZE)
for (j0 = 0; j0 < height; j0 += BLOCK_SIZE)
{
int max_j = MIN(j0 + BLOCK_SIZE, height);
int max_i = MIN(i0 + BLOCK_SIZE, width);
int i, j;
for (i = i0; i < max_i; i++)
for (j = j0; j < max_j; j++)
new_buffer[i * height + j] = buffer[j * width + i];
}
g_free (buffer);
return new_buffer;
}
#undef BLOCK_SIZE
}
static void
make_shadow (MetaShadow *shadow,
cairo_region_t *region)
{
int d = get_box_filter_size (shadow->key.radius);
int spread = get_shadow_spread (shadow->key.radius);
cairo_rectangle_int_t extents;
cairo_region_t *row_convolve_region;
cairo_region_t *column_convolve_region;
guchar *buffer;
int buffer_width;
int buffer_height;
int x_offset;
int y_offset;
int n_rectangles, j, k;
cairo_region_get_extents (region, &extents);
/* In the case where top_fade >= 0 and the portion above the top
* edge of the shape will be cropped, it seems like we could create
* a smaller buffer and omit the top portion, but actually, in our
* multi-pass blur algorithm, the blur into the area above the window
* in the first pass will contribute back to the final pixel values
* for the top pixels, so we create a buffer as if we weren't cropping
* and only crop when creating the CoglTexture.
*/
buffer_width = extents.width + 2 * spread;
buffer_height = extents.height + 2 * spread;
/* Round up so we have aligned rows/columns */
buffer_width = (buffer_width + 3) & ~3;
buffer_height = (buffer_height + 3) & ~3;
/* Square buffer allows in-place swaps, which are roughly 70% faster, but we
* don't want to over-allocate too much memory.
*/
if (buffer_height < buffer_width && buffer_height > (3 * buffer_width) / 4)
buffer_height = buffer_width;
if (buffer_width < buffer_height && buffer_width > (3 * buffer_height) / 4)
buffer_width = buffer_height;
buffer = g_malloc0 (buffer_width * buffer_height);
/* Blurring with multiple box-blur passes is fast, but (especially for
* large shadow sizes) we can improve efficiency by restricting the blur
* to the region that actually needs to be blurred.
*/
row_convolve_region = meta_make_border_region (region, spread, spread, FALSE);
column_convolve_region = meta_make_border_region (region, 0, spread, TRUE);
/* Offsets between coordinates of the regions and coordinates in the buffer */
x_offset = spread;
y_offset = spread;
/* Step 1: unblurred image */
n_rectangles = cairo_region_num_rectangles (region);
for (k = 0; k < n_rectangles; k++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, k, &rect);
for (j = y_offset + rect.y; j < y_offset + rect.y + rect.height; j++)
memset (buffer + buffer_width * j + x_offset + rect.x, 255, rect.width);
}
/* Step 2: swap rows and columns */
buffer = flip_buffer (buffer, buffer_width, buffer_height);
/* Step 3: blur rows (really columns) */
blur_rows (column_convolve_region, y_offset, x_offset,
buffer, buffer_height, buffer_width,
d);
/* Step 4: swap rows and columns */
buffer = flip_buffer (buffer, buffer_height, buffer_width);
/* Step 5: blur rows */
blur_rows (row_convolve_region, x_offset, y_offset,
buffer, buffer_width, buffer_height,
d);
/* Step 6: fade out the top, if applicable */
if (shadow->key.top_fade >= 0)
{
for (j = y_offset; j < y_offset + MIN (shadow->key.top_fade, extents.height + shadow->outer_border_bottom); j++)
fade_bytes(buffer + j * buffer_width, buffer_width, j - y_offset, shadow->key.top_fade);
}
/* We offset the passed in pixels to crop off the extra area we allocated at the top
* in the case of top_fade >= 0. We also account for padding at the left for symmetry
* though that doesn't currently occur.
*/
shadow->texture = cogl_texture_new_from_data (shadow->outer_border_left + extents.width + shadow->outer_border_right,
shadow->outer_border_top + extents.height + shadow->outer_border_bottom,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_A_8,
COGL_PIXEL_FORMAT_ANY,
buffer_width,
(buffer +
(y_offset - shadow->outer_border_top) * buffer_width +
(x_offset - shadow->outer_border_left)));
cairo_region_destroy (row_convolve_region);
cairo_region_destroy (column_convolve_region);
g_free (buffer);
shadow->material = meta_create_texture_material (shadow->texture);
}
static MetaShadowParams *
get_shadow_params (MetaShadowFactory *factory,
const char *class_name,
gboolean focused,
gboolean create)
{
MetaShadowClassInfo *class_info = g_hash_table_lookup (factory->shadow_classes,
class_name);
if (class_info == NULL)
{
if (create)
{
class_info = g_slice_new0 (MetaShadowClassInfo);
*class_info = default_shadow_classes[0];
class_info->name = g_strdup (class_info->name);
g_hash_table_insert (factory->shadow_classes,
(char *)class_info->name, class_info);
}
else
{
class_info = &default_shadow_classes[0];
}
}
if (focused)
return &class_info->focused;
else
return &class_info->unfocused;
}
/**
* meta_shadow_factory_get_shadow:
* @factory: a #MetaShadowFactory
* @shape: the size-invariant shape of the window's region
* @width: the actual width of the window's region
* @height: the actual height of the window's region
* @class_name: name of the class of window shadows
* @focused: whether the shadow is for a focused window
*
* Gets the appropriate shadow object for drawing shadows for the
* specified window shape. The region that we are shadowing is specified
* as a combination of a size-invariant extracted shape and the size.
* In some cases, the same shadow object can be shared between sizes;
* in other cases a different shadow object is used for each size.
*
* Return value: (transfer full): a newly referenced #MetaShadow; unref with
* meta_shadow_unref()
*/
MetaShadow *
meta_shadow_factory_get_shadow (MetaShadowFactory *factory,
MetaWindowShape *shape,
int width,
int height,
const char *class_name,
gboolean focused)
{
MetaShadowParams *params;
MetaShadowCacheKey key;
MetaShadow *shadow;
cairo_region_t *region;
int spread;
int shape_border_top, shape_border_right, shape_border_bottom, shape_border_left;
int inner_border_top, inner_border_right, inner_border_bottom, inner_border_left;
int outer_border_top, outer_border_right, outer_border_bottom, outer_border_left;
gboolean scale_width, scale_height;
gboolean cacheable;
int center_width, center_height;
g_return_val_if_fail (META_IS_SHADOW_FACTORY (factory), NULL);
g_return_val_if_fail (shape != NULL, NULL);
/* Using a single shadow texture for different window sizes only works
* when there is a central scaled area that is greater than twice
* the spread of the gaussian blur we are applying to get to the
* shadow image.
* ********* ***********
* /----------\ *###########* *#############*
* | | => **#*********#** => **#***********#**
* | | **#** **#** **#** **#**
* | | **#*********#** **#***********#**
* \----------/ *###########* *#############*
* ********** ************
* Original Blur Stretched Blur
*
* For smaller sizes, we create a separate shadow image for each size;
* since we assume that there will be little reuse, we don't try to
* cache such images but just recreate them. (Since the current cache
* policy is to only keep around referenced shadows, there wouldn't
* be any harm in caching them, it would just make the book-keeping
* a bit tricker.)
*
* In the case where we are fading a the top, that also has to fit
* within the top unscaled border.
*/
params = get_shadow_params (factory, class_name, focused, FALSE);
spread = get_shadow_spread (params->radius);
meta_window_shape_get_borders (shape,
&shape_border_top,
&shape_border_right,
&shape_border_bottom,
&shape_border_left);
inner_border_top = MAX (shape_border_top + spread, params->top_fade);
outer_border_top = params->top_fade >= 0 ? 0 : spread;
inner_border_right = shape_border_right + spread;
outer_border_right = spread;
inner_border_bottom = shape_border_bottom + spread;
outer_border_bottom = spread;
inner_border_left = shape_border_left + spread;
outer_border_left = spread;
scale_width = inner_border_left + inner_border_right <= width;
scale_height = inner_border_top + inner_border_bottom <= height;
cacheable = scale_width && scale_height;
if (cacheable)
{
key.shape = shape;
key.radius = params->radius;
key.top_fade = params->top_fade;
shadow = g_hash_table_lookup (factory->shadows, &key);
if (shadow)
return meta_shadow_ref (shadow);
}
shadow = g_slice_new0 (MetaShadow);
shadow->ref_count = 1;
shadow->factory = factory;
shadow->key.shape = meta_window_shape_ref (shape);
shadow->key.radius = params->radius;
shadow->key.top_fade = params->top_fade;
shadow->outer_border_top = outer_border_top;
shadow->inner_border_top = inner_border_top;
shadow->outer_border_right = outer_border_right;
shadow->inner_border_right = inner_border_right;
shadow->outer_border_bottom = outer_border_bottom;
shadow->inner_border_bottom = inner_border_bottom;
shadow->outer_border_left = outer_border_left;
shadow->inner_border_left = inner_border_left;
shadow->scale_width = scale_width;
if (scale_width)
center_width = inner_border_left + inner_border_right - (shape_border_left + shape_border_right);
else
center_width = width - (shape_border_left + shape_border_right);
shadow->scale_height = scale_height;
if (scale_height)
center_height = inner_border_top + inner_border_bottom - (shape_border_top + shape_border_bottom);
else
center_height = height - (shape_border_top + shape_border_bottom);
g_assert (center_width >= 0 && center_height >= 0);
region = meta_window_shape_to_region (shape, center_width, center_height);
make_shadow (shadow, region);
cairo_region_destroy (region);
if (cacheable)
g_hash_table_insert (factory->shadows, &shadow->key, shadow);
return shadow;
}
/**
* meta_shadow_factory_set_params:
* @factory: a #MetaShadowFactory
* @class_name: name of the class of shadow to set the params for.
* the default shadow classes are the names of the different
* theme frame types (normal, dialog, modal_dialog, utility,
* border, menu, attached) and in addition, popup-menu
* and dropdown-menu.
* @focused: whether the shadow is for a focused window
* @params: new parameter values
*
* Updates the shadow parameters for a particular class of shadows
* for either the focused or unfocused state. If the class name
* does not name an existing class, a new class will be created
* (the other focus state for that class will have default values
* assigned to it.)
*/
void
meta_shadow_factory_set_params (MetaShadowFactory *factory,
const char *class_name,
gboolean focused,
MetaShadowParams *params)
{
MetaShadowParams *stored_params;
g_return_if_fail (META_IS_SHADOW_FACTORY (factory));
g_return_if_fail (class_name != NULL);
g_return_if_fail (params != NULL);
g_return_if_fail (params->radius >= 0);
stored_params = get_shadow_params (factory, class_name, focused, TRUE);
*stored_params = *params;
g_signal_emit (factory, signals[CHANGED], 0);
}
/**
* meta_shadow_factory_get_params:
* @factory: a #MetaShadowFactory
* @class_name: name of the class of shadow to get the params for
* @focused: whether the shadow is for a focused window
* @params: (out caller-allocates): location to store the current parameter values
*
* Gets the shadow parameters for a particular class of shadows
* for either the focused or unfocused state. If the class name
* does not name an existing class, default values will be returned
* without printing an error.
*/
void
meta_shadow_factory_get_params (MetaShadowFactory *factory,
const char *class_name,
gboolean focused,
MetaShadowParams *params)
{
MetaShadowParams *stored_params;
g_return_if_fail (META_IS_SHADOW_FACTORY (factory));
g_return_if_fail (class_name != NULL);
stored_params = get_shadow_params (factory, class_name, focused, FALSE);
if (params)
*params = *stored_params;
}

View File

@ -25,143 +25,136 @@
#include <config.h>
#include "mutter-shaped-texture.h"
#include "mutter-texture-tower.h"
#include "meta-shaped-texture.h"
#include "meta-texture-tower.h"
#include <clutter/clutter.h>
#include <cogl/cogl.h>
#include <string.h>
static void mutter_shaped_texture_dispose (GObject *object);
static void mutter_shaped_texture_finalize (GObject *object);
static void mutter_shaped_texture_notify (GObject *object,
static void meta_shaped_texture_dispose (GObject *object);
static void meta_shaped_texture_finalize (GObject *object);
static void meta_shaped_texture_notify (GObject *object,
GParamSpec *pspec);
static void mutter_shaped_texture_paint (ClutterActor *actor);
static void mutter_shaped_texture_pick (ClutterActor *actor,
const ClutterColor *color);
static void meta_shaped_texture_paint (ClutterActor *actor);
static void meta_shaped_texture_pick (ClutterActor *actor,
const ClutterColor *color);
static void mutter_shaped_texture_update_area (ClutterX11TexturePixmap *texture,
int x,
int y,
int width,
int height);
static void meta_shaped_texture_update_area (ClutterX11TexturePixmap *texture,
int x,
int y,
int width,
int height);
static void mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex);
static void meta_shaped_texture_dirty_mask (MetaShapedTexture *stex);
#ifdef HAVE_GLX_TEXTURE_PIXMAP
G_DEFINE_TYPE (MutterShapedTexture, mutter_shaped_texture,
G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
CLUTTER_GLX_TYPE_TEXTURE_PIXMAP);
#else /* HAVE_GLX_TEXTURE_PIXMAP */
G_DEFINE_TYPE (MutterShapedTexture, mutter_shaped_texture,
G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
CLUTTER_X11_TYPE_TEXTURE_PIXMAP);
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
#define MUTTER_SHAPED_TEXTURE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_SHAPED_TEXTURE, \
MutterShapedTexturePrivate))
#define META_SHAPED_TEXTURE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \
MetaShapedTexturePrivate))
struct _MutterShapedTexturePrivate
struct _MetaShapedTexturePrivate
{
MutterTextureTower *paint_tower;
MetaTextureTower *paint_tower;
CoglHandle mask_texture;
CoglHandle material;
CoglHandle material_unshaped;
#if 1 /* see workaround comment in mutter_shaped_texture_paint */
CoglHandle material_workaround;
#endif
GdkRegion *clip_region;
cairo_region_t *clip_region;
guint mask_width, mask_height;
GArray *rectangles;
guint create_mipmaps : 1;
};
static void
mutter_shaped_texture_class_init (MutterShapedTextureClass *klass)
meta_shaped_texture_class_init (MetaShapedTextureClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
ClutterX11TexturePixmapClass *x11_texture_class = (ClutterX11TexturePixmapClass *) klass;
gobject_class->dispose = mutter_shaped_texture_dispose;
gobject_class->finalize = mutter_shaped_texture_finalize;
gobject_class->notify = mutter_shaped_texture_notify;
gobject_class->dispose = meta_shaped_texture_dispose;
gobject_class->finalize = meta_shaped_texture_finalize;
gobject_class->notify = meta_shaped_texture_notify;
actor_class->paint = mutter_shaped_texture_paint;
actor_class->pick = mutter_shaped_texture_pick;
actor_class->paint = meta_shaped_texture_paint;
actor_class->pick = meta_shaped_texture_pick;
x11_texture_class->update_area = mutter_shaped_texture_update_area;
x11_texture_class->update_area = meta_shaped_texture_update_area;
g_type_class_add_private (klass, sizeof (MutterShapedTexturePrivate));
g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate));
}
static void
mutter_shaped_texture_init (MutterShapedTexture *self)
meta_shaped_texture_init (MetaShapedTexture *self)
{
MutterShapedTexturePrivate *priv;
MetaShapedTexturePrivate *priv;
priv = self->priv = MUTTER_SHAPED_TEXTURE_GET_PRIVATE (self);
priv = self->priv = META_SHAPED_TEXTURE_GET_PRIVATE (self);
priv->rectangles = g_array_new (FALSE, FALSE, sizeof (XRectangle));
priv->paint_tower = mutter_texture_tower_new ();
priv->paint_tower = meta_texture_tower_new ();
priv->mask_texture = COGL_INVALID_HANDLE;
priv->create_mipmaps = TRUE;
}
static void
mutter_shaped_texture_dispose (GObject *object)
meta_shaped_texture_dispose (GObject *object)
{
MutterShapedTexture *self = (MutterShapedTexture *) object;
MutterShapedTexturePrivate *priv = self->priv;
MetaShapedTexture *self = (MetaShapedTexture *) object;
MetaShapedTexturePrivate *priv = self->priv;
if (priv->paint_tower)
mutter_texture_tower_free (priv->paint_tower);
meta_texture_tower_free (priv->paint_tower);
priv->paint_tower = NULL;
mutter_shaped_texture_dirty_mask (self);
meta_shaped_texture_dirty_mask (self);
if (priv->material != COGL_INVALID_HANDLE)
{
cogl_material_unref (priv->material);
cogl_handle_unref (priv->material);
priv->material = COGL_INVALID_HANDLE;
}
if (priv->material_unshaped != COGL_INVALID_HANDLE)
{
cogl_material_unref (priv->material_unshaped);
cogl_handle_unref (priv->material_unshaped);
priv->material_unshaped = COGL_INVALID_HANDLE;
}
#if 1 /* see comment in mutter_shaped_texture_paint */
if (priv->material_workaround != COGL_INVALID_HANDLE)
{
cogl_material_unref (priv->material_workaround);
priv->material_workaround = COGL_INVALID_HANDLE;
}
#endif
mutter_shaped_texture_set_clip_region (self, NULL);
meta_shaped_texture_set_clip_region (self, NULL);
G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->dispose (object);
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
}
static void
mutter_shaped_texture_finalize (GObject *object)
meta_shaped_texture_finalize (GObject *object)
{
MutterShapedTexture *self = (MutterShapedTexture *) object;
MutterShapedTexturePrivate *priv = self->priv;
MetaShapedTexture *self = (MetaShapedTexture *) object;
MetaShapedTexturePrivate *priv = self->priv;
g_array_free (priv->rectangles, TRUE);
G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->finalize (object);
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->finalize (object);
}
static void
mutter_shaped_texture_notify (GObject *object,
GParamSpec *pspec)
meta_shaped_texture_notify (GObject *object,
GParamSpec *pspec)
{
if (G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->notify)
G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->notify (object, pspec);
if (G_OBJECT_CLASS (meta_shaped_texture_parent_class)->notify)
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->notify (object, pspec);
/* It seems like we could just do this out of update_area(), but unfortunately,
* clutter_glx_texture_pixmap() doesn't call through the vtable on the
@ -170,18 +163,21 @@ mutter_shaped_texture_notify (GObject *object,
*/
if (strcmp (pspec->name, "cogl-texture") == 0)
{
MutterShapedTexture *stex = (MutterShapedTexture *) object;
MutterShapedTexturePrivate *priv = stex->priv;
MetaShapedTexture *stex = (MetaShapedTexture *) object;
MetaShapedTexturePrivate *priv = stex->priv;
mutter_texture_tower_set_base_texture (priv->paint_tower,
clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)));
meta_shaped_texture_clear (stex);
if (priv->create_mipmaps)
meta_texture_tower_set_base_texture (priv->paint_tower,
clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)));
}
}
static void
mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex)
meta_shaped_texture_dirty_mask (MetaShapedTexture *stex)
{
MutterShapedTexturePrivate *priv = stex->priv;
MetaShapedTexturePrivate *priv = stex->priv;
if (priv->mask_texture != COGL_INVALID_HANDLE)
{
@ -191,18 +187,23 @@ mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex)
cogl_texture_get_gl_texture (priv->mask_texture,
&mask_gl_tex, &mask_gl_target);
#ifdef GL_TEXTURE_RECTANGLE_ARB
if (mask_gl_target == GL_TEXTURE_RECTANGLE_ARB)
glDeleteTextures (1, &mask_gl_tex);
#endif
cogl_texture_unref (priv->mask_texture);
cogl_handle_unref (priv->mask_texture);
priv->mask_texture = COGL_INVALID_HANDLE;
if (priv->material != COGL_INVALID_HANDLE)
cogl_material_set_layer (priv->material, 1, COGL_INVALID_HANDLE);
}
}
static void
mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
meta_shaped_texture_ensure_mask (MetaShapedTexture *stex)
{
MutterShapedTexturePrivate *priv = stex->priv;
MetaShapedTexturePrivate *priv = stex->priv;
CoglHandle paint_tex;
guint tex_width, tex_height;
@ -218,7 +219,7 @@ mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
recreate it */
if (priv->mask_texture != COGL_INVALID_HANDLE
&& (priv->mask_width != tex_width || priv->mask_height != tex_height))
mutter_shaped_texture_dirty_mask (stex);
meta_shaped_texture_dirty_mask (stex);
/* If we don't have a mask texture yet then create one */
if (priv->mask_texture == COGL_INVALID_HANDLE)
@ -254,6 +255,7 @@ mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
cogl_texture_get_gl_texture (paint_tex, NULL, &paint_gl_target);
#ifdef GL_TEXTURE_RECTANGLE_ARB
if (paint_gl_target == GL_TEXTURE_RECTANGLE_ARB)
{
GLuint tex;
@ -276,6 +278,7 @@ mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
COGL_PIXEL_FORMAT_A_8);
}
else
#endif /* GL_TEXTURE_RECTANGLE_ARB */
priv->mask_texture = cogl_texture_new_from_data (tex_width, tex_height,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_A_8,
@ -291,45 +294,44 @@ mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
}
static void
mutter_shaped_texture_paint (ClutterActor *actor)
meta_shaped_texture_paint (ClutterActor *actor)
{
MutterShapedTexture *stex = (MutterShapedTexture *) actor;
MutterShapedTexturePrivate *priv = stex->priv;
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
MetaShapedTexturePrivate *priv = stex->priv;
CoglHandle paint_tex;
guint tex_width, tex_height;
ClutterActorBox alloc;
CoglHandle material;
#if 1 /* please see comment below about workaround */
guint depth;
#endif
if (priv->clip_region && gdk_region_empty (priv->clip_region))
static CoglHandle material_template = COGL_INVALID_HANDLE;
static CoglHandle material_unshaped_template = COGL_INVALID_HANDLE;
CoglHandle material;
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
return;
if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
clutter_actor_realize (CLUTTER_ACTOR (stex));
/* If mipmaps are supported, then the texture filter quality will
* still be HIGH here. In that case we just want to use the base
* texture. If mipmaps are not support then
* on_glx_texture_pixmap_pre_paint() will have reset the texture
* filter quality to MEDIUM, and we should use the MutterTextureTower
* mipmap emulation.
/* The GL EXT_texture_from_pixmap extension does allow for it to be
* used together with SGIS_generate_mipmap, however this is very
* rarely supported. Also, even when it is supported there
* are distinct performance implications from:
*
* http://bugzilla.openedhand.com/show_bug.cgi?id=1877 is an RFE
* for a better way of handling this.
* - Updating mipmaps that we don't need
* - Having to reallocate pixmaps on the server into larger buffers
*
* While it would be nice to have direct access to the 'can_mipmap'
* boolean in ClutterGLXTexturePixmap, since since MutterTextureTower
* creates the scaled down images on demand there is no substantial
* overhead from doing the work to create and update the tower and
* not using it, other than the memory allocated for the MutterTextureTower
* structure itself.
* So, we just unconditionally use our mipmap emulation code. If we
* wanted to use SGIS_generate_mipmap, we'd have to query COGL to
* see if it was supported (no API currently), and then if and only
* if that was the case, set the clutter texture quality to HIGH.
* Setting the texture quality to high without SGIS_generate_mipmap
* support for TFP textures will result in fallbacks to XGetImage.
*/
if (clutter_texture_get_filter_quality (CLUTTER_TEXTURE (stex)) == CLUTTER_TEXTURE_QUALITY_HIGH)
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
if (priv->create_mipmaps)
paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
else
paint_tex = mutter_texture_tower_get_paint_texture (priv->paint_tower);
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
if (paint_tex == COGL_INVALID_HANDLE)
return;
@ -344,54 +346,32 @@ mutter_shaped_texture_paint (ClutterActor *actor)
{
/* If there are no rectangles use a single-layer texture */
if (priv->material_unshaped == COGL_INVALID_HANDLE)
priv->material_unshaped = cogl_material_new ();
if (priv->material_unshaped == COGL_INVALID_HANDLE)
{
if (G_UNLIKELY (material_unshaped_template == COGL_INVALID_HANDLE))
material_unshaped_template = cogl_material_new ();
material = priv->material_unshaped;
priv->material_unshaped = cogl_material_copy (material_unshaped_template);
}
material = priv->material_unshaped;
}
else
{
mutter_shaped_texture_ensure_mask (stex);
meta_shaped_texture_ensure_mask (stex);
if (priv->material == COGL_INVALID_HANDLE)
{
priv->material = cogl_material_new ();
cogl_material_set_layer_combine (priv->material, 1,
if (G_UNLIKELY (material_template == COGL_INVALID_HANDLE))
{
material_template = cogl_material_new ();
cogl_material_set_layer_combine (material_template, 1,
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
NULL);
}
priv->material = cogl_material_copy (material_template);
}
material = priv->material;
#if 1
/* This was added as a workaround. It seems that with the intel
* drivers when multi-texturing using an RGB TFP texture, the
* texture is actually setup internally as an RGBA texture, where
* the alpha channel is mostly 0.0 so you only see a shimmer of the
* window. This workaround forcibly defines the alpha channel as
* 1.0. Maybe there is some clutter/cogl state that is interacting
* with this that is being overlooked, but for now this seems to
* work. */
g_object_get (stex, "pixmap-depth", &depth, NULL);
if (depth == 24)
{
if (priv->material_workaround == COGL_INVALID_HANDLE)
{
material = priv->material_workaround = cogl_material_new ();
cogl_material_set_layer_combine (material, 0,
"RGB = MODULATE (TEXTURE, PREVIOUS)"
"A = REPLACE (PREVIOUS)",
NULL);
cogl_material_set_layer_combine (material, 1,
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
NULL);
}
material = priv->material_workaround;
}
#endif
cogl_material_set_layer (material, 1, priv->mask_texture);
}
@ -410,7 +390,6 @@ mutter_shaped_texture_paint (ClutterActor *actor)
if (priv->clip_region)
{
GdkRectangle *rects;
int n_rects;
int i;
@ -418,31 +397,27 @@ mutter_shaped_texture_paint (ClutterActor *actor)
* fall back and draw the whole thing */
# define MAX_RECTS 16
/* Would be nice to be able to check the number of rects first */
gdk_region_get_rectangles (priv->clip_region, &rects, &n_rects);
if (n_rects > MAX_RECTS)
{
g_free (rects);
/* Fall through to following code */
}
else
n_rects = cairo_region_num_rectangles (priv->clip_region);
if (n_rects <= MAX_RECTS)
{
float coords[8];
float x1, y1, x2, y2;
for (i = 0; i < n_rects; i++)
{
GdkRectangle *rect = &rects[i];
cairo_rectangle_int_t rect;
x1 = rect->x;
y1 = rect->y;
x2 = rect->x + rect->width;
y2 = rect->y + rect->height;
cairo_region_get_rectangle (priv->clip_region, i, &rect);
coords[0] = rect->x / (alloc.x2 - alloc.x1);
coords[1] = rect->y / (alloc.y2 - alloc.y1);
coords[2] = (rect->x + rect->width) / (alloc.x2 - alloc.x1);
coords[3] = (rect->y + rect->height) / (alloc.y2 - alloc.y1);
x1 = rect.x;
y1 = rect.y;
x2 = rect.x + rect.width;
y2 = rect.y + rect.height;
coords[0] = rect.x / (alloc.x2 - alloc.x1);
coords[1] = rect.y / (alloc.y2 - alloc.y1);
coords[2] = (rect.x + rect.width) / (alloc.x2 - alloc.x1);
coords[3] = (rect.y + rect.height) / (alloc.y2 - alloc.y1);
coords[4] = coords[0];
coords[5] = coords[1];
@ -453,8 +428,6 @@ mutter_shaped_texture_paint (ClutterActor *actor)
&coords[0], 8);
}
g_free (rects);
return;
}
}
@ -465,15 +438,15 @@ mutter_shaped_texture_paint (ClutterActor *actor)
}
static void
mutter_shaped_texture_pick (ClutterActor *actor,
const ClutterColor *color)
meta_shaped_texture_pick (ClutterActor *actor,
const ClutterColor *color)
{
MutterShapedTexture *stex = (MutterShapedTexture *) actor;
MutterShapedTexturePrivate *priv = stex->priv;
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
MetaShapedTexturePrivate *priv = stex->priv;
/* If there are no rectangles then use the regular pick */
if (priv->rectangles->len < 1)
CLUTTER_ACTOR_CLASS (mutter_shaped_texture_parent_class)
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)
->pick (actor, color);
else if (clutter_actor_should_pick_paint (actor))
{
@ -492,7 +465,7 @@ mutter_shaped_texture_pick (ClutterActor *actor,
if (tex_width == 0 || tex_height == 0) /* no contents yet */
return;
mutter_shaped_texture_ensure_mask (stex);
meta_shaped_texture_ensure_mask (stex);
cogl_set_source_color4ub (color->red, color->green, color->blue,
color->alpha);
@ -509,71 +482,130 @@ mutter_shaped_texture_pick (ClutterActor *actor,
}
static void
mutter_shaped_texture_update_area (ClutterX11TexturePixmap *texture,
int x,
int y,
int width,
int height)
meta_shaped_texture_update_area (ClutterX11TexturePixmap *texture,
int x,
int y,
int width,
int height)
{
MutterShapedTexture *stex = (MutterShapedTexture *) texture;
MutterShapedTexturePrivate *priv = stex->priv;
MetaShapedTexture *stex = (MetaShapedTexture *) texture;
MetaShapedTexturePrivate *priv = stex->priv;
CLUTTER_X11_TEXTURE_PIXMAP_CLASS (mutter_shaped_texture_parent_class)->update_area (texture,
CLUTTER_X11_TEXTURE_PIXMAP_CLASS (meta_shaped_texture_parent_class)->update_area (texture,
x, y, width, height);
mutter_texture_tower_update_area (priv->paint_tower, x, y, width, height);
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
}
ClutterActor *
mutter_shaped_texture_new (void)
meta_shaped_texture_new (void)
{
ClutterActor *self = g_object_new (MUTTER_TYPE_SHAPED_TEXTURE, NULL);
ClutterActor *self = g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
return self;
}
void
mutter_shaped_texture_clear_rectangles (MutterShapedTexture *stex)
meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
gboolean create_mipmaps)
{
MutterShapedTexturePrivate *priv;
MetaShapedTexturePrivate *priv;
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
create_mipmaps = create_mipmaps != FALSE;
if (create_mipmaps != priv->create_mipmaps)
{
CoglHandle base_texture;
priv->create_mipmaps = create_mipmaps;
base_texture = create_mipmaps ?
clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)) : COGL_INVALID_HANDLE;
meta_texture_tower_set_base_texture (priv->paint_tower, base_texture);
}
}
/* This is a workaround for deficiencies in the hack tower:
*
* When we call clutter_x11_texture_pixmap_set_pixmap(tp, None),
* ClutterX11TexturePixmap knows that it has to get rid of the old texture, but
* clutter_texture_set_cogl_texture(texture, COGL_INVALID_HANDLE) isn't allowed, so
* it grabs the material for the texture and manually sets the texture in it. This means
* that the "cogl-texture" property isn't notified, so we don't find out about it.
*
* And if we keep the CoglX11TexturePixmap around after the X pixmap is freed, then
* we'll trigger X errors when we actually try to free it.
*
* The only correct thing to do here is to change our code to derive
* from ClutterActor and get rid of the inheritance hack tower. Once
* we want to depend on Clutter-1.4 (which has CoglTexturePixmapX11),
* that will be very easy to do.
*/
void
meta_shaped_texture_clear (MetaShapedTexture *stex)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
meta_texture_tower_set_base_texture (priv->paint_tower, COGL_INVALID_HANDLE);
if (priv->material != COGL_INVALID_HANDLE)
cogl_material_set_layer (priv->material, 0, COGL_INVALID_HANDLE);
if (priv->material_unshaped != COGL_INVALID_HANDLE)
cogl_material_set_layer (priv->material_unshaped, 0, COGL_INVALID_HANDLE);
}
void
meta_shaped_texture_clear_rectangles (MetaShapedTexture *stex)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
g_array_set_size (priv->rectangles, 0);
mutter_shaped_texture_dirty_mask (stex);
meta_shaped_texture_dirty_mask (stex);
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
void
mutter_shaped_texture_add_rectangle (MutterShapedTexture *stex,
const XRectangle *rect)
meta_shaped_texture_add_rectangle (MetaShapedTexture *stex,
const XRectangle *rect)
{
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
mutter_shaped_texture_add_rectangles (stex, 1, rect);
meta_shaped_texture_add_rectangles (stex, 1, rect);
}
void
mutter_shaped_texture_add_rectangles (MutterShapedTexture *stex,
size_t num_rects,
const XRectangle *rects)
meta_shaped_texture_add_rectangles (MetaShapedTexture *stex,
size_t num_rects,
const XRectangle *rects)
{
MutterShapedTexturePrivate *priv;
MetaShapedTexturePrivate *priv;
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
g_array_append_vals (priv->rectangles, rects, num_rects);
mutter_shaped_texture_dirty_mask (stex);
meta_shaped_texture_dirty_mask (stex);
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
/**
* mutter_shaped_texture_set_clip_region:
* meta_shaped_texture_set_clip_region:
* @frame: a #TidyTextureframe
* @clip_region: (transfer full): the region of the texture that
* is visible and should be painted. OWNERSHIP IS ASSUMED BY
@ -588,18 +620,18 @@ mutter_shaped_texture_add_rectangles (MutterShapedTexture *stex,
* painting its children, and then unset it afterwards.
*/
void
mutter_shaped_texture_set_clip_region (MutterShapedTexture *stex,
GdkRegion *clip_region)
meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
cairo_region_t *clip_region)
{
MutterShapedTexturePrivate *priv;
MetaShapedTexturePrivate *priv;
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
if (priv->clip_region)
{
gdk_region_destroy (priv->clip_region);
cairo_region_destroy (priv->clip_region);
priv->clip_region = NULL;
}

View File

@ -0,0 +1,92 @@
/*
* shaped texture
*
* An actor to draw a texture clipped to a list of rectangles
*
* Authored By Neil Roberts <neil@linux.intel.com>
*
* Copyright (C) 2008 Intel Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_SHAPED_TEXTURE_H__
#define __META_SHAPED_TEXTURE_H__
#include <config.h>
#include <clutter/clutter.h>
#ifdef HAVE_GLX_TEXTURE_PIXMAP
#include <clutter/glx/clutter-glx.h>
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
G_BEGIN_DECLS
#define META_TYPE_SHAPED_TEXTURE (meta_shaped_texture_get_type())
#define META_SHAPED_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),META_TYPE_SHAPED_TEXTURE, MetaShapedTexture))
#define META_SHAPED_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SHAPED_TEXTURE, MetaShapedTextureClass))
#define META_IS_SHAPED_TEXTURE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SHAPED_TEXTURE))
#define META_IS_SHAPED_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SHAPED_TEXTURE))
#define META_SHAPED_TEXTURE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SHAPED_TEXTURE, MetaShapedTextureClass))
typedef struct _MetaShapedTexture MetaShapedTexture;
typedef struct _MetaShapedTextureClass MetaShapedTextureClass;
typedef struct _MetaShapedTexturePrivate MetaShapedTexturePrivate;
struct _MetaShapedTextureClass
{
#ifdef HAVE_GLX_TEXTURE_PIXMAP
ClutterGLXTexturePixmapClass parent_class;
#else
ClutterX11TexturePixmapClass parent_class;
#endif
};
struct _MetaShapedTexture
{
#ifdef HAVE_GLX_TEXTURE_PIXMAP
ClutterGLXTexturePixmap parent;
#else
ClutterX11TexturePixmap parent;
#endif
MetaShapedTexturePrivate *priv;
};
GType meta_shaped_texture_get_type (void) G_GNUC_CONST;
ClutterActor *meta_shaped_texture_new (void);
void meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
gboolean create_mipmaps);
void meta_shaped_texture_clear (MetaShapedTexture *stex);
void meta_shaped_texture_clear_rectangles (MetaShapedTexture *stex);
void meta_shaped_texture_add_rectangle (MetaShapedTexture *stex,
const XRectangle *rect);
void meta_shaped_texture_add_rectangles (MetaShapedTexture *stex,
size_t num_rects,
const XRectangle *rects);
/* Assumes ownership of clip_region */
void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
cairo_region_t *clip_region);
G_END_DECLS
#endif /* __META_SHAPED_TEXTURE_H__ */

View File

@ -1,6 +1,6 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MutterTextureTower
* MetaTextureTower
*
* Mipmap emulation by creation of scaled down images
*
@ -25,21 +25,12 @@
#include <math.h>
#include <string.h>
#include "mutter-texture-tower.h"
#include "meta-texture-tower.h"
#ifndef M_LOG2E
#define M_LOG2E 1.4426950408889634074
#endif
#if !CLUTTER_CHECK_VERSION(1,1,3)
static PFNGLACTIVETEXTUREARBPROC activeTexture;
static PFNGLGENFRAMEBUFFERSPROC genFramebuffers;
static PFNGLDELETEFRAMEBUFFERSPROC deleteFramebuffers;
static PFNGLBINDFRAMEBUFFERPROC bindFramebuffer;
static PFNGLFRAMEBUFFERTEXTURE2DPROC framebufferTexture2D;
#endif
#define MAX_TEXTURE_LEVELS 12
/* If the texture format in memory doesn't match this, then Mesa
@ -64,52 +55,49 @@ typedef struct
guint16 y2;
} Box;
struct _MutterTextureTower
struct _MetaTextureTower
{
int n_levels;
CoglHandle textures[MAX_TEXTURE_LEVELS];
#if CLUTTER_CHECK_VERSION(1,1,3)
CoglHandle fbos[MAX_TEXTURE_LEVELS];
#else
GLuint fbos[MAX_TEXTURE_LEVELS];
#endif
Box invalid[MAX_TEXTURE_LEVELS];
};
/**
* mutter_texture_tower_new:
* meta_texture_tower_new:
*
* Creates a new texture tower. The base texture has to be set with
* mutter_texture_tower_set_base_texture() before use.
* meta_texture_tower_set_base_texture() before use.
*
* Return value: the new texture tower. Free with mutter_texture_tower_free()
* Return value: the new texture tower. Free with meta_texture_tower_free()
*/
MutterTextureTower *
mutter_texture_tower_new (void)
MetaTextureTower *
meta_texture_tower_new (void)
{
MutterTextureTower *tower;
MetaTextureTower *tower;
tower = g_slice_new0 (MutterTextureTower);
tower = g_slice_new0 (MetaTextureTower);
return tower;
}
/**
* mutter_texture_tower_free:
* @tower: a #MutterTextureTower
* meta_texture_tower_free:
* @tower: a #MetaTextureTower
*
* Frees a texture tower created with mutter_texture_tower_new().
* Frees a texture tower created with meta_texture_tower_new().
*/
void
mutter_texture_tower_free (MutterTextureTower *tower)
meta_texture_tower_free (MetaTextureTower *tower)
{
g_return_if_fail (tower != NULL);
mutter_texture_tower_set_base_texture (tower, COGL_INVALID_HANDLE);
meta_texture_tower_set_base_texture (tower, COGL_INVALID_HANDLE);
g_slice_free (MutterTextureTower, tower);
g_slice_free (MetaTextureTower, tower);
}
#ifdef GL_TEXTURE_RECTANGLE_ARB
static gboolean
texture_is_rectangle (CoglHandle texture)
{
@ -119,10 +107,12 @@ texture_is_rectangle (CoglHandle texture)
cogl_texture_get_gl_texture (texture, &gl_tex, &gl_target);
return gl_target == GL_TEXTURE_RECTANGLE_ARB;
}
#endif /* GL_TEXTURE_RECTANGLE_ARB */
static void
free_texture (CoglHandle texture)
{
#ifdef GL_TEXTURE_RECTANGLE_ARB
GLuint gl_tex;
GLenum gl_target;
@ -130,13 +120,14 @@ free_texture (CoglHandle texture)
if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
glDeleteTextures (1, &gl_tex);
#endif /* GL_TEXTURE_RECTANGLE_ARB */
cogl_texture_unref (texture);
cogl_handle_unref (texture);
}
/**
* mutter_texture_tower_update_area:
* @tower: a MutterTextureTower
* meta_texture_tower_update_area:
* @tower: a MetaTextureTower
* @texture: the new texture used as a base for scaled down versions
*
* Sets the base texture that is the scaled texture that the
@ -145,8 +136,8 @@ free_texture (CoglHandle texture)
* unset or until the tower is freed.
*/
void
mutter_texture_tower_set_base_texture (MutterTextureTower *tower,
CoglHandle texture)
meta_texture_tower_set_base_texture (MetaTextureTower *tower,
CoglHandle texture)
{
int i;
@ -165,22 +156,14 @@ mutter_texture_tower_set_base_texture (MutterTextureTower *tower,
tower->textures[i] = COGL_INVALID_HANDLE;
}
#if CLUTTER_CHECK_VERSION(1,1,3)
if (tower->fbos[i] != COGL_INVALID_HANDLE)
{
cogl_handle_unref (tower->fbos[i]);
tower->fbos[i] = COGL_INVALID_HANDLE;
}
#else
if (tower->fbos[i] != 0)
{
(*deleteFramebuffers) (1, &tower->fbos[i]);
tower->fbos[i] = 0;
}
#endif
}
cogl_texture_unref (tower->textures[0]);
cogl_handle_unref (tower->textures[0]);
}
tower->textures[0] = texture;
@ -189,7 +172,7 @@ mutter_texture_tower_set_base_texture (MutterTextureTower *tower,
{
int width, height;
cogl_texture_ref (tower->textures[0]);
cogl_handle_ref (tower->textures[0]);
width = cogl_texture_get_width (tower->textures[0]);
height = cogl_texture_get_height (tower->textures[0]);
@ -197,7 +180,7 @@ mutter_texture_tower_set_base_texture (MutterTextureTower *tower,
tower->n_levels = 1 + MAX ((int)(M_LOG2E * log (width)), (int)(M_LOG2E * log (height)));
tower->n_levels = MIN(tower->n_levels, MAX_TEXTURE_LEVELS);
mutter_texture_tower_update_area (tower, 0, 0, width, height);
meta_texture_tower_update_area (tower, 0, 0, width, height);
}
else
{
@ -206,8 +189,8 @@ mutter_texture_tower_set_base_texture (MutterTextureTower *tower,
}
/**
* mutter_texture_tower_update_area:
* @tower: a MutterTextureTower
* meta_texture_tower_update_area:
* @tower: a MetaTextureTower
* @x: X coordinate of upper left of rectangle that changed
* @y: Y coordinate of upper left of rectangle that changed
* @width: width of rectangle that changed
@ -218,11 +201,11 @@ mutter_texture_tower_set_base_texture (MutterTextureTower *tower,
* the appropriate area of the scaled down texture will be updated.
*/
void
mutter_texture_tower_update_area (MutterTextureTower *tower,
int x,
int y,
int width,
int height)
meta_texture_tower_update_area (MetaTextureTower *tower,
int x,
int y,
int width,
int height)
{
int texture_width, texture_height;
Box invalid;
@ -278,7 +261,7 @@ mutter_texture_tower_update_area (MutterTextureTower *tower,
* If window is being painted at an angle from the viewer, then we have to
* pick a point in the texture; we use the middle of the texture (which is
* why the width/height are passed in.) This is not the normal case for
* Mutter.
* Meta.
*/
static int
get_paint_level (int width, int height)
@ -383,18 +366,21 @@ get_paint_level (int width, int height)
return (int)(0.5 + lambda);
}
#ifdef GL_TEXTURE_RECTANGLE_ARB
static gboolean
is_power_of_two (int x)
{
return (x & (x - 1)) == 0;
}
#endif /* GL_TEXTURE_RECTANGLE_ARB */
static void
texture_tower_create_texture (MutterTextureTower *tower,
int level,
int width,
int height)
texture_tower_create_texture (MetaTextureTower *tower,
int level,
int width,
int height)
{
#ifdef GL_TEXTURE_RECTANGLE_ARB
if ((!is_power_of_two (width) || !is_power_of_two (height)) &&
texture_is_rectangle (tower->textures[level - 1]))
{
@ -417,6 +403,7 @@ texture_tower_create_texture (MutterTextureTower *tower,
TEXTURE_FORMAT);
}
else
#endif /* GL_TEXTURE_RECTANGLE_ARB */
{
tower->textures[level] = cogl_texture_new_with_size (width, height,
COGL_TEXTURE_NO_AUTO_MIPMAP,
@ -429,20 +416,9 @@ texture_tower_create_texture (MutterTextureTower *tower,
tower->invalid[level].y2 = height;
}
/* The COGL fbo (render-to-texture) support is pretty hard to use in
* Clutter 1.0; there's no way to save and restore the old projection
* matrix and viewport without ugly workarounds that require explicit
* access to the ClutterStage. In Clutter 1.2, the save/restore is
* automatic. For now, until we depend on Clutter 1.2, we use GL
* directly for render-to-texture. The main downside (other than
* a lot of verbosity) is that we have to save the state, reset anything
* that we think COGL might have left in a way we don't want it, then
* restore the old state.
*/
#if CLUTTER_CHECK_VERSION(1,1,3)
static gboolean
texture_tower_revalidate_fbo (MutterTextureTower *tower,
int level)
texture_tower_revalidate_fbo (MetaTextureTower *tower,
int level)
{
CoglHandle source_texture = tower->textures[level - 1];
int source_texture_width = cogl_texture_get_width (source_texture);
@ -454,7 +430,12 @@ texture_tower_revalidate_fbo (MutterTextureTower *tower,
CoglMatrix modelview;
if (tower->fbos[level] == COGL_INVALID_HANDLE)
tower->fbos[level] = cogl_offscreen_new_to_texture (dest_texture);
{
/* Work around http://bugzilla.openedhand.com/show_bug.cgi?id=2110 */
cogl_flush();
tower->fbos[level] = cogl_offscreen_new_to_texture (dest_texture);
}
if (tower->fbos[level] == COGL_INVALID_HANDLE)
return FALSE;
@ -478,162 +459,6 @@ texture_tower_revalidate_fbo (MutterTextureTower *tower,
return TRUE;
}
#else
static void
initialize_gl_functions (void)
{
static gboolean initialized = FALSE;
if (!initialized)
{
initialized = TRUE;
activeTexture = (PFNGLACTIVETEXTUREARBPROC) cogl_get_proc_address ("glActiveTextureARB");
genFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) cogl_get_proc_address ("glGenFramebuffersEXT");
deleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) cogl_get_proc_address ("glDeleteFramebuffersEXT");
bindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) cogl_get_proc_address ("glBindFramebufferEXT");
framebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) cogl_get_proc_address ("glFramebufferTexture2D");
}
}
static gboolean
texture_tower_revalidate_fbo (MutterTextureTower *tower,
int level)
{
CoglHandle source_texture = tower->textures[level - 1];
int source_texture_width = cogl_texture_get_width (source_texture);
int source_texture_height = cogl_texture_get_height (source_texture);
CoglHandle dest_texture = tower->textures[level];
int dest_texture_width = cogl_texture_get_width (dest_texture);
int dest_texture_height = cogl_texture_get_height (dest_texture);
ClutterActorBox source_box;
Box *dest_box;
GLuint source_gl_tex;
GLenum source_gl_target;
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
return FALSE;
initialize_gl_functions ();
/* Create the frame-buffer object that renders to the texture, if
* it doesn't exist; just bind it for rendering if it does */
if (tower->fbos[level] == 0)
{
GLuint dest_gl_tex;
GLenum dest_gl_target;
cogl_texture_get_gl_texture (dest_texture, &dest_gl_tex, &dest_gl_target);
(*genFramebuffers) (1, &tower->fbos[level]);
(*bindFramebuffer) (GL_FRAMEBUFFER_EXT, tower->fbos[level]);
(*framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
dest_gl_target, dest_gl_tex, 0);
}
else
{
(*bindFramebuffer) (GL_FRAMEBUFFER_EXT, tower->fbos[level]);
}
/* Save the old state (other than the transformation matrices) */
glPushAttrib (GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TEXTURE_BIT | GL_VIEWPORT_BIT);
/* And set up the state we need */
glDisable (GL_BLEND);
glDisable (GL_SCISSOR_TEST);
glDisable (GL_STENCIL_TEST);
glDisable (GL_CLIP_PLANE3);
glDisable (GL_CLIP_PLANE2);
glDisable (GL_CLIP_PLANE1);
glDisable (GL_CLIP_PLANE0);
cogl_texture_get_gl_texture (source_texture, &source_gl_tex, &source_gl_target);
(*activeTexture) (GL_TEXTURE0_ARB);
if (source_gl_target == GL_TEXTURE_2D)
glDisable (GL_TEXTURE_RECTANGLE_ARB);
else
glDisable (GL_TEXTURE_2D);
glEnable (source_gl_target);
glBindTexture (source_gl_target, source_gl_tex);
glTexParameteri (source_gl_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (source_gl_target, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri (source_gl_target, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
/* In theory, we should loop over all the texture units supported
* by the GL implementation, but here we just assume that no more
* than three are used by Mutter and all GL implementations we care
* about will support at least 3.
*/
(*activeTexture) (GL_TEXTURE1_ARB);
glDisable (GL_TEXTURE_2D);
glDisable (GL_TEXTURE_RECTANGLE_ARB);
(*activeTexture) (GL_TEXTURE2_ARB);
glDisable (GL_TEXTURE_2D);
glDisable (GL_TEXTURE_RECTANGLE_ARB);
glViewport (0, 0, dest_texture_width, dest_texture_height);
/* Save the transformation matrices and set up new ones that map
* coordinates directly onto the destination texture */
glMatrixMode (GL_MODELVIEW);
glPushMatrix ();
glLoadIdentity ();
glMatrixMode (GL_PROJECTION);
glPushMatrix();
glLoadIdentity ();
glOrtho (0, dest_texture_width, 0, dest_texture_height, -1., 1.);
/* Draw */
dest_box = &tower->invalid[level];
if (texture_is_rectangle (source_texture))
{
source_box.x1 = 2 * dest_box->x1;
source_box.y1 = 2 * dest_box->y1;
source_box.x2 = 2 * dest_box->x2;
source_box.y2 = 2 * dest_box->y2;
}
else
{
source_box.x1 = (2. * dest_box->x1) / source_texture_width;
source_box.y1 = (2. * dest_box->y1) / source_texture_height;
source_box.x2 = (2. * dest_box->x2) / source_texture_width;
source_box.y2 = (2. * dest_box->y2) / source_texture_height;
}
glColor3f (0., 1., 1.);
glBegin (GL_QUADS);
glTexCoord2f (source_box.x1, source_box.y1);
glVertex2f (dest_box->x1, dest_box->y1);
glTexCoord2f (source_box.x2, source_box.y1);
glVertex2f (dest_box->x2, dest_box->y1);
glTexCoord2f (source_box.x2, source_box.y2);
glVertex2f (dest_box->x2, dest_box->y2);
glTexCoord2f (source_box.x1, source_box.y2);
glVertex2f (dest_box->x1, dest_box->y2);
glEnd ();
/* And restore everything back the way we found it */
glMatrixMode (GL_PROJECTION);
glPopMatrix ();
glMatrixMode (GL_MODELVIEW);
glPopMatrix ();
glPopAttrib ();
(*bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
return TRUE;
}
#endif
static void
fill_copy (guchar *buf,
@ -670,8 +495,8 @@ fill_scale_down (guchar *buf,
}
static void
texture_tower_revalidate_client (MutterTextureTower *tower,
int level)
texture_tower_revalidate_client (MetaTextureTower *tower,
int level)
{
CoglHandle source_texture = tower->textures[level - 1];
int source_texture_width = cogl_texture_get_width (source_texture);
@ -770,16 +595,16 @@ texture_tower_revalidate_client (MutterTextureTower *tower,
}
static void
texture_tower_revalidate (MutterTextureTower *tower,
int level)
texture_tower_revalidate (MetaTextureTower *tower,
int level)
{
if (!texture_tower_revalidate_fbo (tower, level))
texture_tower_revalidate_client (tower, level);
}
/**
* mutter_texture_tower_get_paint_texture:
* @tower: a MutterTextureTower
* meta_texture_tower_get_paint_texture:
* @tower: a MetaTextureTower
*
* Gets the texture from the tower that best matches the current
* rendering scale. (On the assumption here the texture is going to
@ -791,7 +616,7 @@ texture_tower_revalidate (MutterTextureTower *tower,
* %COGL_INVALID_HANDLE if no base texture has yet been set.
*/
CoglHandle
mutter_texture_tower_get_paint_texture (MutterTextureTower *tower)
meta_texture_tower_get_paint_texture (MetaTextureTower *tower)
{
int texture_width, texture_height;
int level;

View File

@ -1,6 +1,6 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MutterTextureTower
* MetaTextureTower
*
* Mipmap emulation by creation of scaled down images
*
@ -22,18 +22,18 @@
* 02111-1307, USA.
*/
#ifndef __MUTTER_TEXTURE_TOWER_H__
#define __MUTTER_TEXTURE_TOWER_H__
#ifndef __META_TEXTURE_TOWER_H__
#define __META_TEXTURE_TOWER_H__
#include <clutter/clutter.h>
G_BEGIN_DECLS
/**
* SECTION:MutterTextureTower
* SECTION:MetaTextureTower
* @short_description: mipmap emulation by creation of scaled down images
*
* A #MutterTextureTower is used to get good looking scaled down images when
* A #MetaTextureTower is used to get good looking scaled down images when
* we can't use the GL drivers mipmap support. There are two separate reasons
*
* - Some cards (including radeon cards <= r5xx) only support
@ -51,19 +51,19 @@ G_BEGIN_DECLS
* scale for the entire texture.)
*/
typedef struct _MutterTextureTower MutterTextureTower;
typedef struct _MetaTextureTower MetaTextureTower;
MutterTextureTower *mutter_texture_tower_new (void);
void mutter_texture_tower_free (MutterTextureTower *tower);
void mutter_texture_tower_set_base_texture (MutterTextureTower *tower,
CoglHandle texture);
void mutter_texture_tower_update_area (MutterTextureTower *tower,
int x,
int y,
int width,
int height);
CoglHandle mutter_texture_tower_get_paint_texture (MutterTextureTower *tower);
MetaTextureTower *meta_texture_tower_new (void);
void meta_texture_tower_free (MetaTextureTower *tower);
void meta_texture_tower_set_base_texture (MetaTextureTower *tower,
CoglHandle texture);
void meta_texture_tower_update_area (MetaTextureTower *tower,
int x,
int y,
int width,
int height);
CoglHandle meta_texture_tower_get_paint_texture (MetaTextureTower *tower);
G_BEGIN_DECLS
#endif /* __MUTTER_TEXTURE_TOWER_H__ */
#endif /* __META_TEXTURE_TOWER_H__ */

View File

@ -0,0 +1,53 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef META_WINDOW_ACTOR_PRIVATE_H
#define META_WINDOW_ACTOR_PRIVATE_H
#include <config.h>
#include <X11/extensions/Xdamage.h>
#include "compositor-mutter.h"
MetaWindowActor *meta_window_actor_new (MetaWindow *window);
void meta_window_actor_destroy (MetaWindowActor *self);
void meta_window_actor_show (MetaWindowActor *self,
MetaCompEffect effect);
void meta_window_actor_hide (MetaWindowActor *self,
MetaCompEffect effect);
void meta_window_actor_maximize (MetaWindowActor *self,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
void meta_window_actor_unmaximize (MetaWindowActor *self,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
void meta_window_actor_process_damage (MetaWindowActor *self,
XDamageNotifyEvent *event);
void meta_window_actor_pre_paint (MetaWindowActor *self);
void meta_window_actor_invalidate_shadow (MetaWindowActor *self);
gboolean meta_window_actor_effect_in_progress (MetaWindowActor *self);
void meta_window_actor_sync_actor_position (MetaWindowActor *self);
void meta_window_actor_sync_visibility (MetaWindowActor *self);
void meta_window_actor_update_shape (MetaWindowActor *self,
gboolean shaped);
void meta_window_actor_update_opacity (MetaWindowActor *self);
void meta_window_actor_mapped (MetaWindowActor *self);
void meta_window_actor_unmapped (MetaWindowActor *self);
cairo_region_t *meta_window_actor_get_obscured_region (MetaWindowActor *self);
void meta_window_actor_set_visible_region (MetaWindowActor *self,
cairo_region_t *visible_region);
void meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
cairo_region_t *beneath_region);
void meta_window_actor_reset_visible_regions (MetaWindowActor *self);
void meta_window_actor_effect_completed (MetaWindowActor *actor,
gulong event);
#endif /* META_WINDOW_ACTOR_PRIVATE_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +1,29 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#include <config.h>
#define _ISOC99_SOURCE /* for roundf */
#include <math.h>
#include "mutter-window-private.h"
#include "mutter-window-group.h"
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
struct _MutterWindowGroupClass
#include "meta-window-actor-private.h"
#include "meta-window-group.h"
#include "meta-background-actor.h"
struct _MetaWindowGroupClass
{
ClutterGroupClass parent_class;
};
struct _MutterWindowGroup
struct _MetaWindowGroup
{
ClutterGroup parent;
MetaScreen *screen;
};
G_DEFINE_TYPE (MutterWindowGroup, mutter_window_group, CLUTTER_TYPE_GROUP);
G_DEFINE_TYPE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_GROUP);
/* We want to find out if the window is "close enough" to
* 1:1 transform. We do that by converting the transformed coordinates
@ -96,11 +101,13 @@ actor_is_untransformed (ClutterActor *actor,
}
static void
mutter_window_group_paint (ClutterActor *actor)
meta_window_group_paint (ClutterActor *actor)
{
MutterWindowGroup *window_group = MUTTER_WINDOW_GROUP (actor);
GdkRegion *visible_region;
GdkRectangle screen_rect = { 0 };
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
cairo_region_t *visible_region;
GLboolean scissor_test;
cairo_rectangle_int_t screen_rect = { 0 };
cairo_rectangle_int_t scissor_rect;
GList *children, *l;
/* We walk the list from top to bottom (opposite of painting order),
@ -116,77 +123,113 @@ mutter_window_group_paint (ClutterActor *actor)
* optimization, however.)
*/
meta_screen_get_size (window_group->screen, &screen_rect.width, &screen_rect.height);
visible_region = gdk_region_rectangle (&screen_rect);
/* When doing a partial stage paint, Clutter will set the GL scissor
* box to the clip rectangle for the partial repaint. We combine the screen
* rectangle with the scissor box to get the region we need to
* paint. (Strangely, the scissor box sometimes seems to be bigger
* than the stage ... Clutter should probably be clampimg)
*/
glGetBooleanv (GL_SCISSOR_TEST, &scissor_test);
if (scissor_test)
{
GLint scissor_box[4];
glGetIntegerv (GL_SCISSOR_BOX, scissor_box);
scissor_rect.x = scissor_box[0];
scissor_rect.y = screen_rect.height - (scissor_box[1] + scissor_box[3]);
scissor_rect.width = scissor_box[2];
scissor_rect.height = scissor_box[3];
gdk_rectangle_intersect (&scissor_rect, &screen_rect, &scissor_rect);
}
else
{
scissor_rect = screen_rect;
}
visible_region = cairo_region_create_rectangle (&scissor_rect);
for (l = children; l; l = l->next)
{
MutterWindow *cw;
gboolean x, y;
if (!MUTTER_IS_WINDOW (l->data) || !CLUTTER_ACTOR_IS_VISIBLE (l->data))
if (!CLUTTER_ACTOR_IS_VISIBLE (l->data))
continue;
cw = l->data;
if (!actor_is_untransformed (CLUTTER_ACTOR (cw), &x, &y))
continue;
/* Temporarily move to the coordinate system of the actor */
gdk_region_offset (visible_region, - x, - y);
mutter_window_set_visible_region (cw, visible_region);
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (cw)) == 0xff)
if (META_IS_WINDOW_ACTOR (l->data))
{
GdkRegion *obscured_region = mutter_window_get_obscured_region (cw);
if (obscured_region)
gdk_region_subtract (visible_region, obscured_region);
}
MetaWindowActor *window_actor = l->data;
gboolean x, y;
mutter_window_set_visible_region_beneath (cw, visible_region);
gdk_region_offset (visible_region, x, y);
if (!actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
continue;
/* Temporarily move to the coordinate system of the actor */
cairo_region_translate (visible_region, - x, - y);
meta_window_actor_set_visible_region (window_actor, visible_region);
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
{
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
if (obscured_region)
cairo_region_subtract (visible_region, obscured_region);
}
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))
{
MetaBackgroundActor *background_actor = l->data;
meta_background_actor_set_visible_region (background_actor, visible_region);
}
}
gdk_region_destroy (visible_region);
cairo_region_destroy (visible_region);
CLUTTER_ACTOR_CLASS (mutter_window_group_parent_class)->paint (actor);
CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
/* Now that we are done painting, unset the visible regions (they will
* mess up painting clones of our actors)
*/
for (l = children; l; l = l->next)
{
MutterWindow *cw;
if (!MUTTER_IS_WINDOW (l->data))
continue;
cw = l->data;
mutter_window_reset_visible_regions (cw);
if (META_IS_WINDOW_ACTOR (l->data))
{
MetaWindowActor *window_actor = l->data;
window_actor = l->data;
meta_window_actor_reset_visible_regions (window_actor);
}
else if (META_IS_BACKGROUND_ACTOR (l->data))
{
MetaBackgroundActor *background_actor = l->data;
meta_background_actor_set_visible_region (background_actor, NULL);
}
}
g_list_free (children);
}
static void
mutter_window_group_class_init (MutterWindowGroupClass *klass)
meta_window_group_class_init (MetaWindowGroupClass *klass)
{
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
actor_class->paint = mutter_window_group_paint;
actor_class->paint = meta_window_group_paint;
}
static void
mutter_window_group_init (MutterWindowGroup *window_group)
meta_window_group_init (MetaWindowGroup *window_group)
{
}
ClutterActor *
mutter_window_group_new (MetaScreen *screen)
meta_window_group_new (MetaScreen *screen)
{
MutterWindowGroup *window_group;
MetaWindowGroup *window_group;
window_group = g_object_new (MUTTER_TYPE_WINDOW_GROUP, NULL);
window_group = g_object_new (META_TYPE_WINDOW_GROUP, NULL);
window_group->screen = screen;

View File

@ -1,17 +1,17 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef MUTTER_WINDOW_GROUP_H
#define MUTTER_WINDOW_GROUP_H
#ifndef META_WINDOW_GROUP_H
#define META_WINDOW_GROUP_H
#include <clutter/clutter.h>
#include "screen.h"
/**
* MutterWindowGroup:
* MetaWindowGroup:
*
* This class is a subclass of ClutterGroup with special handling for
* MutterWindow when painting the group. When we are painting a stack
* MetaWindowActor when painting the group. When we are painting a stack
* of 5-10 maximized windows, the standard bottom-to-top method of
* drawing every actor results in a tremendous amount of overdraw
* and can easily max out the available memory bandwidth on a low-end
@ -21,7 +21,7 @@
* The basic technique applied here is to do a pre-pass before painting
* where we walk window from top to bottom and compute the visible area
* at each step by subtracting out the windows above it. The visible
* area is passed to MutterWindow which uses it to clip the portion of
* area is passed to MetaWindowActor which uses it to clip the portion of
* the window which drawn and avoid redrawing the shadow if it is completely
* obscured.
*
@ -34,19 +34,19 @@
* we have lots of memory and bandwidth.)
*/
#define MUTTER_TYPE_WINDOW_GROUP (mutter_window_group_get_type ())
#define MUTTER_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_WINDOW_GROUP, MutterWindowGroup))
#define MUTTER_WINDOW_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_WINDOW_GROUP, MutterWindowGroupClass))
#define MUTTER_IS_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_TYPE_WINDOW_GROUP))
#define MUTTER_IS_WINDOW_GROU_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_WINDOW_GROUP))
#define MUTTER_WINDOW_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_WINDOW_GROUP, MutterWindowGroupClass))
#define META_TYPE_WINDOW_GROUP (meta_window_group_get_type ())
#define META_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_WINDOW_GROUP, MetaWindowGroup))
#define META_WINDOW_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_WINDOW_GROUP, MetaWindowGroupClass))
#define META_IS_WINDOW_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_WINDOW_GROUP))
#define META_IS_WINDOW_GROUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_WINDOW_GROUP))
#define META_WINDOW_GROUP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_WINDOW_GROUP, MetaWindowGroupClass))
typedef struct _MutterWindowGroup MutterWindowGroup;
typedef struct _MutterWindowGroupClass MutterWindowGroupClass;
typedef struct _MutterWindowGroupPrivate MutterWindowGroupPrivate;
typedef struct _MetaWindowGroup MetaWindowGroup;
typedef struct _MetaWindowGroupClass MetaWindowGroupClass;
typedef struct _MetaWindowGroupPrivate MetaWindowGroupPrivate;
GType mutter_window_group_get_type (void);
GType meta_window_group_get_type (void);
ClutterActor *mutter_window_group_new (MetaScreen *screen);
ClutterActor *meta_window_group_new (MetaScreen *screen);
#endif /* MUTTER_WINDOW_GROUP_H */
#endif /* META_WINDOW_GROUP_H */

View File

@ -0,0 +1,254 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MetaWindowShape
*
* Extracted invariant window shape
*
* Copyright (C) 2010 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 <string.h>
#include "meta-window-shape.h"
#include "region-utils.h"
struct _MetaWindowShape
{
guint ref_count;
int top, right, bottom, left;
int n_rectangles;
cairo_rectangle_int_t *rectangles;
guint hash;
};
MetaWindowShape *
meta_window_shape_new (cairo_region_t *region)
{
MetaWindowShape *shape;
MetaRegionIterator iter;
cairo_rectangle_int_t extents;
int max_yspan_y1 = 0;
int max_yspan_y2 = 0;
int max_xspan_x1 = -1;
int max_xspan_x2 = -1;
guint hash;
shape = g_slice_new0 (MetaWindowShape);
shape->ref_count = 1;
cairo_region_get_extents (region, &extents);
shape->n_rectangles = cairo_region_num_rectangles (region);
if (shape->n_rectangles == 0)
{
shape->rectangles = NULL;
shape->top = shape->right = shape->bottom = shape->left = 0;
shape->hash = 0;
return shape;
}
for (meta_region_iterator_init (&iter, region);
!meta_region_iterator_at_end (&iter);
meta_region_iterator_next (&iter))
{
int max_line_xspan_x1 = -1;
int max_line_xspan_x2 = -1;
if (iter.rectangle.width > max_line_xspan_x2 - max_line_xspan_x1)
{
max_line_xspan_x1 = iter.rectangle.x;
max_line_xspan_x2 = iter.rectangle.x + iter.rectangle.width;
}
if (iter.line_end)
{
if (iter.rectangle.height > max_yspan_y2 - max_yspan_y1)
{
max_yspan_y1 = iter.rectangle.y;
max_yspan_y2 = iter.rectangle.y + iter.rectangle.height;
}
if (max_xspan_x1 < 0) /* First line */
{
max_xspan_x1 = max_line_xspan_x1;
max_xspan_x2 = max_line_xspan_x2;
}
else
{
max_xspan_x1 = MAX (max_xspan_x1, max_line_xspan_x1);
max_xspan_x2 = MIN (max_xspan_x2, max_line_xspan_x2);
if (max_xspan_x2 < max_xspan_x1)
max_xspan_x2 = max_xspan_x1;
}
}
}
#if 0
g_print ("xspan: %d -> %d, yspan: %d -> %d\n",
max_xspan_x1, max_xspan_x2,
max_yspan_y1, max_yspan_y2);
#endif
shape->top = max_yspan_y1 - extents.y;
shape->right = extents.x + extents.width - max_xspan_x2;
shape->bottom = extents.y + extents.height - max_yspan_y2;
shape->left = max_xspan_x1 - extents.x;
shape->rectangles = g_new (cairo_rectangle_int_t, shape->n_rectangles);
hash = 0;
for (meta_region_iterator_init (&iter, region);
!meta_region_iterator_at_end (&iter);
meta_region_iterator_next (&iter))
{
int x1, x2, y1, y2;
x1 = iter.rectangle.x;
x2 = iter.rectangle.x + iter.rectangle.width;
y1 = iter.rectangle.y;
y2 = iter.rectangle.y + iter.rectangle.height;
if (x1 > max_xspan_x1)
x1 -= MIN (x1, max_xspan_x2 - 1) - max_xspan_x1;
if (x2 > max_xspan_x1)
x2 -= MIN (x2, max_xspan_x2 - 1) - max_xspan_x1;
if (y1 > max_yspan_y1)
y1 -= MIN (y1, max_yspan_y2 - 1) - max_yspan_y1;
if (y2 > max_yspan_y1)
y2 -= MIN (y2, max_yspan_y2 - 1) - max_yspan_y1;
shape->rectangles[iter.i].x = x1 - extents.x;
shape->rectangles[iter.i].y = y1 - extents.y;
shape->rectangles[iter.i].width = x2 - x1;
shape->rectangles[iter.i].height = y2 - y1;
#if 0
g_print ("%d: +%d+%dx%dx%d => +%d+%dx%dx%d\n",
iter.i, iter.rectangle.x, iter.rectangle.y, iter.rectangle.width, iter.rectangle.height,
shape->rectangles[iter.i].x, shape->rectangles[iter.i].y,
hape->rectangles[iter.i].width, shape->rectangles[iter.i].height);
#endif
hash = hash * 31 + x1 * 17 + x2 * 27 + y1 * 37 + y2 * 43;
}
shape->hash = hash;
#if 0
g_print ("%d %d %d %d: %#x\n\n", shape->top, shape->right, shape->bottom, shape->left, shape->hash);
#endif
return shape;
}
MetaWindowShape *
meta_window_shape_ref (MetaWindowShape *shape)
{
shape->ref_count++;
return shape;
}
void
meta_window_shape_unref (MetaWindowShape *shape)
{
shape->ref_count--;
if (shape->ref_count == 0)
{
g_free (shape->rectangles);
g_slice_free (MetaWindowShape, shape);
}
}
guint
meta_window_shape_hash (MetaWindowShape *shape)
{
return shape->hash;
}
gboolean
meta_window_shape_equal (MetaWindowShape *shape_a,
MetaWindowShape *shape_b)
{
if (shape_a->n_rectangles != shape_b->n_rectangles)
return FALSE;
return memcmp (shape_a->rectangles, shape_b->rectangles,
sizeof (cairo_rectangle_int_t) * shape_a->n_rectangles) == 0;
}
void
meta_window_shape_get_borders (MetaWindowShape *shape,
int *border_top,
int *border_right,
int *border_bottom,
int *border_left)
{
if (border_top)
*border_top = shape->top;
if (border_right)
*border_right = shape->right;
if (border_bottom)
*border_bottom = shape->bottom;
if (border_left)
*border_left = shape->left;
}
/**
* meta_window_shape_to_region:
* @shape: a #MetaWindowShape
* @center_width: size of the central region horizontally
* @center_height: size of the central region vertically
*
* Converts the shape to to a cairo_region_t using the given width
* and height for the central scaled region.
*
* Return value: a newly created region
*/
cairo_region_t *
meta_window_shape_to_region (MetaWindowShape *shape,
int center_width,
int center_height)
{
cairo_region_t *region;
int i;
region = cairo_region_create ();
for (i = 0; i < shape->n_rectangles; i++)
{
cairo_rectangle_int_t rect = shape->rectangles[i];
if (rect.x <= shape->left && rect.x + rect.width >= shape->left + 1)
rect.width += center_width;
else if (rect.x >= shape->left + 1)
rect.x += center_width;
if (rect.y <= shape->top && rect.y + rect.height >= shape->top + 1)
rect.height += center_height;
else if (rect.y >= shape->top + 1)
rect.y += center_height;
cairo_region_union_rectangle (region, &rect);
}
return region;
}

View File

@ -0,0 +1,60 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MetaWindowShape
*
* Extracted invariant window shape
*
* Copyright (C) 2010 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_WINDOW_SHAPE_H__
#define __META_WINDOW_SHAPE_H__
#include <cairo.h>
#include <glib.h>
/**
* MetaWindowShape:
* #MetaWindowShape represents a 9-sliced region with borders on all sides that
* are unscaled, and a constant central region that is scaled. For example,
* the regions representing two windows that are rounded rectangles,
* with the same corner radius but different sizes, have the
* same MetaWindowShape.
*
* #MetaWindowShape is designed to be used as part of a hash table key, so has
* efficient hash and equal functions.
*/
typedef struct _MetaWindowShape MetaWindowShape;
MetaWindowShape * meta_window_shape_new (cairo_region_t *region);
MetaWindowShape * meta_window_shape_ref (MetaWindowShape *shape);
void meta_window_shape_unref (MetaWindowShape *shape);
guint meta_window_shape_hash (MetaWindowShape *shape);
gboolean meta_window_shape_equal (MetaWindowShape *shape_a,
MetaWindowShape *shape_b);
void meta_window_shape_get_borders (MetaWindowShape *shape,
int *border_top,
int *border_right,
int *border_bottom,
int *border_left);
cairo_region_t *meta_window_shape_to_region (MetaWindowShape *shape,
int center_width,
int center_height);
#endif /* __META_WINDOW_SHAPE_H __*/

View File

@ -1,63 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (c) 2008 Intel Corp.
*
* Author: Tomas Frydrych <tf@linux.intel.com>
*
* 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 MUTTER_PLUGIN_MANAGER_H_
#define MUTTER_PLUGIN_MANAGER_H_
#include "types.h"
#include "screen.h"
#define MUTTER_PLUGIN_FROM_MANAGER_
#include "mutter-plugin.h"
#undef MUTTER_PLUGIN_FROM_MANAGER_
typedef struct MutterPluginManager MutterPluginManager;
MutterPluginManager * mutter_plugin_manager_new (MetaScreen *screen);
gboolean mutter_plugin_manager_load (MutterPluginManager *mgr);
gboolean mutter_plugin_manager_initialize (MutterPluginManager *plugin_mgr);
gboolean mutter_plugin_manager_event_simple (MutterPluginManager *mgr,
MutterWindow *actor,
unsigned long event);
gboolean mutter_plugin_manager_event_maximize (MutterPluginManager *mgr,
MutterWindow *actor,
unsigned long event,
gint target_x,
gint target_y,
gint target_width,
gint target_height);
void mutter_plugin_manager_update_workspaces (MutterPluginManager *mgr);
void mutter_plugin_manager_update_workspace (MutterPluginManager *mgr, MetaWorkspace *w);
gboolean mutter_plugin_manager_switch_workspace (MutterPluginManager *mgr,
const GList **actors,
gint from,
gint to,
MetaMotionDirection direction);
gboolean mutter_plugin_manager_xevent_filter (MutterPluginManager *mgr,
XEvent *xev);
#endif

View File

@ -1,101 +0,0 @@
/*
* shaped texture
*
* An actor to draw a texture clipped to a list of rectangles
*
* Authored By Neil Roberts <neil@linux.intel.com>
*
* Copyright (C) 2008 Intel Corporation
*
* 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 __MUTTER_SHAPED_TEXTURE_H__
#define __MUTTER_SHAPED_TEXTURE_H__
#include <clutter/clutter.h>
#ifdef HAVE_GLX_TEXTURE_PIXMAP
#include <clutter/glx/clutter-glx.h>
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
#include <gdk/gdkregion.h>
G_BEGIN_DECLS
#define MUTTER_TYPE_SHAPED_TEXTURE \
(mutter_shaped_texture_get_type())
#define MUTTER_SHAPED_TEXTURE(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
MUTTER_TYPE_SHAPED_TEXTURE, \
MutterShapedTexture))
#define MUTTER_SHAPED_TEXTURE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST ((klass), \
MUTTER_TYPE_SHAPED_TEXTURE, \
MutterShapedTextureClass))
#define MUTTER_IS_SHAPED_TEXTURE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), \
MUTTER_TYPE_SHAPED_TEXTURE))
#define MUTTER_IS_SHAPED_TEXTURE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), \
MUTTER_TYPE_SHAPED_TEXTURE))
#define MUTTER_SHAPED_TEXTURE_GET_CLASS(obj) \
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
MUTTER_TYPE_SHAPED_TEXTURE, \
MutterShapedTextureClass))
typedef struct _MutterShapedTexture MutterShapedTexture;
typedef struct _MutterShapedTextureClass MutterShapedTextureClass;
typedef struct _MutterShapedTexturePrivate MutterShapedTexturePrivate;
struct _MutterShapedTextureClass
{
#ifdef HAVE_GLX_TEXTURE_PIXMAP
ClutterGLXTexturePixmapClass parent_class;
#else
ClutterX11TexturePixmapClass parent_class;
#endif
};
struct _MutterShapedTexture
{
#ifdef HAVE_GLX_TEXTURE_PIXMAP
ClutterGLXTexturePixmap parent;
#else
ClutterX11TexturePixmap parent;
#endif
MutterShapedTexturePrivate *priv;
};
GType mutter_shaped_texture_get_type (void) G_GNUC_CONST;
ClutterActor *mutter_shaped_texture_new (void);
void mutter_shaped_texture_clear_rectangles (MutterShapedTexture *stex);
void mutter_shaped_texture_add_rectangle (MutterShapedTexture *stex,
const XRectangle *rect);
void mutter_shaped_texture_add_rectangles (MutterShapedTexture *stex,
size_t num_rects,
const XRectangle *rects);
/* Assumes ownership of clip_region */
void mutter_shaped_texture_set_clip_region (MutterShapedTexture *stex,
GdkRegion *clip_region);
G_END_DECLS
#endif /* __MUTTER_SHAPED_TEXTURE_H__ */

View File

@ -1,51 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#ifndef MUTTER_WINDOW_PRIVATE_H
#define MUTTER_WINDOW_PRIVATE_H
#include <X11/extensions/Xdamage.h>
#include <gdk/gdk.h>
#include "compositor-mutter.h"
MutterWindow *mutter_window_new (MetaWindow *window);
void mutter_window_destroy (MutterWindow *cw);
void mutter_window_show (MutterWindow *cw,
MetaCompEffect effect);
void mutter_window_hide (MutterWindow *cw,
MetaCompEffect effect);
void mutter_window_maximize (MutterWindow *cw,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
void mutter_window_unmaximize (MutterWindow *cw,
MetaRectangle *old_rect,
MetaRectangle *new_rect);
void mutter_window_process_damage (MutterWindow *cw,
XDamageNotifyEvent *event);
void mutter_window_pre_paint (MutterWindow *self);
gboolean mutter_window_effect_in_progress (MutterWindow *cw);
void mutter_window_sync_actor_position (MutterWindow *cw);
void mutter_window_sync_visibility (MutterWindow *cw);
void mutter_window_update_window_type (MutterWindow *cw);
void mutter_window_update_shape (MutterWindow *cw,
gboolean shaped);
void mutter_window_update_opacity (MutterWindow *cw);
void mutter_window_mapped (MutterWindow *cw);
void mutter_window_unmapped (MutterWindow *cw);
GdkRegion *mutter_window_get_obscured_region (MutterWindow *cw);
void mutter_window_set_visible_region (MutterWindow *cw,
GdkRegion *visible_region);
void mutter_window_set_visible_region_beneath (MutterWindow *cw,
GdkRegion *beneath_region);
void mutter_window_reset_visible_regions (MutterWindow *cw);
void mutter_window_effect_completed (MutterWindow *actor,
gulong event);
#endif /* MUTTER_WINDOW_PRIVATE_H */

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,8 @@
* 02111-1307, USA.
*/
#include "mutter-plugin.h"
#include "meta-plugin.h"
#include "window.h"
#include <libintl.h>
#define _(x) dgettext (GETTEXT_PACKAGE, x)
@ -39,71 +40,78 @@
#define ACTOR_DATA_KEY "MCCP-Default-actor-data"
#define MUTTER_TYPE_DEFAULT_PLUGIN (mutter_default_plugin_get_type ())
#define MUTTER_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPlugin))
#define MUTTER_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginClass))
#define MUTTER_IS_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MUTTER_DEFAULT_PLUGIN_TYPE))
#define MUTTER_IS_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MUTTER_TYPE_DEFAULT_PLUGIN))
#define MUTTER_DEFAULT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginClass))
#define META_TYPE_DEFAULT_PLUGIN (meta_default_plugin_get_type ())
#define META_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPlugin))
#define META_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPluginClass))
#define META_IS_DEFAULT_PLUGIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_DEFAULT_PLUGIN_TYPE))
#define META_IS_DEFAULT_PLUGIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEFAULT_PLUGIN))
#define META_DEFAULT_PLUGIN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPluginClass))
#define MUTTER_DEFAULT_PLUGIN_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_DEFAULT_PLUGIN, MutterDefaultPluginPrivate))
#define META_DEFAULT_PLUGIN_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_DEFAULT_PLUGIN, MetaDefaultPluginPrivate))
typedef struct _MutterDefaultPlugin MutterDefaultPlugin;
typedef struct _MutterDefaultPluginClass MutterDefaultPluginClass;
typedef struct _MutterDefaultPluginPrivate MutterDefaultPluginPrivate;
typedef struct _MetaDefaultPlugin MetaDefaultPlugin;
typedef struct _MetaDefaultPluginClass MetaDefaultPluginClass;
typedef struct _MetaDefaultPluginPrivate MetaDefaultPluginPrivate;
struct _MutterDefaultPlugin
struct _MetaDefaultPlugin
{
MutterPlugin parent;
MetaPlugin parent;
MutterDefaultPluginPrivate *priv;
MetaDefaultPluginPrivate *priv;
};
struct _MutterDefaultPluginClass
struct _MetaDefaultPluginClass
{
MutterPluginClass parent_class;
MetaPluginClass parent_class;
};
static GQuark actor_data_quark = 0;
static void minimize (MutterPlugin *plugin,
MutterWindow *actor);
static void map (MutterPlugin *plugin,
MutterWindow *actor);
static void destroy (MutterPlugin *plugin,
MutterWindow *actor);
static void maximize (MutterPlugin *plugin,
MutterWindow *actor,
gint x, gint y, gint width, gint height);
static void unmaximize (MutterPlugin *plugin,
MutterWindow *actor,
gint x, gint y, gint width, gint height);
static void minimize (MetaPlugin *plugin,
MetaWindowActor *actor);
static void map (MetaPlugin *plugin,
MetaWindowActor *actor);
static void destroy (MetaPlugin *plugin,
MetaWindowActor *actor);
static void maximize (MetaPlugin *plugin,
MetaWindowActor *actor,
gint x,
gint y,
gint width,
gint height);
static void unmaximize (MetaPlugin *plugin,
MetaWindowActor *actor,
gint x,
gint y,
gint width,
gint height);
static void switch_workspace (MutterPlugin *plugin,
const GList **actors, gint from, gint to,
MetaMotionDirection direction);
static void switch_workspace (MetaPlugin *plugin,
gint from,
gint to,
MetaMotionDirection direction);
static void kill_effect (MutterPlugin *plugin,
MutterWindow *actor, gulong event);
static void kill_window_effects (MetaPlugin *plugin,
MetaWindowActor *actor);
static void kill_switch_workspace (MetaPlugin *plugin);
static const MutterPluginInfo * plugin_info (MutterPlugin *plugin);
static const MetaPluginInfo * plugin_info (MetaPlugin *plugin);
MUTTER_PLUGIN_DECLARE(MutterDefaultPlugin, mutter_default_plugin);
META_PLUGIN_DECLARE(MetaDefaultPlugin, meta_default_plugin);
/*
* Plugin private data that we store in the .plugin_private member.
*/
struct _MutterDefaultPluginPrivate
struct _MetaDefaultPluginPrivate
{
/* Valid only when switch_workspace effect is in progress */
ClutterTimeline *tml_switch_workspace1;
ClutterTimeline *tml_switch_workspace2;
GList **actors;
ClutterActor *desktop1;
ClutterActor *desktop2;
MutterPluginInfo info;
MetaPluginInfo info;
gboolean debug_mode : 1;
};
@ -128,26 +136,26 @@ typedef struct _ActorPrivate
typedef struct
{
ClutterActor *actor;
MutterPlugin *plugin;
MetaPlugin *plugin;
} EffectCompleteData;
static void
mutter_default_plugin_dispose (GObject *object)
meta_default_plugin_dispose (GObject *object)
{
/* MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (object)->priv;
/* MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (object)->priv;
*/
G_OBJECT_CLASS (mutter_default_plugin_parent_class)->dispose (object);
G_OBJECT_CLASS (meta_default_plugin_parent_class)->dispose (object);
}
static void
mutter_default_plugin_finalize (GObject *object)
meta_default_plugin_finalize (GObject *object)
{
G_OBJECT_CLASS (mutter_default_plugin_parent_class)->finalize (object);
G_OBJECT_CLASS (meta_default_plugin_parent_class)->finalize (object);
}
static void
mutter_default_plugin_set_property (GObject *object,
meta_default_plugin_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
@ -161,7 +169,7 @@ mutter_default_plugin_set_property (GObject *object,
}
static void
mutter_default_plugin_get_property (GObject *object,
meta_default_plugin_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
@ -175,10 +183,9 @@ mutter_default_plugin_get_property (GObject *object,
}
static void
mutter_default_plugin_constructed (GObject *object)
start (MetaPlugin *plugin)
{
MutterPlugin *plugin = MUTTER_PLUGIN (object);
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (object)->priv;
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
guint destroy_timeout = DESTROY_TIMEOUT;
guint minimize_timeout = MINIMIZE_TIMEOUT;
@ -186,7 +193,7 @@ mutter_default_plugin_constructed (GObject *object)
guint map_timeout = MAP_TIMEOUT;
guint switch_timeout = SWITCH_TIMEOUT;
if (mutter_plugin_debug_mode (plugin))
if (meta_plugin_debug_mode (plugin))
{
g_debug ("Plugin %s: Entering debug mode.", priv->info.name);
@ -201,39 +208,39 @@ mutter_default_plugin_constructed (GObject *object)
map_timeout *= 2;
switch_timeout *= 2;
}
}
static void
mutter_default_plugin_class_init (MutterDefaultPluginClass *klass)
meta_default_plugin_class_init (MetaDefaultPluginClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
MutterPluginClass *plugin_class = MUTTER_PLUGIN_CLASS (klass);
MetaPluginClass *plugin_class = META_PLUGIN_CLASS (klass);
gobject_class->finalize = mutter_default_plugin_finalize;
gobject_class->dispose = mutter_default_plugin_dispose;
gobject_class->constructed = mutter_default_plugin_constructed;
gobject_class->set_property = mutter_default_plugin_set_property;
gobject_class->get_property = mutter_default_plugin_get_property;
gobject_class->finalize = meta_default_plugin_finalize;
gobject_class->dispose = meta_default_plugin_dispose;
gobject_class->set_property = meta_default_plugin_set_property;
gobject_class->get_property = meta_default_plugin_get_property;
plugin_class->start = start;
plugin_class->map = map;
plugin_class->minimize = minimize;
plugin_class->maximize = maximize;
plugin_class->unmaximize = unmaximize;
plugin_class->destroy = destroy;
plugin_class->switch_workspace = switch_workspace;
plugin_class->kill_effect = kill_effect;
plugin_class->plugin_info = plugin_info;
plugin_class->kill_window_effects = kill_window_effects;
plugin_class->kill_switch_workspace = kill_switch_workspace;
g_type_class_add_private (gobject_class, sizeof (MutterDefaultPluginPrivate));
g_type_class_add_private (gobject_class, sizeof (MetaDefaultPluginPrivate));
}
static void
mutter_default_plugin_init (MutterDefaultPlugin *self)
meta_default_plugin_init (MetaDefaultPlugin *self)
{
MutterDefaultPluginPrivate *priv;
MetaDefaultPluginPrivate *priv;
self->priv = priv = MUTTER_DEFAULT_PLUGIN_GET_PRIVATE (self);
self->priv = priv = META_DEFAULT_PLUGIN_GET_PRIVATE (self);
priv->info.name = "Default Effects";
priv->info.version = "0.1";
@ -253,7 +260,7 @@ free_actor_private (gpointer data)
}
static ActorPrivate *
get_actor_private (MutterWindow *actor)
get_actor_private (MetaWindowActor *actor)
{
ActorPrivate *priv = g_object_get_qdata (G_OBJECT (actor), actor_data_quark);
@ -272,26 +279,18 @@ get_actor_private (MutterWindow *actor)
return priv;
}
typedef struct SwitchWorkspaceData
{
MutterPlugin *plugin;
const GList **actors;
} SwitchWorkspaceData;
static void
on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data)
{
SwitchWorkspaceData *sw_data = data;
MutterPlugin *plugin = sw_data->plugin;
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
GList *l = *((GList**)sw_data->actors);
MutterWindow *actor_for_cb = l->data;
MetaPlugin *plugin = META_PLUGIN (data);
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
GList *l = meta_plugin_get_window_actors (plugin);
while (l)
{
ClutterActor *a = l->data;
MutterWindow *mc_window = MUTTER_WINDOW (a);
ActorPrivate *apriv = get_actor_private (mc_window);
MetaWindowActor *window_actor = META_WINDOW_ACTOR (a);
ActorPrivate *apriv = get_actor_private (window_actor);
if (apriv->orig_parent)
{
@ -305,40 +304,32 @@ on_switch_workspace_effect_complete (ClutterTimeline *timeline, gpointer data)
clutter_actor_destroy (priv->desktop1);
clutter_actor_destroy (priv->desktop2);
priv->actors = NULL;
priv->tml_switch_workspace1 = NULL;
priv->tml_switch_workspace2 = NULL;
priv->desktop1 = NULL;
priv->desktop2 = NULL;
g_free (data);
mutter_plugin_effect_completed (plugin, actor_for_cb,
MUTTER_PLUGIN_SWITCH_WORKSPACE);
meta_plugin_switch_workspace_completed (plugin);
}
static void
switch_workspace (MutterPlugin *plugin,
const GList **actors, gint from, gint to,
switch_workspace (MetaPlugin *plugin,
gint from, gint to,
MetaMotionDirection direction)
{
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
GList *l;
gint n_workspaces;
ClutterActor *workspace0 = clutter_group_new ();
ClutterActor *workspace1 = clutter_group_new ();
ClutterActor *stage;
int screen_width, screen_height;
MetaScreen *screen = mutter_plugin_get_screen (plugin);
SwitchWorkspaceData *sw_data = g_new (SwitchWorkspaceData, 1);
MetaScreen *screen = meta_plugin_get_screen (plugin);
ClutterAnimation *animation;
sw_data->plugin = plugin;
sw_data->actors = actors;
stage = meta_plugin_get_stage (plugin);
stage = mutter_plugin_get_stage (plugin);
mutter_plugin_query_screen_size (plugin,
meta_plugin_query_screen_size (plugin,
&screen_width,
&screen_height);
clutter_actor_set_anchor_point (workspace1,
@ -355,32 +346,31 @@ switch_workspace (MutterPlugin *plugin,
if (from == to)
{
mutter_plugin_effect_completed (plugin, NULL,
MUTTER_PLUGIN_SWITCH_WORKSPACE);
meta_plugin_switch_workspace_completed (plugin);
return;
}
n_workspaces = meta_screen_get_n_workspaces (screen);
l = g_list_last (*((GList**) actors));
l = g_list_last (meta_plugin_get_window_actors (plugin));
while (l)
{
MutterWindow *mc_window = l->data;
ActorPrivate *apriv = get_actor_private (mc_window);
ClutterActor *window = CLUTTER_ACTOR (mc_window);
gint win_workspace;
MetaWindowActor *window_actor = l->data;
ActorPrivate *apriv = get_actor_private (window_actor);
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
gint win_workspace;
win_workspace = mutter_window_get_workspace (mc_window);
win_workspace = meta_window_actor_get_workspace (window_actor);
if (win_workspace == to || win_workspace == from)
{
apriv->orig_parent = clutter_actor_get_parent (window);
apriv->orig_parent = clutter_actor_get_parent (actor);
clutter_actor_reparent (window,
clutter_actor_reparent (actor,
win_workspace == to ? workspace1 : workspace0);
clutter_actor_show_all (window);
clutter_actor_raise_top (window);
clutter_actor_show_all (actor);
clutter_actor_raise_top (actor);
}
else if (win_workspace < 0)
{
@ -390,14 +380,13 @@ switch_workspace (MutterPlugin *plugin,
else
{
/* Window on some other desktop */
clutter_actor_hide (window);
clutter_actor_hide (actor);
apriv->orig_parent = NULL;
}
l = l->prev;
}
priv->actors = (GList **)actors;
priv->desktop1 = workspace0;
priv->desktop2 = workspace1;
@ -410,7 +399,7 @@ switch_workspace (MutterPlugin *plugin,
g_signal_connect (priv->tml_switch_workspace1,
"completed",
G_CALLBACK (on_switch_workspace_effect_complete),
sw_data);
plugin);
animation = clutter_actor_animate (workspace1, CLUTTER_EASE_IN_SINE,
SWITCH_TIMEOUT,
@ -432,11 +421,11 @@ on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
* Must reverse the effect of the effect; must hide it first to ensure
* that the restoration will not be visible.
*/
MutterPlugin *plugin = data->plugin;
MetaPlugin *plugin = data->plugin;
ActorPrivate *apriv;
MutterWindow *mc_window = MUTTER_WINDOW (data->actor);
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
apriv = get_actor_private (MUTTER_WINDOW (data->actor));
apriv = get_actor_private (META_WINDOW_ACTOR (data->actor));
apriv->tml_minimize = NULL;
clutter_actor_hide (data->actor);
@ -448,8 +437,7 @@ on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
CLUTTER_GRAVITY_NORTH_WEST);
/* Now notify the manager that we are done with this effect */
mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_MINIMIZE);
meta_plugin_minimize_completed (plugin, window_actor);
g_free (data);
}
@ -459,18 +447,20 @@ on_minimize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
* completion).
*/
static void
minimize (MutterPlugin *plugin, MutterWindow *mc_window)
minimize (MetaPlugin *plugin, MetaWindowActor *window_actor)
{
MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
MetaWindowType type;
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
type = mutter_window_get_window_type (mc_window);
if (type == META_COMP_WINDOW_NORMAL)
type = meta_window_get_window_type (meta_window);
if (type == META_WINDOW_NORMAL)
{
ClutterAnimation *animation;
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
ActorPrivate *apriv = get_actor_private (mc_window);
ActorPrivate *apriv = get_actor_private (window_actor);
apriv->is_minimized = TRUE;
@ -492,8 +482,7 @@ minimize (MutterPlugin *plugin, MutterWindow *mc_window)
}
else
mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_MINIMIZE);
meta_plugin_minimize_completed (plugin, window_actor);
}
/*
@ -506,9 +495,9 @@ on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
/*
* Must reverse the effect of the effect.
*/
MutterPlugin * plugin = data->plugin;
MutterWindow *mc_window = MUTTER_WINDOW (data->actor);
ActorPrivate *apriv = get_actor_private (mc_window);
MetaPlugin *plugin = data->plugin;
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
ActorPrivate *apriv = get_actor_private (window_actor);
apriv->tml_maximize = NULL;
@ -518,8 +507,7 @@ on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
CLUTTER_GRAVITY_NORTH_WEST);
/* Now notify the manager that we are done with this effect */
mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_MAXIMIZE);
meta_plugin_maximize_completed (plugin, window_actor);
g_free (data);
}
@ -533,25 +521,26 @@ on_maximize_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data
* (Something like a sound would be more appropriate.)
*/
static void
maximize (MutterPlugin *plugin,
MutterWindow *mc_window,
maximize (MetaPlugin *plugin,
MetaWindowActor *window_actor,
gint end_x, gint end_y, gint end_width, gint end_height)
{
MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
MetaWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
gdouble scale_x = 1.0;
gdouble scale_y = 1.0;
gfloat anchor_x = 0;
gfloat anchor_y = 0;
type = mutter_window_get_window_type (mc_window);
type = meta_window_get_window_type (meta_window);
if (type == META_COMP_WINDOW_NORMAL)
if (type == META_WINDOW_NORMAL)
{
ClutterAnimation *animation;
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
ActorPrivate *apriv = get_actor_private (mc_window);
ActorPrivate *apriv = get_actor_private (window_actor);
gfloat width, height;
gfloat x, y;
@ -589,8 +578,7 @@ maximize (MutterPlugin *plugin,
return;
}
mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_MAXIMIZE);
meta_plugin_maximize_completed (plugin, window_actor);
}
/*
@ -599,22 +587,22 @@ maximize (MutterPlugin *plugin,
* (Just a skeleton code.)
*/
static void
unmaximize (MutterPlugin *plugin,
MutterWindow *mc_window,
unmaximize (MetaPlugin *plugin,
MetaWindowActor *window_actor,
gint end_x, gint end_y, gint end_width, gint end_height)
{
MetaCompWindowType type = mutter_window_get_window_type (mc_window);
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
MetaWindowType type = meta_window_get_window_type (meta_window);
if (type == META_COMP_WINDOW_NORMAL)
if (type == META_WINDOW_NORMAL)
{
ActorPrivate *apriv = get_actor_private (mc_window);
ActorPrivate *apriv = get_actor_private (window_actor);
apriv->is_maximized = FALSE;
}
/* Do this conditionally, if the effect requires completion callback. */
mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_UNMAXIMIZE);
meta_plugin_unmaximize_completed (plugin, window_actor);
}
static void
@ -623,9 +611,9 @@ on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
/*
* Must reverse the effect of the effect.
*/
MutterPlugin *plugin = data->plugin;
MutterWindow *mc_window = MUTTER_WINDOW (data->actor);
ActorPrivate *apriv = get_actor_private (mc_window);
MetaPlugin *plugin = data->plugin;
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
ActorPrivate *apriv = get_actor_private (window_actor);
apriv->tml_map = NULL;
@ -633,7 +621,7 @@ on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
CLUTTER_GRAVITY_NORTH_WEST);
/* Now notify the manager that we are done with this effect */
mutter_plugin_effect_completed (plugin, mc_window, MUTTER_PLUGIN_MAP);
meta_plugin_map_completed (plugin, window_actor);
g_free (data);
}
@ -643,18 +631,19 @@ on_map_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
* completion).
*/
static void
map (MutterPlugin *plugin, MutterWindow *mc_window)
map (MetaPlugin *plugin, MetaWindowActor *window_actor)
{
MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
MetaWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
type = mutter_window_get_window_type (mc_window);
type = meta_window_get_window_type (meta_window);
if (type == META_COMP_WINDOW_NORMAL)
if (type == META_WINDOW_NORMAL)
{
ClutterAnimation *animation;
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
ActorPrivate *apriv = get_actor_private (mc_window);
ActorPrivate *apriv = get_actor_private (window_actor);
clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_CENTER);
@ -679,8 +668,7 @@ map (MutterPlugin *plugin, MutterWindow *mc_window)
}
else
mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_MAP);
meta_plugin_map_completed (plugin, window_actor);
}
/*
@ -690,32 +678,32 @@ map (MutterPlugin *plugin, MutterWindow *mc_window)
static void
on_destroy_effect_complete (ClutterTimeline *timeline, EffectCompleteData *data)
{
MutterPlugin *plugin = data->plugin;
MutterWindow *mc_window = MUTTER_WINDOW (data->actor);
ActorPrivate *apriv = get_actor_private (mc_window);
MetaPlugin *plugin = data->plugin;
MetaWindowActor *window_actor = META_WINDOW_ACTOR (data->actor);
ActorPrivate *apriv = get_actor_private (window_actor);
apriv->tml_destroy = NULL;
mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_DESTROY);
meta_plugin_destroy_completed (plugin, window_actor);
}
/*
* Simple TV-out like effect.
*/
static void
destroy (MutterPlugin *plugin, MutterWindow *mc_window)
destroy (MetaPlugin *plugin, MetaWindowActor *window_actor)
{
MetaCompWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (mc_window);
MetaWindowType type;
ClutterActor *actor = CLUTTER_ACTOR (window_actor);
MetaWindow *meta_window = meta_window_actor_get_meta_window (window_actor);
type = mutter_window_get_window_type (mc_window);
type = meta_window_get_window_type (meta_window);
if (type == META_COMP_WINDOW_NORMAL)
if (type == META_WINDOW_NORMAL)
{
ClutterAnimation *animation;
EffectCompleteData *data = g_new0 (EffectCompleteData, 1);
ActorPrivate *apriv = get_actor_private (mc_window);
ActorPrivate *apriv = get_actor_private (window_actor);
clutter_actor_move_anchor_point_from_gravity (actor,
CLUTTER_GRAVITY_CENTER);
@ -734,64 +722,59 @@ destroy (MutterPlugin *plugin, MutterWindow *mc_window)
data);
}
else
mutter_plugin_effect_completed (plugin, mc_window,
MUTTER_PLUGIN_DESTROY);
meta_plugin_destroy_completed (plugin, window_actor);
}
static void
kill_effect (MutterPlugin *plugin, MutterWindow *mc_window, gulong event)
kill_switch_workspace (MetaPlugin *plugin)
{
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
if (priv->tml_switch_workspace1)
{
clutter_timeline_stop (priv->tml_switch_workspace1);
clutter_timeline_stop (priv->tml_switch_workspace2);
g_signal_emit_by_name (priv->tml_switch_workspace1, "completed", NULL);
}
}
static void
kill_window_effects (MetaPlugin *plugin,
MetaWindowActor *window_actor)
{
ActorPrivate *apriv;
if (event & MUTTER_PLUGIN_SWITCH_WORKSPACE)
{
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
apriv = get_actor_private (window_actor);
if (priv->tml_switch_workspace1)
{
clutter_timeline_stop (priv->tml_switch_workspace1);
clutter_timeline_stop (priv->tml_switch_workspace2);
g_signal_emit_by_name (priv->tml_switch_workspace1, "completed", NULL);
}
if (!(event & ~MUTTER_PLUGIN_SWITCH_WORKSPACE))
{
/* Workspace switch only, nothing more to do */
return;
}
}
apriv = get_actor_private (mc_window);
if ((event & MUTTER_PLUGIN_MINIMIZE) && apriv->tml_minimize)
if (apriv->tml_minimize)
{
clutter_timeline_stop (apriv->tml_minimize);
g_signal_emit_by_name (apriv->tml_minimize, "completed", NULL);
}
if ((event & MUTTER_PLUGIN_MAXIMIZE) && apriv->tml_maximize)
if (apriv->tml_maximize)
{
clutter_timeline_stop (apriv->tml_maximize);
g_signal_emit_by_name (apriv->tml_maximize, "completed", NULL);
}
if ((event & MUTTER_PLUGIN_MAP) && apriv->tml_map)
if (apriv->tml_map)
{
clutter_timeline_stop (apriv->tml_map);
g_signal_emit_by_name (apriv->tml_map, "completed", NULL);
}
if ((event & MUTTER_PLUGIN_DESTROY) && apriv->tml_destroy)
if (apriv->tml_destroy)
{
clutter_timeline_stop (apriv->tml_destroy);
g_signal_emit_by_name (apriv->tml_destroy, "completed", NULL);
}
}
static const MutterPluginInfo *
plugin_info (MutterPlugin *plugin)
static const MetaPluginInfo *
plugin_info (MetaPlugin *plugin)
{
MutterDefaultPluginPrivate *priv = MUTTER_DEFAULT_PLUGIN (plugin)->priv;
MetaDefaultPluginPrivate *priv = META_DEFAULT_PLUGIN (plugin)->priv;
return &priv->info;
}

View File

@ -0,0 +1,336 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Utilities for region manipulation
*
* Copyright (C) 2010 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 "region-utils.h"
#include <math.h>
/* MetaRegionBuilder */
/* Various algorithms in this file require unioning together a set of rectangles
* that are unsorted or overlap; unioning such a set of rectangles 1-by-1
* using cairo_region_union_rectangle() produces O(N^2) behavior (if the union
* adds or removes rectangles in the middle of the region, then it has to
* move all the rectangles after that.) To avoid this behavior, MetaRegionBuilder
* creates regions for small groups of rectangles and merges them together in
* a binary tree.
*
* Possible improvement: From a glance at the code, accumulating all the rectangles
* into a flat array and then calling the (not usefully documented)
* cairo_region_create_rectangles() would have the same behavior and would be
* simpler and a bit more efficient.
*/
/* Optimium performance seems to be with MAX_CHUNK_RECTANGLES=4; 8 is about 10% slower.
* But using 8 may be more robust to systems with slow malloc(). */
#define MAX_CHUNK_RECTANGLES 8
#define MAX_LEVELS 16
typedef struct
{
/* To merge regions in binary tree order, we need to keep track of
* the regions that we've already merged together at different
* levels of the tree. We fill in an array in the pattern:
*
* |a |
* |b |a |
* |c | |ab |
* |d |c |ab |
* |e | | |abcd|
*/
cairo_region_t *levels[MAX_LEVELS];
int n_levels;
} MetaRegionBuilder;
static void
meta_region_builder_init (MetaRegionBuilder *builder)
{
int i;
for (i = 0; i < MAX_LEVELS; i++)
builder->levels[i] = NULL;
builder->n_levels = 1;
}
static void
meta_region_builder_add_rectangle (MetaRegionBuilder *builder,
int x,
int y,
int width,
int height)
{
cairo_rectangle_int_t rect;
int i;
if (builder->levels[0] == NULL)
builder->levels[0] = cairo_region_create ();
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
cairo_region_union_rectangle (builder->levels[0], &rect);
if (cairo_region_num_rectangles (builder->levels[0]) >= MAX_CHUNK_RECTANGLES)
{
for (i = 1; i < builder->n_levels + 1; i++)
{
if (builder->levels[i] == NULL)
{
if (i < MAX_LEVELS)
{
builder->levels[i] = builder->levels[i - 1];
builder->levels[i - 1] = NULL;
if (i == builder->n_levels)
builder->n_levels++;
}
break;
}
else
{
cairo_region_union (builder->levels[i], builder->levels[i - 1]);
cairo_region_destroy (builder->levels[i - 1]);
builder->levels[i - 1] = NULL;
}
}
}
}
static cairo_region_t *
meta_region_builder_finish (MetaRegionBuilder *builder)
{
cairo_region_t *result = NULL;
int i;
for (i = 0; i < builder->n_levels; i++)
{
if (builder->levels[i])
{
if (result == NULL)
result = builder->levels[i];
else
{
cairo_region_union(result, builder->levels[i]);
cairo_region_destroy (builder->levels[i]);
}
}
}
if (result == NULL)
result = cairo_region_create ();
return result;
}
/* MetaRegionIterator */
void
meta_region_iterator_init (MetaRegionIterator *iter,
cairo_region_t *region)
{
iter->region = region;
iter->i = 0;
iter->n_rectangles = cairo_region_num_rectangles (region);
iter->line_start = TRUE;
if (iter->n_rectangles > 1)
{
cairo_region_get_rectangle (region, 0, &iter->rectangle);
cairo_region_get_rectangle (region, 1, &iter->next_rectangle);
iter->line_end = iter->next_rectangle.y != iter->rectangle.y;
}
else if (iter->n_rectangles > 0)
{
cairo_region_get_rectangle (region, 0, &iter->rectangle);
iter->line_end = TRUE;
}
}
gboolean
meta_region_iterator_at_end (MetaRegionIterator *iter)
{
return iter->i >= iter->n_rectangles;
}
void
meta_region_iterator_next (MetaRegionIterator *iter)
{
iter->i++;
iter->rectangle = iter->next_rectangle;
iter->line_start = iter->line_end;
if (iter->i + 1 < iter->n_rectangles)
{
cairo_region_get_rectangle (iter->region, iter->i + 1, &iter->next_rectangle);
iter->line_end = iter->next_rectangle.y != iter->rectangle.y;
}
else
{
iter->line_end = TRUE;
}
}
static void
add_expanded_rect (MetaRegionBuilder *builder,
int x,
int y,
int width,
int height,
int x_amount,
int y_amount,
gboolean flip)
{
if (flip)
meta_region_builder_add_rectangle (builder,
y - y_amount, x - x_amount,
height + 2 * y_amount, width + 2 * x_amount);
else
meta_region_builder_add_rectangle (builder,
x - x_amount, y - y_amount,
width + 2 * x_amount, height + 2 * y_amount);
}
static cairo_region_t *
expand_region (cairo_region_t *region,
int x_amount,
int y_amount,
gboolean flip)
{
MetaRegionBuilder builder;
int n;
int i;
meta_region_builder_init (&builder);
n = cairo_region_num_rectangles (region);
for (i = 0; i < n; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
add_expanded_rect (&builder,
rect.x, rect.y, rect.width, rect.height,
x_amount, y_amount, flip);
}
return meta_region_builder_finish (&builder);
}
/* This computes a (clipped version) of the inverse of the region
* and expands it by the given amount */
static cairo_region_t *
expand_region_inverse (cairo_region_t *region,
int x_amount,
int y_amount,
gboolean flip)
{
MetaRegionBuilder builder;
MetaRegionIterator iter;
cairo_rectangle_int_t extents;
cairo_region_t *chunk;
int last_x;
meta_region_builder_init (&builder);
cairo_region_get_extents (region, &extents);
add_expanded_rect (&builder,
extents.x, extents.y - 1, extents.width, 1,
x_amount, y_amount, flip);
add_expanded_rect (&builder,
extents.x - 1, extents.y, 1, extents.height,
x_amount, y_amount, flip);
add_expanded_rect (&builder,
extents.x + extents.width, extents.y, 1, extents.height,
x_amount, y_amount, flip);
add_expanded_rect (&builder,
extents.x, extents.y + extents.height, extents.width, 1,
x_amount, y_amount, flip);
chunk = NULL;
last_x = extents.x;
for (meta_region_iterator_init (&iter, region);
!meta_region_iterator_at_end (&iter);
meta_region_iterator_next (&iter))
{
if (chunk == NULL)
chunk = cairo_region_create ();
if (iter.rectangle.x > last_x)
add_expanded_rect (&builder,
last_x, iter.rectangle.y,
iter.rectangle.x - last_x, iter.rectangle.height,
x_amount, y_amount, flip);
if (iter.line_end)
{
if (extents.x + extents.width > iter.rectangle.x + iter.rectangle.width)
add_expanded_rect (&builder,
iter.rectangle.x + iter.rectangle.width, iter.rectangle.y,
(extents.x + extents.width) - (iter.rectangle.x + iter.rectangle.width), iter.rectangle.height,
x_amount, y_amount, flip);
last_x = extents.x;
}
else
last_x = iter.rectangle.x + iter.rectangle.width;
}
return meta_region_builder_finish (&builder);
}
/**
* meta_make_border_region:
* @region: a #cairo_region_t
* @x_amount: distance from the border to extend horizontally
* @y_amount: distance from the border to extend vertically
* @flip: if true, the result is computed with x and y interchanged
*
* Computes the "border region" of a given region, which is roughly
* speaking the set of points near the boundary of the region. If we
* define the operation of growing a region as computing the set of
* points within a given manhattan distance of the region, then the
* border is 'grow(region) intersect grow(inverse(region))'.
*
* If we create an image by filling the region with a solid color,
* the border is the region affected by blurring the region.
*
* Return value: a new region which is the border of the given region
*/
cairo_region_t *
meta_make_border_region (cairo_region_t *region,
int x_amount,
int y_amount,
gboolean flip)
{
cairo_region_t *border_region;
cairo_region_t *inverse_region;
border_region = expand_region (region, x_amount, y_amount, flip);
inverse_region = expand_region_inverse (region, x_amount, y_amount, flip);
cairo_region_intersect (border_region, inverse_region);
cairo_region_destroy (inverse_region);
return border_region;
}

View File

@ -0,0 +1,76 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Utilities for region manipulation
*
* Copyright (C) 2010 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_REGION_UTILS_H__
#define __META_REGION_UTILS_H__
#include <clutter/clutter.h>
#include <cairo.h>
#include <glib.h>
/**
* MetaRegionIterator:
* @region: region being iterated
* @rectangle: current rectangle
* @line_start: whether the current rectangle starts a horizontal band
* @line_end: whether the current rectangle ends a horizontal band
*
* cairo_region_t is a yx banded region; sometimes its useful to iterate through
* such a region treating the start and end of each horizontal band in a distinct
* fashion.
*
* Usage:
*
* MetaRegionIterator iter;
* for (meta_region_iterator_init (&iter, region);
* !meta_region_iterator_at_end (&iter);
* meta_region_iterator_next (&iter))
* {
* [ Use iter.rectangle, iter.line_start, iter.line_end ]
* }
*/
typedef struct _MetaRegionIterator MetaRegionIterator;
struct _MetaRegionIterator {
cairo_region_t *region;
cairo_rectangle_int_t rectangle;
gboolean line_start;
gboolean line_end;
int i;
/*< private >*/
int n_rectangles;
cairo_rectangle_int_t next_rectangle;
};
void meta_region_iterator_init (MetaRegionIterator *iter,
cairo_region_t *region);
gboolean meta_region_iterator_at_end (MetaRegionIterator *iter);
void meta_region_iterator_next (MetaRegionIterator *iter);
cairo_region_t *meta_make_border_region (cairo_region_t *region,
int x_amount,
int y_amount,
gboolean flip);
#endif /* __META_REGION_UTILS_H__ */

View File

@ -1,350 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#define _GNU_SOURCE /* For M_PI */
#include <math.h>
#include "compositor-private.h"
#include "shadow.h"
#include "tidy/tidy-texture-frame.h"
#define SHADOW_RADIUS 8
#define SHADOW_OPACITY 0.9
#define SHADOW_OFFSET_X (SHADOW_RADIUS)
#define SHADOW_OFFSET_Y (SHADOW_RADIUS)
#define MAX_TILE_SZ 8 /* Must be <= shaddow radius */
#define TILE_WIDTH (3*MAX_TILE_SZ)
#define TILE_HEIGHT (3*MAX_TILE_SZ)
static unsigned char* shadow_gaussian_make_tile (void);
ClutterActor *
mutter_create_shadow_frame (MetaCompositor *compositor)
{
ClutterActor *frame;
if (!compositor->shadow_src)
{
guchar *data;
data = shadow_gaussian_make_tile ();
compositor->shadow_src = clutter_texture_new ();
clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (compositor->shadow_src),
data,
TRUE,
TILE_WIDTH,
TILE_HEIGHT,
TILE_WIDTH*4,
4,
0,
NULL);
g_free (data);
}
frame = tidy_texture_frame_new (CLUTTER_TEXTURE (compositor->shadow_src),
MAX_TILE_SZ,
MAX_TILE_SZ,
MAX_TILE_SZ,
MAX_TILE_SZ);
clutter_actor_set_position (frame,
SHADOW_OFFSET_X , SHADOW_OFFSET_Y);
return frame;
}
typedef struct GaussianMap
{
int size;
double * data;
} GaussianMap;
static double
gaussian (double r, double x, double y)
{
return ((1 / (sqrt (2 * M_PI * r))) *
exp ((- (x * x + y * y)) / (2 * r * r)));
}
static GaussianMap *
make_gaussian_map (double r)
{
GaussianMap *c;
int size = ((int) ceil ((r * 3)) + 1) & ~1;
int center = size / 2;
int x, y;
double t = 0.0;
double g;
c = g_malloc (sizeof (GaussianMap) + size * size * sizeof (double));
c->size = size;
c->data = (double *) (c + 1);
for (y = 0; y < size; y++)
for (x = 0; x < size; x++)
{
g = gaussian (r, (double) (x - center), (double) (y - center));
t += g;
c->data[y * size + x] = g;
}
for (y = 0; y < size; y++)
for (x = 0; x < size; x++)
c->data[y*size + x] /= t;
return c;
}
static unsigned char
sum_gaussian (GaussianMap * map, double opacity,
int x, int y, int width, int height)
{
int fx, fy;
double * g_data;
double * g_line = map->data;
int g_size = map->size;
int center = g_size / 2;
int fx_start, fx_end;
int fy_start, fy_end;
double v;
unsigned int r;
/*
* Compute set of filter values which are "in range",
* that's the set with:
* 0 <= x + (fx-center) && x + (fx-center) < width &&
* 0 <= y + (fy-center) && y + (fy-center) < height
*
* 0 <= x + (fx - center) x + fx - center < width
* center - x <= fx fx < width + center - x
*/
fx_start = center - x;
if (fx_start < 0)
fx_start = 0;
fx_end = width + center - x;
if (fx_end > g_size)
fx_end = g_size;
fy_start = center - y;
if (fy_start < 0)
fy_start = 0;
fy_end = height + center - y;
if (fy_end > g_size)
fy_end = g_size;
g_line = g_line + fy_start * g_size + fx_start;
v = 0;
for (fy = fy_start; fy < fy_end; fy++)
{
g_data = g_line;
g_line += g_size;
for (fx = fx_start; fx < fx_end; fx++)
v += *g_data++;
}
if (v > 1)
v = 1;
v *= (opacity * 255.0);
r = (unsigned int) v;
return (unsigned char) r;
}
static unsigned char *
shadow_gaussian_make_tile ()
{
unsigned char * data;
int size;
int center;
int x, y;
unsigned char d;
int pwidth, pheight;
double opacity = SHADOW_OPACITY;
static GaussianMap * gaussian_map = NULL;
struct _mypixel
{
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
} * _d;
if (!gaussian_map)
gaussian_map =
make_gaussian_map (SHADOW_RADIUS);
size = gaussian_map->size;
center = size / 2;
/* Top & bottom */
pwidth = MAX_TILE_SZ;
pheight = MAX_TILE_SZ;
data = g_malloc0 (4 * TILE_WIDTH * TILE_HEIGHT);
_d = (struct _mypixel*) data;
/* N */
for (y = 0; y < pheight; y++)
{
d = sum_gaussian (gaussian_map, opacity,
center, y - center,
TILE_WIDTH, TILE_HEIGHT);
for (x = 0; x < pwidth; x++)
{
_d[y*3*pwidth + x + pwidth].r = 0;
_d[y*3*pwidth + x + pwidth].g = 0;
_d[y*3*pwidth + x + pwidth].b = 0;
_d[y*3*pwidth + x + pwidth].a = d;
}
}
/* S */
pwidth = MAX_TILE_SZ;
pheight = MAX_TILE_SZ;
for (y = 0; y < pheight; y++)
{
d = sum_gaussian (gaussian_map, opacity,
center, y - center,
TILE_WIDTH, TILE_HEIGHT);
for (x = 0; x < pwidth; x++)
{
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].r = 0;
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].g = 0;
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].b = 0;
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x + pwidth].a = d;
}
}
/* w */
pwidth = MAX_TILE_SZ;
pheight = MAX_TILE_SZ;
for (x = 0; x < pwidth; x++)
{
d = sum_gaussian (gaussian_map, opacity,
x - center, center,
TILE_WIDTH, TILE_HEIGHT);
for (y = 0; y < pheight; y++)
{
_d[y*3*pwidth + 3*pwidth*pheight + x].r = 0;
_d[y*3*pwidth + 3*pwidth*pheight + x].g = 0;
_d[y*3*pwidth + 3*pwidth*pheight + x].b = 0;
_d[y*3*pwidth + 3*pwidth*pheight + x].a = d;
}
}
/* E */
for (x = 0; x < pwidth; x++)
{
d = sum_gaussian (gaussian_map, opacity,
x - center, center,
TILE_WIDTH, TILE_HEIGHT);
for (y = 0; y < pheight; y++)
{
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].r = 0;
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].g = 0;
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].b = 0;
_d[y*3*pwidth + 3*pwidth*pheight + (pwidth-x-1) + 2*pwidth].a = d;
}
}
/* NW */
pwidth = MAX_TILE_SZ;
pheight = MAX_TILE_SZ;
for (x = 0; x < pwidth; x++)
for (y = 0; y < pheight; y++)
{
d = sum_gaussian (gaussian_map, opacity,
x-center, y-center,
TILE_WIDTH, TILE_HEIGHT);
_d[y*3*pwidth + x].r = 0;
_d[y*3*pwidth + x].g = 0;
_d[y*3*pwidth + x].b = 0;
_d[y*3*pwidth + x].a = d;
}
/* SW */
for (x = 0; x < pwidth; x++)
for (y = 0; y < pheight; y++)
{
d = sum_gaussian (gaussian_map, opacity,
x-center, y-center,
TILE_WIDTH, TILE_HEIGHT);
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].r = 0;
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].g = 0;
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].b = 0;
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + x].a = d;
}
/* SE */
for (x = 0; x < pwidth; x++)
for (y = 0; y < pheight; y++)
{
d = sum_gaussian (gaussian_map, opacity,
x-center, y-center,
TILE_WIDTH, TILE_HEIGHT);
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
2*pwidth].r = 0;
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
2*pwidth].g = 0;
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
2*pwidth].b = 0;
_d[(pheight-y-1)*3*pwidth + 6*pwidth*pheight + (pwidth-x-1) +
2*pwidth].a = d;
}
/* NE */
for (x = 0; x < pwidth; x++)
for (y = 0; y < pheight; y++)
{
d = sum_gaussian (gaussian_map, opacity,
x-center, y-center,
TILE_WIDTH, TILE_HEIGHT);
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].r = 0;
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].g = 0;
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].b = 0;
_d[y*3*pwidth + (pwidth - x - 1) + 2*pwidth].a = d;
}
/* center */
pwidth = MAX_TILE_SZ;
pheight = MAX_TILE_SZ;
d = sum_gaussian (gaussian_map, opacity,
center, center, TILE_WIDTH, TILE_HEIGHT);
for (x = 0; x < pwidth; x++)
for (y = 0; y < pheight; y++)
{
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].r = 0;
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].g = 0;
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].b = 0;
_d[y*3*pwidth + 3*pwidth*pheight + x + pwidth].a = 0;
}
return data;
}

View File

@ -1,9 +0,0 @@
#ifndef SHADOW_H
#define SHADOW_H
#include <clutter/clutter.h>
#include "compositor.h"
ClutterActor *mutter_create_shadow_frame (MetaCompositor *compositor);
#endif /* SHADOW_H */

View File

@ -1,641 +0,0 @@
/* tidy-texture-frame.h: Expandible texture actor
*
* Copyright (C) 2007 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/**
* SECTION:tidy-texture-frame
* @short_description: Stretch a texture to fit the entire allocation
*
* #TidyTextureFrame
*
*/
#include <cogl/cogl.h>
#include "tidy-texture-frame.h"
#define TIDY_PARAM_READABLE \
(G_PARAM_READABLE | \
G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB)
#define TIDY_PARAM_READWRITE \
(G_PARAM_READABLE | G_PARAM_WRITABLE | \
G_PARAM_STATIC_NICK | G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB)
enum
{
PROP_0,
PROP_PARENT_TEXTURE,
PROP_LEFT,
PROP_TOP,
PROP_RIGHT,
PROP_BOTTOM
};
G_DEFINE_TYPE (TidyTextureFrame, tidy_texture_frame, CLUTTER_TYPE_ACTOR);
#define TIDY_TEXTURE_FRAME_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFramePrivate))
struct _TidyTextureFramePrivate
{
ClutterTexture *parent_texture;
gfloat left;
gfloat top;
gfloat right;
gfloat bottom;
CoglHandle material;
guint needs_paint : 1;
};
static void
tidy_texture_frame_get_preferred_width (ClutterActor *self,
gfloat for_height,
gfloat *min_width_p,
gfloat *natural_width_p)
{
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
if (G_UNLIKELY (priv->parent_texture == NULL))
{
if (min_width_p)
*min_width_p = 0;
if (natural_width_p)
*natural_width_p = 0;
}
else
{
ClutterActorClass *klass;
/* by directly querying the parent texture's class implementation
* we are going around any override mechanism the parent texture
* might have in place, and we ask directly for the original
* preferred width
*/
klass = CLUTTER_ACTOR_GET_CLASS (priv->parent_texture);
klass->get_preferred_width (CLUTTER_ACTOR (priv->parent_texture),
for_height,
min_width_p,
natural_width_p);
}
}
static void
tidy_texture_frame_get_preferred_height (ClutterActor *self,
gfloat for_width,
gfloat *min_height_p,
gfloat *natural_height_p)
{
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
if (G_UNLIKELY (priv->parent_texture == NULL))
{
if (min_height_p)
*min_height_p = 0;
if (natural_height_p)
*natural_height_p = 0;
}
else
{
ClutterActorClass *klass;
/* by directly querying the parent texture's class implementation
* we are going around any override mechanism the parent texture
* might have in place, and we ask directly for the original
* preferred height
*/
klass = CLUTTER_ACTOR_GET_CLASS (priv->parent_texture);
klass->get_preferred_height (CLUTTER_ACTOR (priv->parent_texture),
for_width,
min_height_p,
natural_height_p);
}
}
static void
tidy_texture_frame_realize (ClutterActor *self)
{
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
if (priv->material != COGL_INVALID_HANDLE)
return;
priv->material = cogl_material_new ();
CLUTTER_ACTOR_SET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
}
static void
tidy_texture_frame_unrealize (ClutterActor *self)
{
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
if (priv->material == COGL_INVALID_HANDLE)
return;
cogl_material_unref (priv->material);
priv->material = COGL_INVALID_HANDLE;
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
}
static void
tidy_texture_frame_paint (ClutterActor *self)
{
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (self)->priv;
CoglHandle cogl_texture = COGL_INVALID_HANDLE;
ClutterActorBox box = { 0, };
gfloat width, height;
gfloat tex_width, tex_height;
gfloat ex, ey;
gfloat tx1, ty1, tx2, ty2;
guint8 opacity;
/* no need to paint stuff if we don't have a texture */
if (G_UNLIKELY (priv->parent_texture == NULL))
return;
if (!priv->needs_paint)
return;
/* parent texture may have been hidden, so need to make sure it gets
* realized
*/
if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent_texture))
clutter_actor_realize (CLUTTER_ACTOR (priv->parent_texture));
cogl_texture = clutter_texture_get_cogl_texture (priv->parent_texture);
if (cogl_texture == COGL_INVALID_HANDLE)
return;
tex_width = cogl_texture_get_width (cogl_texture);
tex_height = cogl_texture_get_height (cogl_texture);
clutter_actor_get_allocation_box (self, &box);
width = box.x2 - box.x1;
height = box.y2 - box.y1;
tx1 = priv->left / tex_width;
tx2 = (tex_width - priv->right) / tex_width;
ty1 = priv->top / tex_height;
ty2 = (tex_height - priv->bottom) / tex_height;
ex = width - priv->right;
if (ex < 0)
ex = priv->right; /* FIXME ? */
ey = height - priv->bottom;
if (ey < 0)
ey = priv->bottom; /* FIXME ? */
opacity = clutter_actor_get_paint_opacity (self);
g_assert (priv->material != COGL_INVALID_HANDLE);
/* set the source material using the parent texture's COGL handle */
cogl_material_set_color4ub (priv->material, opacity, opacity, opacity, opacity);
cogl_material_set_layer (priv->material, 0, cogl_texture);
cogl_set_source (priv->material);
/* top left corner */
cogl_rectangle_with_texture_coords (0, 0, priv->left, priv->top,
0.0, 0.0,
tx1, ty1);
/* top middle */
cogl_rectangle_with_texture_coords (priv->left, 0, ex, priv->top,
tx1, 0.0,
tx2, ty1);
/* top right */
cogl_rectangle_with_texture_coords (ex, 0, width, priv->top,
tx2, 0.0,
1.0, ty1);
/* mid left */
cogl_rectangle_with_texture_coords (0, priv->top, priv->left, ey,
0.0, ty1,
tx1, ty2);
/* center */
cogl_rectangle_with_texture_coords (priv->left, priv->top, ex, ey,
tx1, ty1,
tx2, ty2);
/* mid right */
cogl_rectangle_with_texture_coords (ex, priv->top, width, ey,
tx2, ty1,
1.0, ty2);
/* bottom left */
cogl_rectangle_with_texture_coords (0, ey, priv->left, height,
0.0, ty2,
tx1, 1.0);
/* bottom center */
cogl_rectangle_with_texture_coords (priv->left, ey, ex, height,
tx1, ty2,
tx2, 1.0);
/* bottom right */
cogl_rectangle_with_texture_coords (ex, ey, width, height,
tx2, ty2,
1.0, 1.0);
}
static inline void
tidy_texture_frame_set_frame_internal (TidyTextureFrame *frame,
gfloat left,
gfloat top,
gfloat right,
gfloat bottom)
{
TidyTextureFramePrivate *priv = frame->priv;
GObject *gobject = G_OBJECT (frame);
gboolean changed = FALSE;
g_object_freeze_notify (gobject);
if (priv->top != top)
{
priv->top = top;
g_object_notify (gobject, "top");
changed = TRUE;
}
if (priv->right != right)
{
priv->right = right;
g_object_notify (gobject, "right");
changed = TRUE;
}
if (priv->bottom != bottom)
{
priv->bottom = bottom;
g_object_notify (gobject, "bottom");
changed = TRUE;
}
if (priv->left != left)
{
priv->left = left;
g_object_notify (gobject, "left");
changed = TRUE;
}
if (changed && CLUTTER_ACTOR_IS_VISIBLE (frame))
clutter_actor_queue_redraw (CLUTTER_ACTOR (frame));
g_object_thaw_notify (gobject);
}
static void
tidy_texture_frame_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
TidyTextureFrame *frame = TIDY_TEXTURE_FRAME (gobject);
TidyTextureFramePrivate *priv = frame->priv;
switch (prop_id)
{
case PROP_PARENT_TEXTURE:
tidy_texture_frame_set_parent_texture (frame,
g_value_get_object (value));
break;
case PROP_TOP:
tidy_texture_frame_set_frame_internal (frame,
priv->left,
g_value_get_float (value),
priv->right,
priv->bottom);
break;
case PROP_RIGHT:
tidy_texture_frame_set_frame_internal (frame,
priv->top,
g_value_get_float (value),
priv->bottom,
priv->left);
break;
case PROP_BOTTOM:
tidy_texture_frame_set_frame_internal (frame,
priv->top,
priv->right,
g_value_get_float (value),
priv->left);
break;
case PROP_LEFT:
tidy_texture_frame_set_frame_internal (frame,
priv->top,
priv->right,
priv->bottom,
g_value_get_float (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
tidy_texture_frame_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (gobject)->priv;
switch (prop_id)
{
case PROP_PARENT_TEXTURE:
g_value_set_object (value, priv->parent_texture);
break;
case PROP_LEFT:
g_value_set_float (value, priv->left);
break;
case PROP_TOP:
g_value_set_float (value, priv->top);
break;
case PROP_RIGHT:
g_value_set_float (value, priv->right);
break;
case PROP_BOTTOM:
g_value_set_float (value, priv->bottom);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
tidy_texture_frame_dispose (GObject *gobject)
{
TidyTextureFramePrivate *priv = TIDY_TEXTURE_FRAME (gobject)->priv;
if (priv->parent_texture)
{
g_object_unref (priv->parent_texture);
priv->parent_texture = NULL;
}
if (priv->material)
{
cogl_material_unref (priv->material);
priv->material = COGL_INVALID_HANDLE;
}
G_OBJECT_CLASS (tidy_texture_frame_parent_class)->dispose (gobject);
}
static void
tidy_texture_frame_class_init (TidyTextureFrameClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (gobject_class, sizeof (TidyTextureFramePrivate));
actor_class->get_preferred_width =
tidy_texture_frame_get_preferred_width;
actor_class->get_preferred_height =
tidy_texture_frame_get_preferred_height;
actor_class->realize = tidy_texture_frame_realize;
actor_class->unrealize = tidy_texture_frame_unrealize;
actor_class->paint = tidy_texture_frame_paint;
gobject_class->set_property = tidy_texture_frame_set_property;
gobject_class->get_property = tidy_texture_frame_get_property;
gobject_class->dispose = tidy_texture_frame_dispose;
pspec = g_param_spec_object ("parent-texture",
"Parent Texture",
"The parent ClutterTexture",
CLUTTER_TYPE_TEXTURE,
TIDY_PARAM_READWRITE |
G_PARAM_CONSTRUCT);
g_object_class_install_property (gobject_class, PROP_PARENT_TEXTURE, pspec);
pspec = g_param_spec_float ("left",
"Left",
"Left offset",
0, G_MAXFLOAT,
0,
TIDY_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_LEFT, pspec);
pspec = g_param_spec_float ("top",
"Top",
"Top offset",
0, G_MAXFLOAT,
0,
TIDY_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_TOP, pspec);
pspec = g_param_spec_float ("bottom",
"Bottom",
"Bottom offset",
0, G_MAXFLOAT,
0,
TIDY_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_BOTTOM, pspec);
pspec = g_param_spec_float ("right",
"Right",
"Right offset",
0, G_MAXFLOAT,
0,
TIDY_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_RIGHT, pspec);
}
static void
tidy_texture_frame_init (TidyTextureFrame *self)
{
TidyTextureFramePrivate *priv;
self->priv = priv = TIDY_TEXTURE_FRAME_GET_PRIVATE (self);
priv->material = COGL_INVALID_HANDLE;
}
/**
* tidy_texture_frame_new:
* @texture: a #ClutterTexture or %NULL
* @left: left margin preserving its content
* @top: top margin preserving its content
* @right: right margin preserving its content
* @bottom: bottom margin preserving its content
*
* A #TidyTextureFrame is a specialized texture that efficiently clones
* an area of the given @texture while keeping preserving portions of the
* same texture.
*
* A #TidyTextureFrame can be used to make a rectangular texture fit a
* given size without stretching its borders.
*
* Return value: the newly created #TidyTextureFrame
*/
ClutterActor*
tidy_texture_frame_new (ClutterTexture *texture,
gfloat left,
gfloat top,
gfloat right,
gfloat bottom)
{
g_return_val_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture), NULL);
return g_object_new (TIDY_TYPE_TEXTURE_FRAME,
"parent-texture", texture,
"left", left,
"top", top,
"right", right,
"bottom", bottom,
NULL);
}
ClutterTexture *
tidy_texture_frame_get_parent_texture (TidyTextureFrame *frame)
{
g_return_val_if_fail (TIDY_IS_TEXTURE_FRAME (frame), NULL);
return frame->priv->parent_texture;
}
void
tidy_texture_frame_set_parent_texture (TidyTextureFrame *frame,
ClutterTexture *texture)
{
TidyTextureFramePrivate *priv;
gboolean was_visible;
g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
g_return_if_fail (texture == NULL || CLUTTER_IS_TEXTURE (texture));
priv = frame->priv;
was_visible = CLUTTER_ACTOR_IS_VISIBLE (frame);
if (priv->parent_texture == texture)
return;
if (priv->parent_texture)
{
g_object_unref (priv->parent_texture);
priv->parent_texture = NULL;
if (was_visible)
clutter_actor_hide (CLUTTER_ACTOR (frame));
}
if (texture)
{
priv->parent_texture = g_object_ref (texture);
if (was_visible && CLUTTER_ACTOR_IS_VISIBLE (priv->parent_texture))
clutter_actor_show (CLUTTER_ACTOR (frame));
}
clutter_actor_queue_relayout (CLUTTER_ACTOR (frame));
g_object_notify (G_OBJECT (frame), "parent-texture");
}
void
tidy_texture_frame_set_frame (TidyTextureFrame *frame,
gfloat top,
gfloat right,
gfloat bottom,
gfloat left)
{
g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
tidy_texture_frame_set_frame_internal (frame, top, right, bottom, left);
}
void
tidy_texture_frame_get_frame (TidyTextureFrame *frame,
gfloat *top,
gfloat *right,
gfloat *bottom,
gfloat *left)
{
TidyTextureFramePrivate *priv;
g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
priv = frame->priv;
if (top)
*top = priv->top;
if (right)
*right = priv->right;
if (bottom)
*bottom = priv->bottom;
if (left)
*left = priv->left;
}
/**
* tidy_texture_frame_set_needs_paint:
* @frame: a #TidyTextureframe
* @needs_paint: if %FALSE, the paint will be skipped
*
* Provides a hint to the texture frame that it is totally obscured
* and doesn't need to be painted. This would typically be called
* by a parent container if it detects the condition prior to
* painting its children and then unset afterwards.
*
* Since it is not supposed to have any effect on display, it does
* not queue a repaint.
*/
void
tidy_texture_frame_set_needs_paint (TidyTextureFrame *frame,
gboolean needs_paint)
{
TidyTextureFramePrivate *priv;
g_return_if_fail (TIDY_IS_TEXTURE_FRAME (frame));
priv = frame->priv;
priv->needs_paint = needs_paint;
}

View File

@ -1,84 +0,0 @@
/* tidy-texture-frame.h: Expandible texture actor
*
* Copyright (C) 2007, 2008 OpenedHand Ltd
* Copyright (C) 2009 Intel Corp.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _HAVE_TIDY_TEXTURE_FRAME_H
#define _HAVE_TIDY_TEXTURE_FRAME_H
#include <clutter/clutter.h>
G_BEGIN_DECLS
#define TIDY_TYPE_TEXTURE_FRAME (tidy_texture_frame_get_type ())
#define TIDY_TEXTURE_FRAME(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrame))
#define TIDY_TEXTURE_FRAME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrameClass))
#define TIDY_IS_TEXTURE_FRAME(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TIDY_TYPE_TEXTURE_FRAME))
#define TIDY_IS_TEXTURE_FRAME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TIDY_TYPE_TEXTURE_FRAME))
#define TIDY_TEXTURE_FRAME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TIDY_TYPE_TEXTURE_FRAME, TidyTextureFrameClass))
typedef struct _TidyTextureFrame TidyTextureFrame;
typedef struct _TidyTextureFramePrivate TidyTextureFramePrivate;
typedef struct _TidyTextureFrameClass TidyTextureFrameClass;
struct _TidyTextureFrame
{
/*< private >*/
ClutterActor parent_instance;
TidyTextureFramePrivate *priv;
};
struct _TidyTextureFrameClass
{
ClutterActorClass parent_class;
/* padding for future expansion */
void (*_clutter_box_1) (void);
void (*_clutter_box_2) (void);
void (*_clutter_box_3) (void);
void (*_clutter_box_4) (void);
};
GType tidy_texture_frame_get_type (void) G_GNUC_CONST;
ClutterActor * tidy_texture_frame_new (ClutterTexture *texture,
gfloat top,
gfloat right,
gfloat bottom,
gfloat left);
void tidy_texture_frame_set_parent_texture (TidyTextureFrame *frame,
ClutterTexture *texture);
ClutterTexture *tidy_texture_frame_get_parent_texture (TidyTextureFrame *frame);
void tidy_texture_frame_set_frame (TidyTextureFrame *frame,
gfloat top,
gfloat right,
gfloat bottom,
gfloat left);
void tidy_texture_frame_get_frame (TidyTextureFrame *frame,
gfloat *top,
gfloat *right,
gfloat *bottom,
gfloat *left);
void tidy_texture_frame_set_needs_paint (TidyTextureFrame *frame,
gboolean needs_paint);
G_END_DECLS
#endif /* _HAVE_TIDY_TEXTURE_FRAME_H */

View File

@ -0,0 +1,241 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Find the keycode for the key above the tab key */
/*
* Copyright 2010 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.
*/
/* The standard cycle-windows keybinding should be the key above the
* tab key. This will have a different keysym on different keyboards -
* it's the ` (grave) key on US keyboards but something else on many
* other national layouts. So we need to figure out the keycode for
* this key without reference to key symbol.
*
* The "correct" way to do this is to get the XKB geometry from the
* X server, find the Tab key, find the key above the Tab key in the
* same section and use the keycode for that key. This is what I
* implemented here, but unfortunately, fetching the geometry is rather
* slow (It could take 20ms or more.)
*
* If you looking for a way to optimize Mutter startup performance:
* On all Linux systems using evdev the key above TAB will have
* keycode 49. (KEY_GRAVE=41 + the 8 code point offset between
* evdev keysyms and X keysyms.) So a configure option
* --with-above-tab-keycode=49 could be added that bypassed this
* code. It wouldn't work right for displaying Mutter remotely
* to a non-Linux X server, but that is pretty rare.
*/
#include <config.h>
#include <string.h>
#include "display-private.h"
#include <X11/keysym.h>
#ifdef HAVE_XKB
#include <X11/XKBlib.h>
#include <X11/extensions/XKBgeom.h>
static guint
compute_above_tab_keycode (Display *xdisplay)
{
XkbDescPtr keyboard;
XkbGeometryPtr geometry;
int i, j, k;
int tab_keycode;
char *tab_name;
XkbSectionPtr tab_section;
XkbBoundsRec tab_bounds;
XkbKeyPtr best_key = NULL;
guint best_keycode = (guint)-1;
int best_x_dist = G_MAXINT;
int best_y_dist = G_MAXINT;
/* We need only the Names and the Geometry, but asking for these results
* in the Keyboard information retrieval failing for unknown reasons.
* (Testing with xorg-1.9.1.) So we ask for a part that we don't need
* as well.
*/
keyboard = XkbGetKeyboard (xdisplay,
XkbGBN_ClientSymbolsMask | XkbGBN_KeyNamesMask | XkbGBN_GeometryMask,
XkbUseCoreKbd);
geometry = keyboard->geom;
/* There could potentially be multiple keys with the Tab keysym on the keyboard;
* but XKeysymToKeycode() returns us the one that the alt-Tab binding will
* use which is good enough
*/
tab_keycode = XKeysymToKeycode (xdisplay, XK_Tab);
if (tab_keycode == 0 || tab_keycode < keyboard->min_key_code || tab_keycode > keyboard->max_key_code)
goto out;
/* The keyboard geometry is stored by key "name" rather than keycode.
* (Key names are 4-character strings like like TAB or AE01.) We use the
* 'names' part of the keyboard description to map keycode to key name.
*
* XKB has a "key aliases" feature where a single keyboard key can have
* multiple names (with separate sets of aliases in the 'names' part and
* in the 'geometry' part), but I don't really understand it or how it is used,
* so I'm ignoring it here.
*/
tab_name = keyboard->names->keys[tab_keycode].name; /* Not NULL terminated! */
/* First, iterate through the keyboard geometry to find the tab key; the keyboard
* geometry has a three-level heirarchy of section > row > key
*/
for (i = 0; i < geometry->num_sections; i++)
{
XkbSectionPtr section = &geometry->sections[i];
for (j = 0; j < section->num_rows; j++)
{
int x = 0;
int y = 0;
XkbRowPtr row = &section->rows[j];
for (k = 0; k < row->num_keys; k++)
{
XkbKeyPtr key = &row->keys[k];
XkbShapePtr shape = XkbKeyShape (geometry, key);
if (row->vertical)
y += key->gap;
else
x += key->gap;
if (strncmp (key->name.name, tab_name, XkbKeyNameLength) == 0)
{
tab_section = section;
tab_bounds = shape->bounds;
tab_bounds.x1 += row->left + x;
tab_bounds.x2 += row->left + x;
tab_bounds.y1 += row->top + y;
tab_bounds.y2 += row->top + y;
goto found_tab;
}
if (row->vertical)
y += (shape->bounds.y2 - shape->bounds.y1);
else
x += (shape->bounds.x2 - shape->bounds.x1);
}
}
}
/* No tab key found */
goto out;
found_tab:
/* Now find the key that:
* - Is in the same section as the Tab key
* - Has a horizontal center in the Tab key's horizonal bounds
* - Is above the Tab key at a distance closer than any other key
* - In case of ties, has its horizontal center as close as possible
* to the Tab key's horizontal center
*/
for (j = 0; j < tab_section->num_rows; j++)
{
int x = 0;
int y = 0;
XkbRowPtr row = &tab_section->rows[j];
for (k = 0; k < row->num_keys; k++)
{
XkbKeyPtr key = &row->keys[k];
XkbShapePtr shape = XkbKeyShape(geometry, key);
XkbBoundsRec bounds = shape->bounds;
int x_center;
int x_dist, y_dist;
if (row->vertical)
y += key->gap;
else
x += key->gap;
bounds.x1 += row->left + x;
bounds.x2 += row->left + x;
bounds.y1 += row->top + y;
bounds.y2 += row->top + y;
y_dist = tab_bounds.y1 - bounds.y2;
if (y_dist < 0)
continue;
x_center = (bounds.x1 + bounds.x2) / 2;
if (x_center < tab_bounds.x1 || x_center > tab_bounds.x2)
continue;
x_dist = ABS (x_center - (tab_bounds.x1 + tab_bounds.x2) / 2);
if (y_dist < best_y_dist ||
(y_dist == best_y_dist && x_dist < best_x_dist))
{
best_key = key;
best_x_dist = x_dist;
best_y_dist = y_dist;
}
if (row->vertical)
y += (shape->bounds.y2 - shape->bounds.y1);
else
x += (shape->bounds.x2 - shape->bounds.x1);
}
}
if (best_key == NULL)
goto out;
/* Now we need to resolve the name of the best key back to a keycode */
for (i = keyboard->min_key_code; i < keyboard->max_key_code; i++)
{
if (strncmp (best_key->name.name, keyboard->names->keys[i].name, XkbKeyNameLength) == 0)
{
best_keycode = i;
break;
}
}
out:
XkbFreeKeyboard (keyboard, 0, True);
return best_keycode;
}
#else /* !HAVE_XKB */
static guint
compute_above_tab_keycode (Display *xdisplay)
{
return XKeysymToKeycode (xdisplay, XK_grave);
}
#endif /* HAVE_XKB */
guint
meta_display_get_above_tab_keycode (MetaDisplay *display)
{
if (display->above_tab_keycode == 0) /* not yet computed */
display->above_tab_keycode = compute_above_tab_keycode (display->xdisplay);
if (display->above_tab_keycode == (guint)-1) /* failed to compute */
return 0;
else
return display->above_tab_keycode;
}

220
src/core/boxes-private.h Normal file
View File

@ -0,0 +1,220 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Simple box operations */
/*
* Copyright (C) 2005, 2006 Elijah Newren
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_BOXES_PRIVATE_H
#define META_BOXES_PRIVATE_H
#include <glib-object.h>
#include "common.h"
#include "boxes.h"
#define BOX_LEFT(box) ((box).x) /* Leftmost pixel of rect */
#define BOX_RIGHT(box) ((box).x + (box).width) /* One pixel past right */
#define BOX_TOP(box) ((box).y) /* Topmost pixel of rect */
#define BOX_BOTTOM(box) ((box).y + (box).height) /* One pixel past bottom */
typedef enum
{
FIXED_DIRECTION_NONE = 0,
FIXED_DIRECTION_X = 1 << 0,
FIXED_DIRECTION_Y = 1 << 1,
} FixedDirections;
/* Output functions -- note that the output buffer had better be big enough:
* rect_to_string: RECT_LENGTH
* region_to_string: (RECT_LENGTH+strlen(separator_string)) *
* g_list_length (region)
* edge_to_string: EDGE_LENGTH
* edge_list_to_...: (EDGE_LENGTH+strlen(separator_string)) *
* g_list_length (edge_list)
*/
#define RECT_LENGTH 27
#define EDGE_LENGTH 37
char* meta_rectangle_to_string (const MetaRectangle *rect,
char *output);
char* meta_rectangle_region_to_string (GList *region,
const char *separator_string,
char *output);
char* meta_rectangle_edge_to_string (const MetaEdge *edge,
char *output);
char* meta_rectangle_edge_list_to_string (
GList *edge_list,
const char *separator_string,
char *output);
/* Resize old_rect to the given new_width and new_height, but store the
* result in rect. NOTE THAT THIS IS RESIZE ONLY SO IT CANNOT BE USED FOR
* A MOVERESIZE OPERATION (that simplies the routine a little bit as it
* means there's no difference between NorthWestGravity and StaticGravity.
* Also, I lied a little bit--technically, you could use it in a MoveResize
* operation if you muck with old_rect just right).
*/
void meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect,
MetaRectangle *rect,
int gravity,
int new_width,
int new_height);
/* find a list of rectangles with the property that a window is contained
* in the given region if and only if it is contained in one of the
* rectangles in the list.
*
* In this case, the region is given by taking basic_rect, removing from
* it the intersections with all the rectangles in the all_struts list,
* then expanding all the rectangles in the resulting list by the given
* amounts on each side.
*
* See boxes.c for more details.
*/
GList* meta_rectangle_get_minimal_spanning_set_for_region (
const MetaRectangle *basic_rect,
const GSList *all_struts);
/* Expand all rectangles in region by the given amount on each side */
GList* meta_rectangle_expand_region (GList *region,
const int left_expand,
const int right_expand,
const int top_expand,
const int bottom_expand);
/* Same as for meta_rectangle_expand_region except that rectangles not at
* least min_x or min_y in size are not expanded in that direction
*/
GList* meta_rectangle_expand_region_conditionally (
GList *region,
const int left_expand,
const int right_expand,
const int top_expand,
const int bottom_expand,
const int min_x,
const int min_y);
/* Expand rect in direction to the size of expand_to, and then clip out any
* overlapping struts oriented orthognal to the expansion direction. (Think
* horizontal or vertical maximization)
*/
void meta_rectangle_expand_to_avoiding_struts (
MetaRectangle *rect,
const MetaRectangle *expand_to,
const MetaDirection direction,
const GSList *all_struts);
/* Free the list created by
* meta_rectangle_get_minimal_spanning_set_for_region()
* or
* meta_rectangle_find_onscreen_edges ()
* or
* meta_rectangle_find_nonintersected_monitor_edges()
*/
void meta_rectangle_free_list_and_elements (GList *filled_list);
/* could_fit_in_region determines whether one of the spanning_rects is
* big enough to contain rect. contained_in_region checks whether one
* actually contains it.
*/
gboolean meta_rectangle_could_fit_in_region (
const GList *spanning_rects,
const MetaRectangle *rect);
gboolean meta_rectangle_contained_in_region (
const GList *spanning_rects,
const MetaRectangle *rect);
gboolean meta_rectangle_overlaps_with_region (
const GList *spanning_rects,
const MetaRectangle *rect);
/* Make the rectangle small enough to fit into one of the spanning_rects,
* but make it no smaller than min_size.
*/
void meta_rectangle_clamp_to_fit_into_region (
const GList *spanning_rects,
FixedDirections fixed_directions,
MetaRectangle *rect,
const MetaRectangle *min_size);
/* Clip the rectangle so that it fits into one of the spanning_rects, assuming
* it overlaps with at least one of them
*/
void meta_rectangle_clip_to_region (const GList *spanning_rects,
FixedDirections fixed_directions,
MetaRectangle *rect);
/* Shove the rectangle into one of the spanning_rects, assuming it fits in
* one of them.
*/
void meta_rectangle_shove_into_region(
const GList *spanning_rects,
FixedDirections fixed_directions,
MetaRectangle *rect);
/* Finds the point on the line connecting (x1,y1) to (x2,y2) which is closest
* to (px, py). Useful for finding an optimal rectangle size when given a
* range between two sizes that are all candidates.
*/
void meta_rectangle_find_linepoint_closest_to_point (double x1, double y1,
double x2, double y2,
double px, double py,
double *valx, double *valy);
/***************************************************************************/
/* */
/* Switching gears to code for edges instead of just rectangles */
/* */
/***************************************************************************/
/* Return whether an edge overlaps or is adjacent to the rectangle in the
* nonzero-width dimension of the edge.
*/
gboolean meta_rectangle_edge_aligns (const MetaRectangle *rect,
const MetaEdge *edge);
/* Compare two edges, so that sorting functions can put a list of edges in
* canonical order.
*/
gint meta_rectangle_edge_cmp (gconstpointer a, gconstpointer b);
/* Compare two edges, so that sorting functions can put a list of edges in
* order. This function doesn't separate left edges first, then right edges,
* etc., but rather compares only upon location.
*/
gint meta_rectangle_edge_cmp_ignore_type (gconstpointer a, gconstpointer b);
/* Removes an parts of edges in the given list that intersect any box in the
* given rectangle list. Returns the result.
*/
GList* meta_rectangle_remove_intersections_with_boxes_from_edges (
GList *edges,
const GSList *rectangles);
/* Finds all the edges of an onscreen region, returning a GList* of
* MetaEdgeRect's.
*/
GList* meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
const GSList *all_struts);
/* Finds edges between adjacent monitors which are not covered by the given
* struts.
*/
GList* meta_rectangle_find_nonintersected_monitor_edges (
const GList *monitor_rects,
const GSList *all_struts);
#endif /* META_BOXES_PRIVATE_H */

View File

@ -26,10 +26,39 @@
* 02111-1307, USA.
*/
#include "boxes.h"
#include "boxes-private.h"
#include "util.h"
#include <X11/Xutil.h> /* Just for the definition of the various gravities */
/* It would make sense to use GSlice here, but until we clean up the
* rest of this file and the internal API to use these functions, we
* leave it using g_malloc()/g_free() for consistency.
*/
MetaRectangle *
meta_rectangle_copy (const MetaRectangle *rect)
{
return g_memdup (rect, sizeof (MetaRectangle));
}
void
meta_rectangle_free (MetaRectangle *rect)
{
g_free (rect);
}
GType
meta_rectangle_get_type (void)
{
static GType type_id = 0;
if (!type_id)
type_id = g_boxed_type_register_static (g_intern_static_string ("MetaRectangle"),
(GBoxedCopyFunc) meta_rectangle_copy,
(GBoxedFreeFunc) meta_rectangle_free);
return type_id;
}
char*
meta_rectangle_to_string (const MetaRectangle *rect,
char *output)
@ -500,7 +529,12 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
return b_area - a_area; /* positive ret value denotes b > a, ... */
}
/* This function is trying to find a "minimal spanning set (of rectangles)"
/**
* meta_rectangle_get_minimal_spanning_set_for_region:
* @basic_rect: Input rectangle
* @all_struts: (element-type Meta.Rectangle): List of struts
*
* This function is trying to find a "minimal spanning set (of rectangles)"
* for a given region.
*
* The region is given by taking basic_rect, then removing the areas
@ -513,10 +547,7 @@ compare_rect_areas (gconstpointer a, gconstpointer b)
* the region if and only if it is contained within at least one of the
* rectangles.
*
* The GList* returned will be a list of (allocated) MetaRectangles.
* The list will need to be freed by calling
* meta_rectangle_free_spanning_set() on it (or by manually
* implementing that function...)
* Returns: (transfer full) (element-type Meta.Rectangle): Minimal spanning set
*/
GList*
meta_rectangle_get_minimal_spanning_set_for_region (
@ -649,6 +680,10 @@ meta_rectangle_get_minimal_spanning_set_for_region (
return ret;
}
/**
* meta_rectangle_expand_region: (skip)
*
*/
GList*
meta_rectangle_expand_region (GList *region,
const int left_expand,
@ -665,6 +700,10 @@ meta_rectangle_expand_region (GList *region,
0);
}
/**
* meta_rectangle_expand_region_conditionally: (skip)
*
*/
GList*
meta_rectangle_expand_region_conditionally (GList *region,
const int left_expand,
@ -1642,7 +1681,10 @@ fix_up_edges (MetaRectangle *rect, MetaEdge *edge,
}
}
/* This function removes intersections of edges with the rectangles from the
/**
* meta_rectangle_remove_intersections_with_boxes_from_edges: (skip)
*
* This function removes intersections of edges with the rectangles from the
* list of edges.
*/
GList*
@ -1708,7 +1750,11 @@ meta_rectangle_remove_intersections_with_boxes_from_edges (
return edges;
}
/* This function is trying to find all the edges of an onscreen region. */
/**
* meta_rectangle_find_onscreen_edges: (skip)
*
* This function is trying to find all the edges of an onscreen region.
*/
GList*
meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
const GSList *all_struts)
@ -1791,6 +1837,10 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
return ret;
}
/**
* meta_rectangle_find_nonintersected_monitor_edges: (skip)
*
*/
GList*
meta_rectangle_find_nonintersected_monitor_edges (
const GList *monitor_rects,

View File

@ -24,6 +24,7 @@
*/
#include <config.h>
#include "boxes-private.h"
#include "constraints.h"
#include "workspace-private.h"
#include "place.h"
@ -98,6 +99,7 @@ typedef enum
PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA = 1,
PRIORITY_SIZE_HINTS_INCREMENTS = 1,
PRIORITY_MAXIMIZATION = 2,
PRIORITY_TILING = 2,
PRIORITY_FULLSCREEN = 2,
PRIORITY_SIZE_HINTS_LIMITS = 3,
PRIORITY_TITLEBAR_VISIBLE = 4,
@ -140,11 +142,18 @@ typedef struct
GList *usable_screen_region;
GList *usable_monitor_region;
} ConstraintInfo;
static gboolean constrain_modal_dialog (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only);
static gboolean constrain_maximization (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only);
static gboolean constrain_tiling (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only);
static gboolean constrain_fullscreen (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
@ -210,7 +219,9 @@ typedef struct {
} Constraint;
static const Constraint all_constraints[] = {
{constrain_modal_dialog, "constrain_modal_dialog"},
{constrain_maximization, "constrain_maximization"},
{constrain_tiling, "constrain_tiling"},
{constrain_fullscreen, "constrain_fullscreen"},
{constrain_size_increments, "constrain_size_increments"},
{constrain_size_limits, "constrain_size_limits"},
@ -726,6 +737,48 @@ get_size_limits (const MetaWindow *window,
}
}
static gboolean
constrain_modal_dialog (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only)
{
int x, y;
MetaWindow *parent = meta_window_get_transient_for (window);
gboolean constraint_already_satisfied;
if (!meta_prefs_get_attach_modal_dialogs ())
return TRUE;
if (window->type != META_WINDOW_MODAL_DIALOG || !parent || parent == window)
return TRUE;
x = parent->rect.x + (parent->rect.width / 2 - info->current.width / 2);
y = 0;
if (parent->frame)
{
MetaFrameGeometry fgeom;
x += parent->frame->rect.x;
y += parent->frame->rect.y;
meta_frame_calc_geometry (parent->frame, &fgeom);
y += fgeom.top_height;
y += info->fgeom->top_height;
}
else
y = parent->rect.y + info->fgeom->top_height;
constraint_already_satisfied = (x == info->current.x) && (y == info->current.y);
if (check_only || constraint_already_satisfied)
return constraint_already_satisfied;
info->current.y = y;
info->current.x = x;
return TRUE;
}
static gboolean
constrain_maximization (MetaWindow *window,
ConstraintInfo *info,
@ -742,7 +795,8 @@ constrain_maximization (MetaWindow *window,
return TRUE;
/* Determine whether constraint applies; exit if it doesn't */
if (!window->maximized_horizontally && !window->maximized_vertically)
if ((!window->maximized_horizontally && !window->maximized_vertically) ||
META_WINDOW_TILED_SIDE_BY_SIDE (window))
return TRUE;
/* Calculate target_size = maximized size of (window + frame) */
@ -810,6 +864,59 @@ constrain_maximization (MetaWindow *window,
return TRUE;
}
static gboolean
constrain_tiling (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only)
{
MetaRectangle target_size;
MetaRectangle min_size, max_size;
gboolean hminbad, vminbad;
gboolean horiz_equal, vert_equal;
gboolean constraint_already_satisfied;
if (priority > PRIORITY_TILING)
return TRUE;
/* Determine whether constraint applies; exit if it doesn't */
if (!META_WINDOW_TILED_SIDE_BY_SIDE (window))
return TRUE;
/* Calculate target_size - as the tile previews need this as well, we
* use an external function for the actual calculation
*/
meta_window_get_current_tile_area (window, &target_size);
unextend_by_frame (&target_size, info->fgeom);
/* Check min size constraints; max size constraints are ignored as for
* maximized windows.
*/
get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
hminbad = target_size.width < min_size.width;
vminbad = target_size.height < min_size.height;
if (hminbad || vminbad)
return TRUE;
/* Determine whether constraint is already satisfied; exit if it is */
horiz_equal = target_size.x == info->current.x &&
target_size.width == info->current.width;
vert_equal = target_size.y == info->current.y &&
target_size.height == info->current.height;
constraint_already_satisfied = horiz_equal && vert_equal;
if (check_only || constraint_already_satisfied)
return constraint_already_satisfied;
/*** Enforce constraint ***/
info->current.x = target_size.x;
info->current.width = target_size.width;
info->current.y = target_size.y;
info->current.height = target_size.height;
return TRUE;
}
static gboolean
constrain_fullscreen (MetaWindow *window,
ConstraintInfo *info,
@ -861,6 +968,7 @@ constrain_size_increments (MetaWindow *window,
/* Determine whether constraint applies; exit if it doesn't */
if (META_WINDOW_MAXIMIZED (window) || window->fullscreen ||
META_WINDOW_TILED_SIDE_BY_SIDE (window) ||
info->action_type == ACTION_MOVE)
return TRUE;
@ -992,6 +1100,7 @@ constrain_aspect_ratio (MetaWindow *window,
constraints_are_inconsistent = minr > maxr;
if (constraints_are_inconsistent ||
META_WINDOW_MAXIMIZED (window) || window->fullscreen ||
META_WINDOW_TILED_SIDE_BY_SIDE (window) ||
info->action_type == ACTION_MOVE)
return TRUE;

View File

@ -28,6 +28,7 @@
#include "frame-private.h"
#include "workspace-private.h"
#include "prefs.h"
#include "errors.h"
/* Looks up the MetaWindow representing the frame of the given X window.
* Used as a helper function by a bunch of the functions below.
@ -116,65 +117,8 @@ meta_core_get (Display *xdisplay,
*((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
break;
case META_CORE_GET_FRAME_TYPE:
{
MetaFrameType base_type = META_FRAME_TYPE_LAST;
switch (window->type)
{
case META_WINDOW_NORMAL:
base_type = META_FRAME_TYPE_NORMAL;
break;
case META_WINDOW_DIALOG:
base_type = META_FRAME_TYPE_DIALOG;
break;
case META_WINDOW_MODAL_DIALOG:
base_type = META_FRAME_TYPE_MODAL_DIALOG;
break;
case META_WINDOW_MENU:
base_type = META_FRAME_TYPE_MENU;
break;
case META_WINDOW_UTILITY:
base_type = META_FRAME_TYPE_UTILITY;
break;
case META_WINDOW_DESKTOP:
case META_WINDOW_DOCK:
case META_WINDOW_TOOLBAR:
case META_WINDOW_SPLASHSCREEN:
case META_WINDOW_DROPDOWN_MENU:
case META_WINDOW_POPUP_MENU:
case META_WINDOW_TOOLTIP:
case META_WINDOW_NOTIFICATION:
case META_WINDOW_COMBO:
case META_WINDOW_DND:
case META_WINDOW_OVERRIDE_OTHER:
/* No frame */
base_type = META_FRAME_TYPE_LAST;
break;
}
if (base_type == META_FRAME_TYPE_LAST)
{
/* can't add border if undecorated */
*((MetaFrameType*)answer) = META_FRAME_TYPE_LAST;
}
else if (window->border_only)
{
/* override base frame type */
*((MetaFrameType*)answer) = META_FRAME_TYPE_BORDER;
}
else
{
*((MetaFrameType*)answer) = base_type;
}
break;
}
*((MetaFrameType*)answer) = meta_window_get_frame_type (window);
break;
case META_CORE_GET_MINI_ICON:
*((GdkPixbuf**)answer) = window->mini_icon;
break;
@ -260,15 +204,14 @@ meta_core_user_raise (Display *xdisplay,
meta_window_raise (window);
}
void
meta_core_user_lower_and_unfocus (Display *xdisplay,
Window frame_xwindow,
guint32 timestamp)
static gboolean
lower_window_and_transients (MetaWindow *window,
gpointer data)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
meta_window_lower (window);
meta_window_foreach_transient (window, lower_window_and_transients, NULL);
if (meta_prefs_get_focus_mode () == META_FOCUS_MODE_CLICK &&
meta_prefs_get_raise_on_click ())
{
@ -296,11 +239,59 @@ meta_core_user_lower_and_unfocus (Display *xdisplay,
}
}
/* focus the default window, if needed */
if (window->has_focus)
meta_workspace_focus_default_window (window->screen->active_workspace,
NULL,
timestamp);
return FALSE;
}
void
meta_core_user_lower_and_unfocus (Display *xdisplay,
Window frame_xwindow,
guint32 timestamp)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
lower_window_and_transients (window, NULL);
/* Rather than try to figure that out whether we just lowered
* the focus window, assume that's always the case. (Typically,
* this will be invoked via keyboard action or by a mouse action;
* in either case the window or a modal child will have been focused.) */
meta_workspace_focus_default_window (window->screen->active_workspace,
NULL,
timestamp);
}
void
meta_core_lower_beneath_focus_window (Display *xdisplay,
Window xwindow,
guint32 timestamp)
{
XWindowChanges changes;
MetaDisplay *display;
MetaScreen *screen;
MetaWindow *focus_window;
display = meta_display_for_x_display (xdisplay);
screen = meta_display_screen_for_xwindow (display, xwindow);
focus_window = meta_stack_get_top (screen->stack);
if (focus_window == NULL)
return;
changes.stack_mode = Below;
changes.sibling = focus_window->frame ? focus_window->frame->xwindow
: focus_window->xwindow;
meta_stack_tracker_record_lower_below (screen->stack_tracker,
xwindow,
changes.sibling,
XNextRequest (screen->display->xdisplay));
meta_error_trap_push (display);
XConfigureWindow (xdisplay,
xwindow,
CWSibling | CWStackMode,
&changes);
meta_error_trap_pop (display);
}
void
@ -526,6 +517,9 @@ meta_core_get_menu_accelerator (MetaMenuOp menu_op,
switch (menu_op)
{
case META_MENU_OP_NONE:
/* No keybinding for this one */
break;
case META_MENU_OP_DELETE:
name = "close";
break;

View File

@ -22,8 +22,7 @@
* 02111-1307, USA.
*/
#define _GNU_SOURCE
#define _SVID_SOURCE /* for gethostname() */
#define _XOPEN_SOURCE /* for kill() */
#include <config.h>
#include "util.h"
@ -32,6 +31,7 @@
#include "workspace.h"
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
@ -136,7 +136,7 @@ meta_window_delete (MetaWindow *window,
window->desc);
XKillClient (window->display->xdisplay, window->xwindow);
}
meta_error_trap_pop (window->display, FALSE);
meta_error_trap_pop (window->display);
meta_display_ping_window (window->display,
window,
@ -178,42 +178,29 @@ meta_window_delete (MetaWindow *window,
void
meta_window_kill (MetaWindow *window)
{
char buf[257];
meta_topic (META_DEBUG_WINDOW_OPS,
"Killing %s brutally\n",
window->desc);
if (window->wm_client_machine != NULL &&
if (!meta_window_is_remote (window) &&
window->net_wm_pid > 0)
{
if (gethostname (buf, sizeof(buf)-1) == 0)
{
if (strcmp (buf, window->wm_client_machine) == 0)
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Killing %s with kill()\n",
window->desc);
meta_topic (META_DEBUG_WINDOW_OPS,
"Killing %s with kill()\n",
window->desc);
if (kill (window->net_wm_pid, 9) < 0)
meta_topic (META_DEBUG_WINDOW_OPS,
"Failed to signal %s: %s\n",
window->desc, strerror (errno));
}
}
else
{
meta_warning (_("Failed to get hostname: %s\n"),
strerror (errno));
}
if (kill (window->net_wm_pid, 9) < 0)
meta_topic (META_DEBUG_WINDOW_OPS,
"Failed to signal %s: %s\n",
window->desc, strerror (errno));
}
meta_topic (META_DEBUG_WINDOW_OPS,
"Disconnecting %s with XKillClient()\n",
window->desc);
meta_error_trap_push (window->display);
XKillClient (window->display->xdisplay, window->xwindow);
meta_error_trap_pop (window->display, FALSE);
meta_error_trap_pop (window->display);
}
void

View File

@ -83,10 +83,11 @@ struct _MetaDisplay
char *name;
Display *xdisplay;
char *hostname;
Window leader_window;
Window timestamp_pinging_window;
/* Pull in all the names of atoms as fields; we will intern them when the
* class is constructed.
*/
@ -184,6 +185,9 @@ struct _MetaDisplay
guint grab_have_pointer : 1;
guint grab_have_keyboard : 1;
guint grab_frame_action : 1;
/* During a resize operation, the directions in which we've broken
* out of the initial maximization state */
guint grab_resize_unmaximize : 2; /* MetaMaximizeFlags */
MetaRectangle grab_initial_window_pos;
int grab_initial_x, grab_initial_y; /* These are only relevant for */
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
@ -217,6 +221,7 @@ struct _MetaDisplay
KeySym *keymap;
int keysyms_per_keycode;
XModifierKeymap *modmap;
unsigned int above_tab_keycode;
unsigned int ignored_modifier_mask;
unsigned int num_lock_mask;
unsigned int scroll_lock_mask;
@ -303,22 +308,15 @@ struct _MetaDisplayClass
GObjectClass parent_class;
};
/* Xserver time can wraparound, thus comparing two timestamps needs to take
* this into account. Here's a little macro to help out. If no wraparound
* has occurred, this is equivalent to
* time1 < time2
* Of course, the rest of the ugliness of this macro comes from accounting
* for the fact that wraparound can occur and the fact that a timestamp of
* 0 must be special-cased since it means older than anything else.
*
* Note that this is NOT an equivalent for time1 <= time2; if that's what
* you need then you'll need to swap the order of the arguments and negate
* the result.
*/
#define XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) \
( (( (time1) < (time2) ) && ( (time2) - (time1) < ((guint32)-1)/2 )) || \
(( (time1) > (time2) ) && ( (time1) - (time2) > ((guint32)-1)/2 )) \
)
/**
* XSERVER_TIME_IS_BEFORE:
*
* See the docs for meta_display_xserver_time_is_before().
*/
#define XSERVER_TIME_IS_BEFORE(time1, time2) \
( (time1) == 0 || \
(XSERVER_TIME_IS_BEFORE_ASSUMING_REAL_TIMESTAMPS(time1, time2) && \
@ -436,4 +434,7 @@ void meta_display_remove_autoraise_callback (MetaDisplay *display);
void meta_display_overlay_key_activate (MetaDisplay *display);
/* In above-tab-keycode.c */
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
#endif

View File

@ -30,6 +30,8 @@
* The display is represented as a MetaDisplay struct.
*/
#define _XOPEN_SOURCE 600 /* for gethostname() */
#include <config.h>
#include "display-private.h"
#include "util.h"
@ -72,6 +74,7 @@
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xfixes.h>
#include <string.h>
#include <unistd.h>
#define GRAB_OP_IS_WINDOW_SWITCH(g) \
(g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \
@ -344,7 +347,7 @@ sn_error_trap_pop (SnDisplay *sn_display,
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
if (display != NULL)
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
#endif
@ -384,26 +387,6 @@ enable_compositor (MetaDisplay *display,
}
}
static void
disable_compositor (MetaDisplay *display)
{
GSList *list;
if (!display->compositor)
return;
for (list = display->screens; list != NULL; list = list->next)
{
MetaScreen *screen = list->data;
meta_compositor_unmanage_screen (screen->display->compositor,
screen);
}
meta_compositor_destroy (display->compositor);
display->compositor = NULL;
}
static void
meta_display_init (MetaDisplay *disp)
{
@ -429,6 +412,7 @@ meta_display_open (void)
GSList *tmp;
int i;
guint32 timestamp;
char buf[257];
/* A list of all atom names, so that we can intern them in one go. */
char *atom_names[] = {
@ -463,6 +447,11 @@ meta_display_open (void)
*/
the_display->name = g_strdup (XDisplayName (NULL));
the_display->xdisplay = xdisplay;
if (gethostname (buf, sizeof(buf)-1) == 0)
{
buf[sizeof(buf)-1] = '\0';
the_display->hostname = g_strdup (buf);
}
the_display->error_trap_synced_at_last_pop = TRUE;
the_display->error_traps = 0;
the_display->error_trap_handler = NULL;
@ -830,8 +819,7 @@ meta_display_open (void)
/* We don't composite the windows here because they will be composited
faster with the call to meta_screen_manage_all_windows further down
the code */
if (1) /* meta_prefs_get_compositing_manager ()) FIXME */
enable_compositor (the_display, FALSE);
enable_compositor (the_display, FALSE);
meta_display_grab (the_display);
@ -881,7 +869,7 @@ meta_display_open (void)
timestamp);
}
meta_error_trap_pop (the_display, FALSE);
meta_error_trap_pop (the_display);
}
meta_display_ungrab (the_display);
@ -1090,7 +1078,7 @@ meta_display_screen_for_xwindow (MetaDisplay *display,
meta_error_trap_push (display);
attr.screen = NULL;
result = XGetWindowAttributes (display->xdisplay, xwindow, &attr);
meta_error_trap_pop (display, TRUE);
meta_error_trap_pop (display);
/* Note, XGetWindowAttributes is on all kinds of crack
* and returns 1 on success 0 on failure, rather than Success
@ -1320,6 +1308,43 @@ meta_grab_op_is_moving (MetaGrabOp op)
}
}
/**
* meta_display_xserver_time_is_before:
* @display: a #MetaDisplay
* @time1: An event timestamp
* @time2: An event timestamp
*
* Xserver time can wraparound, thus comparing two timestamps needs to take
* this into account. If no wraparound has occurred, this is equivalent to
* time1 < time2
* Otherwise, we need to account for the fact that wraparound can occur
* and the fact that a timestamp of 0 must be special-cased since it
* means "older than anything else".
*
* Note that this is NOT an equivalent for time1 <= time2; if that's what
* you need then you'll need to swap the order of the arguments and negate
* the result.
*/
gboolean
meta_display_xserver_time_is_before (MetaDisplay *display,
guint32 time1,
guint32 time2)
{
return XSERVER_TIME_IS_BEFORE(time1, time2);
}
/**
* meta_display_get_last_user_time:
* @display: a #MetaDisplay
*
* Returns: Timestamp of the last user interaction event with a window
*/
guint32
meta_display_get_last_user_time (MetaDisplay *display)
{
return display->last_user_time;
}
/* Get time of current event, or CurrentTime if none. */
guint32
meta_display_get_current_time (MetaDisplay *display)
@ -1446,7 +1471,7 @@ window_raise_with_delay_callback (void *data)
window->xwindow,
&root, &child,
&root_x, &root_y, &x, &y, &mask);
meta_error_trap_pop (window->display, TRUE);
meta_error_trap_pop (window->display);
point_in_window =
(window->frame && POINT_IN_RECT (root_x, root_y, window->frame->rect)) ||
@ -1689,7 +1714,8 @@ event_callback (XEvent *event,
}
#endif /* HAVE_SHAPE */
if (window && ((event->type == KeyPress) || (event->type == ButtonPress)))
if (window && !window->override_redirect &&
((event->type == KeyPress) || (event->type == ButtonPress)))
{
if (CurrentTime == display->current_time)
{
@ -2161,7 +2187,7 @@ event_callback (XEvent *event,
window->frame->xwindow);
meta_error_trap_push (display);
meta_window_destroy_frame (window->frame->window);
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
else
{
@ -2330,7 +2356,7 @@ event_callback (XEvent *event,
meta_error_trap_push (display);
XConfigureWindow (display->xdisplay, event->xconfigurerequest.window,
xwcm, &xwc);
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
else
{
@ -2595,6 +2621,10 @@ event_callback (XEvent *event,
meta_bell_notify (display, xkb_ev);
}
break;
case XkbNewKeyboardNotify:
case XkbMapNotify:
meta_display_process_mapping_event (display, event);
break;
}
}
#endif
@ -3101,7 +3131,7 @@ meta_spew_event (MetaDisplay *display,
meta_error_trap_push (display);
str = XGetAtomName (display->xdisplay,
event->xproperty.atom);
meta_error_trap_pop (display, TRUE);
meta_error_trap_pop (display);
if (event->xproperty.state == PropertyNewValue)
state = "PropertyNewValue";
@ -3135,7 +3165,7 @@ meta_spew_event (MetaDisplay *display,
meta_error_trap_push (display);
str = XGetAtomName (display->xdisplay,
event->xclient.message_type);
meta_error_trap_pop (display, TRUE);
meta_error_trap_pop (display);
extra = g_strdup_printf ("type: %s format: %d\n",
str ? str : "(unknown atom)",
event->xclient.format);
@ -3413,7 +3443,7 @@ meta_display_set_grab_op_cursor (MetaDisplay *display,
meta_topic (META_DEBUG_WINDOW_OPS,
"Changed pointer with XChangeActivePointerGrab()\n");
if (meta_error_trap_pop_with_return (display, FALSE) != Success)
if (meta_error_trap_pop_with_return (display) != Success)
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Error trapped from XChangeActivePointerGrab()\n");
@ -3446,7 +3476,7 @@ meta_display_set_grab_op_cursor (MetaDisplay *display,
"XGrabPointer() failed time %u\n",
timestamp);
}
meta_error_trap_pop (display, TRUE);
meta_error_trap_pop (display);
}
#undef GRAB_MASK
@ -3563,6 +3593,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
display->grab_last_user_action_was_snap = FALSE;
#endif
display->grab_frame_action = frame_action;
display->grab_resize_unmaximize = 0;
if (display->grab_resize_timeout_id)
{
@ -3621,7 +3652,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
XSyncCAEvents,
&values);
if (meta_error_trap_pop_with_return (display, FALSE) != Success)
if (meta_error_trap_pop_with_return (display) != Success)
display->grab_sync_request_alarm = None;
meta_topic (META_DEBUG_RESIZING,
@ -3840,7 +3871,7 @@ meta_change_button_grab (MetaDisplay *display,
{
int result;
result = meta_error_trap_pop_with_return (display, FALSE);
result = meta_error_trap_pop_with_return (display);
if (result != Success)
meta_verbose ("Failed to %s button %d with mask 0x%x for window 0x%lx error code %d\n",
@ -3851,7 +3882,7 @@ meta_change_button_grab (MetaDisplay *display,
++ignored_mask;
}
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
void
@ -4035,7 +4066,7 @@ meta_display_update_active_window_hint (MetaDisplay *display)
XA_WINDOW,
32, PropModeReplace, (guchar*) data, 1);
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
tmp = tmp->next;
}
@ -4132,8 +4163,8 @@ meta_set_syncing (gboolean setting)
if (setting != is_syncing)
{
is_syncing = setting;
XSynchronize (meta_get_display ()->xdisplay, is_syncing);
if (meta_get_display ())
XSynchronize (meta_get_display ()->xdisplay, is_syncing);
}
}
@ -4315,7 +4346,7 @@ process_request_frame_extents (MetaDisplay *display,
display->atom__NET_FRAME_EXTENTS,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 4);
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
meta_XFree (hints);
}
@ -4503,6 +4534,18 @@ find_tab_backward (MetaDisplay *display,
return NULL;
}
/**
* meta_display_get_tab_list:
* @display: a #MetaDisplay
* @type: type of tab list
* @screen: a #MetaScreen
* @workspace: origin workspace
*
* Determine the list of windows that should be displayed for Alt-TAB
* functionality. The windows are returned in most recently used order.
*
* Returns: (transfer container) (element-type Meta.Window): List of windows
*/
GList*
meta_display_get_tab_list (MetaDisplay *display,
MetaTabList type,
@ -4580,6 +4623,21 @@ meta_display_get_tab_list (MetaDisplay *display,
return tab_list;
}
/**
* meta_display_get_tab_next:
* @display: a #MetaDisplay
* @type: type of tab list
* @screen: a #MetaScreen
* @workspace: origin workspace
* @window: (allow-none): starting window
* @backward: If %TRUE, look for the previous window.
*
* Determine the next window that should be displayed for Alt-TAB
* functionality.
*
* Returns: (transfer none): Next window
*
*/
MetaWindow*
meta_display_get_tab_next (MetaDisplay *display,
MetaTabList type,
@ -4630,6 +4688,18 @@ meta_display_get_tab_next (MetaDisplay *display,
return ret;
}
/**
* meta_display_get_tab_current:
* @display: a #MetaDisplay
* @type: type of tab list
* @screen: a #MetaScreen
* @workspace: origin workspace
*
* Determine the active window that should be displayed for Alt-TAB.
*
* Returns: (transfer none): Current window
*
*/
MetaWindow*
meta_display_get_tab_current (MetaDisplay *display,
MetaTabList type,
@ -4754,11 +4824,11 @@ convert_property (MetaDisplay *display,
(unsigned char *)icccm_version, 2);
else
{
meta_error_trap_pop_with_return (display, FALSE);
meta_error_trap_pop_with_return (display);
return FALSE;
}
if (meta_error_trap_pop_with_return (display, FALSE) != Success)
if (meta_error_trap_pop_with_return (display) != Success)
return FALSE;
/* Be sure the PropertyNotify has arrived so we
@ -4790,7 +4860,7 @@ process_selection_request (MetaDisplay *display,
meta_error_trap_push (display);
str = XGetAtomName (display->xdisplay,
event->xselectionrequest.selection);
meta_error_trap_pop (display, TRUE);
meta_error_trap_pop (display);
meta_verbose ("Selection request with selection %s window 0x%lx not a WM_Sn selection we recognize\n",
str ? str : "(bad atom)", event->xselectionrequest.owner);
@ -4824,11 +4894,11 @@ process_selection_request (MetaDisplay *display,
display->atom_ATOM_PAIR,
&type, &format, &num, &rest, &data) != Success)
{
meta_error_trap_pop_with_return (display, TRUE);
meta_error_trap_pop_with_return (display);
return;
}
if (meta_error_trap_pop_with_return (display, TRUE) == Success)
if (meta_error_trap_pop_with_return (display) == Success)
{
/* FIXME: to be 100% correct, should deal with rest > 0,
* but since we have 4 possible targets, we will hardly ever
@ -4851,7 +4921,7 @@ process_selection_request (MetaDisplay *display,
event->xselectionrequest.property,
display->atom_ATOM_PAIR,
32, PropModeReplace, data, num);
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
meta_XFree (data);
}
}
@ -4907,7 +4977,7 @@ process_selection_clear (MetaDisplay *display,
meta_error_trap_push (display);
str = XGetAtomName (display->xdisplay,
event->xselectionclear.selection);
meta_error_trap_pop (display, TRUE);
meta_error_trap_pop (display);
meta_verbose ("Selection clear with selection %s window 0x%lx not a WM_Sn selection we recognize\n",
str ? str : "(bad atom)", event->xselectionclear.window);
@ -4974,6 +5044,34 @@ meta_display_stack_cmp (const void *a,
return 0; /* not reached in theory, if windows on same display */
}
/**
* meta_display_sort_windows_by_stacking:
* @display: a #MetaDisplay
* @windows: (element-type MetaWindow): Set of windows
*
* Sorts a set of windows according to their current stacking order. If windows
* from multiple screens are present in the set of input windows, then all the
* windows on screen 0 are sorted below all the windows on screen 1, and so forth.
* Since the stacking order of override-redirect windows isn't controlled by
* Metacity, if override-redirect windows are in the input, the result may not
* correspond to the actual stacking order in the X server.
*
* An example of using this would be to sort the list of transient dialogs for a
* window into their current stacking order.
*
* Returns: (transfer container): Input windows sorted by stacking order, from lowest to highest
*/
GSList *
meta_display_sort_windows_by_stacking (MetaDisplay *display,
GSList *windows)
{
GSList *copy = g_slist_copy (windows);
copy = g_slist_sort (copy, meta_display_stack_cmp);
return copy;
}
void
meta_display_devirtualize_modifiers (MetaDisplay *display,
MetaVirtualModifier modifiers,
@ -5069,14 +5167,33 @@ prefs_changed_callback (MetaPreference pref,
{
meta_bell_set_audible (display, meta_prefs_bell_is_audible ());
}
else if (pref == META_PREF_COMPOSITING_MANAGER)
else if (pref == META_PREF_ATTACH_MODAL_DIALOGS)
{
gboolean cm = meta_prefs_get_compositing_manager ();
MetaDisplay *display = data;
GSList *windows;
GSList *tmp;
if (cm)
enable_compositor (display, TRUE);
else
disable_compositor (display);
windows = meta_display_list_windows (display, META_LIST_DEFAULT);
for (tmp = windows; tmp != NULL; tmp = tmp->next)
{
MetaWindow *w = tmp->data;
MetaWindow *parent = meta_window_get_transient_for (w);
meta_window_recalc_features (w);
if (w->type == META_WINDOW_MODAL_DIALOG && parent && parent != w)
{
int x, y;
/* Forcing a call to move_resize() does two things: first, it handles
* resizing the dialog frame window to the correct size when we remove
* or add the decorations. Second, it will take care of positioning the
* dialog as "attached" to the parent when we turn the preference on
* via the constrain_modal_dialog() constraint.
**/
meta_window_get_position (w, &x, &y);
meta_window_move (w, FALSE, x, y);
}
}
}
}
@ -5223,7 +5340,7 @@ meta_display_set_input_focus_window (MetaDisplay *display,
focus_frame ? window->frame->xwindow : window->xwindow,
RevertToPointerRoot,
timestamp);
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
display->expected_focus_window = window;
display->last_focus_time = timestamp;
@ -5278,18 +5395,32 @@ meta_display_get_compositor_version (MetaDisplay *display,
*minor = display->composite_minor_version;
}
/**
* meta_display_get_xdisplay: (skip)
*
*/
Display *
meta_display_get_xdisplay (MetaDisplay *display)
{
return display->xdisplay;
}
/**
* meta_display_get_compositor: (skip)
*
*/
MetaCompositor *
meta_display_get_compositor (MetaDisplay *display)
{
return display->compositor;
}
/**
* meta_display_get_screens:
* @display: a #MetaDisplay
*
* Returns: (transfer none) (element-type Meta.Screen): Screens for this display
*/
GSList *
meta_display_get_screens (MetaDisplay *display)
{
@ -5334,9 +5465,32 @@ meta_display_get_shape_event_base (MetaDisplay *display)
}
#endif
/**
* meta_display_get_atom: (skip)
*
* Gets up an X atom that Mutter prefetched at startup.
*
* Return value: the X atom corresponding to the given atom enumeration
*/
Atom meta_display_get_atom (MetaDisplay *display, MetaAtom meta_atom)
{
Atom *atoms = & display->atom_WM_PROTOCOLS;
return atoms[meta_atom - 1];
}
/**
* meta_display_get_leader_window:
* @display: a #MetaDisplay
*
* Returns the window manager's leader window (as defined by the
* _NET_SUPPORTING_WM_CHECK mechanism of EWMH). For use by plugins that wish
* to attach additional custom properties to this window.
*
* Return value: (transfer none): xid of the leader window.
**/
Window
meta_display_get_leader_window (MetaDisplay *display)
{
return display->leader_window;
}

View File

@ -23,7 +23,7 @@
#include <config.h>
#include "edge-resistance.h"
#include "boxes.h"
#include "boxes-private.h"
#include "display-private.h"
#include "workspace-private.h"

View File

@ -29,221 +29,38 @@
#include <stdlib.h>
#include <gdk/gdk.h>
static int x_error_handler (Display *display,
XErrorEvent *error);
static int x_io_error_handler (Display *display);
void
meta_errors_init (void)
{
XSetErrorHandler (x_error_handler);
XSetIOErrorHandler (x_io_error_handler);
}
static void
meta_error_trap_push_internal (MetaDisplay *display,
gboolean need_sync)
{
/* GDK resets the error handler on each push */
int (* old_error_handler) (Display *,
XErrorEvent *);
if (need_sync)
{
XSync (display->xdisplay, False);
}
gdk_error_trap_push ();
/* old_error_handler will just be equal to x_error_handler
* for nested traps
*/
old_error_handler = XSetErrorHandler (x_error_handler);
/* Replace GDK handler, but save it so we can chain up */
if (display->error_trap_handler == NULL)
{
g_assert (display->error_traps == 0);
display->error_trap_handler = old_error_handler;
g_assert (display->error_trap_handler != x_error_handler);
}
display->error_traps += 1;
meta_topic (META_DEBUG_ERRORS, "%d traps remain\n", display->error_traps);
}
static int
meta_error_trap_pop_internal (MetaDisplay *display,
gboolean need_sync)
{
int result;
g_assert (display->error_traps > 0);
if (need_sync)
{
XSync (display->xdisplay, False);
}
result = gdk_error_trap_pop ();
display->error_traps -= 1;
if (display->error_traps == 0)
{
/* check that GDK put our handler back; this
* assumes that there are no pending GDK traps from GDK itself
*/
int (* restored_error_handler) (Display *,
XErrorEvent *);
restored_error_handler = XSetErrorHandler (x_error_handler);
/* remove this */
display->error_trap_handler = NULL;
}
meta_topic (META_DEBUG_ERRORS, "%d traps\n", display->error_traps);
return result;
}
/* In GTK+-3.0, the error trapping code was significantly rewritten. The new code
* has some neat features (like knowing automatically if a sync is needed or not
* and handling errors asynchronously when the error code isn't needed immediately),
* but it's basically incompatible with the hacks we played with GTK+-2.0 to
* use a custom error handler along with gdk_error_trap_push().
*
* Since the main point of our custom error trap was to get the error logged
* to the right place, with GTK+-3.0 we simply omit our own error handler and
* use the GTK+ handling straight-up.
* (See https://bugzilla.gnome.org/show_bug.cgi?id=630216 for restoring logging.)
*/
void
meta_error_trap_push (MetaDisplay *display)
{
meta_error_trap_push_internal (display, FALSE);
gdk_error_trap_push ();
}
void
meta_error_trap_pop (MetaDisplay *display,
gboolean last_request_was_roundtrip)
meta_error_trap_pop (MetaDisplay *display)
{
gboolean need_sync;
/* we only have to sync when popping the outermost trap */
need_sync = (display->error_traps == 1 && !last_request_was_roundtrip);
if (need_sync)
meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_pop, traps = %d, roundtrip = %d\n",
display->error_traps, last_request_was_roundtrip);
display->error_trap_synced_at_last_pop = need_sync || last_request_was_roundtrip;
meta_error_trap_pop_internal (display, need_sync);
gdk_error_trap_pop_ignored ();
}
void
meta_error_trap_push_with_return (MetaDisplay *display)
{
gboolean need_sync;
/* We don't sync on push_with_return if there are no traps
* currently, because we assume that any errors were either covered
* by a previous pop, or were fatal.
*
* More generally, we don't sync if we were synchronized last time
* we popped. This is known to be the case if there are no traps,
* but we also keep a flag so we know whether it's the case otherwise.
*/
if (!display->error_trap_synced_at_last_pop)
need_sync = TRUE;
else
need_sync = FALSE;
if (need_sync)
meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_push_with_return, traps = %d\n",
display->error_traps);
meta_error_trap_push_internal (display, FALSE);
gdk_error_trap_push ();
}
int
meta_error_trap_pop_with_return (MetaDisplay *display,
gboolean last_request_was_roundtrip)
meta_error_trap_pop_with_return (MetaDisplay *display)
{
if (!last_request_was_roundtrip)
meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_pop_with_return, traps = %d, roundtrip = %d\n",
display->error_traps, last_request_was_roundtrip);
display->error_trap_synced_at_last_pop = TRUE;
return meta_error_trap_pop_internal (display,
!last_request_was_roundtrip);
}
static int
x_error_handler (Display *xdisplay,
XErrorEvent *error)
{
int retval;
gchar buf[64];
MetaDisplay *display;
XGetErrorText (xdisplay, error->error_code, buf, 63);
display = meta_display_for_x_display (xdisplay);
/* Display can be NULL here Xlib only has one global error handler; and
* there might be other displays open in the process.
*/
if (display && display->error_traps > 0)
{
/* we're in an error trap, chain to the trap handler
* saved from GDK
*/
meta_verbose ("X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
buf,
error->serial,
error->error_code,
error->request_code,
error->minor_code);
g_assert (display->error_trap_handler != NULL);
g_assert (display->error_trap_handler != x_error_handler);
retval = (* display->error_trap_handler) (xdisplay, error);
}
else
{
meta_bug ("Unexpected X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
buf,
error->serial,
error->error_code,
error->request_code,
error->minor_code);
retval = 1; /* compiler warning */
}
return retval;
}
static int
x_io_error_handler (Display *xdisplay)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
if (errno == EPIPE)
{
meta_warning (_("Lost connection to the display '%s';\n"
"most likely the X server was shut down or you killed/destroyed\n"
"the window manager.\n"),
display ? display->name : DisplayString (xdisplay));
}
else
{
meta_warning (_("Fatal IO error %d (%s) on display '%s'.\n"),
errno, g_strerror (errno),
display ? display->name : DisplayString (xdisplay));
}
/* Xlib would force an exit anyhow */
exit (1);
return 0;
return gdk_error_trap_pop ();
}

View File

@ -153,7 +153,7 @@ meta_window_ensure_frame (MetaWindow *window)
window->rect.x,
window->rect.y);
/* FIXME handle this error */
meta_error_trap_pop (window->display, FALSE);
meta_error_trap_pop (window->display);
/* stick frame to the window */
window->frame = frame;
@ -217,7 +217,7 @@ meta_window_destroy_frame (MetaWindow *window)
*/
window->frame->rect.x,
window->frame->rect.y);
meta_error_trap_pop (window->display, FALSE);
meta_error_trap_pop (window->display);
meta_ui_destroy_frame_window (window->screen->ui, frame->xwindow);
@ -276,7 +276,7 @@ meta_frame_get_flags (MetaFrame *frame)
if (META_WINDOW_ALLOWS_VERTICAL_RESIZE (frame->window))
flags |= META_FRAME_ALLOWS_VERTICAL_RESIZE;
if (frame->window->has_focus)
if (meta_window_appears_focused (frame->window))
flags |= META_FRAME_HAS_FOCUS;
if (frame->window->shaded)
@ -291,6 +291,12 @@ meta_frame_get_flags (MetaFrame *frame)
if (META_WINDOW_MAXIMIZED (frame->window))
flags |= META_FRAME_MAXIMIZED;
if (META_WINDOW_TILED_LEFT (frame->window))
flags |= META_FRAME_TILED_LEFT;
if (META_WINDOW_TILED_RIGHT (frame->window))
flags |= META_FRAME_TILED_RIGHT;
if (frame->window->fullscreen)
flags |= META_FRAME_FULLSCREEN;

View File

@ -104,6 +104,10 @@ meta_group_unref (MetaGroup *group)
}
}
/**
* meta_window_get_group: (skip)
*
*/
MetaGroup*
meta_window_get_group (MetaWindow *window)
{
@ -198,6 +202,10 @@ meta_window_shutdown_group (MetaWindow *window)
remove_window_from_group (window);
}
/**
* meta_display_lookup_group: (skip)
*
*/
MetaGroup*
meta_display_lookup_group (MetaDisplay *display,
Window group_leader)
@ -213,6 +221,12 @@ meta_display_lookup_group (MetaDisplay *display,
return group;
}
/**
* meta_group_list_windows:
* @group: A #MetaGroup
*
* Returns: (transfer container) (element-type Meta.Window): List of windows
*/
GSList*
meta_group_list_windows (MetaGroup *group)
{
@ -263,6 +277,10 @@ meta_group_get_startup_id (MetaGroup *group)
return group->startup_id;
}
/**
* meta_group_property_notify: (skip)
*
*/
gboolean
meta_group_property_notify (MetaGroup *group,
XEvent *event)

View File

@ -241,7 +241,7 @@ read_rgb_icon (MetaDisplay *display,
0, G_MAXLONG,
False, XA_CARDINAL, &type, &format, &nitems,
&bytes_after, &data);
err = meta_error_trap_pop_with_return (display, TRUE);
err = meta_error_trap_pop_with_return (display);
if (err != Success ||
result != Success)
@ -394,21 +394,19 @@ try_pixmap_and_mask (MetaDisplay *display,
get_pixmap_geometry (display, src_pixmap, &w, &h, NULL);
unscaled = meta_gdk_pixbuf_get_from_pixmap (NULL,
src_pixmap,
0, 0, 0, 0,
unscaled = meta_gdk_pixbuf_get_from_pixmap (src_pixmap,
0, 0,
w, h);
if (unscaled && src_mask != None)
{
get_pixmap_geometry (display, src_mask, &w, &h, NULL);
mask = meta_gdk_pixbuf_get_from_pixmap (NULL,
src_mask,
0, 0, 0, 0,
mask = meta_gdk_pixbuf_get_from_pixmap (src_mask,
0, 0,
w, h);
}
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
if (mask)
{
@ -484,7 +482,7 @@ get_kwm_win_icon (MetaDisplay *display,
&bytes_after, &data);
icons = (Pixmap *)data;
err = meta_error_trap_pop_with_return (display, TRUE);
err = meta_error_trap_pop_with_return (display);
if (err != Success ||
result != Success)
return;

View File

@ -117,6 +117,10 @@ reload_keymap (MetaDisplay *display)
if (display->keymap)
meta_XFree (display->keymap);
/* This is expensive to compute, so we'll lazily load if and when we first
* need it */
display->above_tab_keycode = 0;
display->keymap = XGetKeyboardMapping (display->xdisplay,
display->min_keycode,
display->max_keycode -
@ -228,17 +232,26 @@ reload_modmap (MetaDisplay *display)
display->meta_mask);
}
static guint
keysym_to_keycode (MetaDisplay *display,
guint keysym)
{
if (keysym == META_KEY_ABOVE_TAB)
return meta_display_get_above_tab_keycode (display);
else
return XKeysymToKeycode (display->xdisplay, keysym);
}
static void
reload_keycodes (MetaDisplay *display)
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Reloading keycodes for binding tables\n");
if (display->overlay_key_combo.keysym
&& display->overlay_key_combo.keycode == 0)
if (display->overlay_key_combo.keysym != 0)
{
display->overlay_key_combo.keycode = XKeysymToKeycode (
display->xdisplay, display->overlay_key_combo.keysym);
display->overlay_key_combo.keycode =
keysym_to_keycode (display, display->overlay_key_combo.keysym);
}
if (display->key_bindings)
@ -248,9 +261,11 @@ reload_keycodes (MetaDisplay *display)
i = 0;
while (i < display->n_key_bindings)
{
if (display->key_bindings[i].keycode == 0)
display->key_bindings[i].keycode = XKeysymToKeycode (
display->xdisplay, display->key_bindings[i].keysym);
if (display->key_bindings[i].keysym != 0)
{
display->key_bindings[i].keycode =
keysym_to_keycode (display, display->key_bindings[i].keysym);
}
++i;
}
@ -470,7 +485,7 @@ regrab_key_bindings (MetaDisplay *display)
tmp = tmp->next;
}
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
g_slist_free (windows);
}
@ -499,14 +514,25 @@ display_get_keybinding (MetaDisplay *display,
return NULL;
}
static MetaKeyBindingAction
display_get_keybinding_action (MetaDisplay *display,
unsigned int keysym,
unsigned int keycode,
unsigned long mask)
/**
* meta_display_get_keybinding_action:
* @display: A #MetaDisplay
* @keycode: Raw keycode
* @mask: Event mask
*
* Returns: The action that should be taken for the given key, or
* %META_KEYBINDING_ACTION_NONE.
*/
MetaKeyBindingAction
meta_display_get_keybinding_action (MetaDisplay *display,
unsigned int keycode,
unsigned long mask)
{
MetaKeyBinding *binding;
KeySym keysym;
keysym = XKeycodeToKeysym (display->xdisplay, keycode, 0);
mask = mask & 0xff & ~display->ignored_modifier_mask;
binding = display_get_keybinding (display, keysym, keycode, mask);
if (binding)
@ -519,26 +545,51 @@ void
meta_display_process_mapping_event (MetaDisplay *display,
XEvent *event)
{
gboolean keymap_changed = FALSE;
gboolean modmap_changed = FALSE;
#ifdef HAVE_XKB
if (event->type == display->xkb_base_event_type)
{
meta_topic (META_DEBUG_KEYBINDINGS,
"XKB mapping changed, will redo keybindings\n");
keymap_changed = TRUE;
modmap_changed = TRUE;
}
else
#endif
if (event->xmapping.request == MappingModifier)
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Received MappingModifier event, will reload modmap and redo keybindings\n");
reload_modmap (display);
reload_modifiers (display);
regrab_key_bindings (display);
modmap_changed = TRUE;
}
else if (event->xmapping.request == MappingKeyboard)
{
meta_topic (META_DEBUG_KEYBINDINGS,
"Received MappingKeyboard event, will reload keycodes and redo keybindings\n");
reload_keymap (display);
keymap_changed = TRUE;
}
/* Now to do the work itself */
if (keymap_changed || modmap_changed)
{
if (keymap_changed)
reload_keymap (display);
/* Deciphering the modmap depends on the loaded keysyms to find out
* what modifiers is Super and so forth, so we need to reload it
* even when only the keymap changes */
reload_modmap (display);
reload_keycodes (display);
if (keymap_changed)
reload_keycodes (display);
reload_modifiers (display);
regrab_key_bindings (display);
}
@ -606,6 +657,14 @@ meta_display_init_keys (MetaDisplay *display)
/* Keys are actually grabbed in meta_screen_grab_keys() */
meta_prefs_add_listener (bindings_changed_callback, display);
#ifdef HAVE_XKB
/* meta_display_init_keys() should have already called XkbQueryExtension() */
if (display->xkb_base_event_type != -1)
XkbSelectEvents (display->xdisplay, XkbUseCoreKbd,
XkbNewKeyboardNotifyMask | XkbMapNotifyMask,
XkbNewKeyboardNotifyMask | XkbMapNotifyMask);
#endif
}
void
@ -689,7 +748,7 @@ meta_change_keygrab (MetaDisplay *display,
{
int result;
result = meta_error_trap_pop_with_return (display, FALSE);
result = meta_error_trap_pop_with_return (display);
if (grab && result != Success)
{
@ -705,7 +764,7 @@ meta_change_keygrab (MetaDisplay *display,
++ignored_mask;
}
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
static void
@ -747,7 +806,7 @@ grab_keys (MetaKeyBinding *bindings,
++i;
}
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
static void
@ -766,14 +825,14 @@ ungrab_all_keys (MetaDisplay *display,
{
int result;
result = meta_error_trap_pop_with_return (display, FALSE);
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);
}
else
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
void
@ -905,7 +964,7 @@ grab_keyboard (MetaDisplay *display,
if (grab_status != GrabSuccess)
{
meta_error_trap_pop_with_return (display, TRUE);
meta_error_trap_pop_with_return (display);
meta_topic (META_DEBUG_KEYBINDINGS,
"XGrabKeyboard() returned failure status %s time %u\n",
grab_status_to_string (grab_status),
@ -914,7 +973,7 @@ grab_keyboard (MetaDisplay *display,
}
else
{
result = meta_error_trap_pop_with_return (display, TRUE);
result = meta_error_trap_pop_with_return (display);
if (result != Success)
{
meta_topic (META_DEBUG_KEYBINDINGS,
@ -937,7 +996,7 @@ ungrab_keyboard (MetaDisplay *display, guint32 timestamp)
"Ungrabbing keyboard with timestamp %u\n",
timestamp);
XUngrabKeyboard (display->xdisplay, timestamp);
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
gboolean
@ -1362,8 +1421,7 @@ meta_display_process_key_event (MetaDisplay *display,
return FALSE; /* event window is destroyed */
/* ignore key events on popup menus and such. */
if (window == NULL &&
meta_ui_window_is_widget (screen->ui, event->xany.window))
if (meta_ui_window_is_widget (screen->ui, event->xany.window))
return FALSE;
/* window may be NULL */
@ -2098,6 +2156,16 @@ process_tab_grab (MetaDisplay *display,
return TRUE;
}
break;
case META_KEYBINDING_ACTION_NONE:
{
/*
* If this is simply user pressing the Shift key, we do not want
* to cancel the grab.
*/
if (is_modifier (display, event->xkey.keycode))
return TRUE;
}
default:
break;
}
@ -2756,10 +2824,9 @@ process_workspace_switch_grab (MetaDisplay *display,
MetaWorkspace *target_workspace;
MetaKeyBindingAction action;
action = display_get_keybinding_action (display,
keysym,
event->xkey.keycode,
display->grab_mask);
action = meta_display_get_keybinding_action (display,
event->xkey.keycode,
display->grab_mask);
switch (action)
{
@ -2879,7 +2946,7 @@ handle_panel (MetaDisplay *display,
StructureNotifyMask,
(XEvent*) &ev);
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
static void
@ -3526,6 +3593,10 @@ meta_keybindings_set_custom_handler (const gchar *name,
return TRUE;
}
/**
* meta_keybindings_switch_window: (skip)
*
*/
void
meta_keybindings_switch_window (MetaDisplay *display,
MetaScreen *screen,

View File

@ -75,7 +75,7 @@
#ifdef HAVE_INTROSPECTION
#include <girepository.h>
#include "compositor/mutter-plugin-manager.h"
#include "compositor/meta-plugin-manager.h"
#endif
/**
@ -296,18 +296,6 @@ meta_parse_options (int *argc, char ***argv,
N_("Make X calls synchronous"),
NULL
},
{
"composite", 'c', COMPOSITE_OPTS_FLAGS, G_OPTION_ARG_NONE,
&my_args.composite,
N_("Turn compositing on"),
NULL
},
{
"no-composite", 0, COMPOSITE_OPTS_FLAGS, G_OPTION_ARG_NONE,
&my_args.no_composite,
N_("Turn compositing off"),
NULL
},
{
"no-force-fullscreen", 0, COMPOSITE_OPTS_FLAGS, G_OPTION_ARG_NONE,
&my_args.no_force_fullscreen,
@ -401,7 +389,7 @@ static GSourceFuncs event_funcs = {
static void
meta_clutter_init (GOptionContext *ctx, int *argc, char ***argv)
{
clutter_x11_set_display (gdk_display);
clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
clutter_x11_disable_event_retrieval ();
if (CLUTTER_INIT_SUCCESS == clutter_init (argc, argv))
@ -586,8 +574,8 @@ main (int argc, char **argv)
* is initialized at this point, and we don't plan to run any real
* plugin code.
*/
MutterPluginManager *mgr = mutter_plugin_manager_new (NULL);
if (!mutter_plugin_manager_load (mgr))
MetaPluginManager *mgr = meta_plugin_manager_get_default ();
if (!meta_plugin_manager_load (mgr))
g_critical ("failed to load plugins");
}
if (!g_irepository_dump (meta_args.introspect, &error))
@ -623,9 +611,6 @@ main (int argc, char **argv)
g_option_context_free (ctx);
/* must be after UI init so we can override GDK handlers */
meta_errors_init ();
/* Load prefs */
meta_prefs_init ();
meta_prefs_add_listener (prefs_changed_callback, NULL);
@ -708,9 +693,6 @@ main (int argc, char **argv)
g_free (meta_args.display_name);
g_free (meta_args.client_id);
if (meta_args.composite || meta_args.no_composite)
meta_prefs_set_compositing_manager (meta_args.composite);
if (meta_args.no_force_fullscreen)
meta_prefs_set_force_fullscreen (FALSE);

View File

@ -26,6 +26,7 @@
#include <config.h>
#include "boxes-private.h"
#include "place.h"
#include "workspace.h"
#include "prefs.h"

View File

@ -27,6 +27,7 @@
#include "prefs.h"
#include "ui.h"
#include "util.h"
#include "compositor/meta-plugin-manager.h"
#ifdef HAVE_GCONF
#include <gconf/gconf-client.h>
#endif
@ -49,7 +50,6 @@
*/
#define KEY_TITLEBAR_FONT "/apps/metacity/general/titlebar_font"
#define KEY_NUM_WORKSPACES "/apps/metacity/general/num_workspaces"
#define KEY_COMPOSITOR "/apps/metacity/general/compositing_manager"
#define KEY_GNOME_ACCESSIBILITY "/desktop/gnome/interface/accessibility"
#define KEY_COMMAND_DIRECTORY "/apps/metacity/keybinding_commands"
@ -85,6 +85,7 @@ static MetaVirtualModifier mouse_button_mods = Mod1Mask;
static MetaFocusMode focus_mode = META_FOCUS_MODE_CLICK;
static MetaFocusNewWindows focus_new_windows = META_FOCUS_NEW_WINDOWS_SMART;
static gboolean raise_on_click = TRUE;
static gboolean attach_modal_dialogs = FALSE;
static char* current_theme = NULL;
static int num_workspaces = 4;
static MetaActionTitlebar action_double_click_titlebar = META_ACTION_TITLEBAR_TOGGLE_MAXIMIZE;
@ -100,8 +101,8 @@ static gboolean gnome_accessibility = FALSE;
static gboolean gnome_animations = TRUE;
static char *cursor_theme = NULL;
static int cursor_size = 24;
static gboolean compositing_manager = FALSE;
static gboolean resize_with_right_button = FALSE;
static gboolean edge_tiling = FALSE;
static gboolean force_fullscreen = TRUE;
static MetaVisualBellType visual_bell_type = META_VISUAL_BELL_FULLSCREEN_FLASH;
@ -146,6 +147,8 @@ static gboolean update_command (const char *name,
static gboolean update_workspace_name (const char *name,
const char *value);
static void notify_new_value (const char *key,
GConfValue *value);
static void change_notify (GConfClient *client,
guint cnxn_id,
GConfEntry *entry,
@ -228,7 +231,12 @@ static GConfEnumStringPair symtab_titlebar_action[] =
{ 0, NULL },
};
/**
/*
* Note that 'gchar *key' is the first element of all these structures;
* we count on that below in key_is_used and do_override.
*/
/*
* The details of one preference which is constrained to be
* one of a small number of string values-- in other words,
* an enumeration.
@ -241,21 +249,6 @@ static GConfEnumStringPair symtab_titlebar_action[] =
* been outweighed by the bugs caused when the ordering of the enum
* strings got out of sync with the actual enum statement. Also,
* there is existing library code to use this kind of symbol tables.
*
* Other things we might consider doing to clean this up in the
* future include:
*
* - most of the keys begin with the same prefix, and perhaps we
* could assume it if they don't start with a slash
*
* - there are several cases where a single identifier could be used
* to generate an entire entry, and perhaps this could be done
* with a macro. (This would reduce clarity, however, and is
* probably a bad thing.)
*
* - these types all begin with a gchar* (and contain a MetaPreference)
* and we can factor out the repeated code in the handlers by taking
* advantage of this using some kind of union arrangement.
*/
typedef struct
{
@ -368,6 +361,11 @@ static MetaEnumPreference preferences_enum[] =
static MetaBoolPreference preferences_bool[] =
{
{ "/apps/mutter/general/attach_modal_dialogs",
META_PREF_ATTACH_MODAL_DIALOGS,
&attach_modal_dialogs,
TRUE,
},
{ "/apps/metacity/general/raise_on_click",
META_PREF_RAISE_ON_CLICK,
&raise_on_click,
@ -413,16 +411,16 @@ static MetaBoolPreference preferences_bool[] =
&gnome_animations,
TRUE,
},
{ "/apps/metacity/general/compositing_manager",
META_PREF_COMPOSITING_MANAGER,
&compositing_manager,
FALSE,
},
{ "/apps/metacity/general/resize_with_right_button",
META_PREF_RESIZE_WITH_RIGHT_BUTTON,
&resize_with_right_button,
FALSE,
},
{ "/apps/metacity/general/edge_tiling",
META_PREF_EDGE_TILING,
&edge_tiling,
FALSE,
},
{ "/apps/mutter/general/live_hidden_windows",
META_PREF_LIVE_HIDDEN_WINDOWS,
&live_hidden_windows,
@ -496,6 +494,20 @@ static MetaIntPreference preferences_int[] =
{ NULL, 0, NULL, 0, 0, 0, },
};
/*
* This is used to keep track of preferences that have been
* repointed to a different GConf key location; we modify the
* preferences arrays directly, but we also need to remember
* what we have done to handle subsequent overrides correctly.
*/
typedef struct
{
gchar *original_key;
gchar *new_key;
} MetaPrefsOverriddenKey;
static GSList *overridden_keys;
static void
handle_preference_init_enum (void)
{
@ -879,6 +891,10 @@ handle_preference_update_int (const gchar *key, GConfValue *value)
/* Listeners. */
/****************************************************************************/
/**
* meta_prefs_add_listener: (skip)
*
*/
void
meta_prefs_add_listener (MetaPrefsChangedFunc func,
gpointer data)
@ -892,6 +908,10 @@ meta_prefs_add_listener (MetaPrefsChangedFunc func,
listeners = g_list_prepend (listeners, l);
}
/**
* meta_prefs_remove_listener: (skip)
*
*/
void
meta_prefs_remove_listener (MetaPrefsChangedFunc func,
gpointer data)
@ -1031,6 +1051,7 @@ meta_prefs_init (void)
#ifdef HAVE_GCONF
GError *err = NULL;
gchar **gconf_dir_cursor;
MetaPluginManager *plugin_manager;
if (default_client != NULL)
return;
@ -1049,12 +1070,7 @@ meta_prefs_init (void)
cleanup_error (&err);
}
/* Pick up initial values. */
handle_preference_init_enum ();
handle_preference_init_bool ();
handle_preference_init_string ();
handle_preference_init_int ();
/* The plugin list is special and needs to be handled first */
if (!clutter_plugins_overridden)
clutter_plugins = gconf_client_get_list (default_client, KEY_CLUTTER_PLUGINS,
@ -1062,6 +1078,18 @@ meta_prefs_init (void)
cleanup_error (&err);
/* We now initialize plugins so that they can override any preference locations */
plugin_manager = meta_plugin_manager_get_default ();
meta_plugin_manager_load (plugin_manager);
/* Pick up initial values. */
handle_preference_init_enum ();
handle_preference_init_bool ();
handle_preference_init_string ();
handle_preference_init_int ();
/* @@@ Is there any reason we don't do the add_dir here? */
for (gconf_dir_cursor=gconf_dirs_we_are_interested_in;
*gconf_dir_cursor!=NULL;
@ -1094,6 +1122,160 @@ meta_prefs_init (void)
init_workspace_names ();
}
/* This count on the key being the first element of the
* preference structure */
static gboolean
key_is_used (void *prefs,
size_t pref_size,
const char *new_key)
{
void *p = prefs;
while (TRUE)
{
char **key = p;
if (*key == NULL)
break;
if (strcmp (*key, new_key) == 0)
return TRUE;
p = (guchar *)p + pref_size;
}
return FALSE;
}
static gboolean
do_override (void *prefs,
size_t pref_size,
const char *search_key,
char *new_key)
{
void *p = prefs;
while (TRUE)
{
char **key = p;
if (*key == NULL)
break;
if (strcmp (*key, search_key) == 0)
{
*key = new_key;
return TRUE;
}
p = (guchar *)p + pref_size;
}
return FALSE;
}
/**
* meta_prefs_override_preference_location
* @original_key: the normal Metacity preference location
* @new_key: the Metacity preference location to use instead.
*
* Substitute a different location to use instead of a standard Metacity
* GConf key location. This might be used if a plugin expected a different
* value for some preference than the Metacity default. While this function
* can be called at any point, this function should generally be called
* in a plugin's constructor, rather than in its start() method so the
* preference isn't first loaded with one value then changed to another
* value.
*/
void
meta_prefs_override_preference_location (const char *original_key,
const char *new_key)
{
const char *search_key;
char *new_key_copy;
gboolean found;
MetaPrefsOverriddenKey *overridden;
GSList *tmp;
/* Merge identical overrides, this isn't an error */
for (tmp = overridden_keys; tmp; tmp = tmp->next)
{
MetaPrefsOverriddenKey *tmp_overridden = tmp->data;
if (strcmp (tmp_overridden->original_key, original_key) == 0 &&
strcmp (tmp_overridden->new_key, new_key) == 0)
return;
}
/* We depend on a unique mapping from GConf key to preference, so
* enforce this */
if (key_is_used (preferences_enum, sizeof(MetaEnumPreference), new_key) ||
key_is_used (preferences_bool, sizeof(MetaBoolPreference), new_key) ||
key_is_used (preferences_string, sizeof(MetaStringPreference), new_key) ||
key_is_used (preferences_int, sizeof(MetaIntPreference), new_key))
{
meta_warning (_("GConf key %s is already in use and can't be used to override %s\n"),
new_key, original_key);
}
new_key_copy = g_strdup (new_key);
search_key = original_key;
overridden = NULL;
for (tmp = overridden_keys; tmp; tmp = tmp->next)
{
MetaPrefsOverriddenKey *tmp_overridden = tmp->data;
if (strcmp (overridden->original_key, original_key) == 0)
{
overridden = tmp_overridden;
search_key = tmp_overridden->new_key;
}
}
found =
do_override (preferences_enum, sizeof(MetaEnumPreference), search_key, new_key_copy) ||
do_override (preferences_bool, sizeof(MetaBoolPreference), search_key, new_key_copy) ||
do_override (preferences_string, sizeof(MetaStringPreference), search_key, new_key_copy) ||
do_override (preferences_int, sizeof(MetaIntPreference), search_key, new_key_copy);
if (found)
{
if (overridden)
{
g_free (overridden->new_key);
overridden->new_key = new_key_copy;
}
else
{
overridden = g_slice_new (MetaPrefsOverriddenKey);
overridden->original_key = g_strdup (original_key);
overridden->new_key = new_key_copy;
}
#ifdef HAVE_GCONF
if (default_client != NULL)
{
/* We're already initialized, so notify of a change */
GConfValue *value;
GError *err = NULL;
value = gconf_client_get (default_client, new_key, &err);
cleanup_error (&err);
notify_new_value (new_key, value);
if (value)
gconf_value_free (value);
}
#endif /* HAVE_GCONF */
}
else
{
meta_warning (_("Can't override GConf key, %s not found\n"), original_key);
g_free (new_key_copy);
}
}
/****************************************************************************/
/* Updates. */
@ -1109,6 +1291,23 @@ gboolean (*preference_update_handler[]) (const gchar*, GConfValue*) = {
NULL
};
static void
notify_new_value (const char *key,
GConfValue *value)
{
int i = 0;
/* FIXME: Use MetaGenericPreference and save a bit of code duplication */
while (preference_update_handler[i] != NULL)
{
if (preference_update_handler[i] (key, value))
return;
i++;
}
}
static void
change_notify (GConfClient *client,
guint cnxn_id,
@ -1117,25 +1316,13 @@ change_notify (GConfClient *client,
{
const char *key;
GConfValue *value;
gint i=0;
key = gconf_entry_get_key (entry);
value = gconf_entry_get_value (entry);
/* First, search for a handler that might know what to do. */
/* FIXME: When this is all working, since the first item in every
* array is the gchar* of the key, there's no reason we can't
* find the correct record for that key here and save code duplication.
*/
while (preference_update_handler[i]!=NULL)
{
if (preference_update_handler[i] (key, value))
goto out; /* Get rid of this eventually */
i++;
}
notify_new_value (key, value);
if (g_str_has_prefix (key, KEY_WINDOW_BINDINGS_PREFIX) ||
g_str_has_prefix (key, KEY_SCREEN_BINDINGS_PREFIX))
@ -1311,6 +1498,12 @@ meta_prefs_get_focus_new_windows (void)
return focus_new_windows;
}
gboolean
meta_prefs_get_attach_modal_dialogs (void)
{
return attach_modal_dialogs;
}
gboolean
meta_prefs_get_raise_on_click (void)
{
@ -1732,6 +1925,9 @@ meta_preference_to_string (MetaPreference pref)
case META_PREF_FOCUS_NEW_WINDOWS:
return "FOCUS_NEW_WINDOWS";
case META_PREF_ATTACH_MODAL_DIALOGS:
return "ATTACH_MODAL_DIALOGS";
case META_PREF_RAISE_ON_CLICK:
return "RAISE_ON_CLICK";
@ -1801,12 +1997,12 @@ meta_preference_to_string (MetaPreference pref)
case META_PREF_CURSOR_SIZE:
return "CURSOR_SIZE";
case META_PREF_COMPOSITING_MANAGER:
return "COMPOSITING_MANAGER";
case META_PREF_RESIZE_WITH_RIGHT_BUTTON:
return "RESIZE_WITH_RIGHT_BUTTON";
case META_PREF_EDGE_TILING:
return "EDGE_TILING";
case META_PREF_FORCE_FULLSCREEN:
return "FORCE_FULLSCREEN";
@ -1912,6 +2108,8 @@ init_bindings (void)
GConfValue *value;
GHashTable *to_update;
g_assert (G_N_ELEMENTS (key_bindings) == META_KEYBINDING_ACTION_LAST + 1);
to_update = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
for (i = 0; prefix[i]; i++)
@ -2004,6 +2202,8 @@ init_commands (void)
static void
init_workspace_names (void)
{
int i;
#ifdef HAVE_GCONF
GSList *list, *l;
const char *str_val;
@ -2022,14 +2222,14 @@ init_workspace_names (void)
gconf_entry_free (entry);
}
g_slist_free (list);
#else
int i;
#endif /* HAVE_GCONF */
for (i = 0; i < MAX_REASONABLE_WORKSPACES; i++)
workspace_names[i] = g_strdup_printf (_("Workspace %d"), i + 1);
if (workspace_names[i] == NULL)
workspace_names[i] = g_strdup_printf (_("Workspace %d"), i + 1);
meta_topic (META_DEBUG_PREFS,
"Initialized workspace names\n");
#endif /* HAVE_GCONF */
}
static gboolean
@ -2715,6 +2915,12 @@ meta_prefs_get_gnome_animations ()
return gnome_animations;
}
gboolean
meta_prefs_get_edge_tiling ()
{
return edge_tiling;
}
MetaKeyBindingAction
meta_prefs_get_keybinding_action (const char *name)
{
@ -2776,12 +2982,6 @@ meta_prefs_get_window_binding (const char *name,
g_assert_not_reached ();
}
gboolean
meta_prefs_get_compositing_manager (void)
{
return compositing_manager;
}
guint
meta_prefs_get_mouse_button_resize (void)
{
@ -2800,28 +3000,11 @@ meta_prefs_get_force_fullscreen (void)
return force_fullscreen;
}
void
meta_prefs_set_compositing_manager (gboolean whether)
{
#ifdef HAVE_GCONF
GError *err = NULL;
gconf_client_set_bool (default_client,
KEY_COMPOSITOR,
whether,
&err);
if (err)
{
meta_warning (_("Error setting compositor status: %s\n"),
err->message);
g_error_free (err);
}
#else
compositing_manager = whether;
#endif
}
/**
* meta_prefs_get_clutter_plugins:
*
* Returns: (transfer none) (element-type utf8): Plugin names to load
*/
GSList *
meta_prefs_get_clutter_plugins (void)
{

View File

@ -82,6 +82,9 @@ struct _MetaScreen
MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */
MetaUI *ui;
MetaTabPopup *tab_popup, *ws_popup;
MetaTilePreview *tile_preview;
guint tile_preview_timeout_id;
MetaWorkspace *active_workspace;
@ -179,6 +182,9 @@ void meta_screen_workspace_popup_select (MetaScreen *screen,
MetaWorkspace*meta_screen_workspace_popup_get_selected (MetaScreen *screen);
void meta_screen_workspace_popup_destroy (MetaScreen *screen);
void meta_screen_tile_preview_update (MetaScreen *screen,
gboolean delay);
MetaWindow* meta_screen_get_mouse_window (MetaScreen *screen,
MetaWindow *not_this_one);

View File

@ -601,7 +601,7 @@ meta_screen_new (MetaDisplay *display,
attrs.event_mask = StructureNotifyMask;
XChangeWindowAttributes (xdisplay,
current_wm_sn_owner, CWEventMask, &attrs);
if (meta_error_trap_pop_with_return (display, FALSE) != Success)
if (meta_error_trap_pop_with_return (display) != Success)
current_wm_sn_owner = None; /* don't wait for it to die later on */
}
@ -670,7 +670,7 @@ meta_screen_new (MetaDisplay *display,
KeyPressMask | KeyReleaseMask |
FocusChangeMask | StructureNotifyMask |
ExposureMask | attr.your_event_mask);
if (meta_error_trap_pop_with_return (display, FALSE) != Success)
if (meta_error_trap_pop_with_return (display) != Success)
{
meta_warning (_("Screen %d on display \"%s\" already has a window manager\n"),
number, display->name);
@ -770,6 +770,9 @@ meta_screen_new (MetaDisplay *display,
screen->tab_popup = NULL;
screen->ws_popup = NULL;
screen->tile_preview = NULL;
screen->tile_preview_timeout_id = 0;
screen->stack = meta_stack_new (screen);
screen->stack_tracker = meta_stack_tracker_new (screen);
@ -853,7 +856,7 @@ meta_screen_free (MetaScreen *screen,
meta_error_trap_push_with_return (screen->display);
XSelectInput (screen->display->xdisplay, screen->xroot, 0);
if (meta_error_trap_pop_with_return (screen->display, FALSE) != Success)
if (meta_error_trap_pop_with_return (screen->display) != Success)
meta_warning (_("Could not release screen %d on display \"%s\"\n"),
screen->number, screen->display->name);
@ -867,6 +870,12 @@ meta_screen_free (MetaScreen *screen,
if (screen->monitor_infos)
g_free (screen->monitor_infos);
if (screen->tile_preview_timeout_id)
g_source_remove (screen->tile_preview_timeout_id);
if (screen->tile_preview)
meta_tile_preview_free (screen->tile_preview);
g_free (screen->screen_name);
@ -904,7 +913,7 @@ list_windows (MetaScreen *screen)
XGetWindowAttributes (screen->display->xdisplay,
children[i], &info->attrs);
if (meta_error_trap_pop_with_return (screen->display, TRUE))
if (meta_error_trap_pop_with_return (screen->display))
{
meta_verbose ("Failed to get attributes for window 0x%lx\n",
children[i]);
@ -969,7 +978,15 @@ meta_screen_composite_all_windows (MetaScreen *screen)
windows = meta_display_list_windows (display,
META_LIST_INCLUDE_OVERRIDE_REDIRECT);
for (tmp = windows; tmp != NULL; tmp = tmp->next)
meta_compositor_add_window (display->compositor, tmp->data);
{
MetaWindow *window = tmp->data;
meta_compositor_add_window (display->compositor, window);
if (window->visible_to_compositor)
meta_compositor_show_window (display->compositor, window,
META_COMP_EFFECT_NONE);
}
g_slist_free (windows);
/* initialize the compositor's view of the stacking order */
@ -1211,7 +1228,7 @@ set_number_of_spaces_hint (MetaScreen *screen,
screen->display->atom__NET_NUMBER_OF_DESKTOPS,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 1);
meta_error_trap_pop (screen->display, FALSE);
meta_error_trap_pop (screen->display);
}
static void
@ -1232,7 +1249,7 @@ set_desktop_geometry_hint (MetaScreen *screen)
screen->display->atom__NET_DESKTOP_GEOMETRY,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 2);
meta_error_trap_pop (screen->display, FALSE);
meta_error_trap_pop (screen->display);
}
static void
@ -1256,7 +1273,7 @@ set_desktop_viewport_hint (MetaScreen *screen)
screen->display->atom__NET_DESKTOP_VIEWPORT,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 2);
meta_error_trap_pop (screen->display, FALSE);
meta_error_trap_pop (screen->display);
}
void
@ -1266,7 +1283,8 @@ meta_screen_remove_workspace (MetaScreen *screen, MetaWorkspace *workspace,
GList *l;
MetaWorkspace *neighbour = NULL;
GList *next = NULL;
int index;
int index;
int new_num;
l = screen->workspaces;
while (l)
@ -1308,7 +1326,10 @@ meta_screen_remove_workspace (MetaScreen *screen, MetaWorkspace *workspace,
/* This also removes the workspace from the screens list */
meta_workspace_remove (workspace);
set_number_of_spaces_hint (screen, g_list_length (screen->workspaces));
new_num = g_list_length (screen->workspaces);
set_number_of_spaces_hint (screen, new_num);
meta_prefs_set_num_workspaces (new_num);
l = next;
while (l)
@ -1344,6 +1365,7 @@ meta_screen_append_new_workspace (MetaScreen *screen, gboolean activate,
guint32 timestamp)
{
MetaWorkspace *w;
int new_num;
/* This also adds the workspace to the screen list */
w = meta_workspace_new (screen);
@ -1354,7 +1376,10 @@ meta_screen_append_new_workspace (MetaScreen *screen, gboolean activate,
if (activate)
meta_workspace_activate (w, timestamp);
set_number_of_spaces_hint (screen, g_list_length (screen->workspaces));
new_num = g_list_length (screen->workspaces);
set_number_of_spaces_hint (screen, new_num);
meta_prefs_set_num_workspaces (new_num);
meta_screen_queue_workarea_recalc (screen);
@ -1381,6 +1406,9 @@ update_num_workspaces (MetaScreen *screen,
g_assert (new_num > 0);
if (g_list_length (screen->workspaces) == (guint) new_num)
return;
last_remaining = NULL;
extras = NULL;
i = 0;
@ -1732,6 +1760,89 @@ meta_screen_workspace_popup_destroy (MetaScreen *screen)
}
}
static gboolean
meta_screen_tile_preview_update_timeout (gpointer data)
{
MetaScreen *screen = data;
MetaWindow *window = screen->display->grab_window;
gboolean composited = screen->display->compositor != NULL;
gboolean needs_preview = FALSE;
screen->tile_preview_timeout_id = 0;
if (!screen->tile_preview)
{
Window xwindow;
gulong create_serial;
screen->tile_preview = meta_tile_preview_new (screen->number,
composited);
xwindow = meta_tile_preview_get_xwindow (screen->tile_preview,
&create_serial);
meta_stack_tracker_record_add (screen->stack_tracker,
xwindow,
create_serial);
}
if (window)
{
switch (window->tile_mode)
{
case META_TILE_LEFT:
case META_TILE_RIGHT:
if (!META_WINDOW_TILED_SIDE_BY_SIDE (window))
needs_preview = TRUE;
break;
case META_TILE_MAXIMIZED:
if (!META_WINDOW_MAXIMIZED (window))
needs_preview = TRUE;
break;
default:
needs_preview = FALSE;
break;
}
}
if (needs_preview)
{
MetaRectangle tile_rect;
meta_window_get_current_tile_area (window, &tile_rect);
meta_tile_preview_show (screen->tile_preview, &tile_rect);
}
else
meta_tile_preview_hide (screen->tile_preview);
return FALSE;
}
#define TILE_PREVIEW_TIMEOUT_MS 200
void
meta_screen_tile_preview_update (MetaScreen *screen,
gboolean delay)
{
if (delay)
{
if (screen->tile_preview_timeout_id > 0)
return;
screen->tile_preview_timeout_id =
g_timeout_add (TILE_PREVIEW_TIMEOUT_MS,
meta_screen_tile_preview_update_timeout,
screen);
}
else
{
if (screen->tile_preview_timeout_id > 0)
g_source_remove (screen->tile_preview_timeout_id);
meta_screen_tile_preview_update_timeout ((gpointer)screen);
}
}
MetaWindow*
meta_screen_get_mouse_window (MetaScreen *screen,
MetaWindow *not_this_one)
@ -1756,7 +1867,7 @@ meta_screen_get_mouse_window (MetaScreen *screen,
&win_x_return,
&win_y_return,
&mask_return);
meta_error_trap_pop (screen->display, TRUE);
meta_error_trap_pop (screen->display);
window = meta_stack_get_default_focus_window_at_point (screen->stack,
screen->active_workspace,
@ -2159,7 +2270,7 @@ set_workspace_names (MetaScreen *screen)
screen->display->atom_UTF8_STRING,
8, PropModeReplace,
(unsigned char *)flattened->str, flattened->len);
meta_error_trap_pop (screen->display, FALSE);
meta_error_trap_pop (screen->display);
g_string_free (flattened, TRUE);
}
@ -2263,7 +2374,7 @@ set_work_area_hint (MetaScreen *screen)
XA_CARDINAL, 32, PropModeReplace,
(guchar*) data, num_workspaces*4);
g_free (data);
meta_error_trap_pop (screen->display, FALSE);
meta_error_trap_pop (screen->display);
g_signal_emit (screen, screen_signals[WORKAREAS_CHANGED], 0);
}
@ -2638,7 +2749,7 @@ meta_screen_update_showing_desktop_hint (MetaScreen *screen)
screen->display->atom__NET_SHOWING_DESKTOP,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 1);
meta_error_trap_pop (screen->display, FALSE);
meta_error_trap_pop (screen->display);
}
static void
@ -3111,6 +3222,10 @@ meta_screen_get_display (MetaScreen *screen)
return screen->display;
}
/**
* meta_screen_get_xroot: (skip)
*
*/
Window
meta_screen_get_xroot (MetaScreen *screen)
{
@ -3126,6 +3241,10 @@ meta_screen_get_size (MetaScreen *screen,
*height = screen->rect.height;
}
/**
* meta_screen_get_compositor_data: (skip)
*
*/
gpointer
meta_screen_get_compositor_data (MetaScreen *screen)
{
@ -3167,6 +3286,12 @@ meta_screen_unset_cm_selection (MetaScreen *screen)
None, screen->wm_cm_timestamp);
}
/**
* meta_screen_get_workspaces: (skip)
* @screen: a #MetaScreen
*
* Returns: (transfer none) (element-type Meta.Workspace): The workspaces for @screen
*/
GList *
meta_screen_get_workspaces (MetaScreen *screen)
{

View File

@ -23,6 +23,7 @@
#include <string.h>
#include "frame-private.h"
#include "screen-private.h"
#include "stack-tracker.h"
#include "util.h"
@ -53,8 +54,8 @@
*
* When we receive a new event: a) we compare the serial in the event to
* the serial of the queued requests and remove any that are now
* no longer pending b) drop the predicted stacking order to recompute
* it at the next opportunity.
* no longer pending b) if necessary, drop the predicted stacking
* order to recompute it at the next opportunity.
*
* Possible optimizations:
* Keep the stacks as an array + reverse-mapping hash table to avoid
@ -504,6 +505,8 @@ static void
stack_tracker_event_received (MetaStackTracker *tracker,
MetaStackOp *op)
{
gboolean need_sync = FALSE;
meta_stack_op_dump (op, "Stack op event received: ", "\n");
if (op->any.serial < tracker->server_serial)
@ -511,7 +514,8 @@ stack_tracker_event_received (MetaStackTracker *tracker,
tracker->server_serial = op->any.serial;
meta_stack_op_apply (op, tracker->server_stack);
if (meta_stack_op_apply (op, tracker->server_stack))
need_sync = TRUE;
while (tracker->queued_requests->head)
{
@ -521,17 +525,21 @@ stack_tracker_event_received (MetaStackTracker *tracker,
g_queue_pop_head (tracker->queued_requests);
meta_stack_op_free (queued_op);
need_sync = TRUE;
}
if (tracker->predicted_stack)
if (need_sync)
{
g_array_free (tracker->predicted_stack, TRUE);
tracker->predicted_stack = NULL;
if (tracker->predicted_stack)
{
g_array_free (tracker->predicted_stack, TRUE);
tracker->predicted_stack = NULL;
}
meta_stack_tracker_queue_sync_stack (tracker);
}
meta_stack_tracker_dump (tracker);
meta_stack_tracker_queue_sync_stack (tracker);
}
void
@ -682,7 +690,15 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
meta_window = meta_display_lookup_x_window (tracker->screen->display,
windows[i]);
if (meta_window)
/* When mapping back from xwindow to MetaWindow we have to be a bit careful;
* children of the root could include unmapped windows created by toolkits
* for internal purposes, including ones that we have registered in our
* XID => window table. (Wine uses a toplevel for _NET_WM_USER_TIME_WINDOW;
* see window-prop.c:reload_net_wm_user_time_window() for registration.)
*/
if (meta_window &&
(windows[i] == meta_window->xwindow ||
(meta_window->frame && windows[i] == meta_window->frame->xwindow)))
meta_windows = g_list_prepend (meta_windows, meta_window);
}

View File

@ -1026,7 +1026,7 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
xwindow,
CWSibling | CWStackMode,
&changes);
meta_error_trap_pop (screen->display, FALSE);
meta_error_trap_pop (screen->display);
break;
}
@ -1046,7 +1046,7 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
XNextRequest (screen->display->xdisplay));
XLowerWindow (screen->display->xdisplay,
xwindow);
meta_error_trap_pop (screen->display, FALSE);
meta_error_trap_pop (screen->display);
}
}
@ -1267,7 +1267,7 @@ stack_sync_to_server (MetaStack *stack)
all_hidden->len);
g_array_free (all_hidden, TRUE);
meta_error_trap_pop (stack->screen->display, FALSE);
meta_error_trap_pop (stack->screen->display);
/* on error, a window was destroyed; it should eventually
* get removed from the stacking list when we unmanage it
* and we'll fix stacking at that time.

View File

@ -21,7 +21,7 @@
* 02111-1307, USA.
*/
#include "boxes.h"
#include "boxes-private.h"
#include <glib.h>
#include <stdlib.h>
#include <stdio.h>

View File

@ -40,6 +40,13 @@
#include <X11/Xlib.h> /* must explicitly be included for Solaris; #326746 */
#include <X11/Xutil.h> /* Just for the definition of the various gravities */
#ifdef WITH_VERBOSE_MODE
static void
meta_topic_real_valist (MetaDebugTopic topic,
const char *format,
va_list args);
#endif
#ifdef HAVE_BACKTRACE
#include <execinfo.h>
void
@ -71,7 +78,7 @@ meta_print_backtrace (void)
}
#endif
static gboolean is_verbose = FALSE;
static gint verbose_topics = 0;
static gboolean is_debugging = FALSE;
static gboolean replace_current = FALSE;
static int no_prefix = 0;
@ -128,7 +135,7 @@ ensure_logfile (void)
gboolean
meta_is_verbose (void)
{
return is_verbose;
return verbose_topics != 0;
}
void
@ -141,8 +148,48 @@ meta_set_verbose (gboolean setting)
if (setting)
ensure_logfile ();
#endif
is_verbose = setting;
if (setting)
meta_add_verbose_topic (META_DEBUG_VERBOSE);
else
meta_remove_verbose_topic (META_DEBUG_VERBOSE);
}
/**
* meta_add_verbose_topic:
* @topic: Topic for which logging will be started
*
* Ensure log messages for the given topic @topic
* will be printed.
*/
void
meta_add_verbose_topic (MetaDebugTopic topic)
{
if (verbose_topics == META_DEBUG_VERBOSE)
return;
if (topic == META_DEBUG_VERBOSE)
verbose_topics = META_DEBUG_VERBOSE;
else
verbose_topics |= topic;
}
/**
* meta_remove_verbose_topic:
* @topic: Topic for which logging will be stopped
*
* Stop printing log messages for the given topic @topic. Note
* that this method does not stack with meta_add_verbose_topic();
* i.e. if two calls to meta_add_verbose_topic() for the same
* topic are made, one call to meta_remove_verbose_topic() will
* remove it.
*/
void
meta_remove_verbose_topic (MetaDebugTopic topic)
{
if (topic == META_DEBUG_VERBOSE)
verbose_topics = 0;
else
verbose_topics &= ~topic;
}
gboolean
@ -250,27 +297,10 @@ void
meta_verbose_real (const char *format, ...)
{
va_list args;
gchar *str;
FILE *out;
g_return_if_fail (format != NULL);
if (!is_verbose)
return;
va_start (args, format);
str = g_strdup_vprintf (format, args);
meta_topic_real_valist (META_DEBUG_VERBOSE, format, args);
va_end (args);
out = logfile ? logfile : stderr;
if (no_prefix == 0)
utf8_fputs ("Window manager: ", out);
utf8_fputs (str, out);
fflush (out);
g_free (str);
}
#endif /* WITH_VERBOSE_MODE */
@ -324,6 +354,8 @@ topic_name (MetaDebugTopic topic)
return "COMPOSITOR";
case META_DEBUG_EDGE_RESISTANCE:
return "EDGE_RESISTANCE";
case META_DEBUG_VERBOSE:
return "VERBOSE";
}
return "WM";
@ -331,23 +363,22 @@ topic_name (MetaDebugTopic topic)
static int sync_count = 0;
void
meta_topic_real (MetaDebugTopic topic,
const char *format,
...)
static void
meta_topic_real_valist (MetaDebugTopic topic,
const char *format,
va_list args)
{
va_list args;
gchar *str;
FILE *out;
g_return_if_fail (format != NULL);
if (!is_verbose)
if (verbose_topics == 0
|| (topic == META_DEBUG_VERBOSE && verbose_topics != META_DEBUG_VERBOSE)
|| (!(verbose_topics & topic)))
return;
va_start (args, format);
str = g_strdup_vprintf (format, args);
va_end (args);
out = logfile ? logfile : stderr;
@ -366,6 +397,18 @@ meta_topic_real (MetaDebugTopic topic,
g_free (str);
}
void
meta_topic_real (MetaDebugTopic topic,
const char *format,
...)
{
va_list args;
va_start (args, format);
meta_topic_real_valist (topic, format, args);
va_end (args);
}
#endif /* WITH_VERBOSE_MODE */
void

View File

@ -46,9 +46,6 @@
typedef struct _MetaWindowQueue MetaWindowQueue;
typedef gboolean (*MetaWindowForeachFunc) (MetaWindow *window,
void *data);
typedef enum {
META_CLIENT_TYPE_UNKNOWN = 0,
META_CLIENT_TYPE_APPLICATION = 1,
@ -64,6 +61,13 @@ typedef enum {
#define NUMBER_OF_QUEUES 3
typedef enum {
META_TILE_NONE,
META_TILE_LEFT,
META_TILE_RIGHT,
META_TILE_MAXIMIZED
} MetaTileMode;
struct _MetaWindow
{
GObject parent_instance;
@ -99,6 +103,7 @@ struct _MetaWindow
char *sm_client_id;
char *wm_client_machine;
char *startup_id;
char *mutter_hints;
int net_wm_pid;
@ -124,6 +129,11 @@ struct _MetaWindow
guint maximize_vertically_after_placement : 1;
guint minimize_after_placement : 1;
/* The current or requested tile mode. If maximized_vertically is true,
* this is the current mode. If not, it is the mode which will be
* requested after the window grab is released */
guint tile_mode : 2;
/* Whether we're shaded */
guint shaded : 1;
@ -400,8 +410,15 @@ struct _MetaWindowClass
(w)->maximized_vertically)
#define META_WINDOW_MAXIMIZED_VERTICALLY(w) ((w)->maximized_vertically)
#define META_WINDOW_MAXIMIZED_HORIZONTALLY(w) ((w)->maximized_horizontally)
#define META_WINDOW_TILED_SIDE_BY_SIDE(w) ((w)->maximized_vertically && \
!(w)->maximized_horizontally && \
(w)->tile_mode != META_TILE_NONE)
#define META_WINDOW_TILED_LEFT(w) (META_WINDOW_TILED_SIDE_BY_SIDE(w) && \
(w)->tile_mode == META_TILE_LEFT)
#define META_WINDOW_TILED_RIGHT(w) (META_WINDOW_TILED_SIDE_BY_SIDE(w) && \
(w)->tile_mode == META_TILE_RIGHT)
#define META_WINDOW_ALLOWS_MOVE(w) ((w)->has_move_func && !(w)->fullscreen)
#define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w) ((w)->has_resize_func && !META_WINDOW_MAXIMIZED (w) && !(w)->fullscreen && !(w)->shaded)
#define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w) ((w)->has_resize_func && !META_WINDOW_MAXIMIZED (w) && !META_WINDOW_TILED_SIDE_BY_SIDE(w) && !(w)->fullscreen && !(w)->shaded)
#define META_WINDOW_ALLOWS_RESIZE(w) (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) && \
(((w)->size_hints.min_width < (w)->size_hints.max_width) || \
((w)->size_hints.min_height < (w)->size_hints.max_height)))
@ -424,6 +441,11 @@ void meta_window_queue (MetaWindow *window,
void meta_window_maximize_internal (MetaWindow *window,
MetaMaximizeFlags directions,
MetaRectangle *saved_rect);
void meta_window_unmaximize_with_gravity (MetaWindow *window,
MetaMaximizeFlags directions,
int new_width,
int new_height,
int gravity);
void meta_window_make_above (MetaWindow *window);
void meta_window_unmake_above (MetaWindow *window);
void meta_window_shade (MetaWindow *window,
@ -506,8 +528,6 @@ void meta_window_get_geometry (MetaWindow *window,
void meta_window_kill (MetaWindow *window);
void meta_window_focus (MetaWindow *window,
guint32 timestamp);
void meta_window_raise (MetaWindow *window);
void meta_window_lower (MetaWindow *window);
void meta_window_update_unfocused_button_grabs (MetaWindow *window);
@ -565,6 +585,9 @@ void meta_window_get_work_area_for_monitor (MetaWindow *window,
void meta_window_get_work_area_all_monitors (MetaWindow *window,
MetaRectangle *area);
void meta_window_get_current_tile_area (MetaWindow *window,
MetaRectangle *tile_area);
gboolean meta_window_same_application (MetaWindow *window,
MetaWindow *other_window);
@ -582,12 +605,6 @@ void meta_window_refresh_resize_popup (MetaWindow *window);
void meta_window_free_delete_dialog (MetaWindow *window);
void meta_window_foreach_transient (MetaWindow *window,
MetaWindowForeachFunc func,
void *data);
void meta_window_foreach_ancestor (MetaWindow *window,
MetaWindowForeachFunc func,
void *data);
void meta_window_begin_grab_op (MetaWindow *window,
MetaGrabOp op,
@ -610,10 +627,6 @@ void meta_window_stack_just_below (MetaWindow *window,
void meta_window_set_user_time (MetaWindow *window,
guint32 timestamp);
void meta_window_set_demands_attention (MetaWindow *window);
void meta_window_unset_demands_attention (MetaWindow *window);
void meta_window_update_icon_now (MetaWindow *window);
void meta_window_update_role (MetaWindow *window);

View File

@ -442,7 +442,7 @@ set_title_text (MetaWindow *window,
XDeleteProperty (window->display->xdisplay,
window->xwindow,
atom);
meta_error_trap_pop (window->display, FALSE);
meta_error_trap_pop (window->display);
}
return modified;
@ -523,6 +523,49 @@ reload_wm_name (MetaWindow *window,
}
}
static void
reload_mutter_hints (MetaWindow *window,
MetaPropValue *value,
gboolean initial)
{
if (value->type != META_PROP_VALUE_INVALID)
{
char *new_hints = value->v.str;
char *old_hints = window->mutter_hints;
gboolean changed = FALSE;
if (new_hints)
{
if (!old_hints || strcmp (new_hints, old_hints))
changed = TRUE;
}
else
{
if (old_hints)
changed = TRUE;
}
if (changed)
{
g_free (old_hints);
if (new_hints)
window->mutter_hints = g_strdup (new_hints);
else
window->mutter_hints = NULL;
g_object_notify (G_OBJECT (window), "mutter-hints");
}
}
else if (window->mutter_hints)
{
g_free (window->mutter_hints);
window->mutter_hints = NULL;
g_object_notify (G_OBJECT (window), "mutter-hints");
}
}
static void
set_icon_title (MetaWindow *window,
const char *title)
@ -1506,6 +1549,7 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
{ XA_WM_CLASS, META_PROP_VALUE_CLASS_HINT, reload_wm_class, TRUE, TRUE },
{ display->atom__NET_WM_PID, META_PROP_VALUE_CARDINAL, reload_net_wm_pid, TRUE, TRUE },
{ XA_WM_NAME, META_PROP_VALUE_TEXT_PROPERTY, reload_wm_name, TRUE, TRUE },
{ display->atom__MUTTER_HINTS, META_PROP_VALUE_TEXT_PROPERTY, reload_mutter_hints, TRUE, TRUE },
{ display->atom__NET_WM_ICON_NAME, META_PROP_VALUE_UTF8, reload_net_wm_icon_name, TRUE, FALSE },
{ XA_WM_ICON_NAME, META_PROP_VALUE_TEXT_PROPERTY, reload_wm_icon_name, TRUE, FALSE },
{ display->atom__NET_WM_DESKTOP, META_PROP_VALUE_CARDINAL, reload_net_wm_desktop, TRUE, FALSE },

File diff suppressed because it is too large Load Diff

View File

@ -26,6 +26,7 @@
#include <config.h>
#include "workspace.h"
#include "workspace-private.h"
#include "boxes-private.h"
#include "errors.h"
#include "prefs.h"
@ -617,10 +618,20 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
meta_screen_calc_workspace_layout (workspace->screen, num_workspaces,
new_space, &layout2);
if (layout1.current_col < layout2.current_col)
direction = META_MOTION_RIGHT;
if (layout1.current_col > layout2.current_col)
direction = META_MOTION_LEFT;
if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
{
if (layout1.current_col > layout2.current_col)
direction = META_MOTION_RIGHT;
else if (layout1.current_col < layout2.current_col)
direction = META_MOTION_LEFT;
}
else
{
if (layout1.current_col < layout2.current_col)
direction = META_MOTION_RIGHT;
else if (layout1.current_col > layout2.current_col)
direction = META_MOTION_LEFT;
}
if (layout1.current_row < layout2.current_row)
{
@ -706,7 +717,7 @@ meta_workspace_update_window_hints (MetaWorkspace *workspace)
/**
* meta_workspace_list_windows:
* @display: a #MetaDisplay
* @workspace: a #MetaWorkspace
*
* Gets windows contained on the workspace, including workspace->windows
* and also sticky windows. Override-redirect windows are not included.
@ -764,7 +775,7 @@ set_active_space_hint (MetaScreen *screen)
screen->display->atom__NET_CURRENT_DESKTOP,
XA_CARDINAL,
32, PropModeReplace, (guchar*) data, 1);
meta_error_trap_pop (screen->display, FALSE);
meta_error_trap_pop (screen->display);
}
void
@ -1048,7 +1059,7 @@ strut_lists_equal (GSList *l,
/**
* meta_workspace_set_builtin_struts:
* @workspace: a #MetaWorkspace
* @struts: (element-type Strut) (transfer none): list of #MetaStrut
* @struts: (element-type Meta.Strut) (transfer none): list of #MetaStrut
*
* Sets a list of struts that will be used in addition to the struts
* of the windows in the workspace when computing the work area of

View File

@ -126,7 +126,7 @@ validate_or_free_results (GetPropertyResults *results,
type_name = XGetAtomName (results->display->xdisplay, results->type);
expected_name = XGetAtomName (results->display->xdisplay, expected_type);
prop_name = XGetAtomName (results->display->xdisplay, results->xatom);
meta_error_trap_pop (results->display, TRUE);
meta_error_trap_pop (results->display);
w = meta_display_lookup_x_window (results->display, results->xwindow);
@ -204,11 +204,11 @@ get_property (MetaDisplay *display,
{
if (results->prop)
XFree (results->prop);
meta_error_trap_pop_with_return (display, TRUE);
meta_error_trap_pop_with_return (display);
return FALSE;
}
if (meta_error_trap_pop_with_return (display, TRUE) != Success)
if (meta_error_trap_pop_with_return (display) != Success)
{
if (results->prop)
XFree (results->prop);
@ -490,7 +490,7 @@ utf8_list_from_results (GetPropertyResults *results,
meta_error_trap_push (results->display);
name = XGetAtomName (results->display->xdisplay, results->xatom);
meta_error_trap_pop (results->display, TRUE);
meta_error_trap_pop (results->display);
meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n"),
name, results->xwindow, i);
meta_XFree (name);
@ -547,7 +547,7 @@ meta_prop_set_utf8_string_hint (MetaDisplay *display,
xwindow, atom,
display->atom_UTF8_STRING,
8, PropModeReplace, (guchar*) val, strlen (val));
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
static gboolean

View File

@ -167,7 +167,7 @@ keybind (switch_panels_backward, handle_switch, META_TAB_LIST_DOCKS,
"using a popup window"))
keybind (cycle_group, handle_cycle, META_TAB_LIST_GROUP,
BINDING_REVERSES, "<Alt>grave",
BINDING_REVERSES, "<Alt>Above_Tab",
_("Move between windows of an application immediately"))
keybind (cycle_group_backward, handle_cycle, META_TAB_LIST_GROUP,
REVERSES_AND_REVERSED, NULL,

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