Compare commits

...

594 Commits

Author SHA1 Message Date
Owen W. Taylor
3e7d2df6f3 Bump version to 2.91.2 2010-11-08 10:34:56 -05:00
Matthias Clasen
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
Petr Kovar
1114e5effa Update Czech translation 2010-10-31 11:48:40 +01:00
Owen W. Taylor
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
Owen W. Taylor
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
Owen W. Taylor
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
Florian Müllner
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
Owen W. Taylor
95a7f0269a Bump version to 2.91.1 2010-10-27 17:02:04 -04:00
Fran Diéguez
db63764e22 Updated Galician translations 2010-10-26 16:46:11 +02:00
Dan Winship
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
Giovanni Campagna
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
Yinghua Wang
bcded5ae25 Update Simplified Chinese translation. 2010-10-25 16:12:14 +08:00
Rico Tzschichholz
7227b636c6 Fix typo 2010-10-24 12:00:57 +02:00
Owen W. Taylor
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
Owen W. Taylor
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
Owen W. Taylor
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
Owen W. Taylor
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
Dan Winship
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
Nickolas Lloyd
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
Owen W. Taylor
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
Brandon Wright
6ed34976c9 Patch to fix theme breakage in 2.30.2; see bug 630426 2010-10-06 12:40:30 -04:00
Colin Walters
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
Colin Walters
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
Owen W. Taylor
cbedfd680f Bump version to 2.91.0 2010-10-04 13:38:24 -04:00
Owen W. Taylor
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
William Jon McCann
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
Benjamin Otte
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
Florian Müllner
c382d8f7ea Remove unused variable 2010-09-30 18:49:21 +02:00
Adel Gadllah
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
Alban Browaeys
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
Adel Gadllah
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
Matthias Clasen
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
Benjamin Otte
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
Benjamin Otte
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
Yaron Shahrabani
d19295a68e Updated Hebrew translation. 2010-09-26 23:55:12 +02:00
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Kjartan Maraas
1fc91dc459 Updated Norwegian bokmål translation 2010-09-26 11:44:57 +02:00
Florian Müllner
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
Owen W. Taylor
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
Florian Müllner
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
Owen W. Taylor
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
b79e6c0b3e Remove unused code
https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:54:14 +02:00
Benjamin Otte
c6f8ad24bd Remove MetaArea widget
It's unused.

https://bugzilla.gnome.org/show_bug.cgi?id=630203
2010-09-23 12:54:14 +02:00
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Benjamin Otte
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
Florian Müllner
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
Owen W. Taylor
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
Nickolas Lloyd
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
Adel Gadllah
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
Mario Blättermann
476652da0a [i18n] Updated German translation 2010-09-19 13:52:05 +02:00
Bruno Brouard
35289050e4 Updated French translation 2010-09-19 00:22:14 +02:00
Owen W. Taylor
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
Jorge González
a7d1053ff5 Updated Spanish translation 2010-09-17 19:47:59 +02:00
Florian Müllner
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
Florian Müllner
7d8cc4f940 Fix build error introduced in the last commit 2010-09-15 03:15:46 +02:00
Florian Müllner
ee2f995fc7 introspection: Fix annotations
The scanner got stricter again - some annotations need fixing.
2010-09-15 02:31:47 +02:00
Gabor Kelemen
7e852f8c14 Updated Hungarian translation 2010-09-14 12:07:08 +02:00
Matej Urbančič
b4c1692d14 Updated Slovenian translation 2010-09-11 20:29:06 +02:00
Dr.Tirumurti Vasudevan
c0858b247f Updated Tamil translation 2010-09-11 15:16:58 +05:30
A S Alam
0a956f56aa update for Punjabi 2010-09-11 08:35:26 +05:30
Maxim Ermilov
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
Maxim Ermilov
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
Jasper St. Pierre
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
Colin Walters
e3789e31ef introspection: Remove workaround MetaMutter comment
The scanner should understand this better now.
2010-09-09 11:45:08 -04:00
Florian Müllner
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
Piotr Drąg
86b8b9051f Updated Polish translation 2010-09-07 18:17:25 +02:00
Colin Walters
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
Duarte Loreto
599eb5e3e4 Updated Portuguese translation 2010-09-04 23:06:24 +01:00
Luca Ferretti
31fe25aa78 Unfuzzy translations 2010-09-02 22:58:12 +02:00
Luca Ferretti
252657905f Updated Italian translation 2010-09-02 22:56:20 +02:00
Colin Walters
77a5e817a5 introspection: Use new --accept-unprefixed
Also depend on an introspection version which has this.
2010-09-01 13:20:39 -04:00
Michael Kotsarinis
2521e8103d l10n: Updated Greek translation for mutter 2010-09-01 11:50:37 +03:00
Colin Walters
47fcb998f5 introspection: Enable warnings
Also depend on Makefile to ensure we rerun on build changes.
2010-08-31 19:50:43 -04:00
Philip Withnall
455c40677b Update British English translation 2010-08-31 09:56:30 +01:00
Gabor Kelemen
9ae8e4c006 Updated Hungarian translation 2010-08-31 01:19:09 +02:00
Antonio Fernandes C. Neto
d514516543 Updated Brazilian Portuguese translation 2010-08-30 15:11:24 -03:00
Rob Staudinger
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
Tomas Frydrych
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
Tomas Frydrych
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
Alexander Shopov
3d19e800ab Updated Bulgarian translation 2010-08-24 15:45:58 +03:00
Adel Gadllah
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
Thierry Reding
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
Tomas Frydrych
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
Ask H. Larsen
8c11a2e5a3 Updated Danish translation 2010-08-22 13:36:05 +02:00
Chao-Hsiung Liao
693c2bc175 Updated Traditional Chinese translation(Hong Kong and Taiwan) 2010-08-21 21:01:55 +08:00
Owen W. Taylor
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
Nickolas Lloyd
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
Owen W. Taylor
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
Owen W. Taylor
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
Owen W. Taylor
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
Florian Müllner
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
Florian Müllner
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
Adel Gadllah
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
Owen W. Taylor
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
Nils-Christoph Fiedler
77b620e50e Updated LowGerman translation 2010-08-08 15:45:58 +02:00
drtv
9bc723d256 Updated Tamil translation 2010-08-05 11:51:01 +05:30
A S Alam
b9f9a230e6 update Translation in master for Punjabi by A S Alam 2010-08-04 15:17:03 +05:30
Adel Gadllah
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
Aron Xu
17aa36d343 Update Simplified Chinese translation. 2010-07-24 18:36:51 +08:00
Fran Diéguez
cc0965f9f9 Updated Galician translations 2010-07-21 14:36:14 +02:00
Chao-Hsiung Liao
0e728d7751 Updated Traditional Chinese translation(Hong Kong and Taiwan) 2010-07-20 19:28:28 +08:00
Claude Paroz
3e6cf75d73 Updated French translation 2010-07-19 17:50:22 +02:00
Aron Xu
bbedba8b18 Update Simplified Chinese translation. 2010-07-18 11:10:55 +08:00
Mario Blättermann
c8d756dde3 [i18n] Updated German translation 2010-07-16 21:23:23 +02:00
Matej Urbančič
97a8dbb71e Updated Slovenian translation 2010-07-14 15:03:24 +02:00
Kjartan Maraas
6835804dab Updated Norwegian bokmål translation 2010-07-13 18:54:08 +02:00
Owen W. Taylor
1a2a374380 Bump version to 2.31.5 2010-07-12 11:44:09 -04:00
Andreas Mueller
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
Nickolas Lloyd
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
Petr Kovar
7511ea27e2 Update Czech translation 2010-07-11 22:05:46 +02:00
Florian Müllner
adbe3a2312 Fix gtk+ dependency in libmutter-private pkg-config file 2010-07-09 18:05:02 +02:00
Fran Diéguez
eda50a91df Updated Galician translations 2010-07-07 18:05:50 +02:00
Owen W. Taylor
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
Matej Urbančič
37de1b2d25 Updated Slovenian translation 2010-07-06 15:14:58 +02:00
Jorge González
0c4ac0b48a Updated Spanish translation 2010-07-03 12:35:52 +02:00
Yaron Shahrabani
c24cf44c6a Updated Hebrew translation. 2010-07-03 02:05:52 +03:00
Owen W. Taylor
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Nickolas Lloyd
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
Claudio Saavedra
7a04673dd7 Don't use deprecated GtkTooltips type unnecessarily
Bug 622800.
2010-06-30 01:35:42 +03:00
Claudio Saavedra
c47d2da0cb Don't incĺude internal gdk headers directly
Bug 622800.
2010-06-30 01:35:35 +03:00
Claudio Saavedra
fd12eddb5d Use g_signal_connect_data() instead of deprecated gtk_signal_connect_full()
Bug 622800.
2010-06-30 01:35:26 +03:00
Claudio Saavedra
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
Owen W. Taylor
27de94b915 Bump version to 2.31.4 2010-06-25 16:18:39 -04:00
Kjartan Maraas
9e31f2b1de Added Norwegian bokmål translation 2010-06-20 11:41:52 +02:00
Maxim Ermilov
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
Owen W. Taylor
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
A S Alam
275a6ec63f update Punjabi Translation 2010-06-14 08:09:49 +05:30
Colin Walters
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
Colin Walters
72a19dd448 [display] Include unistd.h for gethostname
https://bugzilla.gnome.org/show_bug.cgi?id=620860
2010-06-07 12:32:56 -04:00
Colin Walters
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
Colin Walters
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
Robert Bragg
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
Fran Diéguez
ed19060074 Updated Galician translations 2010-06-03 23:46:58 +02:00
Yaron Shahrabani
f230a67b94 Updated Hebrew translation. 2010-06-03 14:33:17 +03:00
Owen W. Taylor
849f101feb Bump version to 2.31.2 2010-05-25 14:16:40 -04:00
Owen W. Taylor
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
Claude Paroz
4c143ae9af Updated French translation 2010-05-17 20:39:44 +02:00
Khaled Hosny
cd1a1d5778 Updated Arabic translation 2010-05-15 23:55:34 +03:00
Tomas Frydrych
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
Tomas Frydrych
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
Tomas Frydrych
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
Florian Müllner
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
Florian Müllner
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
Javier Jardón
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
Owen W. Taylor
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
Colin Walters
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
Colin Walters
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
Colin Walters
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
Mario Blättermann
22ae86104b Updated German translation 2010-05-02 12:26:41 +02:00
Edward Sheldrake
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
Vincent Untz
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
Owen W. Taylor
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
Colin Walters
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
Colin Walters
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
Robert Bragg
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
Robert Bragg
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
Luca Ferretti
af60dd3634 Add a missing space 2010-04-21 14:09:12 +02:00
Matej Urbančič
ccabce1b34 Updated Slovenian translation 2010-04-17 19:39:08 +02:00
Owen W. Taylor
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
Jorge González
a78373f324 Updated Spanish translation 2010-04-14 19:53:44 +02:00
Owen W. Taylor
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
Owen W. Taylor
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
Owen W. Taylor
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
Owen W. Taylor
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
Owen W. Taylor
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
Owen W. Taylor
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
Owen W. Taylor
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
Owen W. Taylor
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
Dan Winship
debf08cac0 Fix handling of grabbed key events
https://bugzilla.gnome.org/show_bug.cgi?id=596659
2010-04-12 17:52:19 -04:00
Javier Jardón
ce1393d2d4 Fix missing comma in previous commit 2010-04-11 19:59:29 +02:00
Javier Jardón
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
Owen W. Taylor
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
Adel Gadllah
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
Luca Ferretti
0021efd593 Updated Italian translation 2010-04-06 22:53:15 +02:00
Xandru Armesto Fernandez
0d955bb873 Updated asturian translation 2010-03-30 06:03:10 +02:00
Pavol Šimo
7fa2e8d2d3 Updated Slovak translation 2010-03-27 16:48:20 +01:00
Gintautas Miliauskas
713d94d881 Updated Lithuanian translation. 2010-03-27 12:06:07 +02:00
Petr Kovar
4ecf8964b8 Update Czech translation 2010-03-20 02:54:09 +01:00
Inaki Larranaga Murgoitio
11d044fa6e Updated Basque language 2010-03-19 17:28:47 +01:00
Owen W. Taylor
a2104c5404 Bump version to 2.29.1 2010-03-18 18:29:48 -04:00
Dan Winship
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
Bruno Brouard
1465895ff7 Updated French translation 2010-03-17 21:39:21 +01:00
Robert Bragg
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
Tomas Frydrych
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
Colin Walters
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
Owen W. Taylor
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
Owen W. Taylor
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
Alexander Shopov
b5cb353ab5 Added Bulgarian translation 2010-02-27 10:50:32 +02:00
Nils-Christoph Fiedler
17a38dfbed Updated LowGerman translation 2010-02-25 16:59:48 +01:00
Piotr Drąg
f773683601 Updated Polish translation 2010-02-24 19:29:54 +01:00
Aron Xu
abeaf828a3 Update Simplified Chinese translation. 2010-02-24 18:58:13 +08:00
Mario Blättermann
23a8a4201a Updated German translation 2010-02-21 17:00:06 +01:00
Nguyễn Thái Ngọc Duy
2d409e5c09 Remove executable bit from mutter-shaped-texture.c 2010-02-21 21:23:17 +07:00
Owen W. Taylor
2d57904bf4 Bump version to 2.29.0 2010-02-18 17:08:21 -05:00
Owen W. Taylor
8fa83e1be7 Fix fallback to builtin defaults for key bindings
The change to reduce GConf trips by using
gconf_client_all_entries() broke the fallback to builtin values
because update_binding() was no longer called for bindings not
found in GConf. Fix this by keeping track of the bindings we
find from GConf in a hash table, then looping through and setting
all the bindings at the end.

This also improves efficiency by avoiding a linear scan for each
binding in GConf.

https://bugzilla.gnome.org/show_bug.cgi?id=609710
2010-02-18 14:26:12 -05:00
Owen W. Taylor
8875e73765 Fix crash on startup with list bindings
When we are reading bindings initially, update_list_binding() needs
to be passed the correct "string list type" since we are calling
it with a list of strings instead of a list of GConfValue.

https://bugzilla.gnome.org/show_bug.cgi?id=609101
2010-02-18 14:26:12 -05:00
Richard Hughes
65766fcaac Fix the build when using a compiler that defaults to --no-add-needed
https://bugzilla.gnome.org/show_bug.cgi?id=606388
2010-02-16 16:32:11 -05:00
Owen W. Taylor
4cd4010a70 Fix compiling with --disable-gconf
Make the body of meta_prefs_set_clutter_plugins()
conditional on compiling with GConf support.
2010-02-16 15:17:01 -05:00
Florian Müllner
d21da5643b [MetaWindow] Expose maximized state as properties
Add properties for the EWMH _NET_WM_STATE_MAXIMIZED_HORZ and
_NET_WM_STATE_MAXIMIZED_VERT hints.

https://bugzilla.gnome.org/show_bug.cgi?id=590706
2010-02-15 21:40:46 +01:00
Jorge González
ba700e6387 Updated Spanish translation 2010-02-15 11:31:58 +01:00
Neil Roberts
bd90fd7033 Add the group from cogl_get_option_group() to the GOptionContext
Otherwise it's not possible to use the COGL_DEBUG environment variable.

https://bugzilla.gnome.org/show_bug.cgi?id=609350
2010-02-12 11:40:05 +00:00
Tomas Frydrych
fb3d352d3a [MutterShapedTexture] Use cogl multitexture API
The older code relied on Clutter providing default texture coords for any
layers for which texture coords were not specified, which does not work as
of Clutter 1.1.6 (due to commit 8b950bdc87).

https://bugzilla.gnome.org/show_bug.cgi?id=609657
2010-02-12 11:37:30 +00:00
Gabor Kelemen
690852e157 Hungarian translation updated 2010-02-11 23:34:53 +01:00
Matej Urbančič
aa84d21bcf Updated Slovenian translation 2010-02-11 20:59:51 +01:00
Owen W. Taylor
4d62977c7b Accept an empty string as well as "disabled" for keybindings
Treat the empty string the same as "disabled" for GConf keybinding
keys. gnome-keybinding-properties was changed to write disabled
keys as the empty string a year or so ago.

https://bugzilla.gnome.org/show_bug.cgi?id=559816
2010-02-11 13:02:50 -05:00
Owen W. Taylor
cbac2e7bbb Allow applications to raise windows when raise_on_click is off
Whether Metacity honors a raise request from an application should
not be affected by the raise_on_click setting; remove a check that
seems to have been added in error.

https://bugzilla.gnome.org/show_bug.cgi?id=445447
2010-02-11 13:02:50 -05:00
Owen W. Taylor
88ee4c5b30 Don't focus ancestor window on a different workspace
When we are moving a window with a modal dialog to a different
workspace, meta_workspace_focus_default_window() can be called
with 'not_this_one' being the focused modal dialog.

Since the ancestor of that window is also being moved, we must
not focus it as an alternative to the current window; this will
cause windows to be moved back and Metacity to get into an
inconsistent confused state.

https://bugzilla.redhat.com/show_bug.cgi?id=237158

https://bugzilla.gnome.org/show_bug.cgi?id=598995
2010-02-11 13:02:50 -05:00
Owen W. Taylor
12c46c5d8b Allow explicit raises from same client, not just same app
We currently allow XRaiseWindow when the same application (defined
by the window group) is focused, but the kind of old applications
that XRaiseWindow are frequently not setting the window group.

Expand the check to allow the same X client (defined by the looking
at client ID) to raise windows above the focus window.

https://bugzilla.gnome.org/show_bug.cgi?id=567528
2010-02-11 13:02:50 -05:00
Tomislav Vujec
ab7d4e0e60 Don't warn about a missing session file
When started without session related command line parameters (e.g. from
gnome-session), metacity picks up client_id from the DESKTOP_AUTOSTART_ID
environment variable. Unfortunately, there is no way to distinguish if this was
passed from a config file, representing old saved session, or generated by
gnome-session, therefore load_state is attempted in each case. If the client_id
is generated, there will be no session file, and metacity will report a
warning.

Just remove the warning so that users won't always find a warning at the
start of their .xsession-errors.

https://bugzilla.gnome.org/show_bug.cgi?id=577576
2010-02-11 13:02:49 -05:00
Owen W. Taylor
708c6162c4 Handle XError and XIOError for unknown displays
The atk-bridge GTK+ module opens its own display; if we get an
XIOError on that display, we shouldn't abort with a meta_bug()
but just exit normally. Also fix a segfault if we got an XError
for that display.

https://bugzilla.gnome.org/show_bug.cgi?id=604319
2010-02-11 13:02:49 -05:00
Owen W. Taylor
7834bba6f7 Merge changes from Metacity
Merge all relevant changes from Metacity as of Feb 10, 2010

For future merger's reference, the best way to merge changes from
Metacity is to add the Metacity git repository as a remote, then
cherry-pick the desired changes - this will exploit the shared
history of the two repositories when merging in the changes.

Then when finished, use 'git merge -s ours <head commit of metacity>'
to record the merge, and 'git commit --amend' to fix up the
commit message.
2010-02-11 12:15:29 -05:00
Owen W. Taylor
857c8aaaa2 Make libcanberra support optional
Add a configure switch:

 --with-libcanberra=[yes/no/auto]

(defaulting to auto); if libcanberra is not found or explicitly
disabled, then the default system bell will be used for the bell
sound and no switch workspace sound is played.

https://bugzilla.gnome.org/show_bug.cgi?id=609585
2010-02-11 12:04:11 -05:00
Lennart Poettering
1253e6c64e sound: ask libcanberra to cache alert/desktop switch sounds
These sounds are good candidates for caching in the sound server, to
save a bit of CPU and make reaction faster. Hence, tell libcanberra to
cache them.

https://bugzilla.gnome.org/show_bug.cgi?id=609585
2010-02-11 12:04:10 -05:00
Lennart Poettering
b610b2ecc7 tooltip: set window type hint for self-drawn tooltips to GDK_WINDOW_TYPE_HINT_TOOLTIP
libcanberra generates specific tooltip popup sounds and for that
recognizes the tooltip windows by the GtkWindowTypeHint set for them.

This trivial patch simply sets the hint for the self-drawn tooltips
metacity uses.

https://bugzilla.gnome.org/show_bug.cgi?id=609585
2010-02-11 12:04:10 -05:00
Lennart Poettering
11addbe9c8 bell: increase bell rate limit from 1/s to 1/100ms
Right now metacity issues only 1 bell event per second. This is
feels buggy when triggering multiple alarm sounds in a terminal.

This patch simple increases the limit to 1/100ms. 100ms is probably a
good choice since the HIG recommends that all user reaction should
happen within 100ms. With this applied pressing 'Left' in gnome-terminal
feels much more responsive.

https://bugzilla.redhat.com/show_bug.cgi?id=498608

https://bugzilla.gnome.org/show_bug.cgi?id=609585
2010-02-11 12:04:10 -05:00
Matthias Clasen
709ef05714 Don't force CA_PROP_CANBERRA_ENABLE to 1.
* src/core/bell.c: Don't force CA_PROP_CANBERRA_ENABLE to 1.
That was a misunderstanding on my part, and makes it impossible
to get rid of the bell.

svn path=/trunk/; revision=4165

https://bugzilla.gnome.org/show_bug.cgi?id=609585
2010-02-11 12:04:10 -05:00
Matthias Clasen
c51767eef1 Now that we are using libcanberra, don't tell the X server to play the bell
* src/core/bell.c (meta_bell_set_audible): Now that we are
using libcanberra, don't tell the X server to play the system
bell internally.

svn path=/trunk/; revision=4141

https://bugzilla.gnome.org/show_bug.cgi?id=609585
2010-02-11 12:04:10 -05:00
Matthias Clasen
5aab9e878f Use libcanberra to play system bell and workspace switch sounds
Patch by Lennart Poettering

* configure.in: Require libcanberra-gtk

* src/core/bell.c (meta_bell_notify): Play the alert sound from
the sound theme instead of the dreaded system bell.

* src/core/workspace.c (meta_workspace_activate_with_focus): Play
a sound on workspace switch.

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

https://bugzilla.gnome.org/show_bug.cgi?id=609585
2010-02-11 12:04:10 -05:00
Matej Urbančič
e7751e170e Updated Slovenian translation 2010-02-11 15:08:24 +01:00
Kjartan Maraas
776d345bc3 Updated Norwegian bokmål translation 2010-02-11 12:43:02 +01:00
Owen W. Taylor
a8fc30a13f Fix typo when checking the result of getpwuid
Was meant to be:

  errno==0 && pwd!=NULL

Not:

  errno==0 || pwd==NULL

https://bugzilla.gnome.org/show_bug.cgi?id=609586
2010-02-10 16:10:49 -05:00
Matthias Clasen
2d57b1b470 Reduce GConf roundtrips
metacity tries to do the right thing, by preloading all the relevant
directories before getting the keys one-by-one, but GConfClient isn't actually
smart enough to avoid server roundtrips in this case. That should certainly be
fixed in GConf.

In the meantime, here is a patch that reworks the metacity prefs initialization
to avoid roundtrips for individual keys anyway, by using
gconf_client_all_keys().

https://bugzilla.gnome.org/show_bug.cgi?id=574121
https://bugzilla.gnome.org/show_bug.cgi?id=607746
2010-02-10 14:32:48 -05:00
Thomas Hindoe Paaboel Andersen
90f21fa5db Replace usage of deprecated gtk api
Fixes part of GNOME Bug #572332
2010-02-10 14:03:12 -05:00
Vincent Untz
6638d0e507 Increase ping timeout delay to 5s
https://bugzilla.gnome.org/show_bug.cgi?id=568790
2010-02-10 12:49:15 -05:00
Peter Bloomfield
c6793d477a Prevent window self-maximisation
https://bugzilla.gnome.org/show_bug.cgi?id=461927
2010-02-10 12:48:10 -05:00
alexisdm59
11e01ec074 check window has frame before flashing it
https://bugzilla.gnome.org/show_bug.cgi?id=598231
2010-02-10 12:25:40 -05:00
Owen W. Taylor
1d827caaaf Don't call IceCloseConnection() behind libSM's back
The ICE connection is opened by libSM; we can't just close it when
we get an IOError on the ICE connection; instead call SmcCloseConnection()
and mark the connection as closed. This will prevent a segfault if we
exit out of the metacity main loop and get to meta_finalize().

https://bugzilla.gnome.org/show_bug.cgi?id=604867
2010-02-10 12:25:40 -05:00
Travis Watkins
ba4db78ed9 store timestamp for _NET_WM_CM_SX selection
https://bugzilla.gnome.org/show_bug.cgi?id=530702
2010-02-10 12:25:20 -05:00
Thomas Thurman
a321f4c842 Throw away result of write(); it's not important 2010-02-10 12:19:01 -05:00
Claude Paroz
b1c465eab0 Remove markup from translated string 2010-02-10 12:17:43 -05:00
Ray Strode
5134b05af9 Don't call meta_finalize from SIGTERM handler
It's not a legal function to call from a signal handler.
Instead defer until going back to the main loop.

https://bugzilla.gnome.org/show_bug.cgi?id=600864
2010-02-10 12:16:46 -05:00
Owen W. Taylor
dc3a93be99 Add XFCE Terminal as a terminal
Include the XFCE terminal program 'Terminal' in the list of terminals.

https://bugzilla.gnome.org/show_bug.cgi?id=599262
2010-02-10 12:12:58 -05:00
Ray Strode
49aabfec02 Change default cycle_group keybinding to Alt-grave
It makes more sense because the grave key is close
to the tab and escape keys which the other cycle
keybindings use.

This always works better for gnome-shell, which
switchings between applications by default with alt-tab.
The user can now alt-tab to the application they want,
and then move their finger to the grave key to select
the window they want.
2010-02-10 12:12:29 -05:00
Matthias Clasen
11d0d207fd unset _NET_SUPPORTING_WM_CHECK when shutting down 2010-02-10 12:10:55 -05:00
Tomeu Vizoso
eed3245b1b Add a switch to disable autofullscreen'ing maximized windows without decorations 2010-02-10 12:04:42 -05:00
Matt Kraai
a7bbde1699 Don't define meta_spew_event unless verbose mode is on. Closes #571126.
svn path=/trunk/; revision=4132
2010-02-10 11:13:30 -05:00
Matt Kraai
bacccafe3c Only put demands-attention windows into alt-tab if of appropriate type
Windows demanding attention should never appear in the alt-tab list
unless they're of a type which might have appeared there anyway. This
solves a problem under AWN where docks which were marked as demanding
attention appeared in all alt-tab lists; they were irrelevant and it
was impossible to remove them from the lists.

svn path=/trunk/; revision=4123
2010-02-10 11:12:41 -05:00
Thomas James Alexander Thurman
3a80bd47cc some commenting
* src/ui/theme.c: some commenting

svn path=/trunk/; revision=4122
2010-02-10 11:03:01 -05:00
Thomas James Alexander Thurman
152917d5e1 Lines where x1==x2 or y1==y2 may have the second element null
Lines where x1==x2 or y1==y2 may have the second element null. Lines
where both are null, and the width is zero, are points. This speeds
things up surprisingly much.

svn path=/trunk/; revision=4119
2010-02-10 10:53:50 -05:00
Owen W. Taylor
c588e173f8 Remove the year number from the copyright string into a constant
(This is inspired by Metacity commit 45cbaa2 by Thomas Thurman, but
much simpler - the use of g_date_strftime("%Y") ended up being just
%d for all 90+ current translations)
2010-02-10 10:27:48 -05:00
Thomas James Alexander Thurman
c0d2ead351 collapse several strings into one for the translators' benefit.
* src/ui/theme-parser.c: collapse several strings into one
        for the translators' benefit.

svn path=/trunk/; revision=4117
2010-02-10 09:59:28 -05:00
Owen W. Taylor
6ffe5f8343 meta_workspace_set_builtin_struts(): optimize out non-changes
meta_workspace_set_builtin_struts() is slightly expensive; it involves
discarding all our cached computed information about the layout of the
workspace. So catch calls to set_builtin_struts() that don't change
anything.

https://bugzilla.gnome.org/show_bug.cgi?id=609546
2010-02-10 09:56:47 -05:00
Owen W. Taylor
2a823ef3e4 Fix crash when struts change during grab operation
Since meta_workspace_invalidate_work_area() frees the edges
workspace->screen_edges and workspace->monitor_edges, we must clean up
our cached edge resistance data when the invalidate_work_area() is
called on the active workspace, or when the workspace changes.

Make the computation of the edge resistance data lazy so that it
will be recomputed the next time we try to access it.
meta_display_compute_resistance_and_snapping_edges() is made
private to edge-resistance.c

Invaliding the data when active workspace changes also will improve
correctness for edge resistance when the current workspace changes
during a grab operation. (Even with this fix we still don't try to
handle window positions changing during a grab operation; that can't
cause a crash since, unlike screen and monitor edges, the window edges
are freshly allocated, it will just cause slight oddness in that
corner case.)

Root cause tracked down due to much effort by Jon Nettleton.
https://bugzilla.gnome.org/show_bug.cgi?id=608800
2010-02-09 17:00:20 -05:00
Theppitak Karoonboonyanan
5159c3f3ca Updated Thai translation. 2010-02-07 20:20:59 +07:00
Petr Kovar
d092924961 Update Czech translation 2010-02-05 00:05:37 +01:00
Colin Walters
e14132b826 [introspection] Include xlib.gir
We need this for KeySym at least.

https://bugzilla.gnome.org/show_bug.cgi?id=607125
2010-02-03 14:17:41 -05:00
Simos Xenitellis
df36ff638e Updated Greek translation, closes #608572 2010-01-31 05:06:24 -08:00
Ivar Smolin
ad1fee8233 Updating Estonian translation 2010-01-31 10:39:20 +02:00
Ísis Binder
3883d511a9 Updated Brazilian Portuguese translation. 2010-01-29 12:40:29 -05:00
Thomas Thurman
10803b0d25 Update Shavian translation 2010-01-28 19:43:33 -05:00
Jamil Ahmed
a570a57863 Updated Bengali translation 2010-01-29 01:04:35 +06:00
Matej Urbančič
a7590f9717 Updated Slovenian translation 2010-01-27 12:48:28 +01:00
Thomas Thurman
35224ca8d4 post-release bump to 2.28.2 2010-01-25 19:30:02 -05:00
Thomas Thurman
40563e4f84 2.28.1 released 2010-01-25 19:28:50 -05:00
Alexander Shopov
c30901e9be Updated Bulgarian translation 2010-01-25 22:40:20 +02:00
Jorge González
4fc0a91b31 Updated Spanish translation 2010-01-25 19:41:10 +01:00
Dan Winship
576417648a Work around Xlib 64-bit "specialness"
When putting 32-bit properties into longs on 64-bit architectures,
XGetWindowProperty assumes the values are supposed to be signed, and
so it sign-extends values greater than 0x7fffffff. So if they *aren't*
supposed to be signed, we need to chop off the high bits ourselves.

(Most CARDINAL-valued properties only end up using small values
anyway, so it doesn't matter, but _NET_WM_WINDOW_OPACITY uses the full
range, and so was previously failing on 64-bit machines.)

https://bugzilla.gnome.org/show_bug.cgi?id=605678
2010-01-25 11:07:32 -05:00
Owen W. Taylor
0aace5230f Cleanup: split MetaSide from MetaDirection
The MetaDirection enumeration had META_SIDE_* values in it that
were used in some places where an enum with only four directions
was needed. Split this off into a separate enum called MetaSide
and use that enum name where appropriate.
2010-01-22 12:31:20 -05:00
Kjartan Maraas
8d5ba7a6d7 Updated Norwegian bokmål translation 2010-01-22 14:58:23 +01:00
Kjartan Maraas
f8153b84de Updated Norwegian bokmål translation 2010-01-22 14:35:54 +01:00
Matthias Clasen
fac5b0c9e7 Reduce GConf roundtrips 2010-01-21 16:54:22 -05:00
Luis Torres
eb06413188 Replace deprecated symbols in theme-viewer.c
-Replaced calls to gtk_toolbar_insert_stock with gtk_toolbar_insert
-Created appropriated GtkToolButtons
2010-01-21 16:32:35 -05:00
Luis Torres
066c870271 Replaced deprecated symbols in metacity-window-demo.c
-Replaced calls to gtk_toolbar_insert_stock with gtk_toolbar_insert
-Created appropriate GtkToolButton items
2010-01-21 16:31:13 -05:00
Thomas Hindoe Paaboel Andersen
1a92fa788d Replace usage of deprecated gtk api
Fixes part of GNOME Bug #572332
2010-01-21 15:03:47 -05:00
Theppitak Karoonboonyanan
3a0ab1cc0c fix documentation of mouse_button_modifier 2010-01-21 10:58:04 -05:00
Vincent Untz
8a7d588bb0 Increase ping timeout delay to 5s 2010-01-20 15:11:02 -05:00
Peter Bloomfield
4943d79d68 prevent window self-maximisation 2010-01-20 10:59:07 -05:00
Emmanuele Bassi
5de10c34b7 Update the Git ignore file 2010-01-19 02:06:31 +00:00
Emmanuele Bassi
2fbe4c2388 Do not use CGL_* symbols
The CGL_* defines in COGL were always meant to be private and should
have never been exposed in the first place. The API in COGL has been
updated to never require them starting from 1.1, but using the original
GL symbols has always been the intent of the API.

This commit removes the CGL_TEXTURE_RECTANGLE_ARB usage in favour of the
ARB-sanctioned GL_TEXTURE_RECTANGLE_ARB enumeration value.

Signed-off-by: Emmanuele Bassi <ebassi@linux.intel.com>

https://bugzilla.gnome.org/show_bug.cgi?id=607398
2010-01-19 01:34:22 +00:00
alexisdm59
767cb27f78 check window has frame before flashing it 2010-01-17 13:41:59 -05:00
Erdal Ronahi
b8c75c3fc0 Updated Kurdish translations, author simurg56 2010-01-16 00:13:41 +01:00
Owen W. Taylor
edeadf62ef Don't call IceCloseConnection() behind libSM's back
The ICE connection is opened by libSM; we can't just close it when
we get an IOError on the ICE connection; instead call SmcCloseConnection()
and mark the connection as closed. This will prevent a segfault if we
exit out of the metacity main loop and get to meta_finalize().

https://bugzilla.gnome.org/show_bug.cgi?id=604867
2010-01-14 16:43:51 -05:00
Kjartan Maraas
5ac80057c4 Updated Norwegian bokmål translation 2010-01-13 22:29:55 +01:00
Inaki Larranaga Murgoitio
210e30556e Updated Basque language 2010-01-13 19:19:09 +01:00
Daniel Nylander
0487b4213f Updated Swedish translation 2010-01-09 17:33:27 +01:00
Maxim V. Dziumanenko
8f29c14ac4 Update Ukrainian translation 2010-01-06 17:38:35 +02:00
Matej Urbančič
9543d8be10 Updated Slovenian translation 2010-01-06 15:34:35 +01:00
Jorge González
43e0003e79 Updated Spanish translation 2010-01-06 14:37:45 +01:00
Travis Watkins
30e63a7244 store timestamp for _NET_WM_CM_SX selection 2010-01-05 17:29:06 -05:00
Thomas Thurman
575f520461 Throw away result of write(); it's not important 2010-01-05 15:44:01 -05:00
Claude Paroz
df618c9e91 Remove markup from translated string 2010-01-05 15:39:50 -05:00
Djavan Fagundes
ebd13a4bae Updated Brazilian Portuguese translation 2009-12-31 19:41:18 -02:00
Lucian Adrian Grijincu
7aa54b5a23 Update Romanian translation 2009-12-19 12:38:01 +02:00
Nickolas Lloyd
b20cb36f5d Migrate to new cogl framebuffer framework
The 1.2 API for draw-buffers/framebuffers has changed a bit
since the code in mutter-texture-tower.c was written; adapt to
the changes.

https://bugzilla.gnome.org/show_bug.cgi?id=604200
2009-12-14 11:59:08 -05:00
Owen W. Taylor
86f8c1863e Work around Mesa problem with PFNGLACTIVETEXTUREPROC
PFNGLACTIVETEXTUREPROC (a GL-1.2 addition) was inadvertently missing
from some recent versions of Mesa (like that in Fedora 11.) Use
the identical PFNGLACTIVETEXTUREARBPROC instead.
2009-11-30 10:51:45 -05:00
Frederic Peters
19d85c8566 Fix build failure from SIGCHLD nexus left overs
Looks like there are some leftovers in include/util.h:

/**
 * An object which exists purely to attach signals to; this is to receive
 * signals when a child process exits.  The signal is "sigchld" with no detail.
 */
extern MetaNexus *sigchld_nexus;

Removing those lines fixes the build
2009-11-29 20:40:12 -05:00
Khaled Hosny
4241f91a0a Updated Arabic translation 2009-11-28 06:25:49 +02:00
Khaled Hosny
05624f099a Updated Arabic translation 2009-11-28 05:59:23 +02:00
Nils-Christoph Fiedler
920f4099b6 Added LowGerman translation 2009-11-26 22:05:51 +01:00
Nils-Christoph Fiedler
aa26750e01 Added LowGerman translation 2009-11-26 22:05:03 +01:00
Owen W. Taylor
bdb3be7084 Fix compilation with older libGL
the mutlitexture and texture_rectangle extensions have recently
been incorporated into the GL core; fixes needed to work with
libGL that proceeds that:

GL_TEXTURE_RECTANGLE_ARB - use _ARB name
glActiveTextureARB() - use get_proc_address

https://bugzilla.gnome.org/show_bug.cgi?id=602870
2009-11-24 15:58:42 -05:00
Owen W. Taylor
14987f2b21 Remove XOR gc only used in removed reduced-resources mode
Remove screen.root_xor_gc; this was only used for XOR drawing
in reduced-resources mode, which was removed.

https://bugzilla.gnome.org/show_bug.cgi?id=602740
2009-11-24 15:40:35 -05:00
Owen W. Taylor
47af6a0bbf Nice looking scaledown with mipmap emulation
Add MutterTextureTower, an abstraction for getting a image with
the right level of detail for rendering at a particular scale,
by manually scaling down by powers of two.

This results in much better looking scaled window images when
mipmaps can't be used with texture_from_pixmap (which is the
typical case for current GL drivers.)

When framebuffer objects are available, they are used to do
the scaledown using the GPU without having to pull the data
back from video memory. A software codepath is also available
for the case when FBO's are not present, though performance
will suffer

https://bugzilla.gnome.org/show_bug.cgi?id=601032
2009-11-24 15:40:35 -05:00
Lennart Poettering
1487578ff4 sound: ask libcanberra to cache alert/desktop switch sounds
These sounds are good candidates for caching in the sound server, to
save a bit of CPU and make reaction faster. Hence, tell libcanberra to
cache them.
2009-11-20 11:38:21 -05:00
Lennart Poettering
5a03a5d578 tooltip: set window type hint for self-drawn tooltips to GDK_WINDOW_TYPE_HINT_TOOLTIP
libcanberra generates specific tooltip popup sounds and for that
recognizes the tooltip windows by the GtkWindowTypeHint set for them.

This trivial patch simply sets the hint for the self-drawn tooltips
metacity uses.
2009-11-20 11:36:25 -05:00
Lennart Poettering
2dd137329d bell: increase bell rate limit from 1/s to 1/100ms
Right now metacity issues only 1 bell event per second. This is
feels buggy when triggering multiple alarm sounds in a terminal.

This patch simple increases the limit to 1/100ms. 100ms is probably a
good choice since the HIG recommends that all user reaction should
happen within 100ms. With this applied pressing 'Left' in gnome-terminal
feels much more responsive.

https://bugzilla.redhat.com/show_bug.cgi?id=498608
2009-11-20 11:36:10 -05:00
Dan Winship
db37deb589 Fix handling of SIGCHLD
The commit that removed metacity-dialog added a global SIGCHLD handler
that caused problems by (a) calling waitpid(-1) and thus breaking
g_child_watch for everyone else, and (b) doing too much from a signal
handler and sometimes causing deadlocks (bug 596200).

This removes the global handler and has each zenity user create its
own child watch to watch for exit. (It also fixes the window class of
the zenity dialogs, so that meta_window_present_delete_dialog()
will work again.)
2009-11-20 11:34:50 -05:00
Ray Strode
ec7a3c516d Don't call meta_finalize from SIGTERM handler
It's not a legal function to call from a signal handler.
Instead defer until going back to the main loop.

https://bugzilla.gnome.org/show_bug.cgi?id=600864
2009-11-20 11:16:02 -05:00
Dan Winship
988d2ffab6 Fix handling of SIGCHLD
The commit that removed metacity-dialog added a global SIGCHLD handler
that caused problems by (a) calling waitpid(-1) and thus breaking
g_child_watch for everyone else, and (b) doing too much from a signal
handler and sometimes causing deadlocks (bug 596200).

This removes the global handler and has each zenity user create its
own child watch to watch for exit. (It also fixes the window class of
the zenity dialogs, so that meta_window_present_delete_dialog() will
work again.)
2009-11-20 11:15:58 -05:00
Tomas Frydrych
5e2c66e241 [MetaDisplay] added "window-marked-urgent" signal
Having a MetaDisplay window-marked-urgent signal when a window sets its urgent
hint allows for centralized processing

https://bugzilla.gnome.org/show_bug.cgi?id=600068
2009-11-20 08:57:36 +00:00
Tomas Frydrych
0ccfb0d781 [MetaWindow] added urgent property
Property tracking ICCCM urgency hint

https://bugzilla.gnome.org/show_bug.cgi?id=600068
2009-11-20 08:51:19 +00:00
Nickolas Lloyd
01ce961c00 Fix typo in test-resizing.c
Check heightp not *heightp before assigning to heightp

https://bugzilla.gnome.org/show_bug.cgi?id=602349
2009-11-19 17:40:50 -05:00
Tomas Frydrych
7579b691df [MetaDisplay] Added window-demands-attention signal
Having a MetaDisplay::window-demands-attention signal allows to deal with
windows demanding attention in a cetralized fashion.

The signal is emitted when a window is created with initial demands-attention
state and/or when the state changes later on.

Based on original patch by Jon Nettleton.

https://bugzilla.gnome.org/show_bug.cgi?id=597052
2009-11-17 10:06:25 +00:00
Tomas Frydrych
2a14deab0c [MetaWindow] Added boolean demands-attention property
https://bugzilla.gnome.org/show_bug.cgi?id=588065
2009-11-17 10:06:06 +00:00
Kjartan Maraas
1acefb9eac Updated Norwegian bokmål translation. 2009-11-15 15:06:26 +01:00
Owen W. Taylor
fb45b8f45c Correctly initialize window->input field
With the change from bug 582639, we no longer call the reload
functions for properties that are not initially set, so the
initialization of fields in window.c has to match what
window-props.c would set for a missing property.

There was only one discrepancy, window->input, which needs
to be set to TRUE by default (or a window missing a WM_HINTS
property won't get focus); we also add explicit initializers
for a couple of fields that were getting 0-initialized
to the correct default value of FALSE for consistency with
the explicit intialization of the rest of the fields.

Bug reported by Dominique Leuenberger
https://bugzilla.gnome.org/show_bug.cgi?id=601228
2009-11-12 13:57:11 -05:00
Maxim Ermilov
d59a9c2e8a Correct meta_workspace_list_windows annotation.
https://bugzilla.gnome.org/show_bug.cgi?id=591912
2009-11-12 11:50:07 -05:00
Gil Forcada
a1c3d8723d Minor fixes to Catalan translation 2009-11-05 00:24:21 +01:00
Carles Ferrando
c4bd65e97c Updated Catalan (Valencian) translation 2009-11-05 00:20:36 +01:00
Peteris Krisjanis
eac3a2d7ac Updated Latvian translation. 2009-11-02 22:41:55 +02:00
Thomas Thurman
55bb584778 Shavian translation 2009-10-31 21:57:06 -04:00
Reşat SABIQ
4584943531 Another tiny update for Crimean Tatar (Crimean Turkish) translation 2009-10-30 03:34:44 -05:00
Reşat SABIQ
55d2bc0e0b Another update for Crimean Tatar (Crimean Turkish) translation 2009-10-30 03:07:03 -05:00
Reşat SABIQ
c0cc2fa1b8 Minor wording change 2009-10-30 02:11:58 -05:00
Reşat SABIQ
c1ecbd4de1 Added Crimean Tatar (Crimean Turkish) translation 2009-10-30 01:59:58 -05:00
Khaled Hosny
0fb6b8a8ff Updated Arabic translation 2009-10-29 11:18:31 +02:00
Khaled Hosny
78ba9adfed Spelling fixes 2009-10-29 11:04:46 +02:00
Owen W. Taylor
3f642ea34f Add XFCE Terminal as a terminal
Include the XFCE terminal program 'Terminal' in the list of terminals.

https://bugzilla.gnome.org/show_bug.cgi?id=599262
2009-10-21 23:11:01 -04:00
Åsmund Skjæveland
1a3927b40c Updated Norwegian Nynorsk translation 2009-10-17 18:28:32 +02:00
Khaled Hosny
b09d73ab68 Updated Arabic translation 2009-10-16 20:27:15 +02:00
Colin Walters
9311addca3 Add "window-created" signal to MetaDisplay, "unmanaged" signal for MetaWindow
For some consumers it's significantly more convenient to be able
to directly connect to a signal on the Window to know when
Mutter is done with it, rather than having to connect to each
Workspace object (and handle workspace additions, etc.).

Similarly, add window-created which acts globally.

https://bugzilla.gnome.org/show_bug.cgi?id=598289
2009-10-14 14:39:33 -04:00
Richard Hughes
3c76478510 Bump version to 2.28.1 2009-10-14 17:02:44 +01:00
Leonid Kanter
545551e2bc Updated Russian translation 2009-10-11 16:24:24 +03:00
Petr Kovar
d5e0a95ff1 Updated Czech translation 2009-10-10 18:43:53 +02:00
Tomas Frydrych
e811109566 [MutterWindow] Fixed potential NULL dereference
Avoid dereferencing NULL when the window is not yet placed on a workspace.
Added doc comment, noting this function is deprecated.

https://bugzilla.gnome.org/show_bug.cgi?id=592567
2009-10-09 16:50:38 +01:00
Ray Strode
0f805bfdfb Change default cycle_group keybinding to Alt-grave
It makes more sense because the grave key is close
to the tab and escape keys which the other cycle
keybindings use.

This always works better for gnome-shell, which
switchings between applications by default with alt-tab.
The user can now alt-tab to the application they want,
and then move their finger to the grave key to select
the window they want.
2009-10-09 10:21:52 -04:00
Owen W. Taylor
200cd629df Bump version to 2.28.0 2009-10-07 18:40:18 -04:00
Owen W. Taylor
e8a29c1e82 Work around race condition focusing a window on a different workspace
When we focus a window on a different desktop, and the calc_showing
idle that hides/shows the windows gets run before we get focus events
back from X, we think that we are hiding the window with the focus
so we focus a "random" window to avoid leaving the user with no focus.

Work around this temporarily by checking display->expected_focus_window;
this isn't a perfect fix because there are cases where
display->expected_focus_window corresponds to a window we tried to
focus in the past but failed, but it makes things work fairly well.

https://bugzilla.gnome.org/show_bug.cgi?id=597352
2009-10-07 17:28:04 -04:00
Tomas Frydrych
8589e4f3d3 [MutterScreen] Added workareas-changed signal
This signal is emitted when workarea of any workspace belonging to the screen
changes.

https://bugzilla.gnome.org/show_bug.cgi?id=597009
2009-10-07 12:07:00 +01:00
Tomas Frydrych
948e54772d [MutterWindow] Added meta_window_get_transient_for_as_xid()
Accessor for the transient xid hint.

https://bugzilla.gnome.org/show_bug.cgi?id=597010
2009-10-07 11:56:49 +01:00
Claude Paroz
2d4b05a71b Updated French translation 2009-10-05 18:30:50 +02:00
Christian Kirbach
a6433e84f5 Updated German translation 2009-10-04 19:00:26 +02:00
Owen W. Taylor
083854e2de Create the dummy timeline for repaint laters with an "infinite" duration.
When we create the timeline dummy timeline to ensure that our later
functions that should be run during repaint get called called, pass in
G_MAXUINT to make the duration very long, not 0. (It will get reset
whenever there is no repaint later to run, so the fact that G_MAXUINT
is only ~40 days isn't a problem.)

This fixes a warning from Clutter, but also a real problem.
2009-10-02 16:12:11 -04:00
Owen W. Taylor
3508c4aa87 Use "later functions" to fix priority problems with Clutter redraw
There was a problem where if, for example, a restack was triggered
out of a clutter event handler, then after Clutter processed the
events, it would proceed immmediately on to repaint the stage without
ever returning control to the GLib main loop. So even though we
had an idle handler installed with a higher priority than the
Clutter stage repainting the clutter stage repainting would happen
first and we'd get a wrong frame.

Fix this by introducing the idea of "later functions", which abstract
the idea of "doing something later" away from g_idle_add() and use
a combination of GLib idle functions and Clutter "repaint functions"
to get our callbacks triggered at the right time, even when they
are installed from a clutter event handler.

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

This also resolve a FIXME where MUTTER_PRIORITY_BEFORE_REDRAW
could starve stage repainting.
2009-10-02 15:50:16 -04:00
Dan Winship
d04b15ee25 Remove MetaAltTabHandler
gnome-shell is no longer using MetaAltTabHandler, so there's no need
to keep that abstraction around.

This reverts commit 1d5117a6 (and a comment from 7b0ba87b), with a bit
of rebasing and whitespace cleanup.

https://bugzilla.gnome.org/show_bug.cgi?id=596210
2009-10-02 15:47:49 -04:00
Colin Walters
d6143e4c73 mutter_plugin_get_windows returns *Mutter*Window, not MetaWindow 2009-09-28 19:30:24 -04:00
Colin Walters
d8ffc3c187 [mutter_plugin_get_windows] Document it 2009-09-28 16:55:37 -04:00
Owen W. Taylor
2af788956e mutter_begin_modal_for_plugin(): Check result of XGrabKeyboard()
The return value of XGrabKeyboard() wasn't actually being assigned
to the 'result' variable so we didn't notice when grabbing the
keyboard failed.

https://bugzilla.gnome.org/show_bug.cgi?id=596343
2009-09-25 12:59:13 -04:00
Colin Walters
d399141d13 Add meta_window_get_stable_sequence
Useful for plugins which want to order windows in a stable
fashion.

https://bugzilla.gnome.org/show_bug.cgi?id=595882
2009-09-22 12:43:35 -04:00
Frédéric Péters
f6f899f103 [release] 2.28.0 2009-09-22 15:41:33 +02:00
Shankar Prasad
5b8919a246 Updated Kannada(kn) translation 2009-09-21 10:57:57 +05:30
Petr Kovar
fe1989979c Updated Czech translation 2009-09-21 03:15:22 +02:00
Amitakhya Phukan
0895fa9331 Updating Assamese translations 2009-09-20 15:53:01 +05:30
Changwoo Ryu
b90fe0c52a Korean translation update 2009-09-20 09:34:59 +09:00
David Planella
ab0e22159c Updated Catalan translation 2009-09-19 18:29:25 +02:00
Takayuki KUSANO
6ac0afbce0 Updated Japanese translation 2009-09-20 00:56:16 +09:00
Rajesh Ranjan
9532527e52 maithili update, translated by Sangeeta Kumari 2009-09-18 18:28:40 +05:30
Ani
defdf9f34c Updated Malayalam Translations 2009-09-17 23:44:05 +05:30
Yaron Shahrabani
a7dce2dc4e Updated Hebrew translation 2009-09-17 20:01:46 +03:00
Maxim V. Dziumanenko
ea8c51f8f3 Added Ukrainian translation 2009-09-17 19:02:45 +03:00
Manoj Kumar Giri
1e66878447 Upadated Oriya Translation 2009-09-17 18:15:08 +05:30
Manoj Kumar Giri
6cfbdebf6a Upadted Oriya Translation 2009-09-16 19:17:46 +05:30
Antón Méixome
a4469dcc14 Updated Galician Translation 2009-09-16 14:56:21 +02:00
Owen W. Taylor
ac3eac7154 Bump version to 2.27.5 2009-09-15 17:30:07 -04:00
Ani
65ac9065fa Updated Malayalam Translations 2009-09-15 21:26:14 +05:30
Rajesh Ranjan
5143e6763b hindi update by Rajesh Ranjan 2009-09-15 15:12:20 +05:30
Theppitak Karoonboonyanan
5660a8e9f5 Updated Thai translation. 2009-09-15 14:38:08 +07:00
A S Alam
bc2b17df0b Updating Translation for Punjabi 2009-09-15 07:25:17 +05:30
Ani
f9e7c95348 Updaeted Malayalam Translations 2009-09-15 02:54:41 +05:30
Denis ARNAUD
c6afec4759 Updated breton translation 2009-09-14 06:32:03 +02:00
Denis ARNAUD
eb13498fff added br in LINGUAS file 2009-09-14 06:30:37 +02:00
Lucian Adrian Grijincu
163057f521 Updated Romanian translation 2009-09-14 00:10:52 +03:00
Ask H. Larsen
d8ff1f9873 Updated Danish translation 2009-09-13 03:45:00 +02:00
Bruce Cowan
97b7760de8 Updated British English translation 2009-09-12 21:23:02 +01:00
Tommi Vainikainen
acca0f6946 Updated Finnish translation 2009-09-12 22:27:52 +03:00
Matej Urbančič
f3f6d67d46 Updated Slovenian translation 2009-09-12 09:52:02 +02:00
krishnababu k
63773d5226 Updated Telugu Translations 2009-09-11 20:49:57 +05:30
Mario Blättermann
4e4559fc8c Updated German translation 2009-09-10 21:14:43 +02:00
Gintautas Miliauskas
44d540d36c Updated Lithuanian translation. 2009-09-10 14:44:47 +03:00
Fábio Nogueira
c6253a6515 Corrected a bad spacing after a quotation mark in Brazilian Portuguese
translation
2009-09-09 10:06:28 -03:00
Sweta Kothari
65a5ec2ef3 Updated Gujarati Translations 2009-09-09 15:50:22 +05:30
Sandeep Shedmake
70e8b35944 Updated Marathi Translations 2009-09-09 12:54:03 +05:30
Frédéric Péters
ddba25a674 Post-release bump to 2.27.2. 2009-09-08 23:12:45 +02:00
Frédéric Péters
14e6cb6a8f 2.27.1 release 2009-09-08 23:06:42 +02:00
Miloš Popović
d4619150f3 Updated Serbian translation 2009-09-08 13:36:43 +00:00
Colin Walters
5c1a1a2dd5 Fix Super_L specification for overlay_key
A recent commit fixed the schema association, which revealed that our
<Super_L> was wrong, should just be Super_L.
2009-09-07 14:27:09 -04:00
Chao-Hsiung Liao
7cfa690aaf Updated Traditional Chinese translation(Hong Kong and Taiwan) 2009-09-06 15:01:55 +08:00
Owen W. Taylor
8d663ff055 Bump version to 2.27.4
Remove comment about Fibonacci micro numbering. We aren't going
to do that.
2009-09-04 19:00:03 -04:00
Owen W. Taylor
0b86343dd0 Export a _GNOME_WM_KEYBINDINGS property
We need a way to indicate to gnome-control-center that we want the
keybindings capplet to show the Window Manager keybindings for Metacity;
do this through a _GNOME_WM_KEYBINDING property we put on the
_NET_SUPPORTING_WM_CHECK window and set to Mutter,Metacity.

See http://bugzilla.gnome.org/show_bug.cgi?id=594066 for the
gnome-control-center part of this.

http://bugzilla.gnome.org/show_bug.cgi?id=594067
2009-09-04 18:25:39 -04:00
Claude Paroz
e127898312 Updated French translation 2009-09-04 21:32:33 +02:00
Inaki Larranaga Murgoitio
51f83f25e6 Updated Basque language 2009-09-04 11:56:53 +02:00
Colin Walters
8f3da9f68a Use meta_window_set_user_time for setting user time consistently
This is a followup to making user-time a GObject property, this
way we get notifications.
2009-09-03 20:58:19 -04:00
Colin Walters
4c1998f137 Annotate meta_screen_get_active_workspace as (transfer none) 2009-09-03 20:57:39 -04:00
Colin Walters
84dc1c1b85 [MetaWindow] Make user-time a GObject property
Notification of changes are useful for code ordering windows.
2009-09-03 20:57:39 -04:00
Owen W. Taylor
326110e38d Fix owner and applyto for /apps/mutter/general/overlay_key schema
The owner field and the applyto key of
for /schemas//apps/mutter/general/overlay_key were still referencing
metacity not mutter, fix.
2009-09-03 14:48:20 -04:00
Duarte Loreto
f63b81c52a Updated Portuguese translation 2009-09-03 01:08:03 +01:00
Owen W. Taylor
bd2e221da3 Fix broken META_IS_SCREEN macro
Should use META_TYPE_SCREEN not META_SCREEN_TYPE.
2009-09-01 09:38:40 -04:00
Shankar Prasad
1fe673703f Updated Kannada(kn) translation 2009-09-01 11:33:20 +05:30
Dan Winship
c10467d22e Add meta_screen_get_n_monitors() and meta_screen_get_monitor_geometry()
http://bugzilla.gnome.org/show_bug.cgi?id=593686
2009-08-31 18:57:29 -04:00
Owen W. Taylor
e21ec0a271 Fix the dependency for mutter-enum-types.h
mutter-enum-types.h is built from $(libmutterinclude_base_headers) not
the non-existent $(mutter_source_h)
2009-08-31 18:12:29 -04:00
Dan Winship
3a1e492afc Refer to monitors as "monitors" rather than "xineramas"
http://bugzilla.gnome.org/show_bug.cgi?id=593686
2009-08-31 14:39:48 -04:00
Colin Walters
e83c24c91b Add .AUTOPARALLEL flag to Makefile
This automatically enables parallelism with the patched make,
and flags us as maintaining a parallel build.
2009-08-30 20:21:02 -04:00
Colin Walters
81183c71c1 Add public meta_window_get_user_time
Useful for sorting windows by interaction time.
2009-08-30 20:18:11 -04:00
Og B. Maciel
979298ce57 Updated mailing list address. 2009-08-30 12:15:18 -04:00
Baris Cicek
66e727e1b2 Updated Turkish translation. 2009-08-30 18:10:53 +03:00
Jorge González
35b1dda3a3 Updated Spanish translation 2009-08-30 12:47:47 +02:00
Ivar Smolin
6925779f59 Updating Estonian translation 2009-08-30 13:39:01 +03:00
Gabor Kelemen
125d7daf4a Hungarian translation updated 2009-08-29 14:27:23 +02:00
Gabor Kelemen
57c5ea4bd5 Hungarian translation updated 2009-08-29 14:26:10 +02:00
Gabor Kelemen
e75fbdb136 Hungarian translation updated 2009-08-29 14:25:03 +02:00
Gabor Kelemen
cb1020b26d Another update 2009-08-29 14:06:44 +02:00
Gabor Kelemen
e1945506f3 Hungarian translation updated 2009-08-29 13:59:56 +02:00
Owen W. Taylor
8d402971a8 Bump version to 2.27.3 2009-08-28 19:14:34 -04:00
Steve Frécinaux
7e0087304b Add meta_window_is_skip_taskbar
Accessor for the 'skip-taskbar', which will allow gnome-shell not to
consider windows with this hint in its overview thunbnails.
2009-08-28 19:05:17 +02:00
Owen W. Taylor
20b02e738c Make MUTTER_DEBUG_XINERAMA override active Xinerama
It seems a bit cleaner to make the MUTTER_DEBUG_XINERAMA variable
that sets up fake Xinerama take effect even if Xinerama is active;
this means we don't count on Xinerama (or Xrandr if we switch tot
that) special casing the case of one monitor.

http://bugzilla.gnome.org/show_bug.cgi?id=593404
2009-08-28 12:57:29 -04:00
Owen W. Taylor
d042dba4d6 Add meta_display_get_grab_op()
Add a function to determine the current grab op. This can be useful
in a plugin to avoid over-grabbing an X grab held by Mutter.

http://bugzilla.gnome.org/show_bug.cgi?id=593399
2009-08-28 12:27:46 -04:00
Volker Sobek
a69ce37546 Unminimize windows passed to meta_workspace_activate_with_focus()
Unminimize minimized windows passed to meta_workspace_activate_with_focus()
by calling meta_window_activate() on them instead of meta_window_focus()
and meta_window_raise(). This fix makes sense because for the existing
usage inside Mutter meta_workspace_activate_with_focus() is never called
on a minimized window and for calls from outside Mutter there is no
point in focusing a minimized window without unminimizing it first.

Add a doc comment to meta_workspace_activate_with_focus().

http://bugzilla.gnome.org/show_bug.cgi?id=592393
2009-08-28 12:10:41 -04:00
Luca Ferretti
3a798112f2 Updated Italian translation 2009-08-28 09:55:24 +02:00
Tomas Frydrych
3e09b4a725 Check for NULL in meta_screen_tab_popup_destroy() instead of asserting
This function is getting called even when no MetaAltTabHandler object is
installed on the screen, so we need to handle the NULL gracefully.
2009-08-27 17:49:13 +01:00
Inaki Larranaga Murgoitio
c5dd3e5542 Updated Basque language 2009-08-27 17:36:11 +02:00
Ivar Smolin
2fa9cbfd9e Updating Estonian translation 2009-08-27 10:06:35 +03:00
Daniel Nylander
c2c0de1696 Updated Swedish translation 2009-08-27 08:52:02 +02:00
Javier Jardón
cc46d2ebb4 Stop using gtk_toolbar_insert_stock()
Add helper functions instead of using this deprecated symbol.

http://bugzilla.gnome.org/show_bug.cgi?id=587991

A#	../stamp-mutter-marshal.h
2009-08-26 12:57:29 -04:00
Javier Jardón
d0510d8ea2 Stop using GTK_SIGNAL_FUNC, gdk_pixbuf_render_to_drawable
Replace with non-deprecated gdk_draw_pixbuf(), G_CALLBACK()

http://bugzilla.gnome.org/show_bug.cgi?id=587991
2009-08-26 12:56:04 -04:00
Owen W. Taylor
7b0ba87b24 Fix custom-alt-tabs for single-handling of key events
The changes to enforce single handling of all key events were breaking
custom-alt-tab keypress handlers, since that code was assuming that
key event would get to process_tab_grab(), and then maybe to
process_event() and then to the plugin's xevent_filter to detect a
key release.

We centeralize all of this handling into process_tab_grab() and either

 - Invoke a custom handler for the key press
 - Select the current window on modifier release by calling a  new
   pseudo-binding "tab_popup_select"
 - Cancel the grab on an unbound key by calling a new pseudo-binding
   "tab_popup_cancel"

http://bugzilla.gnome.org/show_bug.cgi?id=590754
2009-08-26 12:26:58 -04:00
Owen W. Taylor
67682a2683 Add a modal mode for plugins
mutter_plugin_begin_modal() and mutter_plugin_begin_modal() allow putting
a plugin into a "modal" state. This means:

 - The plugin has the keyboard and mouse grabbed
 - All keyboard and mouse events go exclusively to the plugin

mutter-plugin.[ch]: Add public API
compositor.c compositor-private.h: Implement the API
mutter-plugin-manager.c: When reloading plugins, make sure none of them
  are modal at that moment, and if so force-unmodal them.
common.h: Add META_GRAB_OP_COMPOSITOR
display: When display->grab_op is META_GRAB_OP_COMPOSITOR forward relevant
  events exclusively to the compositor.

http://bugzilla.gnome.org/show_bug.cgi?id=590754
2009-08-26 12:26:58 -04:00
Owen W. Taylor
b1776b5ae5 Enforce a policy of single-handling of key events
Only process each key event once. If all keys are grabbed, then
don't also look for handlers for a key shortcut after processing
the grab op. If all keys are grabbed or we find a key shortcut,
don't pass the event on to the compositing mananger.

http://bugzilla.gnome.org/show_bug.cgi?id=590754
2009-08-26 12:26:58 -04:00
Thomas James Alexander Thurman
7a6968cb46 Only skip the first window in the alt-tab chain if it's actually the
* src/core/display.c: Only skip the first window in
        the alt-tab chain if it's actually the current window
        (urgent windows on other workspaces may precede it).
        Fixes #535887.

http://bugzilla.gnome.org/show_bug.cgi?id=591913

(Metacity commit 92bfe34716)
2009-08-26 15:29:09 +01:00
Runa Bhattacharjee
23af4ee93e Updated Bengali India Translations 2009-08-26 15:42:33 +05:30
Jorge González
0317562605 Updated Spanish translation 2009-08-26 07:57:36 +02:00
Daniel Nylander
1861e0b2cc Updated Swedish translation 2009-08-26 06:04:00 +02:00
Djavan Fagundes
e5974809e8 Updated Brazilian Portuguese translation 2009-08-25 15:21:02 -03:00
Tomasz Dominikowski
abfae17b9a Updated Polish translation 2009-08-25 17:47:45 +02:00
ifelix
84b1a62ad2 Updated Tamil Translations 2009-08-25 17:27:29 +05:30
Denis Arnaud
b6bcaec9bc Updated breton translation 2009-08-25 12:43:20 +02:00
Denis Arnaud
f19ed84cc4 Added br in LINGUAS 2009-08-25 12:43:20 +02:00
Alexander Shopov
6c5a946fda Updated Bulgarian translation 2009-08-24 22:52:12 +03:00
Owen W. Taylor
d58c9a57c6 Avoid accessing freed memory when being replaced
If we are replaced via the window manager selection, then we close
the MetaDisplay before meta_finalize() runs. We should be careful
not to try to close the display again (and access already freed
memory) in that case, so clear the global 'the_display' variable.

See Metacity bug http://bugzilla.gnome.org/show_bug.cgi?id=588119

http://bugzilla.gnome.org/show_bug.cgi?id=592742
2009-08-24 14:29:16 -04:00
Claude Paroz
c6ffc9427e Add missing quotes in strings (Fixes #572046) 2009-08-24 19:49:29 +02:00
krishnababu k
0f1e64f3b2 Updated Telugu Translations 2009-08-24 17:53:05 +05:30
krishnababu k
1ce5ad3003 Added new entry for Telugu [te] in LINGUAS 2009-08-24 17:52:48 +05:30
Khaled Hosny
64694955c0 Updated Arabic translation 2009-08-23 21:40:47 +03:00
Theppitak Karoonboonyanan
97a90d8122 Updated Thai translation. 2009-08-23 15:50:57 +07:00
Changwoo Ryu
3cd2c08277 Update Korean translation 2009-08-23 04:14:10 +09:00
Frédéric Péters
d804a1f146 Remove deprecated Encoding key from desktop files 2009-08-22 14:24:22 +02:00
Colin Walters
01581dc61c [MetaWindow]: Always notify on title property change
The previous notification code was attempting to use the "modified"
boolean returned from set_title_text, but "that boolean doesn't mean
what you think it means".  It actually means "I truncated the title".

Just always notify, it's far simpler than trying to compute
when we don't need to, and callers can compress if they really need
to.
2009-08-21 12:38:30 -04:00
Colin Walters
9cc70a3fb6 Make meta_display_xwindow_is_a_no_focus_window public
Useful for window analysis in plugins.
2009-08-20 14:20:01 -04:00
Henrique P. Machado
c37a2ca1c8 Updated Brazilian Portuguese translation. 2009-08-18 22:34:18 -04:00
Seán de Búrca
80b38210b2 Updated Irish translation 2009-08-17 06:06:18 -06:00
Tommi Vainikainen
e5dffb0097 Updated Finnish translation 2009-08-15 13:59:30 +03:00
Fran Dieguez
7396f5709e Updated Galician Translation 2009-08-15 10:05:52 +02:00
Colin Walters
41cf9134a6 Add meta_window_is_mapped, remove usage of window-private.h from mutter-window.c
mutter-window.c originally grew an #include "window-private.h" for
window->override_redirect, but that was just fixed.  However since
then it also ended up relying on a few other minor private bits.

To fix that, add meta_window_is_mapped, promote meta_window_toplevel_is_mapped
to public, and use the public MetaDisplay accessor.
2009-08-14 19:47:13 -04:00
Colin Walters
e960269653 Add meta_window_is_override_redirect
Trivial function, useful for plugins which are doing analysis
of windows.
2009-08-14 19:47:13 -04:00
Gabor Kelemen
5e581b409c Hungarian translation updated 2009-08-15 01:40:29 +02:00
Owen W. Taylor
f03d39eefb Check the opacity of the right actor
When determining if the window is opaque or not, look at it's opacity,
not the opacity of the window group.

Reported by Matthias Clasen
http://bugzilla.gnome.org/show_bug.cgi?id=591836
2009-08-14 15:58:07 -04:00
Alexander Shopov
deaa897928 Updated Bulgarian translation 2009-08-14 08:00:48 +03:00
Manoj Kumar Giri
3f9758e706 Updated Oriya Translation 2009-08-13 20:29:45 +05:30
Owen W. Taylor
91baf552cf Remove meta_errors_register_foreign_display()
The functionality to propagate errors for other displays to other
a "foreign error handler" was Soeren's compositor and is no longer
being used. Remove it.

(Now that error.h is being installed and scanned, we need to either
do this or add XErrorEvent to xlib-2.0.gir and rename ErrorHandler
to MetaErrorHandler. This way is a bit simpler.)
2009-08-13 07:38:08 -04:00
Michael Meeks
16466cf7d6 install errors.h header, bug 591566 2009-08-13 09:46:15 +01:00
Sweta Kothari
3c25c265df Updated Gujarati Translations 2009-08-12 19:08:55 +05:30
Antón Méixome
a8529bd8d1 Updated Galician translation 2009-08-12 13:21:18 +02:00
Tomas Frydrych
f3e6913d57 Added meta_window_is_modal()
Queries whether the window is in a modal state, as per the _NET_WM_STATE
protocol.
2009-08-12 07:49:08 +01:00
Tomas Frydrych
2c8df7d12e Do not run effects during WM startup
When we first start up, we do not want to run effects on any pre-exising
windows (this is either the case we are starting up and there are no windows,
or we are replacing an exisint window manager, or worse, we crashed, and we
just want to get to the desired desktop as quick as possible).

Dithered about where to place the check; putting into the plugin manager
reduces the number of places (and files) in which it needs to be done.
2009-08-12 07:45:03 +01:00
Owen W. Taylor
dafdecb4e8 Be silent by default
We might as well turn on the AM_SILENT_RULES by default if a new-enough
automake is found rather than requiring --enable-silent-rules.

http://bugzilla.gnome.org/show_bug.cgi?id=591367
2009-08-11 18:53:30 -04:00
Luca Ferretti
ba03ca76c4 Updated Italian translation 2009-08-11 01:19:48 +02:00
Owen W. Taylor
c5874e0da5 Bump version to 2.27.2 2009-08-10 12:24:03 -04:00
Colin Walters
422cd1fbbf Fix use of uninitialized memory in edge-resistance.c
g_new bad, g_new0 good.
2009-08-09 23:40:22 -04:00
Colin Walters
8a9e2877da Export meta_screen_get_startup_sequences, add change signal
It's useful for plugins to be able to get access to the
startup-notification data that Mutter already has.  Add
an accessor and change signal when recieve an event.
2009-08-09 23:36:08 -04:00
Jorge González
71fd54ec9e Updated Spanish translation 2009-08-09 20:27:02 +02:00
Kjartan Maraas
ff84b35e5d Updated Norwegian bokmål translation. 2009-08-09 15:48:46 +02:00
Tomas Frydrych
ae32ac86b4 Use correct timestamp for focus stealing prevention
When window initially maps, use the more recent of NET_WM_USER_TIME and
startup notification timestamps to compare against last known user action to
decide whether to focus the window or not. Once we show the window, clear
the initial_timestamp_set flag, so the startup notification timestamp is not
taken into account again.

Based on patch for metacity by Alexander Larsson

http://bugzilla.gnome.org/show_bug.cgi?id=573922
2009-08-08 17:59:01 +01:00
Tomas Frydrych
bca3eaf709 Removed custom 'GIR' label for gir generation in silent-rules mode
http://bugzilla.gnome.org/show_bug.cgi?id=591120
2009-08-08 13:47:31 +01:00
Christian Kirbach
a03343827e Updated German translation. 2009-08-08 01:47:24 +02:00
Tomas Frydrych
0f64202a29 Added --enable-silent-rules if automake-1.11 is available 2009-08-07 17:58:02 +01:00
Gil Forcada
4fb7c642d5 Minor fix to Catalan translation 2009-08-07 18:57:23 +02:00
Tomas Frydrych
6b36e64e00 Take extra reference on the texture inside MutterWindow
We store a pointer to the texture independently of the ClutterContainer
internals, and rely on the pointer remaining valid until we run dispose.
Since we also provide public API to access this pointer, we should not
rely on the reference ClutterContainer holds to ensure that texture will
not be destroyed (e.g., some nasty developer could reparent the texture).
2009-08-07 17:38:11 +01:00
Tomas Frydrych
84059f1faa Free MutterWindow description string in finalize() not dispose()
We were freeing the description string in dispose and not setting it to NULL,
thus leaving around a dangling pointer for the duration of the disposal.
This commit moves the free into the finalize vfuction, where it belongs.
2009-08-07 16:47:43 +01:00
Owen W. Taylor
15376957f7 Don't allow override-redirect windows to be META_WINDOW_NORMAL
Many override-redirect windows (including the Metacity UI windows!)
will have NET_WM_WINDOW_TYPE_NORMAL set on them because of shared
code paths with normal windows in toolkits.

Some current Compositor plugins (default plugin and gnome-shell)
check type == NORMAL to determine if to run effects. While fixing
such plugins to also check if the window is override-redirect is
posisble, it seems cleanest to simply not allow any of the decorated
window types to be set on an override-redirect window and to force
these types to META_WINDOW_OVERRIDE_OTHER. This will prevent other
similar problems from showing up in the future.

http://bugzilla.gnome.org/show_bug.cgi?id=590971
2009-08-06 12:16:24 -04:00
Owen W. Taylor
da934be354 Elimitate use of arithmetic expansion for portability
Use expr rather than $(( <arithmetic> )) - this is needed at least
for the default Solaris shell.

Based on patch by Halton Huo
http://bugzilla.gnome.org/show_bug.cgi?id=590719
2009-08-04 11:18:43 -04:00
Tomas Frydrych
3eee6b4218 Handle FocusIn events for override redirect windows correctly
Do not try to insert / remove the window from the MRU list; just reset the
MetaDisplay focus window to NULL.

http://bugzilla.gnome.org/show_bug.cgi?id=590611
2009-08-04 14:31:13 +01:00
Tomas Frydrych
ff9400abde Remove deprecated GTK symbols
http://bugzilla.gnome.org/show_bug.cgi?id=587991

(adapted from metacity commit 3f76affbd2,
original patch by Thomas Andersen)
2009-08-04 09:23:37 +01:00
Tomas Frydrych
e985bf0e7a use g_signal_handlers_disconnect_by_func instead of an old deprecated
http://bugzilla.gnome.org/show_bug.cgi?id=587991

(adapted from metacity commit a8f8970601,
original patch by Matt Kraai)
2009-08-04 09:22:49 +01:00
Tomas Frydrych
245908909b Fix check for zero-sized textures in MutterShaped texture
Patch by Jon Nettleton <jon.nettleton@gmail.com>

http://bugzilla.openedhand.com/show_bug.cgi?id=1538
http://bugzilla.gnome.org/show_bug.cgi?id=590646
2009-08-04 08:47:46 +01:00
Xu Li
2f63d321d1 [constraints] Avoid overflow when window maximum size hint is set to INT_MAX
When calculating maximum permissible size of our frame window, we need to
avoid an overflow if the application set its max size hint to INT_MAX.

http://bugzilla.gnome.org/show_bug.cgi?id=590627
2009-08-04 08:38:56 +01:00
Tomas Frydrych
2222cb8fbf Added public prototype for meta_window_is_ancestor_of_transient()
http://bugzilla.gnome.org/show_bug.cgi?id=590439
2009-08-04 08:32:36 +01:00
Tomas Frydrych
897814a153 Added MetaWindow::window-type property
Read-only property for querying the type of MetaWindow.

http://bugzilla.gnome.org/show_bug.cgi?id=588230
2009-08-04 08:06:30 +01:00
Tomas Frydrych
8b7b41df41 Accessors for pid and name of client machine associated with MetaWindow
http://bugzilla.gnome.org/show_bug.cgi?id=590388
2009-08-04 07:58:11 +01:00
Tomas Frydrych
8f9a174f0a Fixed warnings due to missing casts 2009-08-01 11:11:11 +01:00
Colin Walters
df90187e06 Add focus-window property to MetaDisplay
Useful mainly for notify::focus-window.
2009-08-01 04:38:26 -04:00
Tomas Frydrych
c9e0613b53 Set up correct initial values for override redirect windows
As a sideffect of commit a576f7a1ea, override
redirect windows of type _NET_WM_WINDOW_TYPE_NORMAL do not have their
features recalculated during MetaWindow construction (same as regular
windows of type _NET_WM_WINDOW_TYPE_NORMAL), so we need to set the initial
values accordingly.
2009-08-01 09:11:06 +01:00
Tomas Frydrych
a576f7a1ea Tolerate all standard _NET_WM_WINDOW_TYPE types for managed windows
Although the spec designates some window types as typically used for
override redirect windows, it does not prohibit the use of these with
managed windows, so we should not abort if we encounter one of these.

http://bugzilla.gnome.org/show_bug.cgi?id=583870
2009-07-31 19:11:54 +01:00
Owen W. Taylor
239b39cf52 Pass through all scroll events to compositor
As with other events, we want to pass through scroll events (button 4/5 presses)
to the compositor, whether or not they are associated with a particular MetaWindow;
do this by simply falling through to the normal code path instead of
separately delivering the events to the compositor.

http://bugzilla.gnome.org/show_bug.cgi?id=588232
2009-07-31 10:37:26 -04:00
Thomas Wood
1f90529365 Don't explicitly set the size of the MutterWindow texture
Setting the size of the texture causes the minimum and preferred width and
height values to be fixed at the set value. The normal requisition functions
of ClutterTexture will already report the size of the texture pixmap as the
natural size, but also allow scaling down as needed if less space is
available. We don't need that here, but we want to allow someone to make
a ClutterClone of the texture actor.
2009-07-31 13:36:59 +01:00
Colin Walters
acfc498344 Also update Clutter 1.0 pkg-config requirement and README
We need to also change the pkg-config requirement to be 1.0.
2009-07-29 13:04:18 -04:00
Colin Walters
a1ac1f4b2e Build using Clutter 1.0
Clutter just released 1.0, sync to that.
2009-07-29 12:08:53 -04:00
drtvasudevan
8a892d47e5 Updated Tamil translation 2009-07-29 13:48:28 +05:30
Owen W. Taylor
d91d503eb2 Pass event to clutter when the plugin doesn't have xevent_filter
With recent changes, Clutter no longer sets up the viewport correctly,
unless it receives ConfigureNotify events. If there is a plugin with
an xevent_filter function, then it's that plugins responsibility to pass
the event to Clutter if it doesn't want it. If there is no plugin,
or the plugin doesn't have an xevent_filter function, then we should
call clutter_x11_handle_event() ourselves.

http://bugzilla.gnome.org/show_bug.cgi?id=589419
2009-07-28 16:00:24 -04:00
Owen W. Taylor
e84bf7144c Queue redraws on MutterWindow's MutterShapedTexture
When a windows contents or shape changes, we schedule a redraw
with clutter_actor_queue_redraw(); we need to queue the redraw
on the shaped texture rather than on the window actor to support
cloning of just the shaped texture without the shadow: that
is, the shaped is what is really changing and it may be
visible via a clone even if the MutterWindow itself is not
visible.

http://bugzilla.gnome.org/show_bug.cgi?id=589429
2009-07-28 15:50:28 -04:00
Ivar Smolin
73abacc20b Updating Estonian translation 2009-07-23 19:00:46 +03:00
Daniel Nylander
aea24279ba Updated Swedish translation 2009-07-22 15:12:43 +02:00
Chao-Hsiung Liao
5c5968e742 Updated Traditional Chinese translation(Hong Kong and Taiwan) 2009-07-22 16:44:17 +08:00
Yaron Sharabani
3813ed9c2e Updated Hebrew translation 2009-07-22 00:57:22 +03:00
Owen W. Taylor
ec2c197e1f Fix confusion about MetaPreview in introspection build
MetaPreview is only built into libmutter-private, and not included in
the mutter executable. Linking mutter against libmutter-private was
inadvertently added when the introspection build process was set up,
but isn't actually needed, and if -Wl,-as-needed is added during the
build process, then the libmutter-private dependency will be skipped.

* Don't link mutter (or the test programs) against libmutter-private

* Exclude meta-preview.h from the set of headers we feed into the
  introspection build process

Reported by Patryk Zawadzki

http://bugzilla.gnome.org/show_bug.cgi?id=587975
2009-07-17 07:56:19 -04:00
Maxim V. Dziumanenko
594897e9a5 Updated Ukrainian translation 2009-07-09 23:28:00 +03:00
Thomas Thurman
40e9f6fa2c unset _NET_SUPPORTING_WM_CHECK when shutting down 2009-07-09 10:26:20 -04:00
Thomas Thurman
35afd2a8fb update changelog 2009-07-09 10:23:03 -04:00
Jorge González
d9be1d7e32 Updated Spanish translation 2009-07-07 20:47:54 +02:00
Tomeu Vizoso
b625ec30d9 Add a switch to disable autofullscreen'ing maximized windows without decorations 2009-07-06 07:51:45 -04:00
Mark Krapivner
f5313268d7 Updated Hebrew translation 2009-07-04 15:47:15 +03:00
Mattias Põldaru
07dedee37b Updating Estonian translation 2009-06-25 14:31:10 +03:00
Runa Bhattacharjee
75f3127ba5 Updated Bengali India Translations 2009-06-24 15:56:42 +05:30
Ivar Smolin
b13fae2556 Updating Estonian translation 2009-06-19 19:58:46 +03:00
Ray Wang
2e9838699b Updated Simplified Chinese translation. 2009-06-06 17:27:37 +08:00
drtvasudevan
ba9c3f41c9 Updated Tamil translation 2009-05-25 17:50:14 +05:30
Jorge Gonzalez
e35fae8f32 Updated Spanish translation 2009-05-23 19:58:37 +02:00
drtvasudevan
b0d5f3bd64 Updated Tamil translation 2009-05-23 17:53:59 +05:30
drtvasudevan
ed640bb181 Updated Tamil translation 2009-05-21 17:48:02 +05:30
Maxim V. Dziumanenko
a3511ba9e2 Updated Ukrainian translation 2009-04-28 14:06:23 +03:00
Ivar Smolin
4c9c903648 Updating Estonian translation 2009-04-25 18:12:34 +03:00
Luca Ferretti
d12aaddc34 Updated Italian transaltion 2009-04-24 22:17:24 +02:00
Olav Vitters
28955bb449 doap: Add desktop category 2009-04-23 19:35:51 +02:00
Matej Urban
dcd7cae7cf Updated Slovenian translation 2009-04-22 12:18:20 +02:00
Jordi Mas i Hernandez
c954bb9456 Minor fixes to Catalan translation 2009-04-22 09:46:20 +02:00
Shankar Prasad
be0b298d81 Updated Kannada Translation 2009-04-21 12:34:27 +05:30
Jorge Gonzalez
409026044b Updated Spanish translation 2009-04-18 20:55:56 +02:00
Funda Wang
0c311bdcf9 Updated zh_CN translation.
svn path=/trunk/; revision=4238
2009-04-10 03:22:43 +00:00
Marcel Telka
e81775e63d Updated Slovak translation by Pavol Šimo.
2009-04-04  Marcel Telka  <marcel@telka.sk>

	* sk.po: Updated Slovak translation by Pavol Šimo.

svn path=/trunk/; revision=4235
2009-04-04 12:45:30 +00:00
Simos Xenitellis
209d7ef613 Updated Greek translation
svn path=/trunk/; revision=4232
2009-03-27 12:07:25 +00:00
Goran Rakic
a6c76a85ce Updated Serbian translation by Miloš Popović.
svn path=/trunk/; revision=4229
2009-03-21 19:49:40 +00:00
Tomasz Dominikowski
265f9e5433 Updated Polish translation
2009-03-19  Tomasz Dominikowski  <tdominikowski@aviary.pl>

	* pl.po: Updated Polish translation

svn path=/trunk/; revision=4228
2009-03-19 11:30:21 +00:00
Ignacio Casal Quinteiro
b86d988b3c Updated Galician translation by Suso Baleato.
svn path=/trunk/; revision=4224
2009-03-18 19:58:04 +00:00
Alexander Shopov
c4148cec33 Updated Bulgarian translation by Alexander Shopov <ash@contact.bg>
2009-03-17  Alexander Shopov  <ash@contact.bg>

	* bg.po: Updated Bulgarian translation by
	Alexander Shopov <ash@contact.bg>

svn path=/trunk/; revision=4220
2009-03-17 07:19:13 +00:00
Gintautas Miliauskas
aa57becc41 Updated Lithuanian translation.
2009-03-14  Gintautas Miliauskas  <gintautas@miliauskas.lt>

	* lt.po: Updated Lithuanian translation.



svn path=/trunk/; revision=4209
2009-03-14 21:06:17 +00:00
Nickolay V. Shmyrev
7269c37c8f Updated Russian translation by Yuriy Penkin.
2009-03-14  Nickolay V. Shmyrev  <nshmyrev@yandex.ru>

	* ru.po: Updated Russian translation by Yuriy Penkin.


svn path=/trunk/; revision=4206
2009-03-14 19:09:33 +00:00
Thomas James Alexander Thurman
3093d7e95a that should not have been checked in
svn path=/trunk/; revision=4199
2009-03-12 02:06:30 +00:00
Thomas James Alexander Thurman
4e0d8a0cbb Post-release bump to 2.27.1.
svn path=/trunk/; revision=4198
2009-03-12 02:05:26 +00:00
Thomas James Alexander Thurman
523151ddf0 svn path=/trunk/; revision=4196
svn path=/trunk/; revision=4196
2009-03-12 01:50:00 +00:00
Thomas James Alexander Thurman
0a7cb94ea8 2.27.0 release.
* NEWS: 2.27.0 release.


svn path=/trunk/; revision=4195
2009-03-12 01:49:30 +00:00
Thomas James Alexander Thurman
d4b7c0e633 2.27.0 release.
svn path=/trunk/; revision=4194
2009-03-12 01:36:30 +00:00
Thomas James Alexander Thurman
3f76affbd2 Remove deprecated GTK symbols. Refs #572332.
* src/include/util.h:
	* src/tools/metacity-window-demo.c:
	* src/ui/fixedtip.c:
	* src/ui/frames.c:
	* src/ui/frames.h:
	* src/ui/menu.c:
	* src/ui/metaaccellabel.c:
	* src/ui/metaaccellabel.h:
	* src/ui/preview-widget.c:
	* src/ui/preview-widget.h:
	* src/ui/tabpopup.c:
	* src/ui/theme-viewer.c:
	* src/ui/themewidget.c:
	* src/ui/themewidget.h:
	* test/tokentest/tokentest.c:


svn path=/trunk/; revision=4193
2009-03-12 01:26:24 +00:00
Thomas James Alexander Thurman
a8f8970601 use g_signal_handlers_disconnect_by_func instead of an old deprecated
* src/tools/metacity-mag.c: use g_signal_handlers_disconnect_by_func
	instead of an old deprecated function.


svn path=/trunk/; revision=4192
2009-03-12 01:16:52 +00:00
Thomas James Alexander Thurman
178b5ff626 fix problem where the previous code ignored callbacks for properties whose
* src/core/window-props.c: fix problem where the previous
        code ignored callbacks for properties whose values weren't
        looked up.  Closes #572573.


svn path=/trunk/; revision=4191
2009-03-12 01:09:41 +00:00
Petr Kovar
c47f7c2806 Updated Czech translation. Removed "src/ui/metacity-dialog.c".
2009-03-08  Petr Kovar  <pknbe@volny.cz>

	* cs.po: Updated Czech translation.
	* POTFILES.in: Removed "src/ui/metacity-dialog.c".

svn path=/trunk/; revision=4185
2009-03-08 19:34:41 +00:00
Thomas James Alexander Thurman
ab6aa5463f add optional dependency on gtop. Include "(as username)" in the titlebar
* configure.in: add optional dependency on gtop.
	* src/core/window-props.c: Include "(as username)"
          in the titlebar if a window is running as another user.
	* src/core/window.c: check for PID before name, since
          the rendering of the name can now depend on the PID.
        Closes #549389.


svn path=/trunk/; revision=4181
2009-03-06 22:51:02 +00:00
Claude Paroz
42387bff6f Updated French translation (synced with gnome-2-26).
2009-03-02  Claude Paroz  <claude@2xlibre.net>

	* fr.po: Updated French translation (synced with gnome-2-26).

svn path=/trunk/; revision=4177
2009-03-02 21:33:24 +00:00
Jorge Gonzalez Gonzalez
3afd25691a Updated Spanish translation
svn path=/trunk/; revision=4171
2009-02-28 12:29:19 +00:00
Matej Urbančič
a6a963bec1 Updated Slovenian translation
svn path=/trunk/; revision=4170
2009-02-24 14:58:19 +00:00
Matthias Clasen
d6ac4dc22a Don't force CA_PROP_CANBERRA_ENABLE to 1. That was a misunderstanding on
* src/core/bell.c: Don't force CA_PROP_CANBERRA_ENABLE to 1.
        That was a misunderstanding on my part, and makes it impossible
        to get rid of the bell.


svn path=/trunk/; revision=4165
2009-02-21 17:00:26 +00:00
Thomas James Alexander Thurman
0b3f45bb1b Use zenity for the session management dialogue that warns about
clueless clients, not metacity-dialog.  This is the last change
	away from metacity-dialog and therefore closes #521914.
	* src/Makefile.am:
	* src/core/session.c:
	* src/core/util.c:
	* src/include/util.h:
	* src/ui/metacity-dialog.c (deleted):


svn path=/trunk/; revision=4163
2009-02-20 19:48:04 +00:00
Og B. Maciel
24f2df926a Updated Brazilian Portuguese translation.
svn path=/trunk/; revision=4162
2009-02-20 13:56:39 +00:00
Daniel Nylander
f00e8655ac sv.po: Updated Swedish translation
svn path=/trunk/; revision=4159
2009-02-19 19:40:33 +00:00
Ilkka Tuohela
41395d9e00 Updated Finnish translation
svn path=/trunk/; revision=4157
2009-02-19 08:01:05 +00:00
Ilkka Tuohela
3e00bcbf9f Updated Finnish translation
svn path=/trunk/; revision=4156
2009-02-19 08:00:17 +00:00
Gabor Kelemen
0b402b23f7 Translation updated.
2009-02-17  Gabor Kelemen  <kelemeng@gnome.hu>

	* hu.po: Translation updated.

svn path=/trunk/; revision=4153
2009-02-17 01:49:56 +00:00
Wouter Bolsterlee
691fcaeee7 Updated Dutch translation by Wouter Bolsterlee.
2009-02-16  Wouter Bolsterlee  <wbolster@svn.gnome.org>

	* nl.po: Updated Dutch translation by Wouter Bolsterlee.


svn path=/trunk/; revision=4151
2009-02-16 18:38:00 +00:00
Kenneth Nielsen
9f30910653 Updated Danish translation
svn path=/trunk/; revision=4148
2009-02-15 13:05:00 +00:00
Ihar Hrachyshka
41a6c2e501 Updated be@latin.po
svn path=/trunk/; revision=4144
2009-02-14 11:17:08 +00:00
Theppitak Karoonboonyanan
fbc7fc6645 Updated Thai translation (merged from gnome-2-26 branch).
2009-02-13  Theppitak Karoonboonyanan  <thep@linux.thai.net>

	* th.po: Updated Thai translation (merged from gnome-2-26 branch).


svn path=/trunk/; revision=4143
2009-02-13 13:45:17 +00:00
Matthias Clasen
573dbb431e Now that we are using libcanberra, don't tell the X server to play the
* src/core/bell.c (meta_bell_set_audible): Now that we are
        using libcanberra, don't tell the X server to play the system
        bell internally.


svn path=/trunk/; revision=4141
2009-02-13 00:09:44 +00:00
Inaki Larranaga Murgoitio
7b2cba7a6c Updated Basque translation.
2009-02-12  Inaki Larranaga Murgoitio  <dooteo@euskalgnu.org>

	* eu.po: Updated Basque translation.


svn path=/trunk/; revision=4139
2009-02-12 19:22:30 +00:00
Matthias Clasen
91ff5617ef Forgotten file
svn path=/trunk/; revision=4138
2009-02-12 14:43:09 +00:00
Matthias Clasen
f1782868f9 Use libcanberra to play system bell and workspace switch sounds
svn path=/trunk/; revision=4137
2009-02-12 00:53:23 +00:00
Daniel Nylander
66ee22c3e6 sv.po: Updated Swedish translation
svn path=/trunk/; revision=4135
2009-02-11 11:52:27 +00:00
Priit Laes
2db1222e45 Translation updated by Mattias Põldaru
2009-02-11  Priit Laes  <plaes at svn dot gnome dot org>

	* et.po: Translation updated by Mattias Põldaru

svn path=/trunk/; revision=4134
2009-02-11 11:32:47 +00:00
Thomas James Alexander Thurman
abbd057eb9 Session must be saved before display close, and display
shouldn't close during shutdown if it's already closed.
        Can't believe we don't have a bug about this already...
	* src/core/display-private.h:
	* src/core/display.c:
	* src/core/main.c:
	* src/core/session.c:


svn path=/trunk/; revision=4133
2009-02-11 05:26:58 +00:00
Thomas James Alexander Thurman
6da5b8ccc5 Don't define meta_spew_event unless verbose mode is on.
Closes #571126.
	* src/core/display.c:
	* src/core/window.c:


svn path=/trunk/; revision=4132
2009-02-11 04:34:17 +00:00
Thomas James Alexander Thurman
128e2b917d switch is "--disable-verbose-mode", not "--disable-verbose". Closes
* README: switch is "--disable-verbose-mode", not "--disable-verbose".
          Closes #571210.


svn path=/trunk/; revision=4130
2009-02-11 03:13:33 +00:00
Thomas James Alexander Thurman
2f4173b267 rm incorrect comment
* src/include/util.h:


svn path=/trunk/; revision=4129
2009-02-10 12:51:29 +00:00
Gil Forcada Codinachs
3fea1e4df5 Added Asturian translation on behalf of Mikel González
svn path=/trunk/; revision=4127
2009-02-10 08:33:24 +00:00
Kjartan Maraas
13d2552274 Updated Norwegian bokmål translation.
2009-02-10  Kjartan Maraas  <kmaraas@gnome.org>

	* nb.po: Updated Norwegian bokmål translation.

svn path=/trunk/; revision=4126
2009-02-10 07:06:34 +00:00
Thomas James Alexander Thurman
3d0bfbb4f4 Further movement of code out of metacity-dialog into Zenity;
this time it's the "kill or wait?" dialogue.  Much code saved.
	* src/core/delete.c:
	* src/core/keybindings.c:
	* src/core/main.c:
	* src/core/util.c:
	* src/core/window-private.h:
	* src/core/window.c:
	* src/include/util.h:


svn path=/trunk/; revision=4125
2009-02-10 05:12:53 +00:00
Chao-Hsiung Liao
b893e88e8b 2.27.0
svn path=/trunk/; revision=4124
2009-02-09 00:10:40 +00:00
Thomas James Alexander Thurman
f2be9e4381 Windows demanding attention should never appear in the
alt-tab list unless they're of a type which might have appeared
        there anyway.  This solves a problem under AWN where docks which were
        marked as demanding attention appeared in all alt-tab lists;
        they were irrelevant and it was impossible to remove them from the
        lists.
	* src/core/display.c:


svn path=/trunk/; revision=4123
2009-02-08 00:22:12 +00:00
Thomas James Alexander Thurman
53b5d6d167 some commenting
* src/ui/theme.c: some commenting


svn path=/trunk/; revision=4122
2009-02-07 23:55:39 +00:00
Thomas James Alexander Thurman
92bfe34716 Only skip the first window in the alt-tab chain if it's actually the
* src/core/display.c: Only skip the first window in
        the alt-tab chain if it's actually the current window
        (urgent windows on other workspaces may precede it).
        Fixes #535887.


svn path=/trunk/; revision=4121
2009-02-07 23:05:42 +00:00
Thomas James Alexander Thurman
5df096baf3 Lines where x1==x2 or y1==y2 may have the second element
null.  Lines where both are null, and the width is zero,
        are points.  This speeds things up surprisingly much.
	* src/ui/theme-parser.c:
	* src/ui/theme.c:


svn path=/trunk/; revision=4119
2009-02-06 04:50:50 +00:00
Thomas James Alexander Thurman
45cbaa2d13 incredibly baroque system to make sure the translators don't have to
* src/core/main.c: incredibly baroque system to make sure
        the translators don't have to update the year number every year.


svn path=/trunk/; revision=4118
2009-02-05 20:02:59 +00:00
Thomas James Alexander Thurman
720a17acd7 collapse several strings into one for the translators' benefit.
* src/ui/theme-parser.c: collapse several strings into one
        for the translators' benefit.


svn path=/trunk/; revision=4117
2009-02-05 19:26:06 +00:00
Thomas James Alexander Thurman
dab00ab036 post-branch bump to 2.27.0.
* configure.in: post-branch bump to 2.27.0.


svn path=/trunk/; revision=4116
2009-02-05 01:13:01 +00:00
154 changed files with 42151 additions and 45635 deletions

31
.gitignore vendored
View File

@@ -13,17 +13,22 @@ config.sub
configure
depcomp
install-sh
intltool-extract.in
intltool-merge.in
libtool
ltmain.sh
missing
.deps
src/metacity-wm.desktop
src/mutter-wm.desktop
src/mutter.desktop
*.o
*.a
*.lo
*.la
.libs
*.swp
*.gir
*.typelib
tidy-enum-types.[ch]
tidy-marshal.[ch]
stamp-tidy-enum-types.h
@@ -38,19 +43,18 @@ POTFILES
50-metacity-desktop-key.xml
50-metacity-key.xml
inlinepixbufs.h
libmetacity-private.pc
metacity
metacity-dialog
metacity-theme-viewer
metacity.desktop
metacity.schemas
libmutter-private.pc
mutter
mutter-theme-viewer
mutter.desktop
mutter.schemas
testasyncgetprop
testboxes
testgradient
metacity-grayscale
metacity-mag
metacity-message
metacity-window-demo
mutter-grayscale
mutter-mag
mutter-message
mutter-window-demo
focus-window
test-gravity
test-resizing
@@ -58,3 +62,8 @@ test-size-hints
wm-tester
INSTALL
mkinstalldirs
src/mutter-enum-types.[ch]
src/stamp-mutter-enum-types.h
src/mutter-marshal.[ch]
src/stamp-mutter-marshal.h
src/mutter-plugins.pc

2
README
View File

@@ -20,7 +20,7 @@ libstartup-notification at
http://www.freedesktop.org/software/startup-notification/ or on the
GNOME ftp site. You also need GConf 1.2 (unless building a funky
extra-small embedded metacity with --disable-gconf, see below).
You need Clutter 0.9.3. You need gobject-introspection 0.6.3.
You need Clutter 1.0. You need gobject-introspection 0.6.3.
REPORTING BUGS AND SUBMITTING PATCHES
===

View File

@@ -1,15 +1,13 @@
AC_PREREQ(2.50)
m4_define([mutter_major_version], [2])
m4_define([mutter_minor_version], [27])
# Fibonacci sequence for micro version numbering:
# 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987
m4_define([mutter_micro_version], [1])
m4_define([mutter_minor_version], [91])
m4_define([mutter_micro_version], [2])
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])
@@ -18,6 +16,7 @@ AC_CONFIG_SRCDIR(src/core/display.c)
AC_CONFIG_HEADERS(config.h)
AM_INIT_AUTOMAKE([dist-bzip2 no-dist-gzip])
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])],)
AM_MAINTAINER_MODE
MUTTER_MAJOR_VERSION=mutter_major_version
@@ -64,68 +63,75 @@ AC_C_BIGENDIAN
#### Warnings
# 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 "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
if test "$enable_compile_warnings" != no ; then
if test "x$GCC" = "xyes"; then
case " $CFLAGS " in
*[\ \ ]-ansi[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -ansi" ;;
*[\ \ ]-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
*[\ \ ]-pedantic[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -pedantic" ;;
*[\ \ ]-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
MUTTER_PC_MODULES='gtk+-2.0 >= 2.10.0 pango >= 1.2.0'
GTK_MIN_VERSION=2.90.7
CANBERRA_GTK=libcanberra-gtk3
CANBERRA_GTK_VERSION=0.26
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],
@@ -161,6 +167,11 @@ AC_ARG_WITH(introspection,
[disable the use of GObject introspection]),,
with_introspection=auto)
AC_ARG_WITH(libcanberra,
AC_HELP_STRING([--without-libcanberra],
[disable the use of libcanberra for playing sounds]),,
with_libcanberra=auto)
AC_ARG_ENABLE(xsync,
AC_HELP_STRING([--disable-xsync],
[disable mutter's use of the XSync extension]),,
@@ -177,11 +188,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"
@@ -213,6 +224,24 @@ else
echo "Building without libstartup-notification"
fi
have_libcanberra=no
AC_MSG_CHECKING([libcanberra-gtk])
if test x$with_libcanberra = xno ; then
AC_MSG_RESULT([disabled])
else
if $PKG_CONFIG --exists $CANBERRA_GTK '>=' $CANBERRA_GTK_VERSION; then
have_libcanberra=yes
AC_MSG_RESULT(yes)
MUTTER_PC_MODULES="$MUTTER_PC_MODULES $CANBERRA_GTK"
AC_DEFINE([HAVE_LIBCANBERRA], 1, [Building with libcanberra for playing sounds])
else
AC_MSG_RESULT(no)
if test x$with_libcanberra = xyes ; then
AC_MSG_ERROR([libcanberra forced and libcanberra-gtk was not found])
fi
fi
fi
XCOMPOSITE_VERSION=0.2
AC_MSG_CHECKING([Xcomposite >= $XCOMPOSITE_VERSION])
@@ -227,8 +256,8 @@ else
AC_MSG_ERROR([no. Mutter requires the Xcomposite extension to build.])
fi
CLUTTER_VERSION=0.9.3
CLUTTER_PACKAGE=clutter-0.9
CLUTTER_VERSION=1.2.0
CLUTTER_PACKAGE=clutter-1.0
AC_SUBST(CLUTTER_PACKAGE)
if $PKG_CONFIG --atleast-version $CLUTTER_VERSION $CLUTTER_PACKAGE ; then
MUTTER_PC_MODULES="$MUTTER_PC_MODULES $CLUTTER_PACKAGE "
@@ -252,7 +281,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])
@@ -415,7 +444,7 @@ fi
MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
MUTTER_MESSAGE_LIBS="$MUTTER_MESSAGE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
MUTTER_PROPS_LIBS="$MUTTER_PROPS_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
found_sm=no
@@ -483,10 +512,8 @@ 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])
@@ -523,7 +550,7 @@ fi
dnl ==========================================================================
echo "
mutter-$VERSION:
mutter-$VERSION
prefix: ${prefix}
source code location: ${srcdir}
@@ -533,6 +560,7 @@ mutter-$VERSION:
XFree86 Xinerama: ${use_xfree_xinerama}
Solaris Xinerama: ${use_solaris_xinerama}
Startup notification: ${have_startup_notification}
libcanberra: ${have_libcanberra}
Introspection: ${have_introspection}
Session management: ${found_sm}
Shape extension: ${found_shape}
@@ -540,9 +568,10 @@ mutter-$VERSION:
Xcursor: ${have_xcursor}
"
MUTTER_MINOR_VERSION=mutter_minor_version
if test $(( $(echo $MUTTER_MINOR_VERSION) %2)) == "1"; then
stable_version=$(( ($MUTTER_MINOR_VERSION / 2) * 2))
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)"

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,41 @@ 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.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

@@ -10,6 +10,7 @@ be@latin
bg
bn
bn_IN
br
bs
ca
ca@valencia
@@ -56,6 +57,7 @@ mn
mr
ms
nb
nds
ne
nl
nn

View File

@@ -1,5 +1,6 @@
# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
src/core/bell.c
src/core/core.c
src/core/delete.c
src/core/display.c

4989
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

1835
po/br.po Normal file

File diff suppressed because it is too large Load Diff

1521
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

3278
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

2008
po/es.po

File diff suppressed because it is too large Load Diff

1162
po/eu.po

File diff suppressed because it is too large Load Diff

3013
po/fr.po

File diff suppressed because it is too large Load Diff

3199
po/gl.po

File diff suppressed because it is too large Load Diff

2841
po/he.po

File diff suppressed because it is too large Load Diff

1519
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

1472
po/nb.po

File diff suppressed because it is too large Load Diff

1814
po/nds.po Normal file

File diff suppressed because it is too large Load Diff

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

2597
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

783
po/sv.po

File diff suppressed because it is too large Load Diff

2076
po/ta.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

@@ -1,3 +1,6 @@
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
.AUTOPARALLEL:
lib_LTLIBRARIES = libmutter-private.la
SUBDIRS=wm-tester tools compositor/plugins
@@ -13,34 +16,33 @@ mutter_built_sources = \
mutter_SOURCES= \
core/async-getprop.c \
core/async-getprop.h \
core/alttabhandler.c \
include/alttabhandler.h \
core/alttabhandlerdefault.c \
include/alttabhandlerdefault.h \
core/bell.c \
core/bell.h \
core/boxes.c \
core/boxes-private.h \
include/boxes.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-window.c \
compositor/mutter-window-private.h \
compositor/mutter-window-group.c \
compositor/mutter-window-group.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-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/shadow.c \
compositor/shadow.h \
compositor/mutter-shaped-texture.h \
compositor/tidy/tidy-texture-frame.c \
compositor/tidy/tidy-texture-frame.h \
include/compositor.h \
include/mutter-plugin.h \
include/mutter-window.h \
include/meta-plugin.h \
include/meta-window-actor.h \
include/compositor-mutter.h \
core/constraints.c \
core/constraints.h \
@@ -72,7 +74,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 \
@@ -114,12 +116,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)
@@ -138,24 +140,20 @@ 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 = \
include/alttabhandler.h \
include/boxes.h \
ui/gradient.h \
include/main.h \
include/util.h \
include/common.h \
ui/preview-widget.h \
ui/theme-parser.h \
ui/theme.h \
include/prefs.h \
include/window.h \
@@ -163,17 +161,23 @@ libmutterinclude_base_headers = \
include/compositor.h \
include/compositor-mutter.h \
include/types.h \
include/errors.h \
include/screen.h \
include/display.h \
include/group.h \
include/keybindings.h \
include/mutter-plugin.h \
include/mutter-window.h
include/meta-plugin.h \
include/meta-window-actor.h
# Excluded from scanning for introspection but installed
# preview-widget.h: only part of libmutter-private
# atomnames.h: macros cause problems for scanning process
libmutterinclude_extra_headers = \
ui/preview-widget.h \
include/atomnames.h
libmutterincludedir = $(includedir)/mutter/mutter-private
libmutterinclude_HEADERS = \
$(libmutterinclude_base_headers) \
$(libmutterinclude_extra_headers)
@@ -197,31 +201,35 @@ 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)
pwd=`pwd` ; \
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=Clutter-0.9 \
--pkg=clutter-0.9 \
--pkg=gtk+-2.0 \
--include=Gdk-3.0 \
--include=Gtk-3.0 \
--include=Clutter-1.0 \
--pkg=clutter-1.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) \
-o $$pwd/$@
Meta-$(api_version).typelib: $(G_IR_COMPILER) Meta-$(api_version).gir
LD_LIBRARY_PATH=$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}. $(G_IR_COMPILER) Meta-$(api_version).gir -o $@
$(AM_V_GEN) LD_LIBRARY_PATH=$${LD_LIBRARY_PATH:+$$LD_LIBRARY_PATH:}. $(G_IR_COMPILER) Meta-$(api_version).gir -o $@
endif
EFENCE=
mutter_LDADD=@MUTTER_LIBS@ libmutter-private.la $(EFENCE)
mutter_LDADD=@MUTTER_LIBS@ $(EFENCE)
mutter_LDFLAGS=-export-dynamic
mutter_theme_viewer_LDADD= @MUTTER_LIBS@ libmutter-private.la
@@ -232,9 +240,9 @@ testasyncgetprop_SOURCES=core/async-getprop.h core/async-getprop.c core/testasyn
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
testboxes_LDADD= @MUTTER_LIBS@ libmutter-private.la
testgradient_LDADD= @MUTTER_LIBS@ libmutter-private.la
testasyncgetprop_LDADD= @MUTTER_LIBS@ libmutter-private.la
testboxes_LDADD= @MUTTER_LIBS@
testgradient_LDADD= @MUTTER_LIBS@
testasyncgetprop_LDADD= @MUTTER_LIBS@
@INTLTOOL_DESKTOP_RULE@
@@ -304,7 +312,7 @@ CLEANFILES += $(MUTTER_STAMP_FILES)
mutter-marshal.h: stamp-mutter-marshal.h
@true
stamp-mutter-marshal.h: Makefile mutter-marshal.list
$(GLIB_GENMARSHAL) \
$(AM_V_GEN) $(GLIB_GENMARSHAL) \
--prefix=_mutter_marshal \
--header \
$(srcdir)/mutter-marshal.list > xgen-tmh && \
@@ -313,7 +321,7 @@ stamp-mutter-marshal.h: Makefile mutter-marshal.list
echo timestamp > $(@F)
mutter-marshal.c: Makefile mutter-marshal.list
(echo "#include \"mutter-marshal.h\"" ; \
$(AM_V_GEN) (echo "#include \"mutter-marshal.h\"" ; \
$(GLIB_GENMARSHAL) \
--prefix=_mutter_marshal \
--body \
@@ -323,17 +331,17 @@ mutter-marshal.c: Makefile mutter-marshal.list
mutter-enum-types.h: stamp-mutter-enum-types.h Makefile
@true
stamp-mutter-enum-types.h: $(mutter_source_h) mutter-enum-types.h.in
( cd $(srcdir) && \
stamp-mutter-enum-types.h: $(libmutterinclude_base_headers) mutter-enum-types.h.in
$(AM_V_GEN) ( cd $(srcdir) && \
$(GLIB_MKENUMS) \
--template $(srcdir)/mutter-enum-types.h.in \
$(libmutterinclude_base_headers) ) >> xgen-teth && \
(cmp xgen-teth mutter-enum-types.h || cp xgen-teth mutter-enum-types.h) && \
(cmp -s xgen-teth mutter-enum-types.h || cp xgen-teth mutter-enum-types.h) && \
rm -f xgen-teth && \
echo timestamp > $(@F)
mutter-enum-types.c: stamp-mutter-enum-types.h mutter-enum-types.c.in
( cd $(srcdir) && \
$(AM_V_GEN) ( cd $(srcdir) && \
$(GLIB_MKENUMS) \
--template $(srcdir)/mutter-enum-types.c.in \
$(libmutterinclude_base_headers) ) >> xgen-tetc && \

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,6 +23,8 @@ struct _MetaCompositor
ClutterActor *shadow_src;
MetaPlugin *modal_plugin;
gboolean show_redraw : 1;
gboolean debug : 1;
gboolean no_mipmaps : 1;
@@ -43,12 +45,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 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 meta_check_end_modal (MetaScreen *screen);
#endif /* META_COMPOSITOR_PRIVATE_H */

View File

@@ -11,8 +11,8 @@
#include "compositor-mutter.h"
#include "xprops.h"
#include "prefs.h"
#include "mutter-window-private.h"
#include "mutter-window-group.h"
#include "meta-window-actor-private.h"
#include "meta-window-group.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,69 +33,16 @@ 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
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.
@@ -107,7 +54,7 @@ mutter_finish_workspace_switch (MetaCompScreen *info)
}
void
mutter_switch_workspace_completed (MetaScreen *screen)
meta_switch_workspace_completed (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
@@ -120,7 +67,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 +84,72 @@ add_win (MetaWindow *window)
g_return_if_fail (info != NULL);
mutter_window_new (window);
meta_window_actor_new (window);
sync_actor_stacking (info->windows);
}
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 (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 +184,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 +201,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 +218,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 +235,14 @@ mutter_get_window_group_for_screen (MetaScreen *screen)
return info->window_group;
}
/**
* 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 +253,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 +266,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 +295,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,7 +308,118 @@ 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
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
* merge the two.
*/
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
MetaCompositor *compositor = display->compositor;
gboolean pointer_grabbed = FALSE;
gboolean keyboard_grabbed = FALSE;
int result;
if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
return FALSE;
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
{
result = XGrabPointer (xdpy, grab_window,
False, /* owner_events */
(ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask | PointerMotionMask),
GrabModeAsync, GrabModeAsync,
None, /* confine to */
cursor,
timestamp);
if (result != Success)
goto fail;
pointer_grabbed = TRUE;
}
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
{
result = XGrabKeyboard (xdpy, grab_window,
False, /* owner_events */
GrabModeAsync, GrabModeAsync,
timestamp);
if (result != Success)
goto fail;
keyboard_grabbed = TRUE;
}
display->grab_op = META_GRAB_OP_COMPOSITOR;
display->grab_window = NULL;
display->grab_screen = screen;
display->grab_have_pointer = TRUE;
display->grab_have_keyboard = TRUE;
compositor->modal_plugin = plugin;
return TRUE;
fail:
if (pointer_grabbed)
XUngrabPointer (xdpy, timestamp);
if (keyboard_grabbed)
XUngrabKeyboard (xdpy, timestamp);
return FALSE;
}
void
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);
MetaCompositor *compositor = display->compositor;
g_return_if_fail (compositor->modal_plugin == plugin);
XUngrabPointer (xdpy, timestamp);
XUngrabKeyboard (xdpy, timestamp);
display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL;
display->grab_screen = NULL;
display->grab_have_pointer = FALSE;
display->grab_have_keyboard = FALSE;
compositor->modal_plugin = NULL;
}
/* This is used when reloading plugins to make sure we don't have
* a left-over modal grab for this screen.
*/
void
meta_check_end_modal (MetaScreen *screen)
{
MetaDisplay *display = meta_screen_get_display (screen);
MetaCompositor *compositor = display->compositor;
if (compositor->modal_plugin &&
meta_plugin_get_screen (compositor->modal_plugin) == screen)
{
meta_end_modal_for_plugin (screen,
compositor->modal_plugin,
CurrentTime);
}
}
void
@@ -372,7 +444,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);
@@ -394,7 +466,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);
@@ -421,7 +492,7 @@ 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->overlay_group = clutter_group_new ();
info->hidden_group = clutter_group_new ();
@@ -434,10 +505,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");
/*
@@ -489,21 +568,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
@@ -513,11 +592,44 @@ meta_compositor_set_updates (MetaCompositor *compositor,
{
}
static gboolean
is_grabbed_event (XEvent *event)
{
switch (event->xany.type)
{
case ButtonPress:
case ButtonRelease:
case EnterNotify:
case LeaveNotify:
case MotionNotify:
case KeyPress:
case KeyRelease:
return TRUE;
}
return FALSE;
}
/**
* meta_compositor_process_event: (skip)
*
*/
gboolean
meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event,
MetaWindow *window)
{
if (compositor->modal_plugin && is_grabbed_event (event))
{
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (compositor->modal_plugin);
if (klass->xevent_filter)
klass->xevent_filter (compositor->modal_plugin, event);
/* We always consume events even if the plugin says it didn't handle them;
* exclusive is exclusive */
return TRUE;
}
if (window)
{
MetaCompScreen *info;
@@ -526,7 +638,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;
@@ -545,7 +657,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;
@@ -555,38 +667,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)
@@ -604,12 +715,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
@@ -617,12 +728,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
@@ -631,12 +742,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
@@ -645,12 +756,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
@@ -663,7 +774,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);
@@ -672,7 +783,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
}
@@ -698,8 +809,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))
@@ -711,7 +821,7 @@ 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);
}
}
@@ -724,9 +834,9 @@ sync_actor_stacking (GList *windows)
for (tmp = g_list_last (windows); tmp != NULL; tmp = tmp->prev)
{
MutterWindow *cw = tmp->data;
MetaWindowActor *window_actor = tmp->data;
clutter_actor_lower_bottom (CLUTTER_ACTOR (cw));
clutter_actor_lower_bottom (CLUTTER_ACTOR (window_actor));
}
}
@@ -748,12 +858,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
@@ -761,10 +871,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;
@@ -774,10 +884,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);
}
@@ -823,41 +933,41 @@ 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
@@ -884,11 +994,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);
@@ -907,6 +1017,10 @@ mutter_repaint_func (gpointer data)
return TRUE;
}
/**
* meta_compositor_new: (skip)
*
*/
MetaCompositor *
meta_compositor_new (MetaDisplay *display)
{
@@ -926,7 +1040,7 @@ 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));
@@ -937,15 +1051,19 @@ meta_compositor_new (MetaDisplay *display)
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

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

@@ -22,50 +22,55 @@
*/
#include "config.h"
#include "mutter-plugin-manager.h"
#include "compositor-private.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>
#include <clutter/x11/clutter-x11.h>
/*
* There is only one instace of each module per the process.
*/
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)
{
@@ -74,7 +79,6 @@ mutter_plugin_load (MutterPluginManager *mgr,
}
plugin = g_object_new (plugin_type,
"screen", mgr->screen,
"params", params,
NULL);
@@ -87,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;
@@ -105,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;
@@ -150,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);
}
}
@@ -182,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);
}
@@ -208,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;
@@ -233,7 +237,7 @@ mutter_plugin_manager_load (MutterPluginManager *plugin_mgr)
if (plugin_string)
{
MutterModule *module;
MetaModule *module;
gchar *path;
params = strchr (plugin_string, ':');
@@ -249,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)
{
@@ -266,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
@@ -289,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;
@@ -299,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;
}
@@ -331,20 +329,24 @@ 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
* plugins loaded at the same time, so it might not be worth it.
*/
mutter_plugin_manager_unload (plugin_mgr);
return mutter_plugin_manager_load (plugin_mgr);
/* Prevent stale grabs on unloaded plugins */
meta_check_end_modal (plugin_mgr->screen);
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)
{
@@ -352,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.
@@ -393,53 +449,55 @@ 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;
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
if (display->display_opening)
return FALSE;
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;
@@ -464,52 +522,54 @@ 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;
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
if (display->display_opening)
return FALSE;
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);
@@ -535,34 +595,33 @@ 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;
MetaDisplay *display = meta_screen_get_display (plugin_mgr->screen);
if (display->display_opening)
return FALSE;
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);
}
}
@@ -581,23 +640,43 @@ 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;
if (!plugin_mgr)
return FALSE;
l = plugin_mgr->plugins;
/* We need to make sure that clutter gets certain events, like
* ConfigureNotify on the stage window. If there is a plugin that
* provides an xevent_filter function, then it's the responsibility
* of that plugin to pass events to Clutter. Otherwise, we send the
* event directly to Clutter ourselves.
*
* What happens if there are two plugins with xevent_filter functions
* is undefined; in general, multiple competing plugins are something
* we don't support well or care much about.
*
* FIXME: Really, we should just always handle sending the event to
* clutter if a plugin doesn't report the event as handled by
* returning TRUE, but it doesn't seem worth breaking compatibility
* of the plugin interface right now to achieve this; the way it is
* now works fine in practice.
*/
have_plugin_xevent_func = FALSE;
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)
{
have_plugin_xevent_func = TRUE;
if (klass->xevent_filter (plugin, xev) == TRUE)
return TRUE;
}
@@ -605,5 +684,8 @@ mutter_plugin_manager_xevent_filter (MutterPluginManager *plugin_mgr,
l = l->next;
}
if (!have_plugin_xevent_func)
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
return FALSE;
}

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

@@ -0,0 +1,607 @@
/* -*- 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.
*/
#include "meta-plugin.h"
#include "screen.h"
#include "display.h"
#include <string.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/shape.h>
#include <clutter/x11/clutter-x11.h>
#include "compositor-private.h"
#include "meta-window-actor-private.h"
G_DEFINE_ABSTRACT_TYPE (MetaPlugin, meta_plugin, G_TYPE_OBJECT);
#define META_PLUGIN_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_PLUGIN, MetaPluginPrivate))
enum
{
PROP_0,
PROP_SCREEN,
PROP_PARAMS,
PROP_FEATURES,
PROP_DISABLED,
PROP_DEBUG_MODE,
};
struct _MetaPluginPrivate
{
MetaScreen *screen;
gchar *params;
gulong features;
gint running;
gboolean disabled : 1;
gboolean debug : 1;
};
static void
meta_plugin_dispose (GObject *object)
{
G_OBJECT_CLASS (meta_plugin_parent_class)->dispose (object);
}
static void
meta_plugin_finalize (GObject *object)
{
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
g_free (priv->params);
priv->params = NULL;
G_OBJECT_CLASS (meta_plugin_parent_class)->finalize (object);
}
static void
meta_plugin_parse_params (MetaPlugin *plugin)
{
char *p;
gulong features = 0;
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 |= META_PLUGIN_MINIMIZE;
if (klass->maximize)
features |= META_PLUGIN_MAXIMIZE;
if (klass->unmaximize)
features |= META_PLUGIN_UNMAXIMIZE;
if (klass->map)
features |= META_PLUGIN_MAP;
if (klass->destroy)
features |= META_PLUGIN_DESTROY;
if (klass->switch_workspace)
features |= META_PLUGIN_SWITCH_WORKSPACE;
if (priv->params)
{
gboolean debug = FALSE;
if ((p = strstr (priv->params, "disable:")))
{
gchar *d = g_strdup (p+8);
p = strchr (d, ';');
if (p)
*p = 0;
if (strstr (d, "minimize"))
features &= ~ META_PLUGIN_MINIMIZE;
if (strstr (d, "maximize"))
features &= ~ META_PLUGIN_MAXIMIZE;
if (strstr (d, "unmaximize"))
features &= ~ META_PLUGIN_UNMAXIMIZE;
if (strstr (d, "map"))
features &= ~ META_PLUGIN_MAP;
if (strstr (d, "destroy"))
features &= ~ META_PLUGIN_DESTROY;
if (strstr (d, "switch-workspace"))
features &= ~META_PLUGIN_SWITCH_WORKSPACE;
g_free (d);
}
if (strstr (priv->params, "debug"))
debug = TRUE;
if (debug != priv->debug)
{
priv->debug = debug;
g_object_notify (G_OBJECT (plugin), "debug-mode");
}
}
if (features != priv->features)
{
priv->features = features;
g_object_notify (G_OBJECT (plugin), "features");
}
}
static void
meta_plugin_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
switch (prop_id)
{
case PROP_SCREEN:
priv->screen = g_value_get_object (value);
break;
case PROP_PARAMS:
priv->params = g_value_dup_string (value);
meta_plugin_parse_params (META_PLUGIN (object));
break;
case PROP_DISABLED:
priv->disabled = g_value_get_boolean (value);
break;
case PROP_DEBUG_MODE:
priv->debug = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_plugin_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaPluginPrivate *priv = META_PLUGIN (object)->priv;
switch (prop_id)
{
case PROP_SCREEN:
g_value_set_object (value, priv->screen);
break;
case PROP_PARAMS:
g_value_set_string (value, priv->params);
break;
case PROP_DISABLED:
g_value_set_boolean (value, priv->disabled);
break;
case PROP_DEBUG_MODE:
g_value_set_boolean (value, priv->debug);
break;
case PROP_FEATURES:
g_value_set_ulong (value, priv->features);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_plugin_class_init (MetaPluginClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
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,
g_param_spec_object ("screen",
"MetaScreen",
"MetaScreen",
META_TYPE_SCREEN,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_PARAMS,
g_param_spec_string ("params",
"Parameters",
"Plugin Parameters",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_FEATURES,
g_param_spec_ulong ("features",
"Features",
"Plugin Features",
0 , G_MAXULONG, 0,
G_PARAM_READABLE));
g_object_class_install_property (gobject_class,
PROP_DISABLED,
g_param_spec_boolean ("disabled",
"Plugin disabled",
"Plugin disabled",
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_DEBUG_MODE,
g_param_spec_boolean ("debug-mode",
"Debug Mode",
"Debug Mode",
FALSE,
G_PARAM_READABLE));
g_type_class_add_private (gobject_class, sizeof (MetaPluginPrivate));
}
static void
meta_plugin_init (MetaPlugin *self)
{
MetaPluginPrivate *priv;
self->priv = priv = META_PLUGIN_GET_PRIVATE (self);
}
gulong
meta_plugin_features (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return priv->features;
}
gboolean
meta_plugin_disabled (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return priv->disabled;
}
gboolean
meta_plugin_running (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return (priv->running > 0);
}
gboolean
meta_plugin_debug_mode (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return priv->debug;
}
const MetaPluginInfo *
meta_plugin_get_info (MetaPlugin *plugin)
{
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
if (klass && klass->plugin_info)
return klass->plugin_info (plugin);
return NULL;
}
ClutterActor *
meta_plugin_get_overlay_group (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return meta_get_overlay_group_for_screen (priv->screen);
}
ClutterActor *
meta_plugin_get_stage (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return meta_get_stage_for_screen (priv->screen);
}
ClutterActor *
meta_plugin_get_window_group (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return meta_get_window_group_for_screen (priv->screen);
}
/**
* _meta_plugin_effect_started:
* @plugin: the plugin
*
* Mark that an effect has started for the plugin. This is called
* internally by MetaPluginManager.
*/
void
_meta_plugin_effect_started (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
priv->running++;
}
void
meta_plugin_switch_workspace_completed (MetaPlugin *plugin)
{
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)
{
g_warning ("Error in running effect accounting, adjusting.");
priv->running = 0;
}
if (!actor)
{
const MetaPluginInfo *info;
const gchar *name = NULL;
if (plugin && (info = meta_plugin_get_info (plugin)))
name = info->name;
g_warning ("Plugin [%s] passed NULL for actor!",
name ? name : "unknown");
}
meta_window_actor_effect_completed (actor, event);
}
void
meta_plugin_minimize_completed (MetaPlugin *plugin,
MetaWindowActor *actor)
{
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
meta_plugin_set_stage_reactive (MetaPlugin *plugin,
gboolean reactive)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
if (reactive)
meta_set_stage_input_region (screen, None);
else
meta_empty_stage_input_region (screen);
}
void
meta_plugin_set_stage_input_area (MetaPlugin *plugin,
gint x, gint y, gint width, gint height)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
XRectangle rect;
XserverRegion region;
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
region = XFixesCreateRegion (xdpy, &rect, 1);
meta_set_stage_input_region (screen, region);
XFixesDestroyRegion (xdpy, region);
}
void
meta_plugin_set_stage_input_region (MetaPlugin *plugin,
XserverRegion region)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
meta_set_stage_input_region (screen, region);
}
/**
* meta_plugin_get_window_actors:
* @plugin: A #MetaPlugin
*
* 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 MetaWindowActor): Windows in stacking order, topmost last
*/
GList *
meta_plugin_get_window_actors (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return meta_get_window_actors (priv->screen);
}
/**
* meta_plugin_begin_modal:
* @plugin: a #MetaPlugin
* @grab_window: the X window to grab the keyboard and mouse on
* @cursor: the cursor to use for the pointer grab, or None,
* to use the normal cursor for the grab window and
* its descendants.
* @options: flags that modify the behavior of the modal grab
* @timestamp: the timestamp used for establishing grabs
*
* 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 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
* options. This facility is provided for two reasons: first to allow using
* this function to establish modality after a passive grab, and second to
* allow using obscure features of XGrabPointer() and XGrabKeyboard() without
* having to add them to this API.
*
* Return value: whether we successfully grabbed the keyboard and
* mouse and made the plugin modal.
*/
gboolean
meta_plugin_begin_modal (MetaPlugin *plugin,
Window grab_window,
Cursor cursor,
MetaModalOptions options,
guint32 timestamp)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return meta_begin_modal_for_plugin (priv->screen, plugin,
grab_window, cursor, options, timestamp);
}
/**
* 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
* ungrabs both the mouse and keyboard even when
* %META_MODAL_POINTER_ALREADY_GRABBED or
* %META_MODAL_KEYBOARD_ALREADY_GRABBED were provided as options
* when beginnning the modal operation.
*/
void
meta_plugin_end_modal (MetaPlugin *plugin,
guint32 timestamp)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
meta_end_modal_for_plugin (priv->screen, plugin, timestamp);
}
Display *
meta_plugin_get_xdisplay (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
MetaDisplay *display = meta_screen_get_display (priv->screen);
Display *xdpy = meta_display_get_xdisplay (display);
return xdpy;
}
/**
* 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
* multiple screens, multiple plugin instances will be created.
*
* Return value: (transfer none): the #MetaScreen for the plugin
*/
MetaScreen *
meta_plugin_get_screen (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return priv->screen;
}

View File

@@ -0,0 +1,635 @@
/*
* 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.
*/
#include <config.h>
#include "meta-shaped-texture.h"
#include "meta-texture-tower.h"
#include <clutter/clutter.h>
#include <cogl/cogl.h>
#include <string.h>
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 meta_shaped_texture_paint (ClutterActor *actor);
static void meta_shaped_texture_pick (ClutterActor *actor,
const ClutterColor *color);
static void meta_shaped_texture_update_area (ClutterX11TexturePixmap *texture,
int x,
int y,
int width,
int height);
static void meta_shaped_texture_dirty_mask (MetaShapedTexture *stex);
#ifdef HAVE_GLX_TEXTURE_PIXMAP
G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
CLUTTER_GLX_TYPE_TEXTURE_PIXMAP);
#else /* HAVE_GLX_TEXTURE_PIXMAP */
G_DEFINE_TYPE (MetaShapedTexture, meta_shaped_texture,
CLUTTER_X11_TYPE_TEXTURE_PIXMAP);
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
#define META_SHAPED_TEXTURE_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), META_TYPE_SHAPED_TEXTURE, \
MetaShapedTexturePrivate))
struct _MetaShapedTexturePrivate
{
MetaTextureTower *paint_tower;
CoglHandle mask_texture;
CoglHandle material;
CoglHandle material_unshaped;
cairo_region_t *clip_region;
guint mask_width, mask_height;
GArray *rectangles;
guint create_mipmaps : 1;
};
static void
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 = meta_shaped_texture_dispose;
gobject_class->finalize = meta_shaped_texture_finalize;
gobject_class->notify = meta_shaped_texture_notify;
actor_class->paint = meta_shaped_texture_paint;
actor_class->pick = meta_shaped_texture_pick;
x11_texture_class->update_area = meta_shaped_texture_update_area;
g_type_class_add_private (klass, sizeof (MetaShapedTexturePrivate));
}
static void
meta_shaped_texture_init (MetaShapedTexture *self)
{
MetaShapedTexturePrivate *priv;
priv = self->priv = META_SHAPED_TEXTURE_GET_PRIVATE (self);
priv->rectangles = g_array_new (FALSE, FALSE, sizeof (XRectangle));
priv->paint_tower = meta_texture_tower_new ();
priv->mask_texture = COGL_INVALID_HANDLE;
priv->create_mipmaps = TRUE;
}
static void
meta_shaped_texture_dispose (GObject *object)
{
MetaShapedTexture *self = (MetaShapedTexture *) object;
MetaShapedTexturePrivate *priv = self->priv;
if (priv->paint_tower)
meta_texture_tower_free (priv->paint_tower);
priv->paint_tower = NULL;
meta_shaped_texture_dirty_mask (self);
if (priv->material != COGL_INVALID_HANDLE)
{
cogl_handle_unref (priv->material);
priv->material = COGL_INVALID_HANDLE;
}
if (priv->material_unshaped != COGL_INVALID_HANDLE)
{
cogl_handle_unref (priv->material_unshaped);
priv->material_unshaped = COGL_INVALID_HANDLE;
}
meta_shaped_texture_set_clip_region (self, NULL);
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object);
}
static void
meta_shaped_texture_finalize (GObject *object)
{
MetaShapedTexture *self = (MetaShapedTexture *) object;
MetaShapedTexturePrivate *priv = self->priv;
g_array_free (priv->rectangles, TRUE);
G_OBJECT_CLASS (meta_shaped_texture_parent_class)->finalize (object);
}
static void
meta_shaped_texture_notify (GObject *object,
GParamSpec *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
* initial update_area, so we need to look for changes to the texture
* explicitly.
*/
if (strcmp (pspec->name, "cogl-texture") == 0)
{
MetaShapedTexture *stex = (MetaShapedTexture *) object;
MetaShapedTexturePrivate *priv = stex->priv;
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
meta_shaped_texture_dirty_mask (MetaShapedTexture *stex)
{
MetaShapedTexturePrivate *priv = stex->priv;
if (priv->mask_texture != COGL_INVALID_HANDLE)
{
GLuint mask_gl_tex;
GLenum mask_gl_target;
cogl_texture_get_gl_texture (priv->mask_texture,
&mask_gl_tex, &mask_gl_target);
if (mask_gl_target == GL_TEXTURE_RECTANGLE_ARB)
glDeleteTextures (1, &mask_gl_tex);
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
meta_shaped_texture_ensure_mask (MetaShapedTexture *stex)
{
MetaShapedTexturePrivate *priv = stex->priv;
CoglHandle paint_tex;
guint tex_width, tex_height;
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
if (paint_tex == COGL_INVALID_HANDLE)
return;
tex_width = cogl_texture_get_width (paint_tex);
tex_height = cogl_texture_get_height (paint_tex);
/* If the mask texture we have was created for a different size then
recreate it */
if (priv->mask_texture != COGL_INVALID_HANDLE
&& (priv->mask_width != tex_width || priv->mask_height != tex_height))
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)
{
guchar *mask_data;
const XRectangle *rect;
GLenum paint_gl_target;
/* Create data for an empty image */
mask_data = g_malloc0 (tex_width * tex_height);
/* Cut out a hole for each rectangle */
for (rect = (XRectangle *) priv->rectangles->data
+ priv->rectangles->len;
rect-- > (XRectangle *) priv->rectangles->data;)
{
gint x1 = rect->x, x2 = x1 + rect->width;
gint y1 = rect->y, y2 = y1 + rect->height;
guchar *p;
/* Clip the rectangle to the size of the texture */
x1 = CLAMP (x1, 0, (gint) tex_width - 1);
x2 = CLAMP (x2, x1, (gint) tex_width);
y1 = CLAMP (y1, 0, (gint) tex_height - 1);
y2 = CLAMP (y2, y1, (gint) tex_height);
/* Fill the rectangle */
for (p = mask_data + y1 * tex_width + x1;
y1 < y2;
y1++, p += tex_width)
memset (p, 255, x2 - x1);
}
cogl_texture_get_gl_texture (paint_tex, NULL, &paint_gl_target);
if (paint_gl_target == GL_TEXTURE_RECTANGLE_ARB)
{
GLuint tex;
glGenTextures (1, &tex);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex);
glPixelStorei (GL_UNPACK_ROW_LENGTH, tex_width);
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0,
GL_ALPHA, tex_width, tex_height,
0, GL_ALPHA, GL_UNSIGNED_BYTE, mask_data);
priv->mask_texture
= cogl_texture_new_from_foreign (tex,
GL_TEXTURE_RECTANGLE_ARB,
tex_width, tex_height,
0, 0,
COGL_PIXEL_FORMAT_A_8);
}
else
priv->mask_texture = cogl_texture_new_from_data (tex_width, tex_height,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_A_8,
COGL_PIXEL_FORMAT_ANY,
tex_width,
mask_data);
g_free (mask_data);
priv->mask_width = tex_width;
priv->mask_height = tex_height;
}
}
static void
meta_shaped_texture_paint (ClutterActor *actor)
{
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
MetaShapedTexturePrivate *priv = stex->priv;
CoglHandle paint_tex;
guint tex_width, tex_height;
ClutterActorBox alloc;
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));
/* 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:
*
* - Updating mipmaps that we don't need
* - Having to reallocate pixmaps on the server into larger buffers
*
* 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 (priv->create_mipmaps)
paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower);
else
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
if (paint_tex == COGL_INVALID_HANDLE)
return;
tex_width = cogl_texture_get_width (paint_tex);
tex_height = cogl_texture_get_height (paint_tex);
if (tex_width == 0 || tex_height == 0) /* no contents yet */
return;
if (priv->rectangles->len < 1)
{
/* If there are no rectangles use a single-layer texture */
if (priv->material_unshaped == COGL_INVALID_HANDLE)
{
if (G_UNLIKELY (material_unshaped_template == COGL_INVALID_HANDLE))
material_unshaped_template = cogl_material_new ();
priv->material_unshaped = cogl_material_copy (material_unshaped_template);
}
material = priv->material_unshaped;
}
else
{
meta_shaped_texture_ensure_mask (stex);
if (priv->material == COGL_INVALID_HANDLE)
{
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;
cogl_material_set_layer (material, 1, priv->mask_texture);
}
cogl_material_set_layer (material, 0, paint_tex);
{
CoglColor color;
guchar opacity = clutter_actor_get_paint_opacity (actor);
cogl_color_set_from_4ub (&color, opacity, opacity, opacity, opacity);
cogl_material_set_color (material, &color);
}
cogl_set_source (material);
clutter_actor_get_allocation_box (actor, &alloc);
if (priv->clip_region)
{
int n_rects;
int i;
/* Limit to how many separate rectangles we'll draw; beyond this just
* fall back and draw the whole thing */
# define MAX_RECTS 16
n_rects = cairo_region_num_rectangles (priv->clip_region);
if (n_rects <= MAX_RECTS)
{
float coords[8];
float x1, y1, x2, y2;
for (i = 0; i < n_rects; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (priv->clip_region, i, &rect);
x1 = rect.x;
y1 = rect.y;
x2 = rect.x + rect.width;
y2 = rect.y + rect.height;
coords[0] = rect.x / (alloc.x2 - alloc.x1);
coords[1] = rect.y / (alloc.y2 - alloc.y1);
coords[2] = (rect.x + rect.width) / (alloc.x2 - alloc.x1);
coords[3] = (rect.y + rect.height) / (alloc.y2 - alloc.y1);
coords[4] = coords[0];
coords[5] = coords[1];
coords[6] = coords[2];
coords[7] = coords[3];
cogl_rectangle_with_multitexture_coords (x1, y1, x2, y2,
&coords[0], 8);
}
return;
}
}
cogl_rectangle (0, 0,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1);
}
static void
meta_shaped_texture_pick (ClutterActor *actor,
const ClutterColor *color)
{
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 (meta_shaped_texture_parent_class)
->pick (actor, color);
else if (clutter_actor_should_pick_paint (actor))
{
CoglHandle paint_tex;
ClutterActorBox alloc;
guint tex_width, tex_height;
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
if (paint_tex == COGL_INVALID_HANDLE)
return;
tex_width = cogl_texture_get_width (paint_tex);
tex_height = cogl_texture_get_height (paint_tex);
if (tex_width == 0 || tex_height == 0) /* no contents yet */
return;
meta_shaped_texture_ensure_mask (stex);
cogl_set_source_color4ub (color->red, color->green, color->blue,
color->alpha);
clutter_actor_get_allocation_box (actor, &alloc);
/* Paint the mask rectangle in the given color */
cogl_set_source_texture (priv->mask_texture);
cogl_rectangle_with_texture_coords (0, 0,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1,
0, 0, 1, 1);
}
}
static void
meta_shaped_texture_update_area (ClutterX11TexturePixmap *texture,
int x,
int y,
int width,
int height)
{
MetaShapedTexture *stex = (MetaShapedTexture *) texture;
MetaShapedTexturePrivate *priv = stex->priv;
CLUTTER_X11_TEXTURE_PIXMAP_CLASS (meta_shaped_texture_parent_class)->update_area (texture,
x, y, width, height);
meta_texture_tower_update_area (priv->paint_tower, x, y, width, height);
}
ClutterActor *
meta_shaped_texture_new (void)
{
ClutterActor *self = g_object_new (META_TYPE_SHAPED_TEXTURE, NULL);
return self;
}
void
meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex,
gboolean create_mipmaps)
{
MetaShapedTexturePrivate *priv;
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);
meta_shaped_texture_dirty_mask (stex);
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
void
meta_shaped_texture_add_rectangle (MetaShapedTexture *stex,
const XRectangle *rect)
{
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
meta_shaped_texture_add_rectangles (stex, 1, rect);
}
void
meta_shaped_texture_add_rectangles (MetaShapedTexture *stex,
size_t num_rects,
const XRectangle *rects)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
g_array_append_vals (priv->rectangles, rects, num_rects);
meta_shaped_texture_dirty_mask (stex);
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
/**
* 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
* THE FUNCTION (for efficiency to avoid a copy.)
*
* Provides a hint to the texture about what areas of the texture
* are not completely obscured and thus need to be painted. This
* is an optimization and is not supposed to have any effect on
* the output.
*
* Typically a parent container will set the clip region before
* painting its children, and then unset it afterwards.
*/
void
meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
cairo_region_t *clip_region)
{
MetaShapedTexturePrivate *priv;
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
if (priv->clip_region)
{
cairo_region_destroy (priv->clip_region);
priv->clip_region = NULL;
}
priv->clip_region = clip_region;
}

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

@@ -0,0 +1,654 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MetaTextureTower
*
* Mipmap emulation by creation of scaled down images
*
* Copyright (C) 2009 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 <math.h>
#include <string.h>
#include "meta-texture-tower.h"
#ifndef M_LOG2E
#define M_LOG2E 1.4426950408889634074
#endif
#define MAX_TEXTURE_LEVELS 12
/* If the texture format in memory doesn't match this, then Mesa
* will do the conversion, so things will still work, but it might
* be slow depending on how efficient Mesa is. These should be the
* native formats unless the display is 16bpp. If conversions
* here are a bottleneck, investigate whether we are converting when
* storing window data *into* the texture before adding extra code
* to handle multiple texture formats.
*/
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_BGRA_8888_PRE
#else
#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_ARGB_8888_PRE
#endif
typedef struct
{
guint16 x1;
guint16 y1;
guint16 x2;
guint16 y2;
} Box;
struct _MetaTextureTower
{
int n_levels;
CoglHandle textures[MAX_TEXTURE_LEVELS];
CoglHandle fbos[MAX_TEXTURE_LEVELS];
Box invalid[MAX_TEXTURE_LEVELS];
};
/**
* meta_texture_tower_new:
*
* Creates a new texture tower. The base texture has to be set with
* meta_texture_tower_set_base_texture() before use.
*
* Return value: the new texture tower. Free with meta_texture_tower_free()
*/
MetaTextureTower *
meta_texture_tower_new (void)
{
MetaTextureTower *tower;
tower = g_slice_new0 (MetaTextureTower);
return tower;
}
/**
* meta_texture_tower_free:
* @tower: a #MetaTextureTower
*
* Frees a texture tower created with meta_texture_tower_new().
*/
void
meta_texture_tower_free (MetaTextureTower *tower)
{
g_return_if_fail (tower != NULL);
meta_texture_tower_set_base_texture (tower, COGL_INVALID_HANDLE);
g_slice_free (MetaTextureTower, tower);
}
static gboolean
texture_is_rectangle (CoglHandle texture)
{
GLuint gl_tex;
GLenum gl_target;
cogl_texture_get_gl_texture (texture, &gl_tex, &gl_target);
return gl_target == GL_TEXTURE_RECTANGLE_ARB;
}
static void
free_texture (CoglHandle texture)
{
GLuint gl_tex;
GLenum gl_target;
cogl_texture_get_gl_texture (texture, &gl_tex, &gl_target);
if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
glDeleteTextures (1, &gl_tex);
cogl_handle_unref (texture);
}
/**
* 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
* scaled textures of the tower are derived from. The texture itself
* will be used as level 0 of the tower and will be referenced until
* unset or until the tower is freed.
*/
void
meta_texture_tower_set_base_texture (MetaTextureTower *tower,
CoglHandle texture)
{
int i;
g_return_if_fail (tower != NULL);
if (texture == tower->textures[0])
return;
if (tower->textures[0] != COGL_INVALID_HANDLE)
{
for (i = 1; i < tower->n_levels; i++)
{
if (tower->textures[i] != COGL_INVALID_HANDLE)
{
free_texture (tower->textures[i]);
tower->textures[i] = COGL_INVALID_HANDLE;
}
if (tower->fbos[i] != COGL_INVALID_HANDLE)
{
cogl_handle_unref (tower->fbos[i]);
tower->fbos[i] = COGL_INVALID_HANDLE;
}
}
cogl_handle_unref (tower->textures[0]);
}
tower->textures[0] = texture;
if (tower->textures[0] != COGL_INVALID_HANDLE)
{
int width, height;
cogl_handle_ref (tower->textures[0]);
width = cogl_texture_get_width (tower->textures[0]);
height = cogl_texture_get_height (tower->textures[0]);
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);
meta_texture_tower_update_area (tower, 0, 0, width, height);
}
else
{
tower->n_levels = 0;
}
}
/**
* 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
* @height: height rectangle that changed
*
* Mark a region of the base texture as having changed; the next
* time a scaled down version of the base texture is retrieved,
* the appropriate area of the scaled down texture will be updated.
*/
void
meta_texture_tower_update_area (MetaTextureTower *tower,
int x,
int y,
int width,
int height)
{
int texture_width, texture_height;
Box invalid;
int i;
g_return_if_fail (tower != NULL);
texture_width = cogl_texture_get_width (tower->textures[0]);
texture_height = cogl_texture_get_height (tower->textures[0]);
invalid.x1 = x;
invalid.y1 = y;
invalid.x2 = x + width;
invalid.y2 = y + height;
for (i = 1; i < tower->n_levels; i++)
{
texture_width = MAX (1, texture_width / 2);
texture_height = MAX (1, texture_height / 2);
invalid.x1 = invalid.x1 / 2;
invalid.y1 = invalid.y1 / 2;
invalid.x2 = MIN (texture_width, (invalid.x2 + 1) / 2);
invalid.y2 = MIN (texture_height, (invalid.y2 + 1) / 2);
if (tower->invalid[i].x1 == tower->invalid[i].x2 ||
tower->invalid[i].y1 == tower->invalid[i].y2)
{
tower->invalid[i] = invalid;
}
else
{
tower->invalid[i].x1 = MIN (tower->invalid[i].x1, invalid.x1);
tower->invalid[i].y1 = MIN (tower->invalid[i].y1, invalid.y1);
tower->invalid[i].x2 = MAX (tower->invalid[i].x2, invalid.x2);
tower->invalid[i].y2 = MAX (tower->invalid[i].y2, invalid.y2);
}
}
}
/* It generally looks worse if we scale up a window texture by even a
* small amount than if we scale it down using bilinear filtering, so
* we always pick the *larger* adjacent level. */
#define LOD_BIAS (-0.49)
/* This determines the appropriate level of detail to use when drawing the
* texture, in a way that corresponds to what the GL specification does
* when mip-mapping. This is probably fancier and slower than what we need,
* but we do the computation only once each time we paint a window, and
* its easier to just use the equations from the specification than to
* come up with something simpler.
*
* 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
* Meta.
*/
static int
get_paint_level (int width, int height)
{
CoglMatrix projection, modelview, pm;
float v[4];
double viewport_width, viewport_height;
double u0, v0;
double xc, yc, wc;
double dxdu_, dxdv_, dydu_, dydv_;
double det_, det_sq;
double rho_sq;
double lambda;
/* See
* http://www.opengl.org/registry/doc/glspec32.core.20090803.pdf
* Section 3.8.9, p. 1.6.2. Here we have
*
* u(x,y) = x_o;
* v(x,y) = y_o;
*
* Since we are mapping 1:1 from object coordinates into pixel
* texture coordinates, the clip coordinates are:
*
* (x_c) (x_o) (u)
* (y_c) = (M_projection)(M_modelview) (y_o) = (PM) (v)
* (z_c) (z_o) (0)
* (w_c) (w_o) (1)
*/
cogl_get_projection_matrix (&projection);
cogl_get_modelview_matrix (&modelview);
cogl_matrix_multiply (&pm, &projection, &modelview);
cogl_get_viewport (v);
viewport_width = v[2];
viewport_height = v[3];
u0 = width / 2.;
v0 = height / 2.;
xc = pm.xx * u0 + pm.xy * v0 + pm.xw;
yc = pm.yx * u0 + pm.yy * v0 + pm.yw;
wc = pm.wx * u0 + pm.wy * v0 + pm.ww;
/* We'll simplify the equations below for a bit of micro-optimization.
* The commented out code is the unsimplified version.
// Partial derivates of window coordinates:
//
// x_w = 0.5 * viewport_width * x_c / w_c + viewport_center_x
// y_w = 0.5 * viewport_height * y_c / w_c + viewport_center_y
//
// with respect to u, v, using
// d(a/b)/dx = da/dx * (1/b) - a * db/dx / (b^2)
dxdu = 0.5 * viewport_width * (pm.xx - pm.wx * (xc/wc)) / wc;
dxdv = 0.5 * viewport_width * (pm.xy - pm.wy * (xc/wc)) / wc;
dydu = 0.5 * viewport_height * (pm.yx - pm.wx * (yc/wc)) / wc;
dydv = 0.5 * viewport_height * (pm.yy - pm.wy * (yc/wc)) / wc;
// Compute the inverse partials as the matrix inverse
det = dxdu * dydv - dxdv * dydu;
dudx = dydv / det;
dudy = - dxdv / det;
dvdx = - dydu / det;
dvdy = dvdu / det;
// Scale factor; maximum of the distance in texels for a change of 1 pixel
// in the X direction or 1 pixel in the Y direction
rho = MAX (sqrt (dudx * dudx + dvdx * dvdx), sqrt(dudy * dudy + dvdy * dvdy));
// Level of detail
lambda = log2 (rho) + LOD_BIAS;
*/
/* dxdu * wc, etc */
dxdu_ = 0.5 * viewport_width * (pm.xx - pm.wx * (xc/wc));
dxdv_ = 0.5 * viewport_width * (pm.xy - pm.wy * (xc/wc));
dydu_ = 0.5 * viewport_height * (pm.yx - pm.wx * (yc/wc));
dydv_ = 0.5 * viewport_height * (pm.yy - pm.wy * (yc/wc));
/* det * wc^2 */
det_ = dxdu_ * dydv_ - dxdv_ * dydu_;
det_sq = det_ * det_;
if (det_sq == 0.0)
return -1;
/* (rho * det * wc)^2 */
rho_sq = MAX (dydv_ * dydv_ + dydu_ * dydu_, dxdv_ * dxdv_ + dxdu_ * dxdu_);
lambda = 0.5 * M_LOG2E * log (rho_sq * wc * wc / det_sq) + LOD_BIAS;
#if 0
g_print ("%g %g %g\n", 0.5 * viewport_width * pm.xx / pm.ww, 0.5 * viewport_height * pm.yy / pm.ww, lambda);
#endif
if (lambda <= 0.)
return 0;
else
return (int)(0.5 + lambda);
}
static gboolean
is_power_of_two (int x)
{
return (x & (x - 1)) == 0;
}
static void
texture_tower_create_texture (MetaTextureTower *tower,
int level,
int width,
int height)
{
if ((!is_power_of_two (width) || !is_power_of_two (height)) &&
texture_is_rectangle (tower->textures[level - 1]))
{
GLuint tex = 0;
glGenTextures (1, &tex);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0,
GL_RGBA, width,height,
#if TEXTURE_FORMAT == COGL_PIXEL_FORMAT_BGRA_8888_PRE
0, GL_BGRA, GL_UNSIGNED_BYTE,
#else /* assume big endian */
0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
#endif
NULL);
tower->textures[level] = cogl_texture_new_from_foreign (tex, GL_TEXTURE_RECTANGLE_ARB,
width, height,
0, 0,
TEXTURE_FORMAT);
}
else
{
tower->textures[level] = cogl_texture_new_with_size (width, height,
COGL_TEXTURE_NO_AUTO_MIPMAP,
TEXTURE_FORMAT);
}
tower->invalid[level].x1 = 0;
tower->invalid[level].y1 = 0;
tower->invalid[level].x2 = width;
tower->invalid[level].y2 = height;
}
static gboolean
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);
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);
Box *invalid = &tower->invalid[level];
CoglMatrix modelview;
if (tower->fbos[level] == COGL_INVALID_HANDLE)
{
/* 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;
cogl_push_framebuffer (tower->fbos[level]);
cogl_ortho (0, dest_texture_width, dest_texture_height, 0, -1., 1.);
cogl_matrix_init_identity (&modelview);
cogl_set_modelview_matrix (&modelview);
cogl_set_source_texture (tower->textures[level - 1]);
cogl_rectangle_with_texture_coords (invalid->x1, invalid->y1,
invalid->x2, invalid->y2,
(2. * invalid->x1) / source_texture_width,
(2. * invalid->y1) / source_texture_height,
(2. * invalid->x2) / source_texture_width,
(2. * invalid->y2) / source_texture_height);
cogl_pop_framebuffer ();
return TRUE;
}
static void
fill_copy (guchar *buf,
const guchar *source,
int width)
{
memcpy (buf, source, width * 4);
}
static void
fill_scale_down (guchar *buf,
const guchar *source,
int width)
{
while (width > 1)
{
buf[0] = (source[0] + source[4]) / 2;
buf[1] = (source[1] + source[5]) / 2;
buf[2] = (source[2] + source[6]) / 2;
buf[3] = (source[3] + source[7]) / 2;
buf += 4;
source += 8;
width -= 2;
}
if (width > 0)
{
buf[0] = source[0] / 2;
buf[1] = source[1] / 2;
buf[2] = source[2] / 2;
buf[3] = source[3] / 2;
}
}
static void
texture_tower_revalidate_client (MetaTextureTower *tower,
int level)
{
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);
guint source_rowstride;
guchar *source_data;
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);
int dest_x = tower->invalid[level].x1;
int dest_y = tower->invalid[level].y1;
int dest_width = tower->invalid[level].x2 - tower->invalid[level].x1;
int dest_height = tower->invalid[level].y2 - tower->invalid[level].y1;
guchar *dest_data;
guchar *source_tmp1 = NULL, *source_tmp2 = NULL;
int i, j;
source_rowstride = source_texture_width * 4;
source_data = g_malloc (source_texture_height * source_rowstride);
cogl_texture_get_data (source_texture, TEXTURE_FORMAT, source_rowstride,
source_data);
dest_data = g_malloc (dest_height * dest_width * 4);
if (dest_texture_height < source_texture_height)
{
source_tmp1 = g_malloc (dest_width * 4);
source_tmp2 = g_malloc (dest_width * 4);
}
for (i = 0; i < dest_height; i++)
{
guchar *dest_row = dest_data + i * dest_width * 4;
if (dest_texture_height < source_texture_height)
{
guchar *source1, *source2;
guchar *dest;
if (dest_texture_width < source_texture_width)
{
fill_scale_down (source_tmp1,
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 2 * 4,
dest_width * 2);
fill_scale_down (source_tmp2,
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 2 * 4,
dest_width * 2);
}
else
{
fill_copy (source_tmp1,
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 4,
dest_width);
fill_copy (source_tmp2,
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 4,
dest_width);
}
source1 = source_tmp1;
source2 = source_tmp2;
dest = dest_row;
for (j = 0; j < dest_width * 4; j++)
*(dest++) = (*(source1++) + *(source2++)) / 2;
}
else
{
if (dest_texture_width < source_texture_width)
fill_scale_down (dest_row,
source_data + (i + dest_y) * source_rowstride + dest_x * 2 * 4,
dest_width * 2);
else
fill_copy (dest_row,
source_data + (i + dest_y) * source_rowstride,
dest_width);
}
}
cogl_texture_set_region (dest_texture,
0, 0,
dest_x, dest_y,
dest_width, dest_height,
dest_width, dest_height,
TEXTURE_FORMAT,
4 * dest_width,
dest_data);
if (dest_height < source_texture_height)
{
g_free (source_tmp1);
g_free (source_tmp2);
}
g_free (source_data);
g_free (dest_data);
}
static void
texture_tower_revalidate (MetaTextureTower *tower,
int level)
{
if (!texture_tower_revalidate_fbo (tower, level))
texture_tower_revalidate_client (tower, level);
}
/**
* 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
* be rendered with vertex coordinates that correspond to its
* size in pixels, so a 200x200 texture will be rendered on the
* rectangle (0, 0, 200, 200).
*
* Return value: the COGL texture handle to use for painting, or
* %COGL_INVALID_HANDLE if no base texture has yet been set.
*/
CoglHandle
meta_texture_tower_get_paint_texture (MetaTextureTower *tower)
{
int texture_width, texture_height;
int level;
g_return_val_if_fail (tower != NULL, COGL_INVALID_HANDLE);
if (tower->textures[0] == COGL_INVALID_HANDLE)
return COGL_INVALID_HANDLE;
texture_width = cogl_texture_get_width (tower->textures[0]);
texture_height = cogl_texture_get_height (tower->textures[0]);
level = get_paint_level(texture_width, texture_height);
if (level < 0) /* singular paint matrix, scaled to nothing */
return COGL_INVALID_HANDLE;
level = MIN (level, tower->n_levels - 1);
if (tower->textures[level] == COGL_INVALID_HANDLE ||
(tower->invalid[level].x2 != tower->invalid[level].x1 &&
tower->invalid[level].y2 != tower->invalid[level].y1))
{
int i;
for (i = 1; i <= level; i++)
{
/* Use "floor" convention here to be consistent with the NPOT texture extension */
texture_width = MAX (1, texture_width / 2);
texture_height = MAX (1, texture_height / 2);
if (tower->textures[i] == COGL_INVALID_HANDLE)
texture_tower_create_texture (tower, i, texture_width, texture_height);
}
for (i = 1; i <= level; i++)
{
if (tower->invalid[level].x2 != tower->invalid[level].x1 &&
tower->invalid[level].y2 != tower->invalid[level].y1)
texture_tower_revalidate (tower, i);
}
}
return tower->textures[level];
}

View File

@@ -0,0 +1,69 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MetaTextureTower
*
* Mipmap emulation by creation of scaled down images
*
* Copyright (C) 2009 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_TEXTURE_TOWER_H__
#define __META_TEXTURE_TOWER_H__
#include <clutter/clutter.h>
G_BEGIN_DECLS
/**
* SECTION:MetaTextureTower
* @short_description: mipmap emulation by creation of scaled down images
*
* 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
* TEXTURE_RECTANGLE_ARB and not NPOT textures. Rectangular textures
* are defined not to support mipmapping.
* - Even when NPOT textures are available, the combination of NPOT
* textures, texture_from_pixmap, and mipmapping doesn't typically
* work, since the X server doesn't allocate pixmaps in the right
* layout for mipmapping.
*
* So, what we do is create the "mipmap" levels ourselves by successive
* power-of-two scaledowns, and when rendering pick the single texture
* that best matches the scale we are rendering at. (Since we aren't
* typically using perspective transforms, we'll frequently have a single
* scale for the entire texture.)
*/
typedef struct _MetaTextureTower MetaTextureTower;
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 /* __META_TEXTURE_TOWER_H__ */

View File

@@ -0,0 +1,51 @@
/* -*- 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);
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 */

View File

@@ -1,24 +1,26 @@
/* -*- 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 "meta-window-actor-private.h"
#include "meta-window-group.h"
struct _MutterWindowGroupClass
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 +98,11 @@ 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;
cairo_rectangle_int_t screen_rect = { 0 };
GList *children, *l;
/* We walk the list from top to bottom (opposite of painting order),
@@ -116,77 +118,77 @@ 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);
visible_region = cairo_region_create_rectangle (&screen_rect);
for (l = children; l; l = l->next)
{
MutterWindow *cw;
MetaWindowActor *window_actor;
gboolean x, y;
if (!MUTTER_IS_WINDOW (l->data) || !CLUTTER_ACTOR_IS_VISIBLE (l->data))
if (!META_IS_WINDOW_ACTOR (l->data) || !CLUTTER_ACTOR_IS_VISIBLE (l->data))
continue;
cw = l->data;
window_actor = l->data;
if (!actor_is_untransformed (CLUTTER_ACTOR (cw), &x, &y))
if (!actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
continue;
/* Temporarily move to the coordinate system of the actor */
gdk_region_offset (visible_region, - x, - y);
cairo_region_translate (visible_region, - x, - y);
mutter_window_set_visible_region (cw, visible_region);
meta_window_actor_set_visible_region (window_actor, visible_region);
if (clutter_actor_get_paint_opacity (actor) == 0xff)
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
{
GdkRegion *obscured_region = mutter_window_get_obscured_region (cw);
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
if (obscured_region)
gdk_region_subtract (visible_region, obscured_region);
cairo_region_subtract (visible_region, obscured_region);
}
mutter_window_set_visible_region_beneath (cw, visible_region);
gdk_region_offset (visible_region, x, y);
meta_window_actor_set_visible_region_beneath (window_actor, visible_region);
cairo_region_translate (visible_region, x, y);
}
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;
MetaWindowActor *window_actor;
if (!MUTTER_IS_WINDOW (l->data))
if (!META_IS_WINDOW_ACTOR (l->data))
continue;
cw = l->data;
mutter_window_reset_visible_regions (cw);
window_actor = l->data;
meta_window_actor_reset_visible_regions (window_actor);
}
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

@@ -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,497 +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.
*/
#include "mutter-plugin.h"
#include "screen.h"
#include "display.h"
#include <string.h>
#include <X11/Xlib.h>
#include <X11/extensions/Xfixes.h>
#include <X11/extensions/shape.h>
#include <clutter/x11/clutter-x11.h>
#include "compositor-private.h"
#include "mutter-window-private.h"
G_DEFINE_ABSTRACT_TYPE (MutterPlugin, mutter_plugin, G_TYPE_OBJECT);
#define MUTTER_PLUGIN_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE ((obj), MUTTER_TYPE_PLUGIN, MutterPluginPrivate))
enum
{
PROP_0,
PROP_SCREEN,
PROP_PARAMS,
PROP_FEATURES,
PROP_DISABLED,
PROP_DEBUG_MODE,
};
struct _MutterPluginPrivate
{
MetaScreen *screen;
gchar *params;
gulong features;
gint running;
gboolean disabled : 1;
gboolean debug : 1;
};
static void
mutter_plugin_dispose (GObject *object)
{
G_OBJECT_CLASS (mutter_plugin_parent_class)->dispose (object);
}
static void
mutter_plugin_finalize (GObject *object)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
g_free (priv->params);
priv->params = NULL;
G_OBJECT_CLASS (mutter_plugin_parent_class)->finalize (object);
}
static void
mutter_plugin_parse_params (MutterPlugin *plugin)
{
char *p;
gulong features = 0;
MutterPluginPrivate *priv = plugin->priv;
MutterPluginClass *klass = MUTTER_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;
if (klass->maximize)
features |= MUTTER_PLUGIN_MAXIMIZE;
if (klass->unmaximize)
features |= MUTTER_PLUGIN_UNMAXIMIZE;
if (klass->map)
features |= MUTTER_PLUGIN_MAP;
if (klass->destroy)
features |= MUTTER_PLUGIN_DESTROY;
if (klass->switch_workspace)
features |= MUTTER_PLUGIN_SWITCH_WORKSPACE;
if (priv->params)
{
gboolean debug = FALSE;
if ((p = strstr (priv->params, "disable:")))
{
gchar *d = g_strdup (p+8);
p = strchr (d, ';');
if (p)
*p = 0;
if (strstr (d, "minimize"))
features &= ~ MUTTER_PLUGIN_MINIMIZE;
if (strstr (d, "maximize"))
features &= ~ MUTTER_PLUGIN_MAXIMIZE;
if (strstr (d, "unmaximize"))
features &= ~ MUTTER_PLUGIN_UNMAXIMIZE;
if (strstr (d, "map"))
features &= ~ MUTTER_PLUGIN_MAP;
if (strstr (d, "destroy"))
features &= ~ MUTTER_PLUGIN_DESTROY;
if (strstr (d, "switch-workspace"))
features &= ~MUTTER_PLUGIN_SWITCH_WORKSPACE;
g_free (d);
}
if (strstr (priv->params, "debug"))
debug = TRUE;
if (debug != priv->debug)
{
priv->debug = debug;
g_object_notify (G_OBJECT (plugin), "debug-mode");
}
}
if (features != priv->features)
{
priv->features = features;
g_object_notify (G_OBJECT (plugin), "features");
}
}
static void
mutter_plugin_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
switch (prop_id)
{
case PROP_SCREEN:
priv->screen = g_value_get_object (value);
break;
case PROP_PARAMS:
priv->params = g_value_dup_string (value);
mutter_plugin_parse_params (MUTTER_PLUGIN (object));
break;
case PROP_DISABLED:
priv->disabled = g_value_get_boolean (value);
break;
case PROP_DEBUG_MODE:
priv->debug = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
mutter_plugin_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (object)->priv;
switch (prop_id)
{
case PROP_SCREEN:
g_value_set_object (value, priv->screen);
break;
case PROP_PARAMS:
g_value_set_string (value, priv->params);
break;
case PROP_DISABLED:
g_value_set_boolean (value, priv->disabled);
break;
case PROP_DEBUG_MODE:
g_value_set_boolean (value, priv->debug);
break;
case PROP_FEATURES:
g_value_set_ulong (value, priv->features);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
mutter_plugin_class_init (MutterPluginClass *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;
g_object_class_install_property (gobject_class,
PROP_SCREEN,
g_param_spec_object ("screen",
"MetaScreen",
"MetaScreen",
META_TYPE_SCREEN,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (gobject_class,
PROP_PARAMS,
g_param_spec_string ("params",
"Parameters",
"Plugin Parameters",
NULL,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT));
g_object_class_install_property (gobject_class,
PROP_FEATURES,
g_param_spec_ulong ("features",
"Features",
"Plugin Features",
0 , G_MAXULONG, 0,
G_PARAM_READABLE));
g_object_class_install_property (gobject_class,
PROP_DISABLED,
g_param_spec_boolean ("disabled",
"Plugin disabled",
"Plugin disabled",
FALSE,
G_PARAM_READWRITE));
g_object_class_install_property (gobject_class,
PROP_DEBUG_MODE,
g_param_spec_boolean ("debug-mode",
"Debug Mode",
"Debug Mode",
FALSE,
G_PARAM_READABLE));
g_type_class_add_private (gobject_class, sizeof (MutterPluginPrivate));
}
static void
mutter_plugin_init (MutterPlugin *self)
{
MutterPluginPrivate *priv;
self->priv = priv = MUTTER_PLUGIN_GET_PRIVATE (self);
}
gulong
mutter_plugin_features (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return priv->features;
}
gboolean
mutter_plugin_disabled (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return priv->disabled;
}
gboolean
mutter_plugin_running (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return (priv->running > 0);
}
gboolean
mutter_plugin_debug_mode (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return priv->debug;
}
const MutterPluginInfo *
mutter_plugin_get_info (MutterPlugin *plugin)
{
MutterPluginClass *klass = MUTTER_PLUGIN_GET_CLASS (plugin);
if (klass && klass->plugin_info)
return klass->plugin_info (plugin);
return NULL;
}
ClutterActor *
mutter_plugin_get_overlay_group (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return mutter_get_overlay_group_for_screen (priv->screen);
}
ClutterActor *
mutter_plugin_get_stage (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return mutter_get_stage_for_screen (priv->screen);
}
ClutterActor *
mutter_plugin_get_window_group (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return mutter_get_window_group_for_screen (priv->screen);
}
/**
* _mutter_plugin_effect_started:
* @plugin: the plugin
*
* Mark that an effect has started for the plugin. This is called
* internally by MutterPluginManager.
*/
void
_mutter_plugin_effect_started (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
priv->running++;
}
void
mutter_plugin_effect_completed (MutterPlugin *plugin,
MutterWindow *actor,
unsigned long event)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
if (priv->running-- < 0)
{
g_warning ("Error in running effect accounting, adjusting.");
priv->running = 0;
}
if (!actor)
{
const MutterPluginInfo *info;
const gchar *name = NULL;
if (plugin && (info = mutter_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);
}
}
void
mutter_plugin_query_screen_size (MutterPlugin *plugin,
int *width,
int *height)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
meta_screen_get_size (priv->screen, width, height);
}
void
mutter_plugin_set_stage_reactive (MutterPlugin *plugin,
gboolean reactive)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
if (reactive)
mutter_set_stage_input_region (screen, None);
else
mutter_empty_stage_input_region (screen);
}
void
mutter_plugin_set_stage_input_area (MutterPlugin *plugin,
gint x, gint y, gint width, gint height)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
XRectangle rect;
XserverRegion region;
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
region = XFixesCreateRegion (xdpy, &rect, 1);
mutter_set_stage_input_region (screen, region);
XFixesDestroyRegion (xdpy, region);
}
void
mutter_plugin_set_stage_input_region (MutterPlugin *plugin,
XserverRegion region)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
MetaScreen *screen = priv->screen;
mutter_set_stage_input_region (screen, region);
}
GList *
mutter_plugin_get_windows (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return mutter_get_windows (priv->screen);
}
Display *
mutter_plugin_get_xdisplay (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_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
*
* Gets the #MetaScreen corresponding to a plugin. Each plugin instance
* is associated with exactly one screen; if Metacity is managing
* multiple screens, multiple plugin instances will be created.
*
* Return value: (transfer none): the #MetaScreen for the plugin
*/
MetaScreen *
mutter_plugin_get_screen (MutterPlugin *plugin)
{
MutterPluginPrivate *priv = MUTTER_PLUGIN (plugin)->priv;
return priv->screen;
}

View File

@@ -1,521 +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.
*/
#include <config.h>
#include "mutter-shaped-texture.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_paint (ClutterActor *actor);
static void mutter_shaped_texture_pick (ClutterActor *actor,
const ClutterColor *color);
static void mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex);
#ifdef HAVE_GLX_TEXTURE_PIXMAP
G_DEFINE_TYPE (MutterShapedTexture, mutter_shaped_texture,
CLUTTER_GLX_TYPE_TEXTURE_PIXMAP);
#else /* HAVE_GLX_TEXTURE_PIXMAP */
G_DEFINE_TYPE (MutterShapedTexture, mutter_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))
struct _MutterShapedTexturePrivate
{
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;
guint mask_width, mask_height;
GArray *rectangles;
};
static void
mutter_shaped_texture_class_init (MutterShapedTextureClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
gobject_class->dispose = mutter_shaped_texture_dispose;
gobject_class->finalize = mutter_shaped_texture_finalize;
actor_class->paint = mutter_shaped_texture_paint;
actor_class->pick = mutter_shaped_texture_pick;
g_type_class_add_private (klass, sizeof (MutterShapedTexturePrivate));
}
static void
mutter_shaped_texture_init (MutterShapedTexture *self)
{
MutterShapedTexturePrivate *priv;
priv = self->priv = MUTTER_SHAPED_TEXTURE_GET_PRIVATE (self);
priv->rectangles = g_array_new (FALSE, FALSE, sizeof (XRectangle));
priv->mask_texture = COGL_INVALID_HANDLE;
}
static void
mutter_shaped_texture_dispose (GObject *object)
{
MutterShapedTexture *self = (MutterShapedTexture *) object;
MutterShapedTexturePrivate *priv = self->priv;
mutter_shaped_texture_dirty_mask (self);
if (priv->material != COGL_INVALID_HANDLE)
{
cogl_material_unref (priv->material);
priv->material = COGL_INVALID_HANDLE;
}
if (priv->material_unshaped != COGL_INVALID_HANDLE)
{
cogl_material_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);
G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->dispose (object);
}
static void
mutter_shaped_texture_finalize (GObject *object)
{
MutterShapedTexture *self = (MutterShapedTexture *) object;
MutterShapedTexturePrivate *priv = self->priv;
g_array_free (priv->rectangles, TRUE);
G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->finalize (object);
}
static void
mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex)
{
MutterShapedTexturePrivate *priv = stex->priv;
if (priv->mask_texture != COGL_INVALID_HANDLE)
{
GLuint mask_gl_tex;
GLenum mask_gl_target;
cogl_texture_get_gl_texture (priv->mask_texture,
&mask_gl_tex, &mask_gl_target);
if (mask_gl_target == CGL_TEXTURE_RECTANGLE_ARB)
glDeleteTextures (1, &mask_gl_tex);
cogl_texture_unref (priv->mask_texture);
priv->mask_texture = COGL_INVALID_HANDLE;
}
}
static void
mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
{
MutterShapedTexturePrivate *priv = stex->priv;
CoglHandle paint_tex;
guint tex_width, tex_height;
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
if (paint_tex == COGL_INVALID_HANDLE)
return;
tex_width = cogl_texture_get_width (paint_tex);
tex_height = cogl_texture_get_height (paint_tex);
/* If the mask texture we have was created for a different size then
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);
/* If we don't have a mask texture yet then create one */
if (priv->mask_texture == COGL_INVALID_HANDLE)
{
guchar *mask_data;
const XRectangle *rect;
GLenum paint_gl_target;
/* Create data for an empty image */
mask_data = g_malloc0 (tex_width * tex_height);
/* Cut out a hole for each rectangle */
for (rect = (XRectangle *) priv->rectangles->data
+ priv->rectangles->len;
rect-- > (XRectangle *) priv->rectangles->data;)
{
gint x1 = rect->x, x2 = x1 + rect->width;
gint y1 = rect->y, y2 = y1 + rect->height;
guchar *p;
/* Clip the rectangle to the size of the texture */
x1 = CLAMP (x1, 0, (gint) tex_width - 1);
x2 = CLAMP (x2, x1, (gint) tex_width);
y1 = CLAMP (y1, 0, (gint) tex_height - 1);
y2 = CLAMP (y2, y1, (gint) tex_height);
/* Fill the rectangle */
for (p = mask_data + y1 * tex_width + x1;
y1 < y2;
y1++, p += tex_width)
memset (p, 255, x2 - x1);
}
cogl_texture_get_gl_texture (paint_tex, NULL, &paint_gl_target);
if (paint_gl_target == CGL_TEXTURE_RECTANGLE_ARB)
{
GLuint tex;
glGenTextures (1, &tex);
glBindTexture (CGL_TEXTURE_RECTANGLE_ARB, tex);
glPixelStorei (GL_UNPACK_ROW_LENGTH, tex_width);
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D (CGL_TEXTURE_RECTANGLE_ARB, 0,
GL_ALPHA, tex_width, tex_height,
0, GL_ALPHA, GL_UNSIGNED_BYTE, mask_data);
priv->mask_texture
= cogl_texture_new_from_foreign (tex,
CGL_TEXTURE_RECTANGLE_ARB,
tex_width, tex_height,
0, 0,
COGL_PIXEL_FORMAT_A_8);
}
else
priv->mask_texture = cogl_texture_new_from_data (tex_width, tex_height,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_A_8,
COGL_PIXEL_FORMAT_ANY,
tex_width,
mask_data);
g_free (mask_data);
priv->mask_width = tex_width;
priv->mask_height = tex_height;
}
}
static void
mutter_shaped_texture_paint (ClutterActor *actor)
{
MutterShapedTexture *stex = (MutterShapedTexture *) actor;
MutterShapedTexturePrivate *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))
return;
if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
clutter_actor_realize (CLUTTER_ACTOR (stex));
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
tex_width = cogl_texture_get_width (paint_tex);
tex_height = cogl_texture_get_height (paint_tex);
if (tex_width == 0 || tex_width == 0) /* no contents yet */
return;
if (paint_tex == COGL_INVALID_HANDLE)
return;
if (priv->rectangles->len < 1)
{
/* If there are no rectangles use a single-layer texture */
if (priv->material_unshaped == COGL_INVALID_HANDLE)
priv->material_unshaped = cogl_material_new ();
material = priv->material_unshaped;
}
else
{
mutter_shaped_texture_ensure_mask (stex);
if (priv->material == COGL_INVALID_HANDLE)
{
priv->material = cogl_material_new ();
cogl_material_set_layer_combine (priv->material, 1,
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
NULL);
}
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);
}
cogl_material_set_layer (material, 0, paint_tex);
{
CoglColor color;
guchar opacity = clutter_actor_get_paint_opacity (actor);
cogl_color_set_from_4ub (&color, opacity, opacity, opacity, opacity);
cogl_material_set_color (material, &color);
}
cogl_set_source (material);
clutter_actor_get_allocation_box (actor, &alloc);
if (priv->clip_region)
{
GdkRectangle *rects;
int n_rects;
int i;
/* Limit to how many separate rectangles we'll draw; beyond this just
* 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
{
float coords[MAX_RECTS * 8];
for (i = 0; i < n_rects; i++)
{
GdkRectangle *rect = &rects[i];
coords[i * 8 + 0] = rect->x;
coords[i * 8 + 1] = rect->y;
coords[i * 8 + 2] = rect->x + rect->width;
coords[i * 8 + 3] = rect->y + rect->height;
coords[i * 8 + 4] = rect->x / (alloc.x2 - alloc.x1);
coords[i * 8 + 5] = rect->y / (alloc.y2 - alloc.y1);
coords[i * 8 + 6] = (rect->x + rect->width) / (alloc.x2 - alloc.x1);
coords[i * 8 + 7] = (rect->y + rect->height) / (alloc.y2 - alloc.y1);
}
g_free (rects);
cogl_rectangles_with_texture_coords (coords, n_rects);
return;
}
}
cogl_rectangle (0, 0,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1);
}
static void
mutter_shaped_texture_pick (ClutterActor *actor,
const ClutterColor *color)
{
MutterShapedTexture *stex = (MutterShapedTexture *) actor;
MutterShapedTexturePrivate *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)
->pick (actor, color);
else if (clutter_actor_should_pick_paint (actor))
{
CoglHandle paint_tex;
ClutterActorBox alloc;
guint tex_width, tex_height;
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
if (paint_tex == COGL_INVALID_HANDLE)
return;
tex_width = cogl_texture_get_width (paint_tex);
tex_height = cogl_texture_get_height (paint_tex);
if (tex_width == 0 || tex_width == 0) /* no contents yet */
return;
mutter_shaped_texture_ensure_mask (stex);
cogl_set_source_color4ub (color->red, color->green, color->blue,
color->alpha);
clutter_actor_get_allocation_box (actor, &alloc);
/* Paint the mask rectangle in the given color */
cogl_set_source_texture (priv->mask_texture);
cogl_rectangle_with_texture_coords (0, 0,
alloc.x2 - alloc.x1,
alloc.y2 - alloc.y1,
0, 0, 1, 1);
}
}
ClutterActor *
mutter_shaped_texture_new (void)
{
ClutterActor *self = g_object_new (MUTTER_TYPE_SHAPED_TEXTURE, NULL);
return self;
}
void
mutter_shaped_texture_clear_rectangles (MutterShapedTexture *stex)
{
MutterShapedTexturePrivate *priv;
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
g_array_set_size (priv->rectangles, 0);
mutter_shaped_texture_dirty_mask (stex);
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
void
mutter_shaped_texture_add_rectangle (MutterShapedTexture *stex,
const XRectangle *rect)
{
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
mutter_shaped_texture_add_rectangles (stex, 1, rect);
}
void
mutter_shaped_texture_add_rectangles (MutterShapedTexture *stex,
size_t num_rects,
const XRectangle *rects)
{
MutterShapedTexturePrivate *priv;
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
g_array_append_vals (priv->rectangles, rects, num_rects);
mutter_shaped_texture_dirty_mask (stex);
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
}
/**
* mutter_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
* THE FUNCTION (for efficiency to avoid a copy.)
*
* Provides a hint to the texture about what areas of the texture
* are not completely obscured and thus need to be painted. This
* is an optimization and is not supposed to have any effect on
* the output.
*
* Typically a parent container will set the clip region before
* painting its children, and then unset it afterwards.
*/
void
mutter_shaped_texture_set_clip_region (MutterShapedTexture *stex,
GdkRegion *clip_region)
{
MutterShapedTexturePrivate *priv;
g_return_if_fail (MUTTER_IS_SHAPED_TEXTURE (stex));
priv = stex->priv;
if (priv->clip_region)
{
gdk_region_destroy (priv->clip_region);
priv->clip_region = NULL;
}
priv->clip_region = clip_region;
}

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 */

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

@@ -20,7 +20,7 @@
static unsigned char* shadow_gaussian_make_tile (void);
ClutterActor *
mutter_create_shadow_frame (MetaCompositor *compositor)
meta_create_shadow_frame (MetaCompositor *compositor)
{
ClutterActor *frame;

View File

@@ -4,6 +4,6 @@
#include <clutter/clutter.h>
#include "compositor.h"
ClutterActor *mutter_create_shadow_frame (MetaCompositor *compositor);
ClutterActor *meta_create_shadow_frame (MetaCompositor *compositor);
#endif /* SHADOW_H */

View File

@@ -155,7 +155,7 @@ tidy_texture_frame_unrealize (ClutterActor *self)
if (priv->material == COGL_INVALID_HANDLE)
return;
cogl_material_unref (priv->material);
cogl_handle_unref (priv->material);
priv->material = COGL_INVALID_HANDLE;
CLUTTER_ACTOR_UNSET_FLAGS (self, CLUTTER_ACTOR_REALIZED);
@@ -415,7 +415,7 @@ tidy_texture_frame_dispose (GObject *gobject)
if (priv->material)
{
cogl_material_unref (priv->material);
cogl_handle_unref (priv->material);
priv->material = COGL_INVALID_HANDLE;
}

View File

@@ -1,138 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Metacity Alt-Tab abstraction */
/*
* Copyright (C) 2009 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 "alttabhandlerdefault.h"
#include "screen-private.h"
static GType handler_type = G_TYPE_INVALID;
GType meta_alt_tab_handler_default_get_type (void);
void
meta_alt_tab_handler_register (GType type)
{
handler_type = type;
}
MetaAltTabHandler *
meta_alt_tab_handler_new (MetaScreen *screen,
gboolean immediate)
{
if (handler_type == G_TYPE_INVALID)
handler_type = meta_alt_tab_handler_default_get_type ();
return g_object_new (handler_type,
"screen", screen,
"immediate", immediate,
NULL);
}
static void meta_alt_tab_handler_class_init (GObjectClass *object_class);
GType
meta_alt_tab_handler_get_type (void)
{
static volatile gsize g_define_type_id__volatile = 0;
if (g_once_init_enter (&g_define_type_id__volatile))
{
const GTypeInfo type_info =
{
sizeof (MetaAltTabHandlerInterface), /* class_size */
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc)meta_alt_tab_handler_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
0,
0, /* n_preallocs */
NULL
};
GType g_define_type_id =
g_type_register_static (G_TYPE_INTERFACE, "MetaAltTabHandler",
&type_info, 0);
g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT);
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
}
return g_define_type_id__volatile;
}
static void
meta_alt_tab_handler_class_init (GObjectClass *object_class)
{
g_object_interface_install_property (object_class,
g_param_spec_object ("screen",
"Screen",
"MetaScreen this is the switcher for",
META_TYPE_SCREEN,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
g_object_interface_install_property (object_class,
g_param_spec_boolean ("immediate",
"Immediate mode",
"Whether or not to select windows immediately",
FALSE,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
}
void
meta_alt_tab_handler_add_window (MetaAltTabHandler *handler,
MetaWindow *window)
{
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->add_window (handler, window);
}
void
meta_alt_tab_handler_show (MetaAltTabHandler *handler,
MetaWindow *initial_selection)
{
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->show (handler,
initial_selection);
}
void
meta_alt_tab_handler_destroy (MetaAltTabHandler *handler)
{
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->destroy (handler);
}
void
meta_alt_tab_handler_forward (MetaAltTabHandler *handler)
{
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->forward (handler);
}
void
meta_alt_tab_handler_backward (MetaAltTabHandler *handler)
{
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->backward (handler);
}
MetaWindow *
meta_alt_tab_handler_get_selected (MetaAltTabHandler *handler)
{
return META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->get_selected (handler);
}

View File

@@ -1,223 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Metacity Alt-Tab abstraction: default implementation */
/*
* Copyright (C) 2009 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 "alttabhandlerdefault.h"
#include "frame-private.h"
#include "window-private.h"
static void meta_alt_tab_handler_default_interface_init (MetaAltTabHandlerInterface *handler_iface);
G_DEFINE_TYPE_WITH_CODE (MetaAltTabHandlerDefault, meta_alt_tab_handler_default, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (META_TYPE_ALT_TAB_HANDLER,
meta_alt_tab_handler_default_interface_init))
enum {
PROP_SCREEN = 1,
PROP_IMMEDIATE
};
static void
meta_alt_tab_handler_default_init (MetaAltTabHandlerDefault *hd)
{
hd->entries = g_array_new (FALSE, FALSE, sizeof (MetaTabEntry));
}
static void
meta_alt_tab_handler_default_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (object);
switch (prop_id)
{
case PROP_SCREEN:
hd->screen = g_value_get_object (value);
break;
case PROP_IMMEDIATE:
hd->immediate_mode = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_alt_tab_handler_default_finalize (GObject *object)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (object);
g_array_free (hd->entries, TRUE);
if (hd->tab_popup)
meta_ui_tab_popup_free (hd->tab_popup);
G_OBJECT_CLASS (meta_alt_tab_handler_default_parent_class)->finalize (object);
}
static void
meta_alt_tab_handler_default_add_window (MetaAltTabHandler *handler,
MetaWindow *window)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
MetaTabEntry entry;
MetaRectangle r;
entry.key = (MetaTabEntryKey) window;
entry.title = window->title;
entry.icon = window->icon;
entry.blank = FALSE;
entry.hidden = !meta_window_showing_on_its_workspace (window);
entry.demands_attention = window->wm_state_demands_attention;
if (hd->immediate_mode || !entry.hidden ||
!meta_window_get_icon_geometry (window, &r))
meta_window_get_outer_rect (window, &r);
entry.rect = r;
/* Find inside of highlight rectangle to be used when window is
* outlined for tabbing. This should be the size of the
* east/west frame, and the size of the south frame, on those
* sides. On the top it should be the size of the south frame
* edge.
*/
#define OUTLINE_WIDTH 5
/* Top side */
if (!entry.hidden &&
window->frame && window->frame->bottom_height > 0 &&
window->frame->child_y >= window->frame->bottom_height)
entry.inner_rect.y = window->frame->bottom_height;
else
entry.inner_rect.y = OUTLINE_WIDTH;
/* Bottom side */
if (!entry.hidden &&
window->frame && window->frame->bottom_height != 0)
entry.inner_rect.height = r.height
- entry.inner_rect.y - window->frame->bottom_height;
else
entry.inner_rect.height = r.height
- entry.inner_rect.y - OUTLINE_WIDTH;
/* Left side */
if (!entry.hidden && window->frame && window->frame->child_x != 0)
entry.inner_rect.x = window->frame->child_x;
else
entry.inner_rect.x = OUTLINE_WIDTH;
/* Right side */
if (!entry.hidden &&
window->frame && window->frame->right_width != 0)
entry.inner_rect.width = r.width
- entry.inner_rect.x - window->frame->right_width;
else
entry.inner_rect.width = r.width
- entry.inner_rect.x - OUTLINE_WIDTH;
g_array_append_val (hd->entries, entry);
}
static void
meta_alt_tab_handler_default_show (MetaAltTabHandler *handler,
MetaWindow *initial_selection)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
if (hd->tab_popup)
return;
hd->tab_popup = meta_ui_tab_popup_new ((MetaTabEntry *)hd->entries->data,
hd->screen->number,
hd->entries->len,
5, /* FIXME */
TRUE);
meta_ui_tab_popup_select (hd->tab_popup, (MetaTabEntryKey) initial_selection);
meta_ui_tab_popup_set_showing (hd->tab_popup, !hd->immediate_mode);
}
static void
meta_alt_tab_handler_default_destroy (MetaAltTabHandler *handler)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
if (hd->tab_popup)
{
meta_ui_tab_popup_free (hd->tab_popup);
hd->tab_popup = NULL;
}
}
static void
meta_alt_tab_handler_default_forward (MetaAltTabHandler *handler)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
if (hd->tab_popup)
meta_ui_tab_popup_forward (hd->tab_popup);
}
static void
meta_alt_tab_handler_default_backward (MetaAltTabHandler *handler)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
if (hd->tab_popup)
meta_ui_tab_popup_backward (hd->tab_popup);
}
static MetaWindow *
meta_alt_tab_handler_default_get_selected (MetaAltTabHandler *handler)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
if (hd->tab_popup)
return (MetaWindow *)meta_ui_tab_popup_get_selected (hd->tab_popup);
else
return NULL;
}
static void
meta_alt_tab_handler_default_class_init (MetaAltTabHandlerDefaultClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = meta_alt_tab_handler_default_set_property;
object_class->finalize = meta_alt_tab_handler_default_finalize;
g_object_class_override_property (object_class, PROP_SCREEN, "screen");
g_object_class_override_property (object_class, PROP_IMMEDIATE, "immediate");
}
static void
meta_alt_tab_handler_default_interface_init (MetaAltTabHandlerInterface *handler_iface)
{
handler_iface->add_window = meta_alt_tab_handler_default_add_window;
handler_iface->show = meta_alt_tab_handler_default_show;
handler_iface->destroy = meta_alt_tab_handler_default_destroy;
handler_iface->forward = meta_alt_tab_handler_default_forward;
handler_iface->backward = meta_alt_tab_handler_default_backward;
handler_iface->get_selected = meta_alt_tab_handler_default_get_selected;
}

View File

@@ -52,6 +52,9 @@
#include "bell.h"
#include "screen-private.h"
#include "prefs.h"
#ifdef HAVE_LIBCANBERRA
#include <canberra-gtk.h>
#endif
/**
* Flashes one entire screen. This is done by making a window the size of the
@@ -228,18 +231,18 @@ bell_flash_window_frame (MetaWindow *window)
*/
static void
bell_flash_frame (MetaDisplay *display,
XkbAnyEvent *xkb_ev)
XkbAnyEvent *xkb_ev)
{
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev;
MetaWindow *window;
g_assert (xkb_ev->xkb_type == XkbBellNotify);
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
if (!window && (display->focus_window) && (display->focus_window->frame))
if (!window && (display->focus_window))
{
window = display->focus_window;
}
if (window)
if (window && window->frame)
{
bell_flash_window_frame (window);
}
@@ -285,6 +288,48 @@ meta_bell_notify (MetaDisplay *display,
/* flash something */
if (meta_prefs_get_visual_bell ())
bell_visual_notify (display, xkb_ev);
#ifdef HAVE_LIBCANBERRA
if (meta_prefs_bell_is_audible ())
{
ca_proplist *p;
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent*) xkb_ev;
MetaWindow *window;
int res;
ca_proplist_create (&p);
ca_proplist_sets (p, CA_PROP_EVENT_ID, "bell-window-system");
ca_proplist_sets (p, CA_PROP_EVENT_DESCRIPTION, _("Bell event"));
ca_proplist_sets (p, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent");
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
if (!window && (display->focus_window) && (display->focus_window->frame))
window = display->focus_window;
if (window)
{
ca_proplist_sets (p, CA_PROP_WINDOW_NAME, window->title);
ca_proplist_setf (p, CA_PROP_WINDOW_X11_XID, "%lu", (unsigned long)window->xwindow);
ca_proplist_sets (p, CA_PROP_APPLICATION_NAME, window->res_name);
ca_proplist_setf (p, CA_PROP_APPLICATION_PROCESS_ID, "%d", window->net_wm_pid);
}
/* First, we try to play a real sound ... */
res = ca_context_play_full (ca_gtk_context_get (), 1, p, NULL, NULL);
ca_proplist_destroy (p);
if (res != CA_SUCCESS && res != CA_ERROR_DISABLED)
{
/* ...and in case that failed we use the classic X11 bell. */
XkbForceDeviceBell (display->xdisplay,
xkb_bell_event->device,
xkb_bell_event->bell_class,
xkb_bell_event->bell_id,
xkb_bell_event->percent);
}
}
#endif /* HAVE_LIBCANBERRA */
}
#endif /* HAVE_XKB */
@@ -292,11 +337,19 @@ void
meta_bell_set_audible (MetaDisplay *display, gboolean audible)
{
#ifdef HAVE_XKB
#ifdef HAVE_LIBCANBERRA
/* When we are playing sounds using libcanberra support, we handle the
* bell whether its an audible bell or a visible bell */
gboolean enable_system_bell = FALSE;
#else
gboolean enable_system_bell = audible;
#endif /* HAVE_LIBCANBERRA */
XkbChangeEnabledControls (display->xdisplay,
XkbUseCoreKbd,
XkbAudibleBellMask,
audible ? XkbAudibleBellMask : 0);
#endif
XkbUseCoreKbd,
XkbAudibleBellMask,
enable_system_bell ? XkbAudibleBellMask : 0);
#endif /* HAVE_XKB */
}
gboolean
@@ -323,11 +376,7 @@ meta_bell_init (MetaDisplay *display)
XkbUseCoreKbd,
XkbBellNotifyMask,
XkbBellNotifyMask);
XkbChangeEnabledControls (display->xdisplay,
XkbUseCoreKbd,
XkbAudibleBellMask,
meta_prefs_bell_is_audible ()
? XkbAudibleBellMask : 0);
meta_bell_set_audible (display, meta_prefs_bell_is_audible ());
if (visual_bell_auto_reset) {
XkbSetAutoResetControls (display->xdisplay,
XkbAudibleBellMask,

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 (
@@ -535,7 +566,7 @@ meta_rectangle_get_minimal_spanning_set_for_region (
* enough to make this worth bothering. Further, it is only called from
* workspace.c:ensure_work_areas_validated (at least as of the time of
* writing this comment), which in turn should only be called if the
* strut list changes or the screen or xinerama size changes. If it ever
* strut list changes or the screen or monitor size changes. If it ever
* does show up on profiles (most likely because people start using
* ridiculously huge numbers of partial struts), possible optimizations
* include:
@@ -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,15 +1837,19 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
return ret;
}
/**
* meta_rectangle_find_nonintersected_monitor_edges: (skip)
*
*/
GList*
meta_rectangle_find_nonintersected_xinerama_edges (
const GList *xinerama_rects,
meta_rectangle_find_nonintersected_monitor_edges (
const GList *monitor_rects,
const GSList *all_struts)
{
/* This function cannot easily be merged with
* meta_rectangle_find_onscreen_edges() because real screen edges
* and strut edges both are of the type "there ain't anything
* immediately on the other side"; xinerama edges are different.
* immediately on the other side"; monitor edges are different.
*/
GList *ret;
const GList *cur;
@@ -1808,14 +1858,14 @@ meta_rectangle_find_nonintersected_xinerama_edges (
/* Initialize the return list to be empty */
ret = NULL;
/* start of ret with all the edges of xineramas that are adjacent to
* another xinerama.
/* start of ret with all the edges of monitors that are adjacent to
* another monitor.
*/
cur = xinerama_rects;
cur = monitor_rects;
while (cur)
{
MetaRectangle *cur_rect = cur->data;
const GList *compare = xinerama_rects;
const GList *compare = monitor_rects;
while (compare)
{
MetaRectangle *compare_rect = compare->data;
@@ -1849,15 +1899,15 @@ meta_rectangle_find_nonintersected_xinerama_edges (
/* If the rectangles really are adjacent */
if (x != INT_MIN)
{
/* We need a left edge for the xinerama on the right, and
* a right edge for the xinerama on the left. Just fill
/* We need a left edge for the monitor on the right, and
* a right edge for the monitor on the left. Just fill
* up the edges and stick 'em on the list.
*/
MetaEdge *new_edge = g_new (MetaEdge, 1);
new_edge->rect = meta_rect (x, y, width, height);
new_edge->side_type = side_type;
new_edge->edge_type = META_EDGE_XINERAMA;
new_edge->edge_type = META_EDGE_MONITOR;
ret = g_list_prepend (ret, new_edge);
}
@@ -1892,15 +1942,15 @@ meta_rectangle_find_nonintersected_xinerama_edges (
/* If the rectangles really are adjacent */
if (y != INT_MIN)
{
/* We need a top edge for the xinerama on the bottom, and
* a bottom edge for the xinerama on the top. Just fill
/* We need a top edge for the monitor on the bottom, and
* a bottom edge for the monitor on the top. Just fill
* up the edges and stick 'em on the list.
*/
MetaEdge *new_edge = g_new (MetaEdge, 1);
new_edge->rect = meta_rect (x, y, width, height);
new_edge->side_type = side_type;
new_edge->edge_type = META_EDGE_XINERAMA;
new_edge->edge_type = META_EDGE_MONITOR;
ret = g_list_prepend (ret, new_edge);
}

View File

@@ -24,9 +24,11 @@
*/
#include <config.h>
#include "boxes-private.h"
#include "constraints.h"
#include "workspace-private.h"
#include "place.h"
#include "prefs.h"
#include <stdlib.h>
#include <math.h>
@@ -93,10 +95,11 @@ typedef enum
{
PRIORITY_MINIMUM = 0, /* Dummy value used for loop start = min(all priorities) */
PRIORITY_ASPECT_RATIO = 0,
PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_XINERAMA = 0,
PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR = 0,
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,
@@ -127,23 +130,30 @@ typedef struct
int resize_gravity;
FixedDirections fixed_directions;
/* work_area_xinerama - current xinerama region minus struts
* entire_xinerama - current xienrama, including strut regions
/* work_area_monitor - current monitor region minus struts
* entire_monitor - current monitor, including strut regions
*/
MetaRectangle work_area_xinerama;
MetaRectangle entire_xinerama;
MetaRectangle work_area_monitor;
MetaRectangle entire_monitor;
/* Spanning rectangles for the non-covered (by struts) region of the
* screen and also for just the current xinerama
* screen and also for just the current monitor
*/
GList *usable_screen_region;
GList *usable_xinerama_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,
@@ -160,7 +170,7 @@ static gboolean constrain_aspect_ratio (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only);
static gboolean constrain_to_single_xinerama (MetaWindow *window,
static gboolean constrain_to_single_monitor (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only);
@@ -209,12 +219,14 @@ 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"},
{constrain_aspect_ratio, "constrain_aspect_ratio"},
{constrain_to_single_xinerama, "constrain_to_single_xinerama"},
{constrain_to_single_monitor, "constrain_to_single_monitor"},
{constrain_fully_onscreen, "constrain_fully_onscreen"},
{constrain_titlebar_visible, "constrain_titlebar_visible"},
{constrain_partially_onscreen, "constrain_partially_onscreen"},
@@ -311,7 +323,7 @@ meta_window_constrain (MetaWindow *window,
*new = info.current;
/* We may need to update window->require_fully_onscreen,
* window->require_on_single_xinerama, and perhaps other quantities
* window->require_on_single_monitor, and perhaps other quantities
* if this was a user move or user move-and-resize operation.
*/
update_onscreen_requirements (window, &info);
@@ -333,7 +345,7 @@ setup_constraint_info (ConstraintInfo *info,
const MetaRectangle *orig,
MetaRectangle *new)
{
const MetaXineramaScreenInfo *xinerama_info;
const MetaMonitorInfo *monitor_info;
MetaWorkspace *cur_workspace;
info->orig = *orig;
@@ -387,15 +399,15 @@ setup_constraint_info (ConstraintInfo *info,
if (!info->is_user_action)
info->fixed_directions = FIXED_DIRECTION_NONE;
xinerama_info =
meta_screen_get_xinerama_for_rect (window->screen, &info->current);
meta_window_get_work_area_for_xinerama (window,
xinerama_info->number,
&info->work_area_xinerama);
monitor_info =
meta_screen_get_monitor_for_rect (window->screen, &info->current);
meta_window_get_work_area_for_monitor (window,
monitor_info->number,
&info->work_area_monitor);
if (!window->fullscreen || window->fullscreen_monitors[0] == -1)
{
info->entire_xinerama = xinerama_info->rect;
info->entire_monitor = monitor_info->rect;
}
else
{
@@ -403,28 +415,29 @@ setup_constraint_info (ConstraintInfo *info,
long monitor;
monitor = window->fullscreen_monitors[i];
info->entire_xinerama =
window->screen->xinerama_infos[monitor].rect;
info->entire_monitor =
window->screen->monitor_infos[monitor].rect;
for (i = 1; i <= 3; i++)
{
monitor = window->fullscreen_monitors[i];
meta_rectangle_union (&info->entire_xinerama,
&window->screen->xinerama_infos[monitor].rect,
&info->entire_xinerama);
meta_rectangle_union (&info->entire_monitor,
&window->screen->monitor_infos[monitor].rect,
&info->entire_monitor);
}
}
cur_workspace = window->screen->active_workspace;
info->usable_screen_region =
meta_workspace_get_onscreen_region (cur_workspace);
info->usable_xinerama_region =
meta_workspace_get_onxinerama_region (cur_workspace,
xinerama_info->number);
info->usable_monitor_region =
meta_workspace_get_onmonitor_region (cur_workspace,
monitor_info->number);
/* Workaround braindead legacy apps that don't know how to
* fullscreen themselves properly.
*/
if (meta_rectangle_equal (new, &xinerama_info->rect) &&
if (meta_prefs_get_force_fullscreen() &&
meta_rectangle_equal (new, &monitor_info->rect) &&
window->has_fullscreen_func &&
!window->fullscreen)
{
@@ -448,8 +461,8 @@ setup_constraint_info (ConstraintInfo *info,
" is_user_action : %s\n"
" resize_gravity : %s\n"
" fixed_directions: %s\n"
" work_area_xinerama: %d,%d +%d,%d\n"
" entire_xinerama : %d,%d +%d,%d\n",
" work_area_monitor: %d,%d +%d,%d\n"
" entire_monitor : %d,%d +%d,%d\n",
info->orig.x, info->orig.y, info->orig.width, info->orig.height,
info->current.x, info->current.y,
info->current.width, info->current.height,
@@ -465,11 +478,11 @@ setup_constraint_info (ConstraintInfo *info,
(info->fixed_directions == FIXED_DIRECTION_X) ? "X fixed" :
(info->fixed_directions == FIXED_DIRECTION_Y) ? "Y fixed" :
"Freakin' Invalid Stupid",
info->work_area_xinerama.x, info->work_area_xinerama.y,
info->work_area_xinerama.width,
info->work_area_xinerama.height,
info->entire_xinerama.x, info->entire_xinerama.y,
info->entire_xinerama.width, info->entire_xinerama.height);
info->work_area_monitor.x, info->work_area_monitor.y,
info->work_area_monitor.width,
info->work_area_monitor.height,
info->entire_monitor.x, info->entire_monitor.y,
info->entire_monitor.width, info->entire_monitor.height);
}
static void
@@ -493,25 +506,25 @@ place_window_if_needed(MetaWindow *window,
{
MetaRectangle placed_rect = info->orig;
MetaWorkspace *cur_workspace;
const MetaXineramaScreenInfo *xinerama_info;
const MetaMonitorInfo *monitor_info;
meta_window_place (window, info->fgeom, info->orig.x, info->orig.y,
&placed_rect.x, &placed_rect.y);
did_placement = TRUE;
/* placing the window may have changed the xinerama. Find the
* new xinerama and update the ConstraintInfo
/* placing the window may have changed the monitor. Find the
* new monitor and update the ConstraintInfo
*/
xinerama_info =
meta_screen_get_xinerama_for_rect (window->screen, &placed_rect);
info->entire_xinerama = xinerama_info->rect;
meta_window_get_work_area_for_xinerama (window,
xinerama_info->number,
&info->work_area_xinerama);
monitor_info =
meta_screen_get_monitor_for_rect (window->screen, &placed_rect);
info->entire_monitor = monitor_info->rect;
meta_window_get_work_area_for_monitor (window,
monitor_info->number,
&info->work_area_monitor);
cur_workspace = window->screen->active_workspace;
info->usable_xinerama_region =
meta_workspace_get_onxinerama_region (cur_workspace,
xinerama_info->number);
info->usable_monitor_region =
meta_workspace_get_onmonitor_region (cur_workspace,
monitor_info->number);
info->current.x = placed_rect.x;
@@ -526,22 +539,23 @@ place_window_if_needed(MetaWindow *window,
if (window->placed || did_placement)
{
if (window->maximize_horizontally_after_placement ||
window->maximize_vertically_after_placement)
window->maximize_vertically_after_placement ||
window->fullscreen_after_placement)
{
/* define a sane saved_rect so that the user can unmaximize to
* something reasonable.
/* define a sane saved_rect so that the user can unmaximize or
* make unfullscreen to something reasonable.
*/
if (info->current.width >= info->work_area_xinerama.width)
if (info->current.width >= info->work_area_monitor.width)
{
info->current.width = .75 * info->work_area_xinerama.width;
info->current.x = info->work_area_xinerama.x +
.125 * info->work_area_xinerama.width;
info->current.width = .75 * info->work_area_monitor.width;
info->current.x = info->work_area_monitor.x +
.125 * info->work_area_monitor.width;
}
if (info->current.height >= info->work_area_xinerama.height)
if (info->current.height >= info->work_area_monitor.height)
{
info->current.height = .75 * info->work_area_xinerama.height;
info->current.y = info->work_area_xinerama.y +
.083 * info->work_area_xinerama.height;
info->current.height = .75 * info->work_area_monitor.height;
info->current.y = info->work_area_monitor.y +
.083 * info->work_area_monitor.height;
}
if (window->maximize_horizontally_after_placement ||
@@ -556,6 +570,15 @@ place_window_if_needed(MetaWindow *window,
if (window->frame && !window->fullscreen)
meta_frame_calc_geometry (window->frame, info->fgeom);
if (window->fullscreen_after_placement)
{
window->saved_rect = info->current;
window->fullscreen = TRUE;
window->fullscreen_after_placement = FALSE;
g_object_notify (G_OBJECT (window), "fullscreen");
}
window->maximize_horizontally_after_placement = FALSE;
window->maximize_vertically_after_placement = FALSE;
}
@@ -589,7 +612,7 @@ update_onscreen_requirements (MetaWindow *window,
return;
/* USABILITY NOTE: Naturally, I only want the require_fully_onscreen,
* require_on_single_xinerama, and require_titlebar_visible flags to
* require_on_single_monitor, and require_titlebar_visible flags to
* *become false* due to user interactions (which is allowed since
* certain constraints are ignored for user interactions regardless of
* the setting of these flags). However, whether to make these flags
@@ -603,7 +626,7 @@ update_onscreen_requirements (MetaWindow *window,
* problematic case but this may need to be revisited.
*/
/* The require onscreen/on-single-xinerama and titlebar_visible
/* The require onscreen/on-single-monitor and titlebar_visible
* stuff is relative to the outer window, not the inner
*/
extend_by_frame (&info->current, info->fgeom);
@@ -622,17 +645,17 @@ update_onscreen_requirements (MetaWindow *window,
window->require_fully_onscreen ? "TRUE" : "FALSE");
/* Update whether we want future constraint runs to require the
* window to be on a single xinerama.
* window to be on a single monitor.
*/
old = window->require_on_single_xinerama;
window->require_on_single_xinerama =
meta_rectangle_contained_in_region (info->usable_xinerama_region,
old = window->require_on_single_monitor;
window->require_on_single_monitor =
meta_rectangle_contained_in_region (info->usable_monitor_region,
&info->current);
if (old ^ window->require_on_single_xinerama)
if (old ^ window->require_on_single_monitor)
meta_topic (META_DEBUG_GEOMETRY,
"require_on_single_xinerama for %s toggled to %s\n",
"require_on_single_monitor for %s toggled to %s\n",
window->desc,
window->require_on_single_xinerama ? "TRUE" : "FALSE");
window->require_on_single_monitor ? "TRUE" : "FALSE");
/* Update whether we want future constraint runs to require the
* titlebar to be visible.
@@ -700,11 +723,62 @@ get_size_limits (const MetaWindow *window,
min_size->width += fw;
min_size->height += fh;
max_size->width += fw;
max_size->height += fh;
/* Do check to avoid overflow (e.g. max_size->width & max_size->height
* may be set to G_MAXINT by meta_set_normal_hints()).
*/
if (max_size->width < (G_MAXINT - fw))
max_size->width += fw;
else
max_size->width = G_MAXINT;
if (max_size->height < (G_MAXINT - fh))
max_size->height += fh;
else
max_size->height = G_MAXINT;
}
}
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,
@@ -721,12 +795,13 @@ 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 (window))
return TRUE;
/* Calculate target_size = maximized size of (window + frame) */
if (window->maximized_horizontally && window->maximized_vertically)
target_size = info->work_area_xinerama;
target_size = info->work_area_monitor;
else
{
/* Amount of maximization possible in a single direction depends
@@ -748,7 +823,7 @@ constrain_maximization (MetaWindow *window,
target_size = info->current;
extend_by_frame (&target_size, info->fgeom);
meta_rectangle_expand_to_avoiding_struts (&target_size,
&info->entire_xinerama,
&info->entire_monitor,
direction,
active_workspace_struts);
}
@@ -789,13 +864,66 @@ 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 (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,
ConstraintPriority priority,
gboolean check_only)
{
MetaRectangle min_size, max_size, xinerama;
MetaRectangle min_size, max_size, monitor;
gboolean too_big, too_small, constraint_already_satisfied;
if (priority > PRIORITY_FULLSCREEN)
@@ -805,22 +933,22 @@ constrain_fullscreen (MetaWindow *window,
if (!window->fullscreen)
return TRUE;
xinerama = info->entire_xinerama;
monitor = info->entire_monitor;
get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
too_big = !meta_rectangle_could_fit_rect (&xinerama, &min_size);
too_small = !meta_rectangle_could_fit_rect (&max_size, &xinerama);
too_big = !meta_rectangle_could_fit_rect (&monitor, &min_size);
too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor);
if (too_big || too_small)
return TRUE;
/* Determine whether constraint is already satisfied; exit if it is */
constraint_already_satisfied =
meta_rectangle_equal (&info->current, &xinerama);
meta_rectangle_equal (&info->current, &monitor);
if (check_only || constraint_already_satisfied)
return constraint_already_satisfied;
/*** Enforce constraint ***/
info->current = xinerama;
info->current = monitor;
return TRUE;
}
@@ -840,7 +968,7 @@ constrain_size_increments (MetaWindow *window,
/* Determine whether constraint applies; exit if it doesn't */
if (META_WINDOW_MAXIMIZED (window) || window->fullscreen ||
info->action_type == ACTION_MOVE)
META_WINDOW_TILED (window) || info->action_type == ACTION_MOVE)
return TRUE;
/* Determine whether constraint is already satisfied; exit if it is */
@@ -971,7 +1099,7 @@ constrain_aspect_ratio (MetaWindow *window,
constraints_are_inconsistent = minr > maxr;
if (constraints_are_inconsistent ||
META_WINDOW_MAXIMIZED (window) || window->fullscreen ||
info->action_type == ACTION_MOVE)
META_WINDOW_TILED (window) || info->action_type == ACTION_MOVE)
return TRUE;
/* Determine whether constraint is already satisfied; exit if it is. We
@@ -1082,7 +1210,7 @@ constrain_aspect_ratio (MetaWindow *window,
}
static gboolean
do_screen_and_xinerama_relative_constraints (
do_screen_and_monitor_relative_constraints (
MetaWindow *window,
GList *region_spanning_rectangles,
ConstraintInfo *info,
@@ -1098,7 +1226,7 @@ do_screen_and_xinerama_relative_constraints (
char spanning_region[1 + 28 * g_list_length (region_spanning_rectangles)];
meta_topic (META_DEBUG_GEOMETRY,
"screen/xinerama constraint; region_spanning_rectangles: %s\n",
"screen/monitor constraint; region_spanning_rectangles: %s\n",
meta_rectangle_region_to_string (region_spanning_rectangles, ", ",
spanning_region));
}
@@ -1156,32 +1284,32 @@ do_screen_and_xinerama_relative_constraints (
}
static gboolean
constrain_to_single_xinerama (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only)
constrain_to_single_monitor (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only)
{
if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_XINERAMA)
if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR)
return TRUE;
/* Exit early if we know the constraint won't apply--note that this constraint
* is only meant for normal windows (e.g. we don't want docks to be shoved
* "onscreen" by their own strut) and we can't apply it to frameless windows
* or else users will be unable to move windows such as XMMS across xineramas.
* or else users will be unable to move windows such as XMMS across monitors.
*/
if (window->type == META_WINDOW_DESKTOP ||
window->type == META_WINDOW_DOCK ||
window->screen->n_xinerama_infos == 1 ||
!window->require_on_single_xinerama ||
window->screen->n_monitor_infos == 1 ||
!window->require_on_single_monitor ||
!window->frame ||
info->is_user_action)
return TRUE;
/* Have a helper function handle the constraint for us */
return do_screen_and_xinerama_relative_constraints (window,
info->usable_xinerama_region,
info,
check_only);
return do_screen_and_monitor_relative_constraints (window,
info->usable_monitor_region,
info,
check_only);
}
static gboolean
@@ -1205,10 +1333,10 @@ constrain_fully_onscreen (MetaWindow *window,
return TRUE;
/* Have a helper function handle the constraint for us */
return do_screen_and_xinerama_relative_constraints (window,
info->usable_screen_region,
info,
check_only);
return do_screen_and_monitor_relative_constraints (window,
info->usable_screen_region,
info,
check_only);
}
static gboolean
@@ -1281,10 +1409,10 @@ constrain_titlebar_visible (MetaWindow *window,
horiz_amount_onscreen,
vert_amount_onscreen);
retval =
do_screen_and_xinerama_relative_constraints (window,
info->usable_screen_region,
info,
check_only);
do_screen_and_monitor_relative_constraints (window,
info->usable_screen_region,
info,
check_only);
meta_rectangle_expand_region_conditionally (info->usable_screen_region,
-horiz_amount_offscreen,
-horiz_amount_offscreen,
@@ -1356,10 +1484,10 @@ constrain_partially_onscreen (MetaWindow *window,
horiz_amount_onscreen,
vert_amount_onscreen);
retval =
do_screen_and_xinerama_relative_constraints (window,
info->usable_screen_region,
info,
check_only);
do_screen_and_monitor_relative_constraints (window,
info->usable_screen_region,
info,
check_only);
meta_rectangle_expand_region_conditionally (info->usable_screen_region,
-horiz_amount_offscreen,
-horiz_amount_offscreen,

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.
@@ -260,15 +261,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 +296,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 +574,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>
@@ -55,27 +55,16 @@ delete_ping_reply_func (MetaDisplay *display,
/* we do nothing */
}
static gboolean
delete_window_callback (gpointer w_p)
{
meta_window_kill ((MetaWindow*) w_p);
return FALSE; /* don't do it again */
}
static void
sigchld_handler (MetaNexus *nexus, guint arg1, gpointer arg2, gpointer user_data)
dialog_exited (GPid pid, int status, gpointer user_data)
{
MetaWindow *ours = (MetaWindow*) user_data;
if (GPOINTER_TO_INT (arg2) == ours->dialog_pid)
{
if (arg1 == 1 /* pressed "force quit" */)
g_idle_add_full (G_PRIORITY_DEFAULT,
delete_window_callback, user_data, NULL);
ours->dialog_pid = -1;
ours->dialog_pid = -1; /* forget it anyway */
}
/* exit status of 1 means the user pressed "Force Quit" */
if (WIFEXITED (status) && WEXITSTATUS (status) == 1)
meta_window_kill (ours);
}
static void
@@ -86,7 +75,7 @@ delete_ping_timeout_func (MetaDisplay *display,
{
MetaWindow *window = user_data;
char *window_title;
gchar *window_content;
gchar *window_content, *tmp;
GPid dialog_pid;
meta_topic (META_DEBUG_PING,
@@ -101,11 +90,14 @@ delete_ping_timeout_func (MetaDisplay *display,
window_title = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL);
window_content = g_strdup_printf(
_("<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>"),
window_title);
/* Translators: %s is a window title */
tmp = g_strdup_printf (_("<tt>%s</tt> is not responding."),
window_title);
window_content = g_strdup_printf (
"<big><b>%s</b></big>\n\n<i>%s</i>",
tmp,
_("You may choose to wait a short while for it to "
"continue or force the application to quit entirely."));
g_free (window_title);
@@ -117,13 +109,10 @@ delete_ping_timeout_func (MetaDisplay *display,
NULL, NULL);
g_free (window_content);
g_free (tmp);
window->dialog_pid = dialog_pid;
g_signal_connect (sigchld_nexus, "sigchld",
G_CALLBACK (sigchld_handler),
window);
g_child_watch_add (dialog_pid, dialog_exited, window);
}
void
@@ -147,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,
@@ -189,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.
*/
@@ -150,6 +151,15 @@ struct _MetaDisplay
guint32 current_time;
/* We maintain a sequence counter, incremented for each #MetaWindow
* created. This is exposed by meta_window_get_stable_sequence()
* but is otherwise not used inside mutter.
*
* It can be useful to plugins which want to sort windows in a
* stable fashion.
*/
guint32 window_sequence_counter;
/* Pings which we're waiting for a reply from */
GSList *pending_pings;
@@ -175,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,8 +230,8 @@ struct _MetaDisplay
MetaKeyCombo overlay_key_combo;
gboolean overlay_key_only_pressed;
/* Xinerama cache */
unsigned int xinerama_cache_invalidated : 1;
/* Monitor cache */
unsigned int monitor_cache_invalidated : 1;
/* Opening the display */
unsigned int display_opening : 1;
@@ -294,22 +307,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) && \
@@ -348,9 +354,9 @@ void meta_display_register_x_window (MetaDisplay *display,
MetaWindow *window);
void meta_display_unregister_x_window (MetaDisplay *display,
Window xwindow);
/* Return whether the xwindow is a no focus window for any of the screens */
gboolean meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
Window xwindow);
void meta_display_notify_window_created (MetaDisplay *display,
MetaWindow *window);
GSList* meta_display_list_windows (MetaDisplay *display,
MetaListWindowsFlags flags);
@@ -381,9 +387,8 @@ void meta_display_grab_focus_window_button (MetaDisplay *display,
void meta_display_ungrab_focus_window_button (MetaDisplay *display,
MetaWindow *window);
/* Next two functions are defined in edge-resistance.c */
void meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display);
void meta_display_cleanup_edges (MetaDisplay *display);
/* Next function is defined in edge-resistance.c */
void meta_display_cleanup_edges (MetaDisplay *display);
/* make a request to ensure the event serial has changed */
void meta_display_increment_event_serial (MetaDisplay *display);

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 || \
@@ -128,9 +131,19 @@ G_DEFINE_TYPE(MetaDisplay, meta_display, G_TYPE_OBJECT);
enum
{
OVERLAY_KEY,
FOCUS_WINDOW,
WINDOW_CREATED,
WINDOW_DEMANDS_ATTENTION,
WINDOW_MARKED_URGENT,
LAST_SIGNAL
};
enum {
PROP_0,
PROP_FOCUS_WINDOW
};
static guint display_signals [LAST_SIGNAL] = { 0 };
/**
@@ -141,8 +154,10 @@ static guint display_signals [LAST_SIGNAL] = { 0 };
*/
static MetaDisplay *the_display = NULL;
#ifdef WITH_VERBOSE_MODE
static void meta_spew_event (MetaDisplay *display,
XEvent *event);
#endif
static gboolean event_callback (XEvent *event,
gpointer data);
@@ -169,9 +184,47 @@ static void sanity_check_timestamps (MetaDisplay *display,
MetaGroup* get_focussed_group (MetaDisplay *display);
static void
meta_display_get_property(GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaDisplay *display = META_DISPLAY (object);
switch (prop_id)
{
case PROP_FOCUS_WINDOW:
g_value_set_object (value, display->focus_window);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_display_set_property(GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
switch (prop_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_display_class_init (MetaDisplayClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = meta_display_get_property;
object_class->set_property = meta_display_set_property;
display_signals[OVERLAY_KEY] =
g_signal_new ("overlay-key",
G_TYPE_FROM_CLASS (klass),
@@ -179,9 +232,46 @@ meta_display_class_init (MetaDisplayClass *klass)
0,
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
G_TYPE_NONE, 0);
display_signals[WINDOW_CREATED] =
g_signal_new ("window-created",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, META_TYPE_WINDOW);
display_signals[WINDOW_DEMANDS_ATTENTION] =
g_signal_new ("window-demands-attention",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, META_TYPE_WINDOW);
display_signals[WINDOW_MARKED_URGENT] =
g_signal_new ("window-marked-urgent",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
META_TYPE_WINDOW);
g_object_class_install_property (object_class,
PROP_FOCUS_WINDOW,
g_param_spec_object ("focus-window",
"Focus window",
"Currently focused window",
META_TYPE_WINDOW,
G_PARAM_READABLE));
}
/**
* Destructor for MetaPingData structs. Will destroy the
* event source for the struct as well.
@@ -257,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
@@ -342,6 +432,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[] = {
@@ -376,6 +467,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;
@@ -429,7 +525,7 @@ meta_display_open (void)
the_display->leader_window = None;
the_display->timestamp_pinging_window = None;
the_display->xinerama_cache_invalidated = TRUE;
the_display->monitor_cache_invalidated = TRUE;
the_display->groups_by_leader = NULL;
@@ -668,6 +764,13 @@ meta_display_open (void)
the_display->leader_window,
the_display->atom__NET_WM_NAME,
"Mutter");
/* The GNOME keybindings capplet should include both the Mutter and Metacity
* keybindings */
meta_prop_set_utf8_string_hint (the_display,
the_display->leader_window,
the_display->atom__GNOME_WM_KEYBINDINGS,
"Mutter,Metacity");
meta_prop_set_utf8_string_hint (the_display,
the_display->leader_window,
@@ -787,7 +890,7 @@ meta_display_open (void)
timestamp);
}
meta_error_trap_pop (the_display, FALSE);
meta_error_trap_pop (the_display);
}
meta_display_ungrab (the_display);
@@ -953,6 +1056,7 @@ meta_display_close (MetaDisplay *display,
meta_compositor_destroy (display->compositor);
g_object_unref (display);
the_display = NULL;
meta_quit (META_EXIT_SUCCESS);
}
@@ -995,7 +1099,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
@@ -1144,6 +1248,7 @@ grab_op_is_mouse (MetaGrabOp op)
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
case META_GRAB_OP_KEYBOARD_MOVING:
case META_GRAB_OP_COMPOSITOR:
return TRUE;
default:
@@ -1173,6 +1278,7 @@ grab_op_is_keyboard (MetaGrabOp op)
case META_GRAB_OP_KEYBOARD_ESCAPING_DOCK:
case META_GRAB_OP_KEYBOARD_ESCAPING_GROUP:
case META_GRAB_OP_KEYBOARD_WORKSPACE_SWITCHING:
case META_GRAB_OP_COMPOSITOR:
return TRUE;
default:
@@ -1223,6 +1329,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)
@@ -1349,7 +1492,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)) ||
@@ -1454,6 +1597,7 @@ event_callback (XEvent *event,
MetaDisplay *display;
Window modified;
gboolean frame_was_receiver;
gboolean bypass_compositor;
gboolean filter_out_event;
display = data;
@@ -1467,9 +1611,10 @@ event_callback (XEvent *event,
sn_display_process_event (display->sn_display, event);
#endif
bypass_compositor = FALSE;
filter_out_event = FALSE;
display->current_time = event_get_time (display, event);
display->xinerama_cache_invalidated = TRUE;
display->monitor_cache_invalidated = TRUE;
modified = event_get_modified_window (display, event);
@@ -1590,7 +1735,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)
{
@@ -1613,21 +1759,26 @@ event_callback (XEvent *event,
{
case KeyPress:
case KeyRelease:
meta_display_process_key_event (display, window, event);
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
break;
/* For key events, it's important to enforce single-handling, or
* we can get into a confused state. So if a keybinding is
* handled (because it's one of our hot-keys, or because we are
* in a keyboard-grabbed mode like moving a window, we don't
* want to pass the key event to the compositor at all.
*/
bypass_compositor = meta_display_process_key_event (display, window, event);
break;
case ButtonPress:
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
break;
if (event->xbutton.button == 4 || event->xbutton.button == 5)
{
if (display->compositor && window)
{
return meta_compositor_process_event (display->compositor,
event,
window);
}
else
return FALSE;
}
else if ((window &&
/* Scrollwheel event, do nothing and deliver event to compositor below */
break;
if ((window &&
grab_op_is_mouse (display->grab_op) &&
display->grab_button != (int) event->xbutton.button &&
display->grab_window == window) ||
@@ -1817,16 +1968,25 @@ event_callback (XEvent *event,
}
break;
case ButtonRelease:
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
break;
if (display->grab_window == window &&
grab_op_is_mouse (display->grab_op))
meta_window_handle_mouse_grab_op_event (window, event);
break;
case MotionNotify:
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
break;
if (display->grab_window == window &&
grab_op_is_mouse (display->grab_op))
meta_window_handle_mouse_grab_op_event (window, event);
break;
case EnterNotify:
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
break;
if (display->grab_window == window &&
grab_op_is_mouse (display->grab_op))
{
@@ -1919,6 +2079,9 @@ event_callback (XEvent *event,
}
break;
case LeaveNotify:
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
break;
if (display->grab_window == window &&
grab_op_is_mouse (display->grab_op))
meta_window_handle_mouse_grab_op_event (window, event);
@@ -2045,7 +2208,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
{
@@ -2214,7 +2377,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
{
@@ -2473,7 +2636,7 @@ event_callback (XEvent *event,
{
case XkbBellNotify:
if (XSERVER_TIME_IS_BEFORE(display->last_bell_time,
xkb_ev->time - 1000))
xkb_ev->time - 100))
{
display->last_bell_time = xkb_ev->time;
meta_bell_notify (display, xkb_ev);
@@ -2485,7 +2648,7 @@ event_callback (XEvent *event,
break;
}
if (display->compositor)
if (display->compositor && !bypass_compositor)
{
if (meta_compositor_process_event (display->compositor,
event,
@@ -2985,7 +3148,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";
@@ -3019,7 +3182,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);
@@ -3127,6 +3290,22 @@ meta_display_unregister_x_window (MetaDisplay *display,
remove_pending_pings_for_window (display, xwindow);
}
void
meta_display_notify_window_created (MetaDisplay *display,
MetaWindow *window)
{
g_signal_emit (display, display_signals[WINDOW_CREATED], 0, window);
}
/**
* meta_display_xwindow_is_a_no_focus_window:
* @display: A #MetaDisplay
* @xwindow: An X11 window
*
* Returns %TRUE iff window is one of mutter's internal "no focus" windows
* (there is one per screen) which will have the focus when there is no
* actual client window focused.
*/
gboolean
meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
Window xwindow)
@@ -3281,7 +3460,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");
@@ -3314,7 +3493,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
@@ -3431,6 +3610,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)
{
@@ -3489,7 +3669,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,
@@ -3506,18 +3686,6 @@ meta_display_begin_grab_op (MetaDisplay *display,
g_assert (display->grab_window != NULL || display->grab_screen != NULL);
g_assert (display->grab_op != META_GRAB_OP_NONE);
/* If this is a move or resize, cache the window edges for
* resistance/snapping
*/
if (meta_grab_op_is_resizing (display->grab_op) ||
meta_grab_op_is_moving (display->grab_op))
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Computing edges to resist-movement or snap-to for %s.\n",
window->desc);
meta_display_compute_resistance_and_snapping_edges (display);
}
/* Save the old stacking */
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
{
@@ -3640,6 +3808,21 @@ meta_display_end_grab_op (MetaDisplay *display,
}
}
/**
* meta_display_get_grab_op:
* Gets the current grab operation, if any.
*
* Return value: the current grab operation, or %META_GRAB_OP_NONE if
* Mutter doesn't currently have a grab. %META_GRAB_OP_COMPOSITOR will
* be returned if a compositor-plugin modal operation is in effect
* (See mutter_begin_modal_for_plugin())
*/
MetaGrabOp
meta_display_get_grab_op (MetaDisplay *display)
{
return display->grab_op;
}
void
meta_display_check_threshold_reached (MetaDisplay *display,
int x,
@@ -3705,7 +3888,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",
@@ -3716,7 +3899,7 @@ meta_change_button_grab (MetaDisplay *display,
++ignored_mask;
}
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
void
@@ -3900,7 +4083,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;
}
@@ -3997,8 +4180,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);
}
}
@@ -4006,7 +4189,7 @@ meta_set_syncing (gboolean setting)
* How long, in milliseconds, we should wait after pinging a window
* before deciding it's not going to get back to us.
*/
#define PING_TIMEOUT_DELAY 2250
#define PING_TIMEOUT_DELAY 5000
/**
* Does whatever it is we decided to do when a window didn't respond
@@ -4180,7 +4363,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);
}
@@ -4368,6 +4551,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,
@@ -4431,7 +4626,8 @@ meta_display_get_tab_list (MetaDisplay *display,
/* Check to see if it demands attention */
if (l_window->wm_state_demands_attention &&
l_window->workspace!=workspace)
l_window->workspace!=workspace &&
IN_TAB_CHAIN (l_window, type))
{
/* if it does, add it to the popup */
tab_list = g_list_prepend (tab_list, l_window);
@@ -4444,6 +4640,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,
@@ -4481,7 +4692,7 @@ meta_display_get_tab_next (MetaDisplay *display,
else
{
skip = display->focus_window != NULL &&
IN_TAB_CHAIN (display->focus_window, type);
tab_list->data == display->focus_window;
if (backward)
ret = find_tab_backward (display, type, screen, workspace,
tab_list, skip);
@@ -4494,6 +4705,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,
@@ -4618,11 +4841,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
@@ -4654,7 +4877,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);
@@ -4688,11 +4911,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
@@ -4715,7 +4938,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);
}
}
@@ -4771,7 +4994,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);
@@ -4838,6 +5061,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,
@@ -4942,6 +5193,34 @@ prefs_changed_callback (MetaPreference pref,
else
disable_compositor (display);
}
else if (pref == META_PREF_ATTACH_MODAL_DIALOGS)
{
MetaDisplay *display = data;
GSList *windows;
GSList *tmp;
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);
}
}
}
}
void
@@ -5011,9 +5290,9 @@ sanity_check_timestamps (MetaDisplay *display,
meta_warning ("%s appears to be one of the offending windows "
"with a timestamp of %u. Working around...\n",
window->desc, window->net_wm_user_time);
window->net_wm_user_time = timestamp;
meta_window_set_user_time (window, timestamp);
}
tmp = tmp->next;
}
@@ -5087,7 +5366,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;
@@ -5142,18 +5421,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)
{
@@ -5198,9 +5491,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"
@@ -63,6 +63,8 @@ struct MetaEdgeResistanceData
ResistanceDataForAnEdge bottom_data;
};
static void compute_resistance_and_snapping_edges (MetaDisplay *display);
/* !WARNING!: this function can return invalid indices (namely, either -1 or
* edges->len); this is by design, but you need to remember this.
*/
@@ -340,12 +342,12 @@ apply_edge_resistance (MetaWindow *window,
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_WINDOW = 16;
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW = 0;
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_XINERAMA = 32;
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_XINERAMA = 0;
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_MONITOR = 32;
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_MONITOR = 0;
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_SCREEN = 32;
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_SCREEN = 0;
const int TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW = 0;
const int TIMEOUT_RESISTANCE_LENGTH_MS_XINERAMA = 0;
const int TIMEOUT_RESISTANCE_LENGTH_MS_MONITOR = 0;
const int TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN = 0;
/* Quit if no movement was specified */
@@ -423,8 +425,8 @@ apply_edge_resistance (MetaWindow *window,
case META_EDGE_WINDOW:
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW;
break;
case META_EDGE_XINERAMA:
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_XINERAMA;
case META_EDGE_MONITOR:
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_MONITOR;
break;
case META_EDGE_SCREEN:
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN;
@@ -468,11 +470,11 @@ apply_edge_resistance (MetaWindow *window,
else
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW;
break;
case META_EDGE_XINERAMA:
case META_EDGE_MONITOR:
if (movement_towards_edge (edge->side_type, increment))
threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_XINERAMA;
threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_MONITOR;
else
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_XINERAMA;
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_MONITOR;
break;
case META_EDGE_SCREEN:
if (movement_towards_edge (edge->side_type, increment))
@@ -550,7 +552,9 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
gboolean modified;
int new_left, new_right, new_top, new_bottom;
g_assert (display->grab_edge_resistance_data != NULL);
if (display->grab_edge_resistance_data == NULL)
compute_resistance_and_snapping_edges (display);
edge_data = display->grab_edge_resistance_data;
if (auto_snap)
@@ -671,7 +675,8 @@ meta_display_cleanup_edges (MetaDisplay *display)
MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data;
GHashTable *edges_to_be_freed;
g_assert (edge_data != NULL);
if (edge_data == NULL) /* Not currently cached */
return;
/* We first need to clean out any window edges */
edges_to_be_freed = g_hash_table_new_full (g_direct_hash, g_direct_equal,
@@ -761,7 +766,7 @@ stupid_sort_requiring_extra_pointer_dereference (gconstpointer a,
static void
cache_edges (MetaDisplay *display,
GList *window_edges,
GList *xinerama_edges,
GList *monitor_edges,
GList *screen_edges)
{
MetaEdgeResistanceData *edge_data;
@@ -776,7 +781,7 @@ cache_edges (MetaDisplay *display,
if (meta_is_verbose())
{
int max_edges = MAX (MAX( g_list_length (window_edges),
g_list_length (xinerama_edges)),
g_list_length (monitor_edges)),
g_list_length (screen_edges));
char big_buffer[(EDGE_LENGTH+2)*max_edges];
@@ -784,9 +789,9 @@ cache_edges (MetaDisplay *display,
meta_topic (META_DEBUG_EDGE_RESISTANCE,
"Window edges for resistance : %s\n", big_buffer);
meta_rectangle_edge_list_to_string (xinerama_edges, ", ", big_buffer);
meta_rectangle_edge_list_to_string (monitor_edges, ", ", big_buffer);
meta_topic (META_DEBUG_EDGE_RESISTANCE,
"Xinerama edges for resistance: %s\n", big_buffer);
"Monitor edges for resistance: %s\n", big_buffer);
meta_rectangle_edge_list_to_string (screen_edges, ", ", big_buffer);
meta_topic (META_DEBUG_EDGE_RESISTANCE,
@@ -807,7 +812,7 @@ cache_edges (MetaDisplay *display,
tmp = window_edges;
break;
case 1:
tmp = xinerama_edges;
tmp = monitor_edges;
break;
case 2:
tmp = screen_edges;
@@ -844,7 +849,7 @@ cache_edges (MetaDisplay *display,
* 2nd: Allocate the edges
*/
g_assert (display->grab_edge_resistance_data == NULL);
display->grab_edge_resistance_data = g_new (MetaEdgeResistanceData, 1);
display->grab_edge_resistance_data = g_new0 (MetaEdgeResistanceData, 1);
edge_data = display->grab_edge_resistance_data;
edge_data->left_edges = g_array_sized_new (FALSE,
FALSE,
@@ -875,7 +880,7 @@ cache_edges (MetaDisplay *display,
tmp = window_edges;
break;
case 1:
tmp = xinerama_edges;
tmp = monitor_edges;
break;
case 2:
tmp = screen_edges;
@@ -938,8 +943,8 @@ initialize_grab_edge_resistance_data (MetaDisplay *display)
edge_data->bottom_data.keyboard_buildup = 0;
}
void
meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display)
static void
compute_resistance_and_snapping_edges (MetaDisplay *display)
{
GList *stacked_windows;
GList *cur_window_iter;
@@ -952,6 +957,11 @@ meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display)
*/
GSList *rem_windows, *rem_win_stacking;
g_assert (display->grab_window != NULL);
meta_topic (META_DEBUG_WINDOW_OPS,
"Computing edges to resist-movement or snap-to for %s.\n",
display->grab_window->desc);
/*
* 1st: Get the list of relevant windows, from bottom to top
*/
@@ -1110,12 +1120,12 @@ meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display)
/*
* 5th: Cache the combination of these edges with the onscreen and
* xinerama edges in an array for quick access. Free the edges since
* monitor edges in an array for quick access. Free the edges since
* they've been cached elsewhere.
*/
cache_edges (display,
edges,
display->grab_screen->active_workspace->xinerama_edges,
display->grab_screen->active_workspace->monitor_edges,
display->grab_screen->active_workspace->screen_edges);
g_list_free (edges);

View File

@@ -29,260 +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);
}
typedef struct ForeignDisplay ForeignDisplay;
struct ForeignDisplay
{
Display *dpy;
ErrorHandler handler;
gpointer data;
ForeignDisplay *next;
};
static ForeignDisplay *foreign_displays;
void
meta_errors_register_foreign_display (Display *foreign_dpy,
ErrorHandler handler,
gpointer data)
{
ForeignDisplay *info = g_new0 (ForeignDisplay, 1);
info->dpy = foreign_dpy;
info->handler = handler;
info->data = data;
info->next = foreign_displays;
foreign_displays = info;
}
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;
ForeignDisplay *foreign;
for (foreign = foreign_displays; foreign != NULL; foreign = foreign->next)
{
if (foreign->dpy == xdisplay)
{
foreign->handler (xdisplay, error, foreign->data);
return 0;
}
}
XGetErrorText (xdisplay, error->error_code, buf, 63);
display = meta_display_for_x_display (xdisplay);
/* Display can be NULL here because the compositing manager
* has its own Display, but Xlib only has one global error handler
*/
if (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 (display == NULL)
meta_bug ("IO error received for unknown display?\n");
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->name);
}
else
{
meta_warning (_("Fatal IO error %d (%s) on display '%s'.\n"),
errno, g_strerror (errno),
display->name);
}
/* 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)

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

@@ -45,7 +45,7 @@ gboolean meta_window_grab_all_keys (MetaWindow *window,
guint32 timestamp);
void meta_window_ungrab_all_keys (MetaWindow *window,
guint32 timestamp);
void meta_display_process_key_event (MetaDisplay *display,
gboolean meta_display_process_key_event (MetaDisplay *display,
MetaWindow *window,
XEvent *event);
void meta_set_keybindings_disabled (gboolean setting);

View File

@@ -470,16 +470,16 @@ regrab_key_bindings (MetaDisplay *display)
tmp = tmp->next;
}
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
g_slist_free (windows);
}
static MetaKeyBindingAction
display_get_keybinding_action (MetaDisplay *display,
unsigned int keysym,
unsigned int keycode,
unsigned long mask)
static MetaKeyBinding *
display_get_keybinding (MetaDisplay *display,
unsigned int keysym,
unsigned int keycode,
unsigned long mask)
{
int i;
@@ -490,13 +490,40 @@ display_get_keybinding_action (MetaDisplay *display,
display->key_bindings[i].keycode == keycode &&
display->key_bindings[i].mask == mask)
{
return meta_prefs_get_keybinding_action (display->key_bindings[i].name);
return &display->key_bindings[i];
}
--i;
}
return META_KEYBINDING_ACTION_NONE;
return NULL;
}
/**
* 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)
return meta_prefs_get_keybinding_action (binding->name);
else
return META_KEYBINDING_ACTION_NONE;
}
void
@@ -673,7 +700,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)
{
@@ -689,7 +716,7 @@ meta_change_keygrab (MetaDisplay *display,
++ignored_mask;
}
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
static void
@@ -731,7 +758,7 @@ grab_keys (MetaKeyBinding *bindings,
++i;
}
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
static void
@@ -750,14 +777,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
@@ -889,7 +916,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),
@@ -898,7 +925,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,
@@ -921,7 +948,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
@@ -1197,6 +1224,45 @@ process_overlay_key (MetaDisplay *display,
return TRUE;
}
static void
invoke_handler (MetaDisplay *display,
MetaScreen *screen,
MetaKeyHandler *handler,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding)
{
if (handler->func)
(* handler->func) (display, screen,
handler->flags & BINDING_PER_WINDOW ?
window : NULL,
event,
binding,
handler->user_data);
else
(* handler->default_func) (display, screen,
handler->flags & BINDING_PER_WINDOW ?
window: NULL,
event,
binding,
NULL);
}
static void
invoke_handler_by_name (MetaDisplay *display,
MetaScreen *screen,
const char *handler_name,
MetaWindow *window,
XEvent *event)
{
MetaKeyHandler *handler;
handler = find_handler (key_handlers, handler_name);
if (handler)
invoke_handler (display, screen, handler, window, event, NULL);
}
/* now called from only one place, may be worth merging */
static gboolean
process_event (MetaKeyBinding *bindings,
@@ -1253,20 +1319,7 @@ process_event (MetaKeyBinding *bindings,
*/
display->allow_terminal_deactivation = TRUE;
if (handler->func)
(* handler->func) (display, screen,
bindings[i].handler->flags & BINDING_PER_WINDOW ?
window: NULL,
event,
&bindings[i],
handler->user_data);
else
(* handler->default_func) (display, screen,
bindings[i].handler->flags & BINDING_PER_WINDOW ?
window: NULL,
event,
&bindings[i],
NULL);
invoke_handler (display, screen, handler, window, event, &bindings[i]);
return TRUE;
}
@@ -1281,13 +1334,16 @@ process_event (MetaKeyBinding *bindings,
* right. This cannot cause infinite recursion because we never call
* ourselves when there wasn't a grab, and we always clear the grab
* first; the invariant is enforced using an assertion. See #112560.
*
* The return value is whether we handled the key event.
*
* FIXME: We need to prove there are no race conditions here.
* FIXME: Does it correctly handle alt-Tab being followed by another
* grabbing keypress without letting go of alt?
* FIXME: An iterative solution would probably be simpler to understand
* (and help us solve the other fixmes).
*/
void
gboolean
meta_display_process_key_event (MetaDisplay *display,
MetaWindow *window,
XEvent *event)
@@ -1303,7 +1359,7 @@ meta_display_process_key_event (MetaDisplay *display,
all_bindings_disabled ? ReplayKeyboard : AsyncKeyboard,
event->xkey.time);
if (all_bindings_disabled)
return;
return FALSE;
/* if key event was on root window, we have a shortcut */
screen = meta_display_screen_for_root (display, event->xkey.window);
@@ -1314,12 +1370,11 @@ meta_display_process_key_event (MetaDisplay *display,
event->xany.window);
if (screen == NULL)
return; /* event window is destroyed */
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))
return;
if (meta_ui_window_is_widget (screen->ui, event->xany.window))
return FALSE;
/* window may be NULL */
@@ -1339,7 +1394,7 @@ meta_display_process_key_event (MetaDisplay *display,
if (all_keys_grabbed)
{
if (display->grab_op == META_GRAB_OP_NONE)
return;
return TRUE;
/* If we get here we have a global grab, because
* we're in some special keyboard mode such as window move
* mode.
@@ -1416,18 +1471,20 @@ meta_display_process_key_event (MetaDisplay *display,
"Ending grab op %u on key event sym %s\n",
display->grab_op, XKeysymToString (keysym));
meta_display_end_grab_op (display, event->xkey.time);
return;
}
}
return TRUE;
}
handled = process_overlay_key (display, screen, event, keysym);
if (handled)
return TRUE;
/* Do the normal keybindings */
if (!handled)
process_event (display->key_bindings,
display->n_key_bindings,
display, screen, window, event, keysym,
!all_keys_grabbed && window);
return process_event (display->key_bindings,
display->n_key_bindings,
display, screen, window, event, keysym,
!all_keys_grabbed && window);
}
static gboolean
@@ -1980,6 +2037,7 @@ process_tab_grab (MetaDisplay *display,
XEvent *event,
KeySym keysym)
{
MetaKeyBinding *binding;
MetaKeyBindingAction action;
gboolean popup_not_showing;
gboolean backward;
@@ -1989,79 +2047,84 @@ process_tab_grab (MetaDisplay *display,
if (screen != display->grab_screen)
return FALSE;
action = display_get_keybinding_action (display,
keysym,
event->xkey.keycode,
display->grab_mask);
binding = display_get_keybinding (display,
keysym,
event->xkey.keycode,
display->grab_mask);
if (binding)
action = meta_prefs_get_keybinding_action (binding->name);
else
action = META_KEYBINDING_ACTION_NONE;
/*
* If there is no tab_pop up object, i.e., there is some custom handler
* implementing Alt+Tab & Co., we call this custom handler; we do not
* mess about with the grab, as that is up to the handler to deal with.
*/
if (!screen->tab_handler)
if (!screen->tab_popup)
{
MetaKeyHandler *handler = NULL;
const gchar *handler_name = NULL;
if (event->type == KeyRelease)
{
if (end_keyboard_grab (display, event->xkey.keycode))
{
invoke_handler_by_name (display, screen, "tab_popup_select", NULL, event);
/* We return FALSE to end the grab; if the handler ended the grab itself
* that will be a noop. If the handler didn't end the grab, then it's a
* safety measure to prevent a stuck grab.
*/
return FALSE;
}
return TRUE;
}
switch (action)
{
case META_KEYBINDING_ACTION_CYCLE_PANELS:
handler_name = "cycle_group";
break;
case META_KEYBINDING_ACTION_CYCLE_WINDOWS:
handler_name = "cycle_windows";
break;
case META_KEYBINDING_ACTION_CYCLE_PANELS_BACKWARD:
handler_name = "cycle_panels_backward";
break;
case META_KEYBINDING_ACTION_CYCLE_WINDOWS_BACKWARD:
handler_name = "cycle_windows_backward";
break;
case META_KEYBINDING_ACTION_SWITCH_PANELS:
handler_name = "switch_panels";
break;
case META_KEYBINDING_ACTION_SWITCH_WINDOWS:
handler_name = "switch_windows";
break;
case META_KEYBINDING_ACTION_SWITCH_PANELS_BACKWARD:
handler_name = "switch_panels_backward";
break;
case META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD:
handler_name = "switch_windows_backward";
break;
case META_KEYBINDING_ACTION_CYCLE_GROUP:
handler_name = "cycle_group";
break;
case META_KEYBINDING_ACTION_CYCLE_GROUP_BACKWARD:
handler_name = "cycle_group_backward";
break;
case META_KEYBINDING_ACTION_SWITCH_GROUP:
handler_name = "switch_group";
break;
case META_KEYBINDING_ACTION_SWITCH_GROUP_BACKWARD:
handler_name = "switch_group_backward";
break;
default:
/*
* This is the case when the Alt key is released; we preserve
* the grab, as it is up to the custom implementaiton to free it
* (a plugin can catch this in their xevent_filter function).
/* These are the tab-popup bindings. If a custom Alt-Tab implementation
* is in effect, we expect it to want to handle all of these as a group
*
* If there are some of them that the custom implementation didn't
* handle, we treat them as "unbound" for the duration - running the
* normal handlers could get us into trouble.
*/
return TRUE;
if (binding->handler &&
binding->handler->func &&
binding->handler->func != binding->handler->default_func)
{
invoke_handler (display, screen, binding->handler, NULL, event, binding);
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;
}
/*
* We do not want to actually call the handler, we just want to ensure
* that if a custom handler is installed, we do not release the grab here.
* The handler will get called as normal in the process_event() function.
*/
handler = find_handler (key_handlers, handler_name);
if (!handler || !handler->func || handler->func == handler->default_func)
return FALSE;
return TRUE;
/* Some unhandled key press */
invoke_handler_by_name (display, screen, "tab_popup_cancel", NULL, event);
return FALSE;
}
if (event->type == KeyRelease &&
@@ -2506,7 +2569,7 @@ handle_move_to_corner_backend (MetaDisplay *display,
int new_x, new_y;
int frame_width, frame_height;
meta_window_get_work_area_all_xineramas (window, &work_area);
meta_window_get_work_area_all_monitors (window, &work_area);
meta_window_get_outer_rect (window, &outer);
meta_window_get_position (window, &orig_x, &orig_y);
@@ -2638,7 +2701,7 @@ handle_move_to_center (MetaDisplay *display,
int orig_x, orig_y;
int frame_width, frame_height;
meta_window_get_work_area_all_xineramas (window, &work_area);
meta_window_get_work_area_all_monitors (window, &work_area);
meta_window_get_outer_rect (window, &outer);
meta_window_get_position (window, &orig_x, &orig_y);
@@ -2713,10 +2776,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)
{
@@ -2836,7 +2898,7 @@ handle_panel (MetaDisplay *display,
StructureNotifyMask,
(XEvent*) &ev);
meta_error_trap_pop (display, FALSE);
meta_error_trap_pop (display);
}
static void
@@ -3043,6 +3105,27 @@ handle_cycle (MetaDisplay *display,
backwards, FALSE);
}
static void
handle_tab_popup_select (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding,
gpointer dummy)
{
/* Stub for custom handlers; no default implementation */
}
static void
handle_tab_popup_cancel (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
XEvent *event,
MetaKeyBinding *binding,
gpointer dummy)
{
/* Stub for custom handlers; no default implementation */
}
static void
handle_toggle_fullscreen (MetaDisplay *display,
@@ -3462,6 +3545,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

@@ -68,13 +68,14 @@
#include <fcntl.h>
#include <locale.h>
#include <time.h>
#include <unistd.h>
#include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h>
#ifdef HAVE_INTROSPECTION
#include <girepository.h>
#include "compositor/mutter-plugin-manager.h"
#include "compositor/meta-plugin-manager.h"
#endif
/**
@@ -124,11 +125,13 @@ log_handler (const gchar *log_domain,
static void
version (void)
{
const int latest_year = 2010;
g_print (_("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"),
VERSION);
VERSION, latest_year);
exit (0);
}
@@ -226,6 +229,7 @@ typedef struct
gboolean sync;
gboolean composite;
gboolean no_composite;
gboolean no_force_fullscreen;
gboolean no_tab_popup;
gchar *introspect;
} MetaArguments;
@@ -304,6 +308,12 @@ meta_parse_options (int *argc, char ***argv,
N_("Turn compositing off"),
NULL
},
{
"no-force-fullscreen", 0, COMPOSITE_OPTS_FLAGS, G_OPTION_ARG_NONE,
&my_args.no_force_fullscreen,
N_("Don't make fullscreen windows that are maximized and have no decorations"),
NULL
},
{
"mutter-plugins", 0, 0, G_OPTION_ARG_STRING,
&my_args.mutter_plugins,
@@ -331,6 +341,7 @@ meta_parse_options (int *argc, char ***argv,
ctx = g_option_context_new (NULL);
g_option_context_add_main_entries (ctx, options, "mutter");
g_option_context_add_group (ctx, clutter_get_option_group_without_init ());
g_option_context_add_group (ctx, cogl_get_option_group ());
if (!g_option_context_parse (ctx, argc, argv, &error))
{
@@ -390,7 +401,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))
@@ -427,43 +438,37 @@ meta_select_display (gchar *display_name)
static void
meta_finalize (void)
{
meta_display_close (meta_get_display (),
CurrentTime); /* I doubt correct timestamps matter here */
MetaDisplay *display = meta_get_display ();
if (display)
meta_display_close (display,
CurrentTime); /* I doubt correct timestamps matter here */
meta_session_shutdown ();
}
static int sigterm_pipe_fds[2] = { -1, -1 };
static void
sigterm_handler (int signum)
{
meta_finalize ();
exit (meta_exit_code);
}
static guint sigchld_signal_id = 0;
static void
sigchld_handler (int signum, siginfo_t *info, void *context)
{
int stat;
if (info->si_code == CLD_EXITED)
if (sigterm_pipe_fds[1] >= 0)
{
g_signal_emit (sigchld_nexus, sigchld_signal_id, 0,
info->si_status,
GINT_TO_POINTER (info->si_pid));
int dummy;
dummy = write (sigterm_pipe_fds[1], "", 1);
close (sigterm_pipe_fds[1]);
sigterm_pipe_fds[1] = -1;
}
g_signal_handlers_disconnect_matched (sigchld_nexus,
G_SIGNAL_MATCH_DATA,
sigchld_signal_id,
0, NULL, NULL,
GINT_TO_POINTER (info->si_pid));
waitpid (info->si_pid, &stat, WNOHANG);
}
static gboolean
on_sigterm (void)
{
meta_quit (META_EXIT_SUCCESS);
return FALSE;
}
/**
* This is where the story begins. It parses commandline options and
* environment variables, sets up the screen, hands control off to
@@ -486,8 +491,9 @@ main (int argc, char **argv)
"Pango", "GLib-GObject", "GThread"
};
guint i;
GIOChannel *channel;
GOptionContext *ctx;
if (!g_thread_supported ())
g_thread_init (NULL);
@@ -509,29 +515,21 @@ main (int argc, char **argv)
g_strerror (errno));
#endif
if (pipe (sigterm_pipe_fds) != 0)
g_printerr ("Failed to create SIGTERM pipe: %s\n",
g_strerror (errno));
channel = g_io_channel_unix_new (sigterm_pipe_fds[0]);
g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
g_io_add_watch (channel, G_IO_IN, (GIOFunc) on_sigterm, NULL);
g_io_channel_set_close_on_unref (channel, TRUE);
g_io_channel_unref (channel);
act.sa_handler = &sigterm_handler;
if (sigaction (SIGTERM, &act, NULL) < 0)
g_printerr ("Failed to register SIGTERM handler: %s\n",
g_strerror (errno));
sigchld_nexus = g_object_new (META_TYPE_NEXUS, NULL);
sigchld_signal_id =
g_signal_new ("sigchld", META_TYPE_NEXUS,
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__UINT_POINTER,
G_TYPE_NONE,
2,
G_TYPE_UINT, G_TYPE_POINTER);
act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
act.sa_handler = SIG_DFL;
act.sa_sigaction = &sigchld_handler;
if (sigaction (SIGCHLD, &act, NULL) < 0)
g_printerr ("Failed to register SIGCHLD handler: %s\n",
g_strerror (errno));
if (g_getenv ("MUTTER_VERBOSE"))
meta_set_verbose (TRUE);
if (g_getenv ("MUTTER_DEBUG"))
@@ -588,8 +586,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))
@@ -625,9 +623,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);
@@ -713,6 +708,9 @@ main (int argc, char **argv)
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);
if (meta_args.no_tab_popup)
{
meta_prefs_override_no_tab_popup (TRUE);

View File

@@ -26,6 +26,7 @@
#include <config.h>
#include "boxes-private.h"
#include "place.h"
#include "workspace.h"
#include "prefs.h"
@@ -104,7 +105,7 @@ find_next_cascade (MetaWindow *window,
int window_width, window_height;
int cascade_stage;
MetaRectangle work_area;
const MetaXineramaScreenInfo* current;
const MetaMonitorInfo* current;
sorted = g_list_copy (windows);
sorted = g_list_sort (sorted, northwestcmp);
@@ -135,8 +136,8 @@ find_next_cascade (MetaWindow *window,
* of NW corner of window frame.
*/
current = meta_screen_get_current_xinerama (window->screen);
meta_window_get_work_area_for_xinerama (window, current->number, &work_area);
current = meta_screen_get_current_monitor (window->screen);
meta_window_get_work_area_for_monitor (window, current->number, &work_area);
cascade_x = MAX (0, work_area.x);
cascade_y = MAX (0, work_area.y);
@@ -257,7 +258,7 @@ find_most_freespace (MetaWindow *window,
frame_size_left = fgeom ? fgeom->left_width : 0;
frame_size_top = fgeom ? fgeom->top_height : 0;
meta_window_get_work_area_current_xinerama (focus_window, &work_area);
meta_window_get_work_area_current_monitor (focus_window, &work_area);
meta_window_get_outer_rect (focus_window, &avoid);
meta_window_get_outer_rect (window, &outer);
@@ -508,7 +509,7 @@ find_first_fit (MetaWindow *window,
MetaFrameGeometry *fgeom,
/* visible windows on relevant workspaces */
GList *windows,
int xinerama,
int monitor,
int x,
int y,
int *new_x,
@@ -551,16 +552,16 @@ find_first_fit (MetaWindow *window,
#ifdef WITH_VERBOSE_MODE
{
char xinerama_location_string[RECT_LENGTH];
meta_rectangle_to_string (&window->screen->xinerama_infos[xinerama].rect,
xinerama_location_string);
char monitor_location_string[RECT_LENGTH];
meta_rectangle_to_string (&window->screen->monitor_infos[monitor].rect,
monitor_location_string);
meta_topic (META_DEBUG_XINERAMA,
"Natural xinerama is %s\n",
xinerama_location_string);
"Natural monitor is %s\n",
monitor_location_string);
}
#endif
meta_window_get_work_area_for_xinerama (window, xinerama, &work_area);
meta_window_get_work_area_for_monitor (window, monitor, &work_area);
center_tile_rect_in_area (&rect, &work_area);
@@ -658,7 +659,7 @@ meta_window_place (MetaWindow *window,
int *new_y)
{
GList *windows;
const MetaXineramaScreenInfo *xi;
const MetaMonitorInfo *xi;
/* frame member variables should NEVER be used in here, only
* MetaFrameGeometry. But remember fgeom == NULL
@@ -810,11 +811,11 @@ meta_window_place (MetaWindow *window,
window->type == META_WINDOW_MODAL_DIALOG ||
window->type == META_WINDOW_SPLASHSCREEN)
{
/* Center on current xinerama (i.e. on current monitor) */
/* Center on current monitor */
int w, h;
/* Warning, this function is a round trip! */
xi = meta_screen_get_current_xinerama (window->screen);
xi = meta_screen_get_current_monitor (window->screen);
w = xi->rect.width;
h = xi->rect.height;
@@ -825,7 +826,7 @@ meta_window_place (MetaWindow *window,
x += xi->rect.x;
y += xi->rect.y;
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on screen %d xinerama %d\n",
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on screen %d monitor %d\n",
window->desc, window->screen->number, xi->number);
goto done_check_denied_focus;
@@ -859,7 +860,7 @@ meta_window_place (MetaWindow *window,
}
/* Warning, this is a round trip! */
xi = meta_screen_get_current_xinerama (window->screen);
xi = meta_screen_get_current_monitor (window->screen);
/* "Origin" placement algorithm */
x = xi->rect.x;
@@ -880,9 +881,9 @@ meta_window_place (MetaWindow *window,
MetaRectangle workarea;
MetaRectangle outer;
meta_window_get_work_area_for_xinerama (window,
xi->number,
&workarea);
meta_window_get_work_area_for_monitor (window,
xi->number,
&workarea);
meta_window_get_outer_rect (window, &outer);
/* If the window is bigger than the screen, then automaximize. Do NOT

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
@@ -52,6 +53,7 @@
#define KEY_COMPOSITOR "/apps/metacity/general/compositing_manager"
#define KEY_GNOME_ACCESSIBILITY "/desktop/gnome/interface/accessibility"
#define KEY_COMMAND_DIRECTORY "/apps/metacity/keybinding_commands"
#define KEY_COMMAND_PREFIX "/apps/metacity/keybinding_commands/command_"
#define KEY_TERMINAL_DIR "/desktop/gnome/applications/terminal"
@@ -62,6 +64,7 @@
#define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings"
#define KEY_LIST_BINDINGS_SUFFIX "_list"
#define KEY_WORKSPACE_NAME_DIRECTORY "/apps/metacity/workspace_names"
#define KEY_WORKSPACE_NAME_PREFIX "/apps/metacity/workspace_names/name_"
#define KEY_CLUTTER_PLUGINS "/apps/mutter/general/clutter_plugins"
@@ -83,6 +86,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,6 +104,8 @@ static char *cursor_theme = NULL;
static int cursor_size = 24;
static gboolean compositing_manager = FALSE;
static gboolean resize_with_right_button = FALSE;
static gboolean side_by_side_tiling = FALSE;
static gboolean force_fullscreen = TRUE;
static MetaVisualBellType visual_bell_type = META_VISUAL_BELL_FULLSCREEN_FLASH;
static MetaButtonLayout button_layout;
@@ -121,18 +127,30 @@ static gboolean no_tab_popup = FALSE;
#ifdef HAVE_GCONF
static gboolean handle_preference_update_enum (const gchar *key, GConfValue *value);
static gboolean update_key_binding (const char *name,
static char *binding_name (const char *gconf_key);
static gboolean update_key_binding (const char *key,
const char *value);
static gboolean find_and_update_list_binding (MetaKeyPref *bindings,
const char *name,
GSList *value);
static gboolean update_key_list_binding (const char *name,
GSList *value);
typedef enum
{
META_LIST_OF_STRINGS,
META_LIST_OF_GCONFVALUE_STRINGS
} MetaStringListType;
static gboolean find_and_update_list_binding (MetaKeyPref *bindings,
const char *key,
GSList *value,
MetaStringListType type_of_value);
static gboolean update_key_list_binding (const char *key,
GSList *value,
MetaStringListType type_of_value);
static gboolean update_command (const char *name,
const char *value);
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,
@@ -142,14 +160,8 @@ static char* gconf_key_for_workspace_name (int i);
static void queue_changed (MetaPreference pref);
typedef enum
{
META_LIST_OF_STRINGS,
META_LIST_OF_GCONFVALUE_STRINGS
} MetaStringListType;
static gboolean update_list_binding (MetaKeyPref *binding,
GSList *value,
static gboolean update_list_binding (MetaKeyPref *binding,
GSList *value,
MetaStringListType type_of_value);
static void cleanup_error (GError **error);
@@ -221,7 +233,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.
@@ -234,21 +251,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
{
@@ -361,6 +363,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,
@@ -416,6 +423,11 @@ static MetaBoolPreference preferences_bool[] =
&resize_with_right_button,
FALSE,
},
{ "/apps/metacity/general/side_by_side_tiling",
META_PREF_SIDE_BY_SIDE_TILING,
&side_by_side_tiling,
FALSE,
},
{ "/apps/mutter/general/live_hidden_windows",
META_PREF_LIVE_HIDDEN_WINDOWS,
&live_hidden_windows,
@@ -489,6 +501,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)
{
@@ -872,6 +898,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)
@@ -885,6 +915,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)
@@ -1024,6 +1058,7 @@ meta_prefs_init (void)
#ifdef HAVE_GCONF
GError *err = NULL;
gchar **gconf_dir_cursor;
MetaPluginManager *plugin_manager;
if (default_client != NULL)
return;
@@ -1042,12 +1077,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,
@@ -1055,6 +1085,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;
@@ -1087,6 +1129,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. */
@@ -1102,6 +1298,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,
@@ -1110,25 +1323,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))
@@ -1146,7 +1347,7 @@ change_notify (GConfClient *client,
list = value ? gconf_value_get_list (value) : NULL;
if (update_key_list_binding (key, list))
if (update_key_list_binding (key, list, META_LIST_OF_GCONFVALUE_STRINGS))
queue_changed (META_PREF_KEYBINDINGS);
}
else
@@ -1304,6 +1505,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)
{
@@ -1725,6 +1932,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";
@@ -1800,6 +2010,12 @@ meta_preference_to_string (MetaPreference pref)
case META_PREF_RESIZE_WITH_RIGHT_BUTTON:
return "RESIZE_WITH_RIGHT_BUTTON";
case META_PREF_SIDE_BY_SIDE_TILING:
return "SIDE_BY_SIDE_TILING";
case META_PREF_FORCE_FULLSCREEN:
return "FORCE_FULLSCREEN";
case META_PREF_CLUTTER_PLUGINS:
return "CLUTTER_PLUGINS";
@@ -1888,57 +2104,66 @@ init_special_bindings (void)
static void
init_bindings (void)
{
#ifdef HAVE_GCONF
int i = 0;
GError *err;
#ifdef HAVE_GCONF
const char *prefix[] = {
KEY_WINDOW_BINDINGS_PREFIX,
KEY_SCREEN_BINDINGS_PREFIX,
NULL
};
int i;
GSList *list, *l, *list_val;
const char *str_val;
const char *key;
GConfEntry *entry;
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++)
{
list = gconf_client_all_entries (default_client, prefix[i], NULL);
for (l = list; l; l = l->next)
{
entry = l->data;
key = gconf_entry_get_key (entry);
value = gconf_entry_get_value (entry);
if (g_str_has_suffix (key, KEY_LIST_BINDINGS_SUFFIX))
{
/* List bindings are used in addition to the normal bindings and never
* have defaults, so we just go ahead and set them immediately; there
* will be only a few of them, so don't worry about the linear scan
* in find_and_update_list_binding.
*/
list_val = gconf_client_get_list (default_client, key, GCONF_VALUE_STRING, NULL);
update_key_list_binding (key, list_val, META_LIST_OF_STRINGS);
g_slist_foreach (list_val, (GFunc)g_free, NULL);
g_slist_free (list_val);
}
else
{
str_val = gconf_value_get_string (value);
g_hash_table_insert (to_update, binding_name (key), g_strdup (str_val));
}
gconf_entry_free (entry);
}
g_slist_free (list);
}
i = 0;
while (key_bindings[i].name)
{
GSList *list_val, *tmp;
char *str_val;
char *key;
key = g_strconcat (key_bindings[i].per_window?
KEY_WINDOW_BINDINGS_PREFIX:
KEY_SCREEN_BINDINGS_PREFIX,
"/",
key_bindings[i].name, NULL);
err = NULL;
str_val = gconf_client_get_string (default_client, key, &err);
cleanup_error (&err);
update_binding (&key_bindings[i], str_val);
g_free (str_val);
g_free (key);
key = g_strconcat (key_bindings[i].per_window?
KEY_WINDOW_BINDINGS_PREFIX:
KEY_SCREEN_BINDINGS_PREFIX,
"/",
key_bindings[i].name,
KEY_LIST_BINDINGS_SUFFIX, NULL);
err = NULL;
list_val = gconf_client_get_list (default_client, key, GCONF_VALUE_STRING, &err);
cleanup_error (&err);
update_list_binding (&key_bindings[i], list_val, META_LIST_OF_STRINGS);
tmp = list_val;
while (tmp)
{
g_free (tmp->data);
tmp = tmp->next;
}
g_slist_free (list_val);
g_free (key);
update_binding (&key_bindings[i],
g_hash_table_lookup (to_update, key_bindings[i].name));
++i;
}
g_hash_table_destroy (to_update);
#else /* HAVE_GCONF */
int i = 0;
while (key_bindings[i].name)
@@ -1960,28 +2185,23 @@ static void
init_commands (void)
{
#ifdef HAVE_GCONF
int i;
GError *err;
i = 0;
while (i < MAX_COMMANDS)
GSList *list, *l;
const char *str_val;
const char *key;
GConfEntry *entry;
GConfValue *value;
list = gconf_client_all_entries (default_client, KEY_COMMAND_DIRECTORY, NULL);
for (l = list; l; l = l->next)
{
char *str_val;
char *key;
key = meta_prefs_get_gconf_key_for_command (i);
err = NULL;
str_val = gconf_client_get_string (default_client, key, &err);
cleanup_error (&err);
entry = l->data;
key = gconf_entry_get_key (entry);
value = gconf_entry_get_value (entry);
str_val = gconf_value_get_string (value);
update_command (key, str_val);
g_free (str_val);
g_free (key);
++i;
gconf_entry_free (entry);
}
g_slist_free (list);
#else
int i;
for (i = 0; i < MAX_COMMANDS; i++)
@@ -1992,39 +2212,34 @@ init_commands (void)
static void
init_workspace_names (void)
{
int i;
#ifdef HAVE_GCONF
int i;
GError *err;
i = 0;
while (i < MAX_REASONABLE_WORKSPACES)
GSList *list, *l;
const char *str_val;
const char *key;
GConfEntry *entry;
GConfValue *value;
list = gconf_client_all_entries (default_client, KEY_WORKSPACE_NAME_DIRECTORY, NULL);
for (l = list; l; l = l->next)
{
char *str_val;
char *key;
key = gconf_key_for_workspace_name (i);
err = NULL;
str_val = gconf_client_get_string (default_client, key, &err);
cleanup_error (&err);
entry = l->data;
key = gconf_entry_get_key (entry);
value = gconf_entry_get_value (entry);
str_val = gconf_value_get_string (value);
update_workspace_name (key, str_val);
g_assert (workspace_names[i] != NULL);
g_free (str_val);
g_free (key);
++i;
gconf_entry_free (entry);
}
#else
int i;
g_slist_free (list);
#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
@@ -2275,16 +2490,22 @@ update_list_binding (MetaKeyPref *binding,
return changed;
}
static const gchar*
relative_key (const gchar* key)
static char *
binding_name (const char *gconf_key)
{
const gchar* end;
end = strrchr (key, '/');
const char *start, *end;
++end;
if (*gconf_key == '/')
start = strrchr (gconf_key, '/') + 1;
else
start = gconf_key;
return end;
if (g_str_has_suffix (gconf_key, KEY_LIST_BINDINGS_SUFFIX))
end = gconf_key + strlen(gconf_key) - strlen (KEY_LIST_BINDINGS_SUFFIX);
else
end = gconf_key + strlen(gconf_key);
return g_strndup (start, end - start);
}
/* Return value is TRUE if a preference changed and we need to
@@ -2292,22 +2513,19 @@ relative_key (const gchar* key)
*/
static gboolean
find_and_update_binding (MetaKeyPref *bindings,
const char *name,
const char *key,
const char *value)
{
const char *key;
char *name = binding_name (key);
int i;
if (*name == '/')
key = relative_key (name);
else
key = name;
i = 0;
while (bindings[i].name &&
strcmp (key, bindings[i].name) != 0)
strcmp (name, bindings[i].name) != 0)
++i;
g_free (name);
if (bindings[i].name)
return update_binding (&bindings[i], value);
else
@@ -2315,46 +2533,40 @@ find_and_update_binding (MetaKeyPref *bindings,
}
static gboolean
update_key_binding (const char *name,
const char *value)
update_key_binding (const char *key,
const char *value)
{
return find_and_update_binding (key_bindings, name, value);
return find_and_update_binding (key_bindings, key, value);
}
static gboolean
find_and_update_list_binding (MetaKeyPref *bindings,
const char *name,
GSList *value)
find_and_update_list_binding (MetaKeyPref *bindings,
const char *key,
GSList *value,
MetaStringListType type_of_value)
{
const char *key;
char *name = binding_name (key);
int i;
gchar *name_without_suffix = g_strdup(name);
name_without_suffix[strlen(name_without_suffix) - strlen(KEY_LIST_BINDINGS_SUFFIX)] = 0;
if (*name_without_suffix == '/')
key = relative_key (name_without_suffix);
else
key = name_without_suffix;
i = 0;
while (bindings[i].name &&
strcmp (key, bindings[i].name) != 0)
strcmp (name, bindings[i].name) != 0)
++i;
g_free (name_without_suffix);
g_free (name);
if (bindings[i].name)
return update_list_binding (&bindings[i], value, META_LIST_OF_GCONFVALUE_STRINGS);
return update_list_binding (&bindings[i], value, type_of_value);
else
return FALSE;
}
static gboolean
update_key_list_binding (const char *name,
GSList *value)
update_key_list_binding (const char *key,
GSList *value,
MetaStringListType type_of_value)
{
return find_and_update_list_binding (key_bindings, name, value);
return find_and_update_list_binding (key_bindings, key, value, type_of_value);
}
static gboolean
@@ -2713,6 +2925,12 @@ meta_prefs_get_gnome_animations ()
return gnome_animations;
}
gboolean
meta_prefs_get_side_by_side_tiling ()
{
return side_by_side_tiling;
}
MetaKeyBindingAction
meta_prefs_get_keybinding_action (const char *name)
{
@@ -2792,6 +3010,12 @@ meta_prefs_get_mouse_button_menu (void)
return resize_with_right_button ? 2: 3;
}
gboolean
meta_prefs_get_force_fullscreen (void)
{
return force_fullscreen;
}
void
meta_prefs_set_compositing_manager (gboolean whether)
{
@@ -2814,6 +3038,11 @@ meta_prefs_set_compositing_manager (gboolean whether)
#endif
}
/**
* meta_prefs_get_clutter_plugins:
*
* Returns: (transfer none) (element-type utf8): Plugin names to load
*/
GSList *
meta_prefs_get_clutter_plugins (void)
{
@@ -2823,6 +3052,7 @@ meta_prefs_get_clutter_plugins (void)
void
meta_prefs_set_clutter_plugins (GSList *list)
{
#ifdef HAVE_GCONF
GError *err = NULL;
gconf_client_set_list (default_client,
@@ -2837,6 +3067,7 @@ meta_prefs_set_clutter_plugins (GSList *list)
err->message);
g_error_free (err);
}
#endif
}
void
@@ -2957,3 +3188,10 @@ init_button_layout(void)
};
#endif
void
meta_prefs_set_force_fullscreen (gboolean whether)
{
force_fullscreen = whether;
}

View File

@@ -37,12 +37,11 @@
#include "screen.h"
#include <X11/Xutil.h>
#include "stack-tracker.h"
#include "alttabhandler.h"
#include "ui.h"
typedef struct _MetaXineramaScreenInfo MetaXineramaScreenInfo;
typedef struct _MetaMonitorInfo MetaMonitorInfo;
struct _MetaXineramaScreenInfo
struct _MetaMonitorInfo
{
int number;
MetaRectangle rect;
@@ -82,9 +81,11 @@ struct _MetaScreen
Visual *default_xvisual;
MetaRectangle rect; /* Size of screen; rect.x & rect.y are always 0 */
MetaUI *ui;
MetaAltTabHandler *tab_handler;
MetaTabPopup *ws_popup;
MetaTabPopup *tab_popup, *ws_popup;
MetaTilePreview *tile_preview;
guint tile_preview_timeout_id;
MetaWorkspace *active_workspace;
/* This window holds the focus when we don't want to focus
@@ -105,11 +106,11 @@ struct _MetaScreen
Atom wm_sn_atom;
guint32 wm_sn_timestamp;
MetaXineramaScreenInfo *xinerama_infos;
int n_xinerama_infos;
MetaMonitorInfo *monitor_infos;
int n_monitor_infos;
/* Cache the current Xinerama */
int last_xinerama_index;
/* Cache the current monitor */
int last_monitor_index;
#ifdef HAVE_STARTUP_NOTIFICATION
SnMonitorContext *sn_context;
@@ -118,8 +119,9 @@ struct _MetaScreen
#endif
Window wm_cm_selection_window;
guint32 wm_cm_timestamp;
guint work_area_idle;
guint work_area_later;
int rows_of_workspaces;
int columns_of_workspaces;
@@ -131,9 +133,6 @@ struct _MetaScreen
int closing;
/* gc for XOR on root window */
GC root_xor_gc;
/* Managed by compositor.c */
gpointer compositor_data;
@@ -147,7 +146,8 @@ struct _MetaScreenClass
{
GObjectClass parent_class;
void (*restacked) (MetaScreen *);
void (*restacked) (MetaScreen *);
void (*workareas_changed) (MetaScreen *);
};
MetaScreen* meta_screen_new (MetaDisplay *display,
@@ -182,22 +182,25 @@ 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);
const MetaXineramaScreenInfo* meta_screen_get_current_xinerama (MetaScreen *screen);
const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_rect (MetaScreen *screen,
MetaRectangle *rect);
const MetaXineramaScreenInfo* meta_screen_get_xinerama_for_window (MetaScreen *screen,
MetaWindow *window);
const MetaMonitorInfo* meta_screen_get_current_monitor (MetaScreen *screen);
const MetaMonitorInfo* meta_screen_get_monitor_for_rect (MetaScreen *screen,
MetaRectangle *rect);
const MetaMonitorInfo* meta_screen_get_monitor_for_window (MetaScreen *screen,
MetaWindow *window);
const MetaXineramaScreenInfo* meta_screen_get_xinerama_neighbor (MetaScreen *screen,
int which_xinerama,
MetaScreenDirection dir);
void meta_screen_get_natural_xinerama_list (MetaScreen *screen,
int** xineramas_list,
int* n_xineramas);
const MetaMonitorInfo* meta_screen_get_monitor_neighbor (MetaScreen *screen,
int which_monitor,
MetaScreenDirection dir);
void meta_screen_get_natural_monitor_list (MetaScreen *screen,
int** monitors_list,
int* n_monitors);
void meta_screen_update_workspace_layout (MetaScreen *screen);
void meta_screen_update_workspace_names (MetaScreen *screen);

File diff suppressed because it is too large Load Diff

View File

@@ -29,6 +29,7 @@
#include <X11/Xatom.h>
#include <time.h>
#include <sys/wait.h>
#ifndef HAVE_SM
void
@@ -83,6 +84,7 @@ static char* load_state (const char *previous_save_file);
static void regenerate_save_file (void);
static const char* full_save_file (void);
static void warn_about_lame_clients_and_finish_interact (gboolean shutdown);
static void disconnect (void);
/* This is called when data is available on an ICE connection. */
static gboolean
@@ -105,9 +107,12 @@ process_ice_messages (GIOChannel *channel,
IcePointer context = IceGetConnectionContext (connection);
#endif
/* We were disconnected */
IceSetShutdownNegotiation (connection, False);
IceCloseConnection (connection);
/* We were disconnected; close our connection to the
* session manager, this will result in the ICE connection
* being cleaned up, since it is owned by libSM.
*/
disconnect ();
meta_quit (META_EXIT_SUCCESS);
return FALSE;
}
@@ -1104,8 +1109,6 @@ load_state (const char *previous_save_file)
{
/* oh, just give up */
meta_warning (_("Failed to read saved session file %s: %s\n"),
canonical_session_file, error->message);
g_error_free (error);
g_free (session_file);
g_free (canonical_session_file);
@@ -1749,11 +1752,11 @@ finish_interact (gboolean shutdown)
}
static void
sigchld_handler (MetaNexus *nexus, guint arg1, gpointer arg2, gpointer user_data)
dialog_closed (GPid pid, int status, gpointer user_data)
{
gboolean shutdown = GPOINTER_TO_INT (user_data);
if (arg1 == 0) /* pressed "OK" */
if (WIFEXITED (status) && WEXITSTATUS (status) == 0) /* pressed "OK" */
{
finish_interact (shutdown);
}
@@ -1767,6 +1770,7 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown)
GSList *lame_details = NULL;
GSList *tmp;
GSList *columns = NULL;
GPid pid;
windows = meta_display_list_windows (meta_get_display (), META_LIST_DEFAULT);
tmp = windows;
@@ -1814,23 +1818,20 @@ warn_about_lame_clients_and_finish_interact (gboolean shutdown)
}
g_slist_free (lame);
meta_show_dialog("--list",
_("These windows do not support &quot;save current setup&quot; "
"and will have to be restarted manually next time "
"you log in."),
"240",
meta_screen_get_screen_number (meta_get_display()->active_screen),
NULL, NULL,
None,
columns,
lame_details);
pid = meta_show_dialog("--list",
_("These windows do not support &quot;save current setup&quot; "
"and will have to be restarted manually next time "
"you log in."),
"240",
meta_screen_get_screen_number (meta_get_display()->active_screen),
NULL, NULL,
None,
columns,
lame_details);
g_slist_free (lame_details);
g_signal_connect (sigchld_nexus, "sigchld",
G_CALLBACK (sigchld_handler),
GINT_TO_POINTER (shutdown));
g_child_watch_add (pid, dialog_closed, GINT_TO_POINTER (shutdown));
}
#endif /* HAVE_SM */

View File

@@ -23,6 +23,7 @@
#include <string.h>
#include "frame-private.h"
#include "screen-private.h"
#include "stack-tracker.h"
#include "util.h"
@@ -134,7 +135,7 @@ struct _MetaStackTracker
/* Idle function used to sync the compositor's view of the window
* stack up with our best guess before a frame is drawn.
*/
guint sync_stack_idle;
guint sync_stack_later;
};
static void
@@ -383,8 +384,8 @@ meta_stack_tracker_new (MetaScreen *screen)
void
meta_stack_tracker_free (MetaStackTracker *tracker)
{
if (tracker->sync_stack_idle)
g_source_remove (tracker->sync_stack_idle);
if (tracker->sync_stack_later)
meta_later_remove (tracker->sync_stack_later);
g_array_free (tracker->server_stack, TRUE);
if (tracker->predicted_stack)
@@ -667,10 +668,10 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
int n_windows;
int i;
if (tracker->sync_stack_idle)
if (tracker->sync_stack_later)
{
g_source_remove (tracker->sync_stack_idle);
tracker->sync_stack_idle = 0;
meta_later_remove (tracker->sync_stack_later);
tracker->sync_stack_later = 0;
}
meta_stack_tracker_get_stack (tracker, &windows, &n_windows);
@@ -682,7 +683,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);
}
@@ -696,7 +705,7 @@ meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
}
static gboolean
stack_tracker_sync_stack_idle (gpointer data)
stack_tracker_sync_stack_later (gpointer data)
{
meta_stack_tracker_sync_stack (data);
@@ -719,10 +728,10 @@ stack_tracker_sync_stack_idle (gpointer data)
void
meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker)
{
if (tracker->sync_stack_idle == 0)
if (tracker->sync_stack_later == 0)
{
tracker->sync_stack_idle = g_idle_add_full (META_PRIORITY_BEFORE_REDRAW,
stack_tracker_sync_stack_idle,
tracker->sync_stack_later = meta_later_add (META_LATER_BEFORE_REDRAW,
stack_tracker_sync_stack_later,
tracker, NULL);
}
}

View File

@@ -224,14 +224,14 @@ is_focused_foreach (MetaWindow *window,
}
static gboolean
windows_on_different_xinerama (MetaWindow *a,
MetaWindow *b)
windows_on_different_monitor (MetaWindow *a,
MetaWindow *b)
{
if (a->screen != b->screen)
return TRUE;
return meta_screen_get_xinerama_for_window (a->screen, a) !=
meta_screen_get_xinerama_for_window (b->screen, b);
return meta_screen_get_monitor_for_window (a->screen, a) !=
meta_screen_get_monitor_for_window (b->screen, b);
}
/* Get layer ignoring any transient or group relationships */
@@ -275,8 +275,8 @@ get_standalone_layer (MetaWindow *window)
window == window->display->expected_focus_window ||
window->display->expected_focus_window == NULL ||
(window->display->expected_focus_window != NULL &&
windows_on_different_xinerama (window,
window->display->expected_focus_window))))
windows_on_different_monitor (window,
window->display->expected_focus_window))))
layer = META_LAYER_FULLSCREEN;
else if (window->wm_state_above)
layer = META_LAYER_TOP;
@@ -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>
@@ -85,7 +85,7 @@ new_screen_edge (int x, int y, int width, int height, int side_type)
}
static MetaEdge*
new_xinerama_edge (int x, int y, int width, int height, int side_type)
new_monitor_edge (int x, int y, int width, int height, int side_type)
{
MetaEdge* temporary;
temporary = g_new (MetaEdge, 1);
@@ -94,7 +94,7 @@ new_xinerama_edge (int x, int y, int width, int height, int side_type)
temporary->rect.width = width;
temporary->rect.height = height;
temporary->side_type = side_type;
temporary->edge_type = META_EDGE_XINERAMA;
temporary->edge_type = META_EDGE_MONITOR;
return temporary;
}
@@ -317,15 +317,15 @@ get_screen_edges (int which)
}
static GList*
get_xinerama_edges (int which_xinerama_set, int which_strut_set)
get_monitor_edges (int which_monitor_set, int which_strut_set)
{
GList *ret;
GSList *struts;
GList *xins;
xins = NULL;
g_assert (which_xinerama_set >=0 && which_xinerama_set <= 3);
switch (which_xinerama_set)
g_assert (which_monitor_set >=0 && which_monitor_set <= 3);
switch (which_monitor_set)
{
case 0:
xins = g_list_prepend (xins, new_meta_rect ( 0, 0, 1600, 1200));
@@ -348,7 +348,7 @@ get_xinerama_edges (int which_xinerama_set, int which_strut_set)
ret = NULL;
struts = get_strut_list (which_strut_set);
ret = meta_rectangle_find_nonintersected_xinerama_edges (xins, struts);
ret = meta_rectangle_find_nonintersected_monitor_edges (xins, struts);
free_strut_list (struts);
meta_rectangle_free_list_and_elements (xins);
@@ -1145,7 +1145,7 @@ test_find_onscreen_edges ()
}
static void
test_find_nonintersected_xinerama_edges ()
test_find_nonintersected_monitor_edges ()
{
GList* edges;
GList* tmp;
@@ -1156,32 +1156,32 @@ test_find_nonintersected_xinerama_edges ()
int bottom = META_DIRECTION_BOTTOM;
/*************************************************************************/
/* Make sure test xinerama set 0 for with region 0 has the correct edges */
/* Make sure test monitor set 0 for with region 0 has the correct edges */
/*************************************************************************/
edges = get_xinerama_edges (0, 0);
edges = get_monitor_edges (0, 0);
tmp = NULL;
verify_edge_lists_are_equal (edges, tmp);
meta_rectangle_free_list_and_elements (tmp);
meta_rectangle_free_list_and_elements (edges);
/*************************************************************************/
/* Make sure test xinerama set 2 for with region 1 has the correct edges */
/* Make sure test monitor set 2 for with region 1 has the correct edges */
/*************************************************************************/
edges = get_xinerama_edges (2, 1);
edges = get_monitor_edges (2, 1);
tmp = NULL;
tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 1600, 0, bottom));
tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 1600, 0, top));
tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 1600, 0, bottom));
tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 1600, 0, top));
verify_edge_lists_are_equal (edges, tmp);
meta_rectangle_free_list_and_elements (tmp);
meta_rectangle_free_list_and_elements (edges);
/*************************************************************************/
/* Make sure test xinerama set 1 for with region 2 has the correct edges */
/* Make sure test monitor set 1 for with region 2 has the correct edges */
/*************************************************************************/
edges = get_xinerama_edges (1, 2);
edges = get_monitor_edges (1, 2);
tmp = NULL;
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 20, 0, 1080, right));
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 20, 0, 1180, left));
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 20, 0, 1080, right));
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 20, 0, 1180, left));
#if 0
#define FUDGE 50
char big_buffer1[(EDGE_LENGTH+2)*FUDGE], big_buffer2[(EDGE_LENGTH+2)*FUDGE];
@@ -1195,36 +1195,36 @@ test_find_nonintersected_xinerama_edges ()
meta_rectangle_free_list_and_elements (edges);
/*************************************************************************/
/* Make sure test xinerama set 3 for with region 3 has the correct edges */
/* Make sure test monitor set 3 for with region 3 has the correct edges */
/*************************************************************************/
edges = get_xinerama_edges (3, 3);
edges = get_monitor_edges (3, 3);
tmp = NULL;
tmp = g_list_prepend (tmp, new_xinerama_edge ( 900, 600, 700, 0, bottom));
tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 700, 0, bottom));
tmp = g_list_prepend (tmp, new_xinerama_edge ( 900, 600, 700, 0, top));
tmp = g_list_prepend (tmp, new_xinerama_edge ( 0, 600, 700, 0, top));
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 675, 0, 425, right));
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 675, 0, 525, left));
tmp = g_list_prepend (tmp, new_monitor_edge ( 900, 600, 700, 0, bottom));
tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 700, 0, bottom));
tmp = g_list_prepend (tmp, new_monitor_edge ( 900, 600, 700, 0, top));
tmp = g_list_prepend (tmp, new_monitor_edge ( 0, 600, 700, 0, top));
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 675, 0, 425, right));
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 675, 0, 525, left));
verify_edge_lists_are_equal (edges, tmp);
meta_rectangle_free_list_and_elements (tmp);
meta_rectangle_free_list_and_elements (edges);
/*************************************************************************/
/* Make sure test xinerama set 3 for with region 4 has the correct edges */
/* Make sure test monitor set 3 for with region 4 has the correct edges */
/*************************************************************************/
edges = get_xinerama_edges (3, 4);
edges = get_monitor_edges (3, 4);
tmp = NULL;
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 600, 800, 0, bottom));
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 600, 800, 0, top));
tmp = g_list_prepend (tmp, new_xinerama_edge ( 800, 600, 0, 600, right));
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 600, 800, 0, bottom));
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 600, 800, 0, top));
tmp = g_list_prepend (tmp, new_monitor_edge ( 800, 600, 0, 600, right));
verify_edge_lists_are_equal (edges, tmp);
meta_rectangle_free_list_and_elements (tmp);
meta_rectangle_free_list_and_elements (edges);
/*************************************************************************/
/* Make sure test xinerama set 3 for with region 5has the correct edges */
/* Make sure test monitor set 3 for with region 5has the correct edges */
/*************************************************************************/
edges = get_xinerama_edges (3, 5);
edges = get_monitor_edges (3, 5);
tmp = NULL;
verify_edge_lists_are_equal (edges, tmp);
meta_rectangle_free_list_and_elements (tmp);
@@ -1405,7 +1405,7 @@ main()
/* And now the functions dealing with edges more than boxes */
test_find_onscreen_edges ();
test_find_nonintersected_xinerama_edges ();
test_find_nonintersected_monitor_edges ();
/* And now the misfit functions that don't quite fit in anywhere else... */
test_gravity_resize ();

View File

@@ -26,9 +26,12 @@
#define _POSIX_C_SOURCE 200112L /* for fdopen() */
#include <config.h>
#include "common.h"
#include "util.h"
#include "main.h"
#include <clutter/clutter.h> /* For clutter_threads_add_repaint_func() */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@@ -37,7 +40,12 @@
#include <X11/Xlib.h> /* must explicitly be included for Solaris; #326746 */
#include <X11/Xutil.h> /* Just for the definition of the various gravities */
MetaNexus *sigchld_nexus;
#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>
@@ -70,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;
@@ -127,7 +135,7 @@ ensure_logfile (void)
gboolean
meta_is_verbose (void)
{
return is_verbose;
return verbose_topics != 0;
}
void
@@ -140,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
@@ -249,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 */
@@ -323,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";
@@ -330,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;
@@ -365,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
@@ -557,7 +601,7 @@ meta_show_dialog (const char *type,
int i=0;
GPid child_pid;
const char **argvl = g_malloc(sizeof (char*) *
(15 +
(17 +
g_slist_length (columns)*2 +
g_slist_length (entries)));
@@ -565,6 +609,8 @@ meta_show_dialog (const char *type,
argvl[i++] = type;
argvl[i++] = "--screen";
argvl[i++] = screen_number_text;
argvl[i++] = "--class";
argvl[i++] = "mutter-dialog";
argvl[i++] = "--title";
/* Translators: This is the title used on dialog boxes */
argvl[i++] = _("Mutter");
@@ -638,29 +684,200 @@ meta_show_dialog (const char *type,
return child_pid;
}
GType
meta_nexus_get_type (void)
/***************************************************************************
* Later functions: like idles but integrated with the Clutter repaint loop
***************************************************************************/
static guint last_later_id = 0;
typedef struct
{
static GType nexus_type = 0;
guint id;
MetaLaterType when;
GSourceFunc func;
gpointer data;
GDestroyNotify notify;
int source;
gboolean run_once;
} MetaLater;
if (!nexus_type)
static GSList *laters = NULL;
/* This is a dummy timeline used to get the Clutter master clock running */
static ClutterTimeline *later_timeline;
static guint later_repaint_func = 0;
static void ensure_later_repaint_func (void);
static void
destroy_later (MetaLater *later)
{
if (later->source)
g_source_remove (later->source);
if (later->notify)
later->notify (later->data);
g_slice_free (MetaLater, later);
}
/* Used to sort the list of laters with the highest priority
* functions first.
*/
static int
compare_laters (gconstpointer a,
gconstpointer b)
{
return ((const MetaLater *)a)->when - ((const MetaLater *)b)->when;
}
static gboolean
run_repaint_laters (gpointer data)
{
GSList *old_laters = laters;
GSList *l;
gboolean keep_timeline_running = FALSE;
laters = NULL;
for (l = old_laters; l; l = l->next)
{
static const GTypeInfo nexus_info =
{
sizeof (MetaNexusClass),
NULL, NULL, NULL, NULL, NULL,
sizeof (MetaNexus),
0,
NULL, NULL
};
nexus_type = g_type_register_static (G_TYPE_OBJECT,
"MetaNexus",
&nexus_info,
0);
MetaLater *later = l->data;
if (later->source == 0 ||
(later->when <= META_LATER_BEFORE_REDRAW && !later->run_once))
{
if (later->func (later->data))
{
if (later->source == 0)
keep_timeline_running = TRUE;
laters = g_slist_insert_sorted (laters, later, compare_laters);
}
else
destroy_later (later);
}
else
laters = g_slist_insert_sorted (laters, later, compare_laters);
}
return nexus_type;
if (!keep_timeline_running)
clutter_timeline_stop (later_timeline);
g_slist_free (old_laters);
/* Just keep the repaint func around - it's cheap if the list is empty */
return TRUE;
}
static void
ensure_later_repaint_func (void)
{
if (!later_timeline)
later_timeline = clutter_timeline_new (G_MAXUINT);
if (later_repaint_func == 0)
later_repaint_func = clutter_threads_add_repaint_func (run_repaint_laters,
NULL, NULL);
/* Make sure the repaint function gets run */
clutter_timeline_start (later_timeline);
}
static gboolean
call_idle_later (gpointer data)
{
MetaLater *later = data;
if (!later->func (later->data))
{
laters = g_slist_remove (laters, later);
later->source = 0;
destroy_later (later);
return FALSE;
}
else
{
later->run_once = TRUE;
return TRUE;
}
}
/**
* meta_later_add:
* @when: enumeration value determining the phase at which to run the callback
* @func: callback to run later
* @data: data to pass to the callback
* @notify: function to call to destroy @data when it is no longer in use, or %NULL
*
* Sets up a callback to be called at some later time. @when determines the
* particular later occasion at which it is called. This is much like g_idle_add(),
* except that the functions interact properly with clutter event handling.
* If a "later" function is added from a clutter event handler, and is supposed
* to be run before the stage is redrawn, it will be run before that redraw
* of the stage, not the next one.
*
* Return value: an integer ID (guaranteed to be non-zero) that can be used
* to cancel the callback and prevent it from being run.
*/
guint
meta_later_add (MetaLaterType when,
GSourceFunc func,
gpointer data,
GDestroyNotify notify)
{
MetaLater *later = g_slice_new0 (MetaLater);
later->id = ++last_later_id;
later->when = when;
later->func = func;
later->data = data;
later->notify = notify;
laters = g_slist_insert_sorted (laters, later, compare_laters);
switch (when)
{
case META_LATER_RESIZE:
/* We add this one two ways - as a high-priority idle and as a
* repaint func. If we are in a clutter event callback, the repaint
* handler will get hit first, and we'll take care of this function
* there so it gets called before the stage is redrawn, even if
* we haven't gotten back to the main loop. Otherwise, the idle
* handler will get hit first and we want to call this function
* there so it will happen before GTK+ repaints.
*/
later->source = g_idle_add_full (META_PRIORITY_RESIZE, call_idle_later, later, NULL);
ensure_later_repaint_func ();
break;
case META_LATER_BEFORE_REDRAW:
ensure_later_repaint_func ();
break;
case META_LATER_IDLE:
later->source = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, call_idle_later, later, NULL);
break;
}
return later->id;
}
/**
* meta_later_remove:
* @later_id: the integer ID returned from meta_later_add()
*
* Removes a callback added with meta_later_add()
*/
void
meta_later_remove (guint later_id)
{
GSList *l;
for (l = laters; l; l = l->next)
{
MetaLater *later = l->data;
if (later->id == later_id)
{
laters = g_slist_remove_link (laters, l);
/* If this was a "repaint func" later, we just let the
* repaint func run and get removed
*/
destroy_later (later);
}
}
}
/* eof util.c */

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,12 @@ typedef enum {
#define NUMBER_OF_QUEUES 3
typedef enum {
META_TILE_NONE,
META_TILE_LEFT,
META_TILE_RIGHT
} MetaTileMode;
struct _MetaWindow
{
GObject parent_instance;
@@ -99,6 +102,7 @@ struct _MetaWindow
char *sm_client_id;
char *wm_client_machine;
char *startup_id;
char *mutter_hints;
int net_wm_pid;
@@ -124,12 +128,23 @@ 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;
/* Whether we're fullscreen */
guint fullscreen : 1;
/* Whether the urgent flag of WM_HINTS is set */
guint wm_hints_urgent : 1;
/* Whether we have to fullscreen after placement */
guint fullscreen_after_placement : 1;
/* Area to cover when in fullscreen mode. If _NET_WM_FULLSCREEN_MONITORS has
* been overridden (via a client message), the window will cover the union of
* these monitors. If not, this is the single monitor which the window's
@@ -139,8 +154,8 @@ struct _MetaWindow
/* Whether we're trying to constrain the window to be fully onscreen */
guint require_fully_onscreen : 1;
/* Whether we're trying to constrain the window to be on a single xinerama */
guint require_on_single_xinerama : 1;
/* Whether we're trying to constrain the window to be on a single monitor */
guint require_on_single_monitor : 1;
/* Whether we're trying to constrain the window's titlebar to be onscreen */
guint require_titlebar_visible : 1;
@@ -246,6 +261,9 @@ struct _MetaWindow
/* Have we placed this window? */
guint placed : 1;
/* Must we force_save_user_window_placement? */
guint force_save_user_rect : 1;
/* Is this not a transient of the focus window which is being denied focus? */
guint denied_focus_and_not_transient : 1;
@@ -316,6 +334,9 @@ struct _MetaWindow
*/
int unmaps_pending;
/* See docs for meta_window_get_stable_sequence() */
guint32 stable_sequence;
/* set to the most recent user-interaction event timestamp that we
know about for this window */
guint32 net_wm_user_time;
@@ -377,6 +398,7 @@ struct _MetaWindowClass
void (*workspace_changed) (MetaWindow *window, int old_workspace);
void (*focus) (MetaWindow *window);
void (*raised) (MetaWindow *window);
void (*unmanaged) (MetaWindow *window);
};
/* These differ from window->has_foo_func in that they consider
@@ -387,8 +409,11 @@ 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(w) ((w)->maximized_vertically && \
!(w)->maximized_horizontally && \
(w)->tile_mode != META_TILE_NONE)
#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(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)))
@@ -411,6 +436,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,
@@ -431,6 +461,8 @@ void meta_window_update_fullscreen_monitors (MetaWindow *window,
unsigned long left,
unsigned long right);
gboolean meta_window_appears_focused (MetaWindow *window);
/* args to move are window pos, not frame pos */
void meta_window_move (MetaWindow *window,
gboolean user_op,
@@ -456,8 +488,6 @@ void meta_window_resize_with_gravity (MetaWindow *window,
/* Return whether the window should be currently mapped */
gboolean meta_window_should_be_showing (MetaWindow *window);
gboolean meta_window_toplevel_is_mapped (MetaWindow *window);
/* See warning in window.c about this function */
gboolean __window_is_terminal (MetaWindow *window);
@@ -495,8 +525,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);
@@ -546,13 +574,16 @@ GList* meta_window_get_workspaces (MetaWindow *window);
gboolean meta_window_located_on_workspace (MetaWindow *window,
MetaWorkspace *workspace);
void meta_window_get_work_area_current_xinerama (MetaWindow *window,
MetaRectangle *area);
void meta_window_get_work_area_for_xinerama (MetaWindow *window,
int which_xinerama,
MetaRectangle *area);
void meta_window_get_work_area_all_xineramas (MetaWindow *window,
MetaRectangle *area);
void meta_window_get_work_area_current_monitor (MetaWindow *window,
MetaRectangle *area);
void meta_window_get_work_area_for_monitor (MetaWindow *window,
int which_monitor,
MetaRectangle *area);
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,
@@ -571,14 +602,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);
gboolean meta_window_is_ancestor_of_transient (MetaWindow *window,
MetaWindow *transient);
void meta_window_foreach_ancestor (MetaWindow *window,
MetaWindowForeachFunc func,
void *data);
void meta_window_begin_grab_op (MetaWindow *window,
MetaGrabOp op,
@@ -601,10 +624,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;
@@ -472,8 +472,8 @@ set_window_title (MetaWindow *window,
meta_ui_set_frame_title (window->screen->ui,
window->frame->xwindow,
window->title);
if (modified)
g_object_notify (G_OBJECT (window), "title");
g_object_notify (G_OBJECT (window), "title");
}
static void
@@ -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)
@@ -604,6 +647,7 @@ reload_net_wm_state (MetaWindow *window,
window->shaded = FALSE;
window->maximized_horizontally = FALSE;
window->maximized_vertically = FALSE;
window->fullscreen = FALSE;
window->wm_state_modal = FALSE;
window->wm_state_skip_taskbar = FALSE;
window->wm_state_skip_pager = FALSE;
@@ -632,13 +676,7 @@ reload_net_wm_state (MetaWindow *window,
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_SKIP_PAGER)
window->wm_state_skip_pager = TRUE;
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_FULLSCREEN)
{
if (!window->fullscreen)
{
window->fullscreen = TRUE;
g_object_notify (G_OBJECT (window), "fullscreen");
}
}
window->fullscreen_after_placement = TRUE;
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_ABOVE)
window->wm_state_above = TRUE;
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_BELOW)
@@ -1350,8 +1388,10 @@ reload_wm_hints (MetaWindow *window,
gboolean initial)
{
Window old_group_leader;
gboolean old_urgent;
old_group_leader = window->xgroup_leader;
old_urgent = window->wm_hints_urgent;
/* Fill in defaults */
window->input = TRUE;
@@ -1359,7 +1399,8 @@ reload_wm_hints (MetaWindow *window,
window->xgroup_leader = None;
window->wm_hints_pixmap = None;
window->wm_hints_mask = None;
window->wm_hints_urgent = FALSE;
if (value->type != META_PROP_VALUE_INVALID)
{
const XWMHints *hints = value->v.wm_hints;
@@ -1378,7 +1419,10 @@ reload_wm_hints (MetaWindow *window,
if (hints->flags & IconMaskHint)
window->wm_hints_mask = hints->icon_mask;
if (hints->flags & XUrgencyHint)
window->wm_hints_urgent = TRUE;
meta_verbose ("Read WM_HINTS input: %d iconic: %d group leader: 0x%lx pixmap: 0x%lx mask: 0x%lx\n",
window->input, window->initially_iconic,
window->xgroup_leader,
@@ -1394,6 +1438,21 @@ reload_wm_hints (MetaWindow *window,
meta_window_group_leader_changed (window);
}
/*
* Do not emit urgency notification on the inital property load
*/
if (!initial && (window->wm_hints_urgent != old_urgent))
g_object_notify (G_OBJECT (window), "urgent");
/*
* Do not emit signal for the initial property load, let the constructor to
* take care of it once the MetaWindow is fully constructed.
*
* Only emit if the property is both changed and set.
*/
if (!initial && window->wm_hints_urgent && !old_urgent)
g_signal_emit_by_name (window->display, "window-marked-urgent", window);
meta_icon_cache_property_changed (&window->icon_cache,
window->display,
XA_WM_HINTS);
@@ -1490,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

@@ -47,12 +47,12 @@ struct _MetaWorkspace
GList *list_containing_self;
MetaRectangle work_area_screen;
MetaRectangle *work_area_xinerama;
MetaRectangle *work_area_monitor;
GList *screen_region;
GList **xinerama_region;
gint n_xinerama_regions;
GList **monitor_region;
gint n_monitor_regions;
GList *screen_edges;
GList *xinerama_edges;
GList *monitor_edges;
GSList *builtin_struts;
GSList *all_struts;
guint work_areas_invalid : 1;
@@ -77,14 +77,12 @@ void meta_workspace_relocate_windows (MetaWorkspace *workspace,
void meta_workspace_invalidate_work_area (MetaWorkspace *workspace);
void meta_workspace_get_work_area_for_xinerama (MetaWorkspace *workspace,
int which_xinerama,
void meta_workspace_get_work_area_for_monitor (MetaWorkspace *workspace,
int which_monitor,
MetaRectangle *area);
GList* meta_workspace_get_onscreen_region (MetaWorkspace *workspace);
GList* meta_workspace_get_onxinerama_region (MetaWorkspace *workspace,
int which_xinerama);
void meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
MetaRectangle *area);
GList* meta_workspace_get_onmonitor_region (MetaWorkspace *workspace,
int which_monitor);
void meta_workspace_focus_default_window (MetaWorkspace *workspace,
MetaWindow *not_this_one,

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"
@@ -33,6 +34,9 @@
#include <X11/Xatom.h>
#include <string.h>
#ifdef HAVE_LIBCANBERRA
#include <canberra-gtk.h>
#endif
enum {
PROP_0,
@@ -170,16 +174,16 @@ meta_workspace_new (MetaScreen *screen)
meta_screen_foreach_window (screen, maybe_add_to_list, &workspace->mru_list);
workspace->work_areas_invalid = TRUE;
workspace->work_area_xinerama = NULL;
workspace->work_area_monitor = NULL;
workspace->work_area_screen.x = 0;
workspace->work_area_screen.y = 0;
workspace->work_area_screen.width = 0;
workspace->work_area_screen.height = 0;
workspace->screen_region = NULL;
workspace->xinerama_region = NULL;
workspace->monitor_region = NULL;
workspace->screen_edges = NULL;
workspace->xinerama_edges = NULL;
workspace->monitor_edges = NULL;
workspace->list_containing_self = g_list_prepend (NULL, workspace);
workspace->builtin_struts = NULL;
@@ -263,7 +267,7 @@ meta_workspace_remove (MetaWorkspace *workspace)
workspace->screen->workspaces =
g_list_remove (workspace->screen->workspaces, workspace);
g_free (workspace->work_area_xinerama);
g_free (workspace->work_area_monitor);
g_list_free (workspace->mru_list);
g_list_free (workspace->list_containing_self);
@@ -280,12 +284,12 @@ meta_workspace_remove (MetaWorkspace *workspace)
if (!workspace->work_areas_invalid)
{
workspace_free_all_struts (workspace);
for (i = 0; i < screen->n_xinerama_infos; i++)
meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]);
g_free (workspace->xinerama_region);
for (i = 0; i < screen->n_monitor_infos; i++)
meta_rectangle_free_list_and_elements (workspace->monitor_region[i]);
g_free (workspace->monitor_region);
meta_rectangle_free_list_and_elements (workspace->screen_region);
meta_rectangle_free_list_and_elements (workspace->screen_edges);
meta_rectangle_free_list_and_elements (workspace->xinerama_edges);
meta_rectangle_free_list_and_elements (workspace->monitor_edges);
}
g_object_unref (workspace);
@@ -439,6 +443,88 @@ meta_workspace_queue_calc_showing (MetaWorkspace *workspace)
}
}
static void
workspace_switch_sound(MetaWorkspace *from,
MetaWorkspace *to)
{
#ifdef HAVE_LIBCANBERRA
MetaWorkspaceLayout layout;
int i, nw, x, y, fi, ti;
const char *e;
nw = meta_screen_get_n_workspaces(from->screen);
fi = meta_workspace_index(from);
ti = meta_workspace_index(to);
meta_screen_calc_workspace_layout(from->screen,
nw,
fi,
&layout);
for (i = 0; i < nw; i++)
if (layout.grid[i] == ti)
break;
if (i >= nw)
{
meta_bug("Failed to find destination workspace in layout\n");
goto finish;
}
y = i / layout.cols;
x = i % layout.cols;
/* We priorize horizontal over vertical movements here. The
rationale for this is that horizontal movements are probably more
interesting for sound effects because speakers are usually
positioned on a horizontal and not a vertical axis. i.e. your
spatial "Woosh!" effects will easily be able to encode horizontal
movement but not such much vertical movement. */
if (x < layout.current_col)
e = "desktop-switch-left";
else if (x > layout.current_col)
e = "desktop-switch-right";
else if (y < layout.current_row)
e = "desktop-switch-up";
else if (y > layout.current_row)
e = "desktop-switch-down";
else
{
meta_bug("Uh, origin and destination workspace at same logic position!\n");
goto finish;
}
ca_context_play(ca_gtk_context_get(), 1,
CA_PROP_EVENT_ID, e,
CA_PROP_EVENT_DESCRIPTION, "Desktop switched",
CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
NULL);
finish:
meta_screen_free_workspace_layout (&layout);
#endif /* HAVE_LIBCANBERRA */
}
/**
* meta_workspace_activate_with_focus:
* @workspace: a #MetaWorkspace
* @focus_this: the #MetaWindow to be focused, or %NULL
* @timestamp: timestamp for @focus_this
*
* Switches to @workspace and possibly activates the window @focus_this.
*
* The window @focus_this is activated by calling meta_window_activate()
* which will unminimize it and transient parents, raise it and give it
* the focus.
*
* If a window is currently being moved by the user, it will be
* moved to @workspace.
*
* The advantage of calling this function instead of meta_workspace_activate()
* followed by meta_window_activate() is that it happens as a unit, so
* no other window gets focused first before @focus_this.
*/
void
meta_workspace_activate_with_focus (MetaWorkspace *workspace,
MetaWindow *focus_this,
@@ -459,6 +545,13 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
if (workspace->screen->active_workspace == workspace)
return;
/* Free any cached pointers to the workspaces's edges from
* a current resize or move operation */
meta_display_cleanup_edges (workspace->screen->display);
if (workspace->screen->active_workspace)
workspace_switch_sound (workspace->screen->active_workspace, workspace);
/* Note that old can be NULL; e.g. when starting up */
old = workspace->screen->active_workspace;
@@ -562,8 +655,7 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
*/
if (focus_this)
{
meta_window_focus (focus_this, timestamp);
meta_window_raise (focus_this);
meta_window_activate (focus_this, timestamp);
}
else if (move_window)
{
@@ -615,12 +707,12 @@ 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.
*
* Return value: (transfer container): the list of windows.
* Return value: (transfer container) (element-type MetaWindow): the list of windows.
*/
GList*
meta_workspace_list_windows (MetaWorkspace *workspace)
@@ -673,7 +765,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
@@ -695,21 +787,26 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
"Invalidating work area for workspace %d\n",
meta_workspace_index (workspace));
g_free (workspace->work_area_xinerama);
workspace->work_area_xinerama = NULL;
/* If we are in the middle of a resize or move operation, we
* might have cached pointers to the workspace's edges */
if (workspace == workspace->screen->active_workspace)
meta_display_cleanup_edges (workspace->screen->display);
g_free (workspace->work_area_monitor);
workspace->work_area_monitor = NULL;
workspace_free_all_struts (workspace);
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]);
g_free (workspace->xinerama_region);
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
meta_rectangle_free_list_and_elements (workspace->monitor_region[i]);
g_free (workspace->monitor_region);
meta_rectangle_free_list_and_elements (workspace->screen_region);
meta_rectangle_free_list_and_elements (workspace->screen_edges);
meta_rectangle_free_list_and_elements (workspace->xinerama_edges);
workspace->xinerama_region = NULL;
meta_rectangle_free_list_and_elements (workspace->monitor_edges);
workspace->monitor_region = NULL;
workspace->screen_region = NULL;
workspace->screen_edges = NULL;
workspace->xinerama_edges = NULL;
workspace->monitor_edges = NULL;
workspace->work_areas_invalid = TRUE;
@@ -762,10 +859,10 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
return;
g_assert (workspace->all_struts == NULL);
g_assert (workspace->xinerama_region == NULL);
g_assert (workspace->monitor_region == NULL);
g_assert (workspace->screen_region == NULL);
g_assert (workspace->screen_edges == NULL);
g_assert (workspace->xinerama_edges == NULL);
g_assert (workspace->monitor_edges == NULL);
/* STEP 1: Get the list of struts */
@@ -785,18 +882,18 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
g_list_free (windows);
/* STEP 2: Get the maximal/spanning rects for the onscreen and
* on-single-xinerama regions
* on-single-monitor regions
*/
g_assert (workspace->xinerama_region == NULL);
g_assert (workspace->monitor_region == NULL);
g_assert (workspace->screen_region == NULL);
workspace->xinerama_region = g_new (GList*,
workspace->screen->n_xinerama_infos);
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
workspace->monitor_region = g_new (GList*,
workspace->screen->n_monitor_infos);
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
{
workspace->xinerama_region[i] =
workspace->monitor_region[i] =
meta_rectangle_get_minimal_spanning_set_for_region (
&workspace->screen->xinerama_infos[i].rect,
&workspace->screen->monitor_infos[i].rect,
workspace->all_struts);
}
workspace->screen_region =
@@ -805,7 +902,7 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
workspace->all_struts);
/* STEP 3: Get the work areas (region-to-maximize-to) for the screen and
* xineramas.
* monitors.
*/
work_area = workspace->screen->rect; /* start with the screen */
if (workspace->screen_region == NULL)
@@ -860,35 +957,35 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
workspace->work_area_screen.width,
workspace->work_area_screen.height);
/* Now find the work areas for each xinerama */
g_free (workspace->work_area_xinerama);
workspace->work_area_xinerama = g_new (MetaRectangle,
workspace->screen->n_xinerama_infos);
/* Now find the work areas for each monitor */
g_free (workspace->work_area_monitor);
workspace->work_area_monitor = g_new (MetaRectangle,
workspace->screen->n_monitor_infos);
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
{
work_area = workspace->screen->xinerama_infos[i].rect;
work_area = workspace->screen->monitor_infos[i].rect;
if (workspace->xinerama_region[i] == NULL)
if (workspace->monitor_region[i] == NULL)
/* FIXME: constraints.c untested with this, but it might be nice for
* a screen reader or magnifier.
*/
work_area = meta_rect (work_area.x, work_area.y, -1, -1);
else
meta_rectangle_clip_to_region (workspace->xinerama_region[i],
meta_rectangle_clip_to_region (workspace->monitor_region[i],
FIXED_DIRECTION_NONE,
&work_area);
workspace->work_area_xinerama[i] = work_area;
workspace->work_area_monitor[i] = work_area;
meta_topic (META_DEBUG_WORKAREA,
"Computed work area for workspace %d "
"xinerama %d: %d,%d %d x %d\n",
"monitor %d: %d,%d %d x %d\n",
meta_workspace_index (workspace),
i,
workspace->work_area_xinerama[i].x,
workspace->work_area_xinerama[i].y,
workspace->work_area_xinerama[i].width,
workspace->work_area_xinerama[i].height);
workspace->work_area_monitor[i].x,
workspace->work_area_monitor[i].y,
workspace->work_area_monitor[i].width,
workspace->work_area_monitor[i].height);
}
/* STEP 4: Make sure the screen_region is nonempty (separate from step 2
@@ -902,17 +999,17 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
workspace->screen_region = g_list_prepend (NULL, nonempty_region);
}
/* STEP 5: Cache screen and xinerama edges for edge resistance and snapping */
/* STEP 5: Cache screen and monitor edges for edge resistance and snapping */
g_assert (workspace->screen_edges == NULL);
g_assert (workspace->xinerama_edges == NULL);
g_assert (workspace->monitor_edges == NULL);
workspace->screen_edges =
meta_rectangle_find_onscreen_edges (&workspace->screen->rect,
workspace->all_struts);
tmp = NULL;
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
tmp = g_list_prepend (tmp, &workspace->screen->xinerama_infos[i].rect);
workspace->xinerama_edges =
meta_rectangle_find_nonintersected_xinerama_edges (tmp,
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
tmp = g_list_prepend (tmp, &workspace->screen->monitor_infos[i].rect);
workspace->monitor_edges =
meta_rectangle_find_nonintersected_monitor_edges (tmp,
workspace->all_struts);
g_list_free (tmp);
@@ -932,10 +1029,27 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
}
}
static gboolean
strut_lists_equal (GSList *l,
GSList *m)
{
for (; l && m; l = l->next, m = m->next)
{
MetaStrut *a = l->data;
MetaStrut *b = m->data;
if (a->side != b->side ||
!meta_rectangle_equal (&a->rect, &b->rect))
return FALSE;
}
return l == NULL && m == NULL;
}
/**
* 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
@@ -945,6 +1059,12 @@ void
meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
GSList *struts)
{
/* Reordering doesn't actually matter, so we don't catch all
* no-impact changes, but this is just a (possibly unnecessary
* anyways) optimization */
if (strut_lists_equal (struts, workspace->builtin_struts))
return;
workspace_free_builtin_struts (workspace);
workspace->builtin_struts = copy_strut_list (struts);
@@ -952,21 +1072,21 @@ meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
}
void
meta_workspace_get_work_area_for_xinerama (MetaWorkspace *workspace,
int which_xinerama,
MetaRectangle *area)
meta_workspace_get_work_area_for_monitor (MetaWorkspace *workspace,
int which_monitor,
MetaRectangle *area)
{
g_assert (which_xinerama >= 0);
g_assert (which_monitor >= 0);
ensure_work_areas_validated (workspace);
g_assert (which_xinerama < workspace->screen->n_xinerama_infos);
g_assert (which_monitor < workspace->screen->n_monitor_infos);
*area = workspace->work_area_xinerama[which_xinerama];
*area = workspace->work_area_monitor[which_monitor];
}
void
meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
MetaRectangle *area)
meta_workspace_get_work_area_all_monitors (MetaWorkspace *workspace,
MetaRectangle *area)
{
ensure_work_areas_validated (workspace);
@@ -982,12 +1102,12 @@ meta_workspace_get_onscreen_region (MetaWorkspace *workspace)
}
GList*
meta_workspace_get_onxinerama_region (MetaWorkspace *workspace,
int which_xinerama)
meta_workspace_get_onmonitor_region (MetaWorkspace *workspace,
int which_monitor)
{
ensure_work_areas_validated (workspace);
return workspace->xinerama_region[which_xinerama];
return workspace->monitor_region[which_monitor];
}
#ifdef WITH_VERBOSE_MODE
@@ -1184,7 +1304,10 @@ focus_ancestor_or_mru_window (MetaWorkspace *workspace,
MetaWindow *ancestor;
ancestor = NULL;
meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor);
if (ancestor != NULL)
if (ancestor != NULL &&
(ancestor->on_all_workspaces ||
ancestor->workspace == workspace) &&
meta_window_showing_on_its_workspace (ancestor))
{
meta_topic (META_DEBUG_FOCUS,
"Focusing %s, ancestor of %s\n",

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);
@@ -264,6 +264,16 @@ cardinal_list_from_results (GetPropertyResults *results,
*n_cardinals_p = results->n_items;
results->prop = NULL;
#if GLIB_SIZEOF_LONG == 8
/* Xlib sign-extends format=32 items, but we want them unsigned */
{
int i;
for (i = 0; i < *n_cardinals_p; i++)
(*cardinals_p)[i] = (*cardinals_p)[i] & 0xffffffff;
}
#endif
return TRUE;
}
@@ -480,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);
@@ -537,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
@@ -608,6 +618,10 @@ cardinal_with_atom_type_from_results (GetPropertyResults *results,
return FALSE;
*cardinal_p = *(gulong*) results->prop;
#if GLIB_SIZEOF_LONG == 8
/* Xlib sign-extends format=32 items, but we want them unsigned */
*cardinal_p &= 0xffffffff;
#endif
XFree (results->prop);
results->prop = NULL;

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>F6",
BINDING_REVERSES, "<Alt>grave",
_("Move between windows of an application immediately"))
keybind (cycle_group_backward, handle_cycle, META_TAB_LIST_GROUP,
REVERSES_AND_REVERSED, NULL,
@@ -186,6 +186,18 @@ keybind (cycle_panels_backward, handle_cycle, META_TAB_LIST_DOCKS,
_("Move backward between panels and the desktop immediately"))
/***********************************/
/* These two are special pseudo-bindings that are provided for allowing
* custom handlers, but will never be bound to a key. While a tab
* grab is in effect, they are invoked for releasing the primary modifier
* or pressing some unbound key, respectively.
*/
keybind (tab_popup_select, handle_tab_popup_select, 0, 0, NULL,
"Select window from tab popup")
keybind (tab_popup_cancel, handle_tab_popup_cancel, 0, 0, NULL,
"Cancel tab popup")
/***********************************/
keybind (show_desktop, handle_show_desktop, 0, 0, "<Control><Alt>d",
_("Hide all normal windows and set focus to the desktop"))

View File

@@ -1,73 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Metacity Alt-Tab abstraction */
/*
* Copyright (C) 2009 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_ALT_TAB_HANDLER_H
#define META_ALT_TAB_HANDLER_H
#include <glib-object.h>
#include "types.h"
#define META_TYPE_ALT_TAB_HANDLER (meta_alt_tab_handler_get_type ())
#define META_ALT_TAB_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_ALT_TAB_HANDLER, MetaAltTabHandler))
#define META_ALT_TAB_HANDLER_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), META_TYPE_ALT_TAB_HANDLER, MetaAltTabHandlerInterface))
typedef struct _MetaAltTabHandler MetaAltTabHandler;
typedef struct _MetaAltTabHandlerInterface MetaAltTabHandlerInterface;
struct _MetaAltTabHandlerInterface {
GTypeInterface g_iface;
void (*add_window) (MetaAltTabHandler *handler,
MetaWindow *window);
void (*show) (MetaAltTabHandler *handler,
MetaWindow *initial_selection);
void (*destroy) (MetaAltTabHandler *handler);
void (*forward) (MetaAltTabHandler *handler);
void (*backward) (MetaAltTabHandler *handler);
MetaWindow * (*get_selected) (MetaAltTabHandler *handler);
};
GType meta_alt_tab_handler_get_type (void);
void meta_alt_tab_handler_register (GType type);
MetaAltTabHandler *meta_alt_tab_handler_new (MetaScreen *screen,
gboolean immediate);
void meta_alt_tab_handler_add_window (MetaAltTabHandler *handler,
MetaWindow *window);
void meta_alt_tab_handler_show (MetaAltTabHandler *handler,
MetaWindow *initial_selection);
void meta_alt_tab_handler_destroy (MetaAltTabHandler *handler);
void meta_alt_tab_handler_forward (MetaAltTabHandler *handler);
void meta_alt_tab_handler_backward (MetaAltTabHandler *handler);
MetaWindow *meta_alt_tab_handler_get_selected (MetaAltTabHandler *handler);
#endif

View File

@@ -1,55 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Metacity Alt-Tab abstraction: default implementation */
/*
* Copyright (C) 2009 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_ALT_TAB_HANDLER_DEFAULT_H
#define META_ALT_TAB_HANDLER_DEFAULT_H
#include "alttabhandler.h"
#include "tabpopup.h"
#define META_TYPE_ALT_TAB_HANDLER_DEFAULT (meta_alt_tab_handler_default_get_type ())
#define META_ALT_TAB_HANDLER_DEFAULT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_ALT_TAB_HANDLER_DEFAULT, MetaAltTabHandlerDefault))
typedef struct _MetaAltTabHandlerDefault MetaAltTabHandlerDefault;
typedef struct _MetaAltTabHandlerDefaultClass MetaAltTabHandlerDefaultClass;
struct _MetaAltTabHandlerDefault {
GObject parent_instance;
MetaScreen *screen;
GArray *entries;
gboolean immediate_mode;
MetaTabPopup *tab_popup;
};
struct _MetaAltTabHandlerDefaultClass {
GObjectClass parent_class;
};
GType meta_alt_tab_handler_default_get_type (void);
#endif

View File

@@ -58,6 +58,8 @@ item(_MUTTER_RESTART_MESSAGE)
item(_MUTTER_RELOAD_THEME_MESSAGE)
item(_MUTTER_SET_KEYBINDINGS_MESSAGE)
item(_MUTTER_TOGGLE_VERBOSE)
item(_MUTTER_HINTS)
item(_GNOME_WM_KEYBINDINGS)
item(_GNOME_PANEL_ACTION)
item(_GNOME_PANEL_ACTION_MAIN_MENU)
item(_GNOME_PANEL_ACTION_RUN_DIALOG)

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