Compare commits

...

255 Commits

Author SHA1 Message Date
31e6cdf345 Bump version to 3.0.2
Update NEWS
2011-05-25 14:40:58 -04:00
c8aaa5e33e Fix crash in meta_display_get_above_tab_keycode
https://bugzilla.gnome.org/show_bug.cgi?id=647777
2011-05-25 14:22:57 -04:00
65aa3e3927 window: don't allow side-by-side tiling of non-maximizable windows
If a window is not maximizable, then that probably means it looks dumb
at very large sizes. Even if its hints would allow you to manually
resize it to a large size, don't allow automatically tiling it to half
the screen.

https://bugzilla.gnome.org/show_bug.cgi?id=647901
2011-05-23 23:50:14 -04:00
b192771b93 Filter mirrored monitors from the monitors list
For the purposes of window placement or arranging window manager or
plugin controls, screens that are just mirrors of other screens should
be ignored, so filter them out of the monitors list.

https://bugzilla.gnome.org/show_bug.cgi?id=649299
2011-05-23 23:49:58 -04:00
c1977b6532 region-utils.c: Squash a memory leak
"chunk" was an allocated but unused variable.

https://bugzilla.gnome.org/show_bug.cgi?id=649504
2011-05-23 23:49:33 -04:00
50d1b53267 theme.c: Squash memory leak
When converting a token to a different type, we need to free its
string.

https://bugzilla.gnome.org/show_bug.cgi?id=649500
2011-05-23 23:49:10 -04:00
cbec96a62f Make _NET_WM_WINDOW_OPACITY orthogonal to window actor opacity
Using MetaWindowActor.opacity for _NET_WM_WINDOW_OPACITY makes it
difficult to implement effects like fading a window in on map.
Instead, set the opacity on the MetaShadedTexture child and use
it when drawing the shadow.

Since the check MetaWindowGroup does on meta_actor_get_paint_opacity()
no longer covers this, we need to handle the opacity in
meta_window_actor_get_obscured_region() explicitly.

https://bugzilla.gnome.org/show_bug.cgi?id=648613
2011-05-23 23:48:48 -04:00
a28a5749db Added UG translation 2011-05-02 18:48:56 +02:00
5eb8aa655b Bump version to 3.0.1
Update NEWS
2011-04-25 17:21:55 -04:00
3543782f39 edge-tiling: Fix cancelling maximize tiling
If a window can not be tiled, e.g. due to its minimum size hints,
dragging away from the top after activating the maximize tile preview
does not cancel the maximization request, the only way to do so is by
hitting Escape.
To fix, reset the tiling state in the maximize-tile code path as
well if necessary.

https://bugzilla.gnome.org/show_bug.cgi?id=646149
2011-04-25 23:12:05 +02:00
4ff4ebebb6 meta_window_is_remote: If WM_CLIENT_MACHINE not set, don't assume remote
Apparently the "fox" toolkit doesn't set WM_CLIENT_MACHINE; while we
could do gymnastics to attempt to figure this out (talk to the X
server?), better to just default to FALSE.

https://bugzilla.gnome.org/show_bug.cgi?id=647662
2011-04-25 16:43:09 -04:00
a3c96c12d6 Updated Turkish translation 2011-04-23 02:08:10 +03:00
eb0e658c99 window: fix a case of appears-focused getting stuck
Since appears-focus only propagates up from modal dialogs, if an
application removed the modal hint from a dialog before destroying it,
then its parent would be left with a stray reference to it in
attached_focus_window, causing it to be permanently appears-focused.

The obvious fix, calling meta_window_propagate_focus_appearance() when
the modal hint is removed, tends to cause noticeable flashing, because
the window will get drawn unfocused and then focused again.

So instead we just change meta_window_propagate_focus_appearance() to
check the window type only when focusing in, not when focusing out.

This would also cause flashing, but in this case we can avoid it by
not notifying the change in appears-focus on the parent window if it
is the expected_focus_window (which it will be by this point). (This
does mean though that if something weird happens and the window
doesn't end up becoming the focus window, it won't get redrawn
unfocused until something else forces it to.)

https://bugzilla.gnome.org/show_bug.cgi?id=647613
2011-04-20 14:40:47 -04:00
4d069650ae Add Esperanto translation 2011-04-19 18:48:55 +02:00
d176755926 Updated Assamese translations 2011-04-05 12:00:38 +05:30
eb2a6946b2 Bump version to 3.0.0 2011-04-04 13:23:45 -04:00
d067ba4431 Add old NEWS
Add text from previews release announcements to NEWS
2011-04-04 13:22:40 -04:00
fdf11f10fb [l10n]Fixes on Catalan translation 2011-04-03 23:45:55 +02:00
8fd1835d1a Update Czech translation 2011-04-03 17:12:10 +02:00
c77075833a Updated Danish translation 2011-04-02 22:38:08 +02:00
b2a7ab270c Updated kn translations 2011-04-02 21:00:21 +05:30
7503d4812c window: don't crash on spurious calls to idle_calc_showing()
If idle_calc_showing() gets called when its queue is empty (which
shouldn't happen), just return rather than crashing.

https://bugzilla.gnome.org/show_bug.cgi?id=642957
2011-04-02 07:34:39 -04:00
1fd8b0b4c5 Updated Korean translation 2011-04-02 20:10:55 +09:00
8615cf88ab Updated Vietnamese translation 2011-04-02 12:49:13 +07:00
f73a13dc4a po/vi.po: import from Damned Lies 2011-04-02 12:47:56 +07:00
f973e2effa Updated Tamil translation 2011-04-01 20:49:02 +05:30
f9fed16608 Updated Hungarian translation 2011-04-01 14:53:23 +02:00
0578ed0c86 Updated Brazilian Portuguese translation. Reviewed by Antonio Fernandes C. Neto <fernandes@pelivre.org> 2011-04-01 09:18:33 -03:00
61520f5bd6 Updated Basque language 2011-04-01 13:25:55 +02:00
be853ec931 Updated Basque language 2011-04-01 13:23:09 +02:00
440b92adf0 [l10n]Updated Catalan translation 2011-03-30 21:20:29 +02:00
8fa4d22937 Updated British English translation 2011-03-30 15:35:46 +01:00
397ae90d5c Updated Traditional Chinese translation(Hong Kong and Taiwan) 2011-03-30 21:32:14 +08:00
7f97d0bdc5 Updated Dutch translation by Wouter Bolsterlee 2011-03-29 23:29:27 +02:00
14956abb6e Updated Indonesian translation 2011-03-29 22:16:32 +07:00
61cea18ff0 Updated Portuguese translation 2011-03-29 00:26:27 +01:00
83a449df95 Bump version to 2.91.93 2011-03-28 18:42:26 -04:00
9c683aaea9 [l10n] Updated German translation 2011-03-29 00:38:27 +02:00
634b76b82c Don't move all window to active workspace if monitors change
https://bugzilla.gnome.org/show_bug.cgi?id=645408
2011-03-28 18:19:25 -04:00
a3ea43da52 display: Fix crash with cycle_group
Commit e3ebcc004d introduced an unsafe
access for 'window', which could cause a segfault.

https://bugzilla.gnome.org/show_bug.cgi?id=645843
2011-03-28 17:38:07 -04:00
f464b85ffc window: add an appears-focused property, redraw shadows when it changes
We need to redraw a window's shadow any time the value of
meta_window_appears_focused() changes. So make that into a property so
we can get notifications on it.

https://bugzilla.gnome.org/show_bug.cgi?id=636904
2011-03-28 12:09:10 -04:00
db055c6029 Updated Latvian translation. 2011-03-28 00:49:45 +03:00
eedc74943b Added UG translation 2011-03-27 21:38:17 +02:00
82b134ed46 Updated Russian translation 2011-03-26 22:13:25 +03:00
cc1de7e7d0 update tranlation for Punjabi by A S Alam 2011-03-26 23:50:11 +05:30
a199d74069 Updated Hebrew translation. 2011-03-26 00:36:10 +02:00
7a23d3024a Update Simplified Chinese translation. 2011-03-24 17:18:27 +00:00
734888406c Updated Swedish translation 2011-03-24 16:14:10 +01:00
e0ce24b3f5 Add description to DOAP file 2011-03-24 13:59:56 +01:00
c13e62f72c Export meta_get_replace_current_wm()
This is necessary for gnome-shell to know whether it should try to
replace the org.gnome.Shell DBus name.

Note: We can't just #include <meta/util.h> because it #defines '_'
at least which obviously conflicts with core gettext.  We should
un-export util.h or fix it.

https://bugzilla.gnome.org/show_bug.cgi?id=645590
2011-03-23 16:08:51 -04:00
3d958de33e Updated Bulgarian translation 2011-03-23 21:39:14 +02:00
4689688af3 Uploaded Ukranian 2011-03-23 15:53:06 +02:00
d402a68c73 Bump version to 2.91.92 2011-03-22 18:20:53 -04:00
66d1dd3679 Updated Italian translation 2011-03-22 22:54:24 +01:00
43e48fc962 Updated Slovenian translation 2011-03-22 22:05:24 +01:00
1fea2a5101 Updated Norwegian bokmål translation 2011-03-22 11:13:39 +01:00
92e317ec2a Adjust the position of attached dialogs to fit on-screen
As the position of attached modal dialogs is determined entirely
by the position of the parent window, the dialog may end up
partially off-screen (especially if the dialog is wider than the
parent). In this case, diverge from the calculated position and
try to fit the dialog on-screen.

https://bugzilla.gnome.org/show_bug.cgi?id=631308
2011-03-22 02:56:51 +01:00
c5d1d2db62 Add and export meta_window_move_to_monitor
This is useful for DnD to another monitor in gnome-shell.
In addition to a normal move it corrects the saved rect for
maximized and fullscreened windows.

https://bugzilla.gnome.org/show_bug.cgi?id=645032
2011-03-22 00:55:37 +01:00
b1725bc18c Updated Galician translations 2011-03-22 00:54:24 +01:00
5500c2b3a8 window: Allow resizing of attached modal dialogs
Currently attached modal dialogs are not resizable, but we don't
communicate this to GTK+, so the dialog may end up with resize
grips anyway. As a fix, allow resizing, but account for the dialog
being centered to its parent.

https://bugzilla.gnome.org/show_bug.cgi?id=643597
2011-03-22 00:27:10 +01:00
82db52aaf4 iconcache: don't crash on a non-alpha mask pixmap
We assume when applying a mask that it is a depth-1 pixmap that
cairo interprets as alpha. So ignore a non-depth-1 mask.

https://bugzilla.gnome.org/show_bug.cgi?id=641975
2011-03-21 18:51:14 -04:00
654d966e6c iconcache: Correctly interpret monochrome icons
Getting the contents of a depth-1 pixmap through cairo gives us
an alpha pixmap. We need to convert to a monochrome pixmap
as is expected by the ICCCM definition of WM_HINTS.

https://bugzilla.gnome.org/show_bug.cgi?id=641975
2011-03-21 18:47:52 -04:00
92663c81f5 iconcache: Fix apply_mask
apply_mask made some wrong assumptions that became untrue
after rendering_cleanup landed, such as the number of channels
in the pixmap, causing corruption.

https://bugzilla.gnome.org/show_bug.cgi?id=641975
2011-03-21 18:15:47 -04:00
Ron
e3ebcc004d display: Grab attached dialogs' parent
Currently, attached modal dialog can be grabbed (either by the
title bar, or using Alt+Button1), though they won't move when
dragged. To address this, grab the parent in that case, which
allows to move both the parent and the attached dialog.

https://bugzilla.gnome.org/show_bug.cgi?id=638674
2011-03-21 22:46:23 +01:00
26e41bc24a tiling: Fix dragging windows free from edge-tiling
Commit 96c43866 changed the tiling behavior to prefer edge tiling
over maximization in corner cases (well, quite literally). As a
side effect, it only allows untiling of edge-tiled windows by
dragging the window towards the correct edge.
This patch restores the old behavior for untiling, while keeping
the new behavior for untiled windows.

https://bugzilla.gnome.org/show_bug.cgi?id=645455
2011-03-21 22:00:54 +01:00
c9e9412540 window: Remove unnecessary checks
For tiling, we check whether the pointer is near the edges of
the monitor where the pointer is located, so checking that the
pointer is within the bounds of the monitor is unnecessary and
confusing.
2011-03-21 22:00:54 +01:00
14d6d63ad0 Updated French translation 2011-03-21 21:30:17 +01:00
2134213f92 Updated Spanish translation 2011-03-21 20:49:11 +01:00
1935e508f7 Updated Polish translation 2011-03-21 20:40:11 +01:00
83b6ec7899 Fix description for workspaces_only_on_primary key
The description was a bit corrupted and didn't make sense. Fix.

https://bugzilla.gnome.org/show_bug.cgi?id=645224
2011-03-21 15:30:28 -04:00
9c0ffc26c1 Updated Russian translation 2011-03-21 21:50:56 +03:00
39b28a7e42 Updated Portuguese translation 2011-03-20 23:56:52 +00:00
09799c6617 Updated Galician translations 2011-03-20 19:00:40 +01:00
9fad2246ae Fix previous commit
It is actually caller-allocates, not callee (the object is provided
by the binding, not by the function)
2011-03-19 20:56:18 +01:00
585da56118 Add introspection annotations for (out) arguments.
Mark that the the third argument to meta_rectangle_union and
meta_rectangle_intersect is an (out) argument that should be created
by the language binding.

https://bugzilla.gnome.org/show_bug.cgi?id=645247
2011-03-19 20:21:35 +01:00
cccb482cd9 Updated Latvian translation. 2011-03-19 20:34:04 +02:00
eb79c75266 Updated Polish translation 2011-03-19 16:16:23 +01:00
19171122ca Updated Indonesian translation 2011-03-19 22:07:36 +07:00
a4665b1a14 Updated Dutch translation by Wouter Bolsterlee 2011-03-19 16:03:51 +01:00
829f9ac61f Updated Korean translation 2011-03-19 23:39:12 +09:00
24b846328f Updated Spanish translation 2011-03-19 14:59:33 +01:00
96c43866b1 Make entire side of screen edge-tiling not maximization
If dragging the title bar to the edge of the screen to side-tile,
it's easy to end up above the workarea and end up maximized instead.
Make the entire side of the screen act as edge-tiling.

https://bugzilla.gnome.org/show_bug.cgi?id=644961
2011-03-18 14:55:52 -04:00
9043191927 Add MUTTER_WM_CLASS_FILTER environment variable
In a performance or regression testing environment, we may want to
only manage windows from a particular test program, and ignore all
other windows. The MUTTER_WM_CLASS_FILTER environment variable is a
list of WM_CLASS values that should be managed; other windows will
be unmapped and ignored.

https://bugzilla.gnome.org/show_bug.cgi?id=644252
2011-03-18 14:55:52 -04:00
6e6ed81c19 .gitignore: update 2011-03-18 13:54:18 -04:00
3597035f67 bell: add a composited flash-screen function
The old bell_flash_screen() has no effect when compositing. Add
meta_compositor_flash_screen(), and use that instead.

https://bugzilla.gnome.org/show_bug.cgi?id=639765
2011-03-18 13:53:53 -04:00
9f39a18fc5 Update meta_show_dialog for gtk's removal of --screen
gtk3 no longer has the --screen command-line argument, which mutter
was passing to zenity. Use --display (with an explicitly-specified
screen number) instead.

https://bugzilla.gnome.org/show_bug.cgi?id=643683
2011-03-18 13:53:53 -04:00
ab2de9dccd Updated Hungarian translation 2011-03-18 18:04:22 +01:00
d66c6cf55e Updated French translation 2011-03-17 20:32:46 +01:00
4f24f7e5fc Updated Slovenian translation 2011-03-17 19:54:20 +01:00
3cd0e86bdd session: Don't set XSMP restart
This made sense back in the day of stateless window managers,
but gnome-shell isn't.  gnome-session will handle gnome-shell
crashing, since it's a required component.

https://bugzilla.gnome.org/show_bug.cgi?id=644529
2011-03-17 13:52:54 -04:00
4d230daf09 Uploaded Ukranian 2011-03-17 18:24:47 +02:00
9dd642f4af Go with a single libmutter library
https://bugzilla.gnome.org/show_bug.cgi?id=644565
2011-03-17 15:31:53 +01:00
a9f9176ba5 [l10n] Updated German translation 2011-03-17 15:12:11 +01:00
637cce0f91 Only show workspace and stick/unstick in menu item for primary monitor
If workspaces_only_on_primary then it makes no sense to have these
menu items on the monitors where workspaces don't take any effect.

https://bugzilla.gnome.org/show_bug.cgi?id=609258
2011-03-17 13:48:54 +01:00
74b97dcd14 Add signals for when windows change monitors
This is useful in order to track e.g. which windows are on the primary
monitor.

https://bugzilla.gnome.org/show_bug.cgi?id=609258
2011-03-17 13:48:54 +01:00
4e28a4d654 Add workspaces_only_on_primary preferences (default FALSE)
This adds a preference that when enabled makes all windows not on
the primary monitor be visible on all workspaces (i.e. not part of the
workspace switching handling).

https://bugzilla.gnome.org/show_bug.cgi?id=609258
2011-03-17 13:48:54 +01:00
9d62d13f88 Split out on_all_workspaces and on_all_workspaces_requested
Sometimes on_all_workspaces is requested by the client/user, and sometimes
its calculated implicitly due to internal state. We split this up so that
we know when the user has explicitly asked for sticky window, when e.g.
setting wmspec properties or storing session info.

on_all_workspaces means this window is visible on all workspaces.

on_all_workspaces_requested, means the user explicitly made the window
sticky somehow (via imported session, _NET_WM_STATE from another wm,
toggled in the window menu, etc). It always implies on_all_workspaces is
TRUE.

Right now the only time we set on_all_workspaces is for override-redirect
windows, but later we can add a "windows on non-primary monitor are not
part of the workspace switching" feature.

https://bugzilla.gnome.org/show_bug.cgi?id=609258
2011-03-17 13:48:54 +01:00
eeca838778 Add meta_window_is_on_primary_monitor function
This is useful in a couple of places to avoid opencoding it.

https://bugzilla.gnome.org/show_bug.cgi?id=609258
2011-03-17 13:48:54 +01:00
d6f0d2c64c Add API to get the monitor of a window
https://bugzilla.gnome.org/show_bug.cgi?id=609258
2011-03-17 13:48:54 +01:00
44cfceba00 Track the monitor for each window
https://bugzilla.gnome.org/show_bug.cgi?id=609258
2011-03-17 13:48:54 +01:00
349fb7c297 MetaWindowActor: keep a reference to the MetaWindow
Until the actor is destroyed, we need to have access to the
MetaWindow to access some fields used for painting. Keep a strong
reference to the window rather than just hoping the window will
not be freed.

https://bugzilla.gnome.org/show_bug.cgi?id=642787
2011-03-16 15:36:55 -04:00
f9b5cdfeb1 Add api to get the primary monitor of the screen
We don't actually use the full xrandr to get the primary monitor, we
just rely on the xrandr xinerama compat code to return the primary
monitor first. This lets us avoid adding unnecessary xrandr code and
avoids issues with _NET_WM_FULLSCREEN_MONITORS monitor indexes being
defined wrt xinerama monitor index order.

https://bugzilla.gnome.org/show_bug.cgi?id=609258
2011-03-16 20:28:33 +01:00
de8eb1f8ee Updated British English translation 2011-03-16 17:53:15 +00:00
0ff602be06 Add MetaScreen::monitors-changed signal
https://bugzilla.gnome.org/show_bug.cgi?id=609258
2011-03-16 10:31:31 +01:00
7246d0ede2 Updated Galician translations 2011-03-15 16:01:35 +01:00
50468b6563 Updated Hungarian translation 2011-03-15 15:21:17 +01:00
6793236642 Updated Romanian translation 2011-03-14 13:42:28 +01:00
d8ccc7896f Updated Romanian translation 2011-03-14 12:59:27 +01:00
defd9aed32 Updated Portuguese translation 2011-03-12 01:54:12 +00:00
6ee1d4348d Uploaded Ukranian 2011-03-11 19:37:45 +02:00
27dbd12d7b Uploaded Ukranian 2011-03-11 19:34:17 +02:00
93fc5c5561 Updated Arabic translation 2011-03-11 15:15:37 +02:00
b48d290064 Updated Polish translation 2011-03-11 09:05:14 +01:00
6bdb3cf115 Updated Italian translation 2011-03-11 02:11:04 +01:00
3b39026ba2 Updated Hebrew translation. 2011-03-10 18:31:45 +02:00
70ffb564ff expose MetaWindow .move(), resize() and add/expose .move_frame()
The latter move method will place the window by the origin of the
enclosing window decoration/frame, while the former will place by the
origin of the inner window, itself.

(Also moved meta_window_showing_on_its_workspace comment into
 gtk-doc)

https://bugzilla.gnome.org/show_bug.cgi?id=642355
2011-03-09 13:49:54 -05:00
4760d043d3 Updated Spanish translation 2011-03-09 19:43:15 +01:00
8405e75931 Updated Slovenian translation 2011-03-09 17:41:13 +01:00
6c4a283b4c Fix initial setting of _NET_WM_STATE on new windows
When reload_net_wm_state() is called at startup to read the initial
value of _NET_WM_STATE, it was calling recalc_window_type(), but not
recalc_features(), which meant that, eg, meta->skip_taskbar would
never get initialized from meta->wm_state_skip_taskbar, which meant
that next time mutter went to update the window's _NET_WM_STATE, it
would overwrite the app-specified initial values. Fix that.

(In metacity, this bug is masked by the fact that recalc_features()
gets called when reading the intial value of WM_NORMAL_HINTS, which
comes after _NET_WM_STATE in metacity's prop_hooks_table. In mutter,
the table got reordered at some point, exposing the bug.)

https://bugzilla.gnome.org/show_bug.cgi?id=624360
2011-03-09 10:21:56 -05:00
7c6b55e79e [l10n] Updated Estonian translation 2011-03-09 14:36:55 +02:00
d8c4b22b88 Updated Catalan translation 2011-03-08 20:41:45 +01:00
bbd98e7b86 Fix ld failure caused by several incomplete LDADD statements
https://bugzilla.gnome.org/show_bug.cgi?id=644188
2011-03-08 11:23:30 -05:00
0536438317 Updated Norwegian bokmål translation 2011-03-08 15:32:29 +01:00
e2151a5fd7 Bump version to 2.91.91 2011-03-07 21:17:35 -05:00
c84da3ce1b Move the installed includes to a subdir
If mutter is going to be a "real" library, then it should install its
includes so that users can do

    #include <meta/display.h>

rather than

    #include <display.h>

So rename the includedir accordingly, move src/include to src/meta,
and fix up all internal references.

There were a handful of header files in src/include that were not
installed; this appears to have been part of a plan to keep core/,
ui/, and compositor/ from looking at each others' private includes,
but that wasn't really working anyway. So move all non-installed
headers back into core/ or ui/.

https://bugzilla.gnome.org/show_bug.cgi?id=643959
2011-03-07 18:19:53 -05:00
bb50f65532 Allow mutter to be used as a library
Move all of the mutter code into a new libmutter-wm.so, split its
main() method into meta_get_option_context(), meta_init() and
meta_run(), add methods for using in-process plugins, and add
libmutter-wm.pc pointing to the new library.

The mutter binary is now just a tiny program that links against
libmutter-wm. The --version and --mutter-plugins options are handled
at the mutter level, not in libmutter-wm, and a few strange unused
command-line options (--no-force-fullscreen and --no-tab-popup) have
been removed.

https://bugzilla.gnome.org/show_bug.cgi?id=643959
2011-03-07 18:19:53 -05:00
28752718c5 Remove meta_restart() / "mutter-message restart"
meta_restart() was broken, in that it restarted mutter with what was
left of argv after GOption and Clutter had possibly modified it.
Rather than try to fix this, just remove it.

https://bugzilla.gnome.org/show_bug.cgi?id=643959
2011-03-07 18:03:43 -05:00
4c76791d4c Remove some unused plugin functionality
Revert the early_initialize changes (which get in the way in the
"libmutter-wm" paradigm), remove the GConf key for setting plugins,
and remove plugin "params", which weren't being used. Also remove all
the logic for unloading and reloading plugins, since the list never
changes after startup now.

https://bugzilla.gnome.org/show_bug.cgi?id=643959
2011-03-07 10:01:37 -05:00
a66ae4ad55 Use standard introspection configure/Makefile bits
This changes the introspection configure flag from
--with/--without-introspection to --enable/--disable-introspection,
and changes it so that trying to enable introspection when g-i is not
installed results in an error, rather than being silently ignored.

https://bugzilla.gnome.org/show_bug.cgi?id=643959
2011-03-06 13:04:58 -05:00
7841e80496 Uploaded Ukranian 2011-03-06 16:25:28 +02:00
27626d14b7 Fix non-GLX build.
Include clutter-x11.h when not building for GLX.
2011-03-02 15:55:51 +02:00
f75e96cd3c introspection: Annotate meta_window_get_rect()
g-ir-scanner assumes (transfer full) for boxeds, and doesn't
warn on missing annotations here.

https://bugzilla.gnome.org/show_bug.cgi?id=643194
2011-02-28 14:08:40 -05:00
9bc1521615 Don't exit on XSMP request
It looks amazingly lame if we simply call exit() during logout.  While
it's true that for applications that use XSMP, gnome-session will
close them before us, that doesn't do anything for non-XSMP apps,
which we really hope is the common case.

Instead, we just go away when the X server does.

https://bugzilla.gnome.org/show_bug.cgi?id=643437
2011-02-28 14:01:08 -05:00
f2158218be plugins: Add early_initialize vfunc
For GNOME Shell, we need to grab our DBus names *before* we talk XSMP.
gnome-session takes our XSMP connection as "I'm ready", and starts
running all the other random crud that people dropped in as autostart
files.  But for example, we need to have claimed
org.freedesktop.Notifications before a lot of said crud starts.

This requires a plugin API version bump.

Misc: Move handling of --version way earlier in main() where
it should be; no point having it wedged after plugin handling.
2011-02-25 14:38:04 -05:00
183190d089 Added Norwegian bokmål translation 2011-02-24 11:29:10 +01:00
ebc3775f19 Updated French translation 2011-02-23 14:37:30 +01:00
97d7e84a04 Bump version to 2.91.90 2011-02-22 22:04:10 -05:00
2b2b728b64 Updated Spanish translation 2011-02-20 15:35:19 +01:00
46fa843b0e Updated Gujarati Translations 2011-02-18 14:16:51 +05:30
e7d336ab0e Don't pass handled key events to GTK+
If we handle a key event then passing it to GTK+ as well can only
cause confusion. Normally GTK+ would do nothing with a key event for
some window it doesn't know about, but plugins might be doing more
things with the GTK+ event queue.

https://bugzilla.gnome.org/show_bug.cgi?id=642426
2011-02-17 11:40:23 -05:00
6e23b0af3b all-keybindings.h: change <Alt>Above_Tab from cycle_group to switch_group
and revert cycle_group back to <Alt>F6 as in GNOME 2.30

https://bugzilla.gnome.org/show_bug.cgi?id=639341
2011-02-15 13:34:32 -05:00
735c33bd9f MetaBackgroundActor: Handle paint opacity
We were ignoring the opacity set on the background actor, causing problems,
e.g., when fading out the workspace thumbnails in GNOME Shell.

https://bugzilla.gnome.org/show_bug.cgi?id=641979
2011-02-12 18:27:09 -05:00
47626a17d7 Update Korean translation 2011-02-13 07:53:47 +09:00
ce86d3f230 Updated Vietnamese translation 2011-02-12 00:31:15 +07:00
31878239c3 po/vi.po: update-po 2011-02-12 00:10:27 +07:00
1133a4ff9c Make plugin loading failure fatal
If a plugin was explicitly specified, falling back to the default
silently is bad; a manager component like gnome-session can
do a better job of handling this scenario.

An example we've hit in gnome-shell is where SpiderMonkey changes
without gjs being rebuilt, and loading the plugin fails due to
unresolved symbols.

But there are obviously others, like the file being missing or
corrupt.

https://bugzilla.gnome.org/show_bug.cgi?id=641384
2011-02-03 14:23:03 -05:00
5822443b20 Updated Italian translation 2011-02-03 18:17:16 +01:00
cf05167c55 [l10n] Updated Estonian translation 2011-02-03 09:44:07 +02:00
a9504f1495 MetaWindowActor: Add a 'position-changed' signal
Similar to the recently added 'size-changed' signal, we may want to do
something in response to a window being repositioned without waiting for
notify::allocation. (Especially since what we can do in notify::allocation
is severely limited by Clutter forbidding queueing an allocation at that
point.)

https://bugzilla.gnome.org/show_bug.cgi?id=641310
2011-02-02 23:55:47 -05:00
3716c30264 When live_hidden_previews is set, force placement for hidden windows
If we are previewing hidden windows, we might be previewing them in a context
like a thumbnail view of a workspace where we care about positioning. So, instead
of waiting until the window is first actually shown to place it, if
live_hidden_previews is set, place the window window when we first compute its
visibility, even if we don't end up showing it.

https://bugzilla.gnome.org/show_bug.cgi?id=641309
2011-02-02 19:19:50 -05:00
c1bf1ec718 Bump version to 2.91.6 2011-02-01 12:25:14 -05:00
8b220079d0 Add ability to override workspace layout
A plugin that does workspace management on its on may want to set the
workspace layout without having to deal with putting a property
on the root window to be read back and parsed.

Add meta_screen_override_window_layout() that allows the same types
of layouts as _NET_DESKTOP_LAYOUT but without setting a property.

https://bugzilla.gnome.org/show_bug.cgi?id=640552
2011-02-01 11:34:56 -05:00
2df95970d9 update Punjabi Translation by A S Alam 2011-01-29 07:49:59 +05:30
a4569974a1 Update Czech translation 2011-01-28 20:36:04 +01:00
c9d3ab772c QA of Galician translations 2011-01-27 03:18:07 +01:00
1a276a2ee5 Don't constantly restack hidden windows
A logic bug was resulting in the bottom hidden window (hidden means means
minimized or on a different workspace) continually being stacked above
the other hidden windows.

https://bugzilla.gnome.org/show_bug.cgi?id=640679
2011-01-26 17:02:17 -05:00
4c4c720dc1 Update _NET_CURRENT_DESKTOP on workspace removal
When we delete a workspace before the active workspace, we need
to upate the _NET_CURRENT_DESKTOP since the active workspace index
changes. To do this workspace.c:set_active_space_hint() is moved
to screen.c:meta_screen_set_active_workspace_hint() so that it
can be shared.

https://bugzilla.gnome.org/show_bug.cgi?id=640581
2011-01-26 17:02:17 -05:00
ad707be01e window-actor: Add "size-changed" signal
Emit a signal when the window size changes. While it is already
possible to connect to notify::allocation (or width/height), the
new signal is emitted outside a clutter allocation cycle, which
makes it more convenient when adjusting an actor's size/position
in response.
2011-01-25 21:32:20 +01:00
19d1f97600 Use G_GNUC_UNUSED to suppress warning
On gcc-4.4 (void)<expr> doesn't suppress warnings from
__attribute__((warn_unused_result)), so use
G_GNUC_UNUSED (which expands to __attribute__((unused))) instead
of removing a dummy variable.

https://bugzilla.gnome.org/show_bug.cgi?id=640508
2011-01-25 08:39:20 -05:00
4f079affea Fix set but not used variables
GCC 4.6 warns about variables that are set but never subsequently
used; fix all such instances.

https://bugzilla.gnome.org/show_bug.cgi?id=640469
2011-01-24 16:26:57 -05:00
b4888103a6 display: Don't crash on Alt-Escape.
Fix a crash caused by 286160646b, where
we don't get a window when called from do_choose_window.

https://bugzilla.gnome.org/show_bug.cgi?id=640229
2011-01-24 19:38:55 +01:00
e2364b82ef Updated Swedish translation 2011-01-23 10:23:31 +01:00
ba92645044 Updated Norwegian bokmål translation 2011-01-20 19:20:25 +01:00
2eb8b09b1a Restore the original tile state when a drag is cancelled
If a drag operation is cancelled, the dragged window should be
restored to its previous state/position. Implement this for tiled
states.

https://bugzilla.gnome.org/show_bug.cgi?id=639988
2011-01-20 18:49:48 +01:00
bca610ed50 Hide tile preview when cancelling a drag with Escape
As the tile preview is shown or hidden when a window is dragged
around, it may stick around if the drag operation is cancelled.
Make sure that the preview is hidden in this case.

https://bugzilla.gnome.org/show_bug.cgi?id=639988
2011-01-20 18:49:48 +01:00
53d6938b55 screen: Add a method to hide the tile preview unconditionally
Add meta_screen_tile_preview_hide() to hide the tile preview
independent from the tile state of the dragged window.

https://bugzilla.gnome.org/show_bug.cgi?id=639988
2011-01-20 18:49:48 +01:00
286160646b display: Keep track of the original tile state during drag
Drag operations may be cancelled, in which case the dragged window
should be restored to the position/state it had when the drag was
initialized. In order to do this for tiled states, the original
state has to be saved during the operation.

https://bugzilla.gnome.org/show_bug.cgi?id=639988
2011-01-20 18:49:48 +01:00
58068260a5 window: Make meta_window_tile() semi-public
The previous tiling state of a grabbed window should be restored
if the drag operation is cancelled (by hitting the Escape key).
This might involve to meta_window_tile(), so export the function
in window-private.h.

https://bugzilla.gnome.org/show_bug.cgi?id=639988
2011-01-20 18:49:48 +01:00
57e8ce0d42 Updated Traditional Chinese translation(Hong Kong and Taiwan) 2011-01-20 22:41:41 +08:00
4ed1e8b3e2 Updated Greek translation 2011-01-19 18:12:00 +02:00
8181454af5 MetaWindowActor: Add meta_window_actor_is_destroyed
Add a meta_window_actor_is_destroyed method which gets
whether the X window that the actor was displaying has been destroyed.

https://bugzilla.gnome.org/show_bug.cgi?id=639853
2011-01-18 19:35:41 +01:00
aa482e6d4f Updated Hungarian translation 2011-01-18 15:56:29 +01:00
0c9b2c6757 Fix a word repetition 2011-01-18 15:55:09 +01:00
bbfc435a5c Teach meta_display_get_keybinding_action() about "Above_Tab" pseudo-keysym
https://bugzilla.gnome.org/show_bug.cgi?id=639532
2011-01-16 13:55:41 -05:00
7e53094044 default plugin: Clean up unused n_workspaces variable.
n_workspaces is unused, which may cause compilation
errors under certain environments.

https://bugzilla.gnome.org/show_bug.cgi?id=639458
2011-01-16 13:54:31 -05:00
565f002bc4 ui: Port to GtkStyleContext
GtkStyle has been deprecated in favor of GtkStyleContext. A full
port would involve replacing GdkColor with GdkRGBA - leave this
out for the time being.

Bump the required version of GTK+.

https://bugzilla.gnome.org/show_bug.cgi?id=637761
2011-01-13 18:55:39 +01:00
42fdd4f4d8 Updated Bulgarian translation 2011-01-12 23:45:34 +02:00
217aa2898e Updated Arabic translation 2011-01-12 11:33:42 +02:00
02e7c1bb2b Updated Arabic translation 2011-01-12 11:32:02 +02:00
bb57a8b6f3 Bump version to 2.91.5 2011-01-11 14:55:19 -05:00
65d0f1a213 [l10n] Updated Estonian translation 2011-01-09 20:42:28 +02:00
4344b7ba69 [l10n] Updated Estonian translation 2011-01-07 10:17:03 +02:00
b0072add05 [l10n] Updated Estonian translation 2011-01-06 19:25:30 +02:00
4ea00e102b Add an "Above_Tab" pseudo-keysym
We want switching between the windows of an application to be an easily
accessible operation. The convenient and memorable keybinding is the
key above the tab key - but the keysym for that key isn't consistent
across different keyboard layouts.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

The way this is current done is:

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

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

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

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

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

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

This commit renames the preference from side_by_side_tiling to
edge_tiling.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

* Remove TidyTextureFrame, which is no longer used

https://bugzilla.gnome.org/show_bug.cgi?id=592382
2010-11-18 09:47:56 -05:00
982a10ac44 Added UG translation 2010-11-14 00:06:42 +01:00
e59a9872b4 Added UG translation 2010-11-13 22:49:22 +01:00
9aedd32e01 Use gtk_button_box_new() instead gtk_[h|v]button_box_new() 2010-11-11 01:25:35 +01:00
dd0ca4dd60 Updated Arabic translation 2010-11-09 03:40:15 +02:00
170 changed files with 48137 additions and 50055 deletions

2
.gitignore vendored
View File

@ -43,7 +43,7 @@ POTFILES
50-metacity-desktop-key.xml
50-metacity-key.xml
inlinepixbufs.h
libmutter-private.pc
libmutter.pc
mutter
mutter-theme-viewer
mutter.desktop

769
NEWS
View File

@ -1,3 +1,772 @@
3.0.2
=====
* Fix a crash when running without XKB support [Adam]
https://bugzilla.gnome.org/show_bug.cgi?id=647777
* Fix smallish memory leaks [Colin]
https://bugzilla.gnome.org/show_bug.cgi?id=649500
https://bugzilla.gnome.org/show_bug.cgi?id=649504
* Ignore mirrored monitors when listing monitors, fixing
drag-and-drop problems in GNOME Shell [Owen]
https://bugzilla.gnome.org/show_bug.cgi?id=649299
* Don't allow side-by-side tiling of non-maximizable windows
like dialogs and utility windows [Dan]
* Fix interaction of _NET_WM_WINDOW_OPACITY with window effects,
making it work again with GNOME Shell
https://bugzilla.gnome.org/show_bug.cgi?id=648613
Contributors:
Adam Jackson, Colin Walters, Dan Winship
Translations:
Abduxukur Abdurixit [ug]
3.0.1
=====
* If WM_CLIENT_MACHINE isn't set, don't assume a window is remote;
fixes behavior of Fox toolkit applications under GNOME Shell.
https://bugzilla.gnome.org/show_bug.cgi?id=647662 [Colin]
* Fix cases where windows could get stuck drawing as focused after
an attached modal dialog was closed. [Dan]
https://bugzilla.gnome.org/show_bug.cgi?id=647613
* Fix a bug where a window that is too big to be tiled side-by-side
would behave strangely when using the gesture of dragging to
the top to maximize. [Florian]
Contributors:
Florian Müllner, Colin Walters, Dan Winship
Translations:
Amitakhya Phukan [as], Kristjan Schmidt [eo], Muhammet Kara [tr]
3.0.0
=====
* Avoid crashing when you have a single window and try to move it between
workspaces. [Dan]
https://bugzilla.gnome.org/show_bug.cgi?id=642957
Contributors:
Dan Winship
Translations:
Jordi Serratosa [ca], Petr Kovar [cz], Ask H. Larsen [da], Bruce Cowan [en_GB],
Inaki Larranaga Murgoitio [eu], Gabor Kelemen [hu], Dirgita [id], Shankar Prasad [kn],
Changwoo Ryu [ko], Wouter Bolsterlee [nl], Duarte Loreto [pt],
Antonio Fernandes C. Neto, Rodrigo Padula de Oliveira [pt_BR], T. Vasudevan [ta],
Nguyễn Thái Ngọc Duy [vi], Chao-Hsiung Liao [zh_HK, zh_TW]
2.91.93
=======
* Fix bug where, when a monitor was hot-plugged, all workspaces
would collapse to a single workspace. (There are still issues
when a secondary monitor is hot-plugged to the left of the
primary monitor.) [Alex]
https://bugzilla.gnome.org/show_bug.cgi?id=645408)
* Fix a crash for the cycle_group action [Jasper]
https://bugzilla.gnome.org/show_bug.cgi?id=645843
* Fix misdrawing of window shadows on some focus changes [Dan]
https://bugzilla.gnome.org/show_bug.cgi?id=636904
* Export meta_get_replace_current_wm() to allow fixing a
GNOME Shell bug with --replace [Colin]
https://bugzilla.gnome.org/show_bug.cgi?id=645590
Contributors:
Alexander Larsson, Jasper St. Pierre, Colin Walters, Dan Winship
Translations:
Alexander Shopov [bg], Christian Kirbach [de], Yaron Shahrabani [he],
Rudolfs Mazurs [lv], A S Alam [pa], Yuri Myasoedov [ru], Daniel Nylander [se],
Abduxukur Abdurixit [ug], Daniel Korostil [uj], Aron Xu [zh_CN]
2.91.92
=======
* Add a workspaces_only_on_primary preferences. When set, this makes
workspaces switching only apply to windows on the primary monitor,
while windows on other monitors are unaffected.
* Export API for monitor handling [Alex]
MetaScreen::monitors-changed signal
meta_screen_get_primary_monitor()
meta_window_is_on_primary_monitor()
meta_window_get_monitor()
MetaWindow::window-entered-monitor, <etaWindow::window-left-monitor
meta_window_move_to_monitor() [Florian]
* Behavior improvemnts for attached modal dialogs:
- Allow dragging dragging on the titlebar to move the parent ["Ron"]
- Allow resizing [Florian]
- Constrain to be on the current monitor [Florian]
* Don't turn on XSMP autorestart [Colin]
* Combine libmutter-wm and libmutter-private into a single libmutter
[Frédéric]
* Export methods to move and resize windows [Jeffery]
meta_window_move(), meta_window_resize(), meta_window_move_frame()
* Add a MUTTER_WM_CLASS_FILTER environment variable to allow existing
windows to be ignored when performance testing. [Owen]
* Add a new compositor-based flash for visual bell [Dan]
* Fix bug where application specified values for properties like
"skip taskbar" were sometimes ignored [Dan]
* Bug fixes [Dan, Florian, Giovanni, Jasper, Owen]
* Build fixes [Rico]
Contributors:
Giovanni Campagna, Florian Müllner, Alexander Larsson, Jeffery Olson,
Frédéric Péters, Owen Taylor, Jasper St. Pierre, Rico Tzschichholz,
"Ron", Colin Walters, Dan Winship
Translations:
Khaled Hosny [ar], David Planella [ca], Mario Blättermann [de],
Bruce Cowan [en_GB], Jorge González, Daniel Mustieles [es], Ivar Smolin [et],
Bruno Brouard [fr], Fran Diéguez [gl], Yaron Shahrabani [he],
Gabor Kelemen [hu], Luca Ferretti [it], Kjartan Maraas [nb], Piotr Drąg [pl],
Duarte Loreto [pt], Lucian Adrian Grijincu, Adi Roiban [ro],
Yuri Myasoedov [ru], Matej Urbančič [sl], Daniel Korostil [uk]
Bugs fixed:
624360 window shows up in when pressing alt+tab, but skip_taskbar_hint is set to True
631308 Dialogs attached to parent sometimes extend out of the screen
638674 [PATCH] Allow moving attached dialogs
639765 a11y: visual alert only works per-window, not screen
641975 Pre-_NET_WM_ICONs look corrupted
642355 patch to expose MetaWindow.move(), .resize() and add/expose .move_frame() to javascript
642787 MetaWindowActor has a dangling reference to its MetaWindow
643597 Attached dialogs not resizable, even by app request
644188 Broken build of 2.91.91
644252 Add MUTTER_WM_CLASS_FILTER environment variable
644529 session: Change XSMP restart style to Never
644565 Kill libmutter-private ?
644961 auto-tiling makes moving already-tiled windows hard
645224 Translation message doesn't make much sense
645247 Methods of Meta.Rectangle are missing annotations.
645455 tiling: Fix dragging windows free from edge-tiling
2.91.91
=======
* Build a libmutter-wm that contains all of the logic and that
can be linked to to create custom executables. The mutter executable
becomes a small stub linked to this library [Dan]
* Move installed headers files into a meta/ subdirectory instead
of polluting the toplevel namespace [Dan]
* Remove various unused complications: [Dan]
- Ability to set the set of plugins via GConf
- Plugin 'params'
- meta_restart() and "mutter-message restart"
* Don't exit when we are requested to exit via XSMP, assume we'll be
killed along with the X server; this avoids visual artifacts from
unmanaging windows when logging out [Colin]
* Build fixes [Dan, Jani, Jeff]
Contributors:
Jani Monoses, Jeff Olson, Colin Walters, Dan Winship
Translations:
Bruno Brouard [fr], Kjartan Maraas [nb], Daniel Korostil [uk]
Bugs fixed:
643194 patch: expose new meta_window_get_window_rect
643437 Don't exit on XSMP request
643959 Make mutter into a library
2.91.90
=======
* Change <Alt>Above_Tab from being a cycle_group binding to
a switch_group binding [Rui]
* Make plugin-loading failure fatal [Colin]
* Add 'position-changed' signal to MetaWindowActor [Owen]
* When 'live_hidden_previews' is enabled, position hidden windows
to allow the creation of workspace previews [Owen]
* Fix bug with opacity of MetaBackgroundActor
Contributors:
Rui Matos, Owen Taylor, Colin Walters
Translations:
Jorge González [es], Mattias Põldaru [et], Sweta Kothari [gu], Luca Ferretti [it],
Changwoo Ryu [ko], Nguyễn Thái Ngọc Duy [vi]
Bugs fixed:
641309 When live_hidden_previews is set, force placement for hidden windows
641310 MetaWindowActor: Add a 'positioned-changed' signal
641979 Visual glitch on workspace selector closing overview mode
641384 Make plugin loading failure fatal
642426 Don't pass handled key events to GTK+
2.91.6
======
* Add meta_screen_override_window_layout() to let a plugin set the workspace
layout [Owen]
* Add a 'size-changed' signal to MetaWindowActor [Florian]
* Add meta_window_actor_is_destroyed() [Adel]
* Fix problems with window tile previews when cancelling a move [Florian]
* Port theme elements that use GTK+ drawing to use GtkStyleContext instead
of the deprecated GtkStyle. [Florian]
* Fix compiler warnings that were causing compilation failures [Jasper, Owen]
* Misc bug fixes [Gabor, Jasper, Owen, Rui]
Contributors:
Adel Gadllah, Gabor Kelemen, Rui Matos, Florian Müllner, Jasper St. Pierre,
Owen Taylor
Translations:
Khaled Hosny [ar], Alexander Shopov [bg], Petr Kovar [cz], Fran Diéguez [gl],
Marios Zindilis [gr], Gabor Kelemen [hu], Kjartan Maraas [nb], A S Alam [pa],
Daniel Nylander [se], Chao-Hsiung Liao [zh_HK, zh_TW]
2.91.5
======
* Add a Above_Tab key symbol that can be used in key bindings to mean
the key above the Tab key. This is now the default binding for
cycle_group in both Mutter and Metacity. [Owen]
* Add new frame states for tiled-on-the-left and tiled-on-the-right [Florian]
* Add new background drawing functions that can be defined in a theme
for single buttons. [Florian]
* Draw the right button backgrounds for all custom button layouts [Florian]
* Remove vestigal --composite/--no-composite command line options [Nickolas]
* Fix building on GLES [Andreas]
* Code cleanups [Adel, Owen]
Contributors:
Adel Gadllah, Nickolas Lloyd, Andreas Mueller, Florian Müllner, Owen Taylor
Translations:
Mattias Põldaru, Ivar Smolin [et], Gheyret T. Kenji [ug]
Bugs fixed:
613124 Invalid visibility-related asserts in MutterWindow
626875 Fix handling of --composite and --no-composite command line options
629282 [PATCH] Fix errors building for gles-systems (clutter-eglx)
635569 Add an "Above_Tab" pseudo-keysym
635683 add specific button background for single button (per side) case
635686 button backgrounds broken with rtl locales
637330 [PATCH] theme: Add tiled_left/tiled_right frame states
2.91.4
======
* Update for GTK+ 3 changes [Benjamin, Colin, Emmanuele, Florian]
* Support maximizing a window by dragging to the top of the screen
in the same way you can tile by dragging to the edge of the screen.
[Ray, Florian]
* Misc bug fixes [Milan, Owen]
Contributors:
Emmanuele Bassi, Milan Bouchet-Valat, Florian Müllner, Benjamin Otte,
Ray Strode, Owen Taylor, Colin Walters
Translations:
Matej Urbančič [sl], Nguyễn Thái Ngọc Duy [vi]
Bugs fixed:
630548 gnome-shell could auto-maximize windows when dragged to top edge of screen
636083 workspace: Consider text direction when switching
636301 Port testgradient example to GTK3
636302 Replace some GDK X11 calls with future-proof ones
636491 valgrind: meta_window_shape_new (meta-window-shape.c:79)
637802 ui: Adapt to GDK API changes
2.91.3
======
* Better shadows: [Owen]
- Shadows can be different for different window types and focus states
- Shadows are larger by default, especially for the currently active
window
- Shadows for attached modal dialogs and menus are drawn not to
overlap the attachment point.
- Shadows follow the shape of shaped windows
* Optimization: [Owen]
- Avoid repainting in situations when windows are potentially restacked
but aren't actually restacked.
- Pay attention to partial stage repaints in obscured window calculations
- Better optimization of painting obscured shadows; turn off shadows
for maximized windows.
- Move background repainting into Mutter; doing it here rather than
in plugins allows not painting obscured parts of the background.
* A new frame type 'attached' is added for attached modal dialogs
and can be referenced in theme files with a theme version of 3.2.
* Fix updating key bindings when the keyboard layout changes
[Derek, Owen, Thomas]
* Bug fixes [Adel, Florian]
* Build fixes [Dan Williams, Diego, Javier, Owen]
Contributors:
Adel Gadllah, Javier Jardón, Florian Müllner, Derek Poon, Owen Taylor,
Thomas Thurman, Diego Escalante Urrelo, Dan Williams
Translations:
Khaled Hosny [ar], Jorge González [es], Fran Diéguez [gl],
Yaron Shahrabani [he], Kjartan Maraas [nb], Gheyret T. Kenji [ug]
Bugs fixed:
634779 MetaWindowGroup: further optimize paints by using current scissor
634833 Draw the root window background
592382 improve shadow effect
628199 Add antialising to arc and line drawing operations
633002 meta-actor-window: Use G_UNLIKELY for TFP check
634771 MetaStackTracker: Avoid queueing resync for obvious no-ops
635421 Fix crash in check_needs_shadow
635493 configure.in: it's git, not Subversion
635528 configure.ac: move call to AM_GNU_GLIB_GETTEXT above cflags modification
635575 meta-window-actor: remove unused meta_window_actor_get_shadow_bounds
636083 workspace: Consider text direction when switching
2.91.2
======
* Remove support for GTK+ 2 [Florian]
* Adapt to deprecation of size_request deprecation in GTK+ [Matthias]
* Include change from Metacity to fix confusion of mouse
tracking when double-clicking on title bar [Owen]
* Fix bug with the the window menu getting stuck when you alt-Tab [Owen]
Contributors:
Matthias Clasen, Florian Müllner, Owen Taylor
Translations:
Petr Kovar [cz]
Bugs fixed:
633133 Remove compatibility for GTK+-2.0
633352 prepare for the demise of size_request
633398 Fix check for events on UI widgets
633401 Fix warning from synthesized events with GdkDevice
2.91.1
======
* Default build is now GTK+ 3 build
* Mutter namespace prefix is removed, in favor of consistent
meta_ namespace prefixing [Owen]. Naming changes:
MutterWindow => MetaWindowActor
mutter_get_windows => meta_get_window_actors
mutter_plugin_get_windows => meta_plugin_get_window_actors
* Add missing values in MetaKeyBindingAction - this fixes a problem where
key binding lookup wasn't working properly for some key bindings. [Dan]
* Remove keysym parameter to meta_display_get_keybinding_action() - the
function expected the default keysym for the keycode to always be passed [Dan]
* Clean up installed header files - in particular, theme-parser.h is merged
into a new public-only theme.h and private internals are moved to
theme-private.h.
* Fix problems with antialiased rendering of themes [Brandon, Owen, Nickolas]
* Fix problem with parsing color constants in themes [Jon, Owen]
* Build fixes [Colin]
* Miscellaneous bug fixes [Giovanni, Rico]
Contributors:
Giovanni Campagna, Nickolas Lloyd, William Jon McCann, Owen Taylor,
Rico Tzschichholz, Colin Walters, Dan Winship, Brandon Wright
Translations:
Fran Diéguez [gl], Yinghua Wang [zh_CN]
Fixed bugs:
628401 tint and line draw ops rendering issues
628520 unfortunate namespacing
631487 Fix drawing of <arc> theme elements
632116 don't clobber gerrors
632149 Fill in missing MetaKeyBindingAction values
632155 meta_display_get_keybinding_action: remove keysym parameter
632474 Remove MetaRegion
632494 introspection: remove --allow-unprefixed
2.91.0
======
* Enable side-by-side tiling via a gesture of dragging to the left or right
edge of the screen. (enabled with an off-by-default GConf key) [Florian]
* Allow breaking out of maximization/tiling using a alt-middle-button window
resize [Owen, Florian]
* Add the ability to have modal dialogs attached to their parent window
(enabled with an off-by-default GConf key) [Maxim]
* Draw with Cairo rather than GDK [Florian, Benjamin]
* Add compatibility for changes in GTK+ 3
[Benjamin, Alban, Florian, Jasper, Matthias, Owen, Thierry]
- libmutter-private is now only installed for GTK+ 3 builds
- Theme parts of libmutter-private API are changed to take cairo_t
rather than GdkDrawable
* Update introspection build and annotations for new behavior of
g-ir-scanner [Colin]
* Fix bug that caused window menu options not to work [Owen]
* Fix misbehavior of Wine windows [Owen, Alban]
* Fix crashes from missing error traps [Adel]
* Build fixes [Colin, Florian, Owen, Rob, Tomas]
* Misc bug fixes [Adel, Jon, Owen, Nickolas, Tomas]
* Cleanups [Adel, Benjamin, Florian]
Contributors:
Alban Browaeys, Matthias Clasen, Maxim Ermilov, Tomas Frydrych, Adel Gadllah,
Nickolas Lloyd, William Jon McCann, Florian Muellner, Benjamin Otte,
Thierry Reding, Rob Staudinger, Jasper St. Pierre, Owen Taylor, Colin Walters
Translations:
Alexander Shopov [bg], Mario Blättermann [de], Ask H. Larsen [dk],
Michael Kotsarinis [el], Philip Withnall [en_UK], Jorge González [es],
Fran Diéguez [gl], Bruno Brouard, Claude Paroz [fr], Yaron Shahrabani [he],
Gabor Kelemen [hu], Luca Ferretti [it], Nils-Christoph Fiedler [nds],
Kjartan Maraas [nb], A S Alam [pa], Piotr Drąg [pl], Duarte Loreto [pt],
Antonio Fernandes C. Neto [pt_BR], Matej Urbančič [sl],
Miloš Popović [sr, sr@latin], Tirumurti Vasudevan [ta], Aron Xu [zh_CN],
Chao-Hsiung Liao [zh_HK, zh_TW]
Fixed Bugs:
597763 With >2 workspaces, Window menu "Move to Another Workspace" menu doesn't work
598603 displays window size when moving terminal window
606158 "Always on top" triggers Window manager warning:
Log level 8: meta_window_set_user_time: assertion `!window->override_redirect' failed
610575 make meta_screen_set_cursor public
613126 Do not cancel Alt+Tab grab due to Shift key events
623235 BadDamage error from XSubtractDamage
624757 Check for TFP usage after actually setting the pixmap
625712 [mutter-shaped-texture] Remove material_workaround
626583 Replace Gdk drawing API with cairo
627087 Mipmap emulation not working
627210 Crash with X error
628544 introspection: Build with --warn-fatal, drop fix-meta-rectangle.py hack
629127 build problem with recent gtk3
629232 Multiple syntax errors in file mutter-message.c when building Mutter for
GNOME Shell dependencies
629350 [mutter-shaped-texture] Use a base material for all instances
629931 Allow breaking out from maximization/tiling during a mouse resize
630195 Use GDK error trapping straight-up
630203 Prepare mutter code for GTK3 rendering-cleanup
630671 prepare mutter for the demise of GtkObject
630843 gtk_window_set_visual was replaced by gtk_widget_set_visua
631147 Adapt to GTK API changes
631175 Mutter error compiling Gnome Shell
2.31.5
======
* Support building with GTK+ 3.0 [Florian]
* Remove deprecated usages for compatibility with GTK+ 3.0
[Claudio, Florian, Nickolas]
* Export a boxed type for MetaRectangle [Owen]
* Allow disabling -Werror with --enable-compile-warnings=yes [Nickolas]
* Build fixes [Andreas, Florian, Owen]
Contributors:
Nickolas Lloyd, Andreas Mueller, Florian Müllner, Claudio Saavedra,
Owen Taylor
Translations:
Petr Kovar [cz], Jorge González [es], Fran Diéguez [gl],
Yaron Shahrabani [he], Matej Urbančič [sl]
Fixed Bugs:
587991 - Remove deprecated GTK+ symbols
616275 - -Werror should not be enabled by default (or should be possible to disable)
622303 - Allow building with Gtk+-3.0
622800 - Make mutter more gtk+ 3.0 friendly
623335 - Make MetaRectangle a boxed type
623639 - Work around g-ir-scanner problem with Gdk.Rectangle
624166 - src/core/util.c: Fix warning in case WITH_VERBOSE_MODE is not set
2.31.4
======
* Clean up MutterPlugin effect interface [Maxim]
* Track damage as the bounding box, a significant optimizations
for rapidly drawing clients [Robert]
* Add meta_window_is_remote() [Colin]
* Add meta_add_debug_topic() for turning on logging of
specific topics [Colin]
* Fix bug with window unmaximization [Owen]
Contributors:
Robert Bragg, Maxim Ermilov, Owen Taylor, Colin Walters
Translations:
Yaron Shahrabani (he), Fran Diéguez (gl), Kjartan Maraas (nb), A S Alam (pa)
Fixed Bugs:
611838 - expose sub-stage redraws by streaming raw updates to ClutterX11TexturePixmap
620585 - Add meta_window_is_remote
620860 - function meta_display_open
621082 - MutterPluginManager should call plugin->switch_workspace,
when screen doesn't have any window. Or function should be renamed.
621413 - Maximize/Unmaximize not behaving properly for some non-gnome based programs
2.31.2
======
* Theme enhancements [Owen]
- Add a flexible version mechanism for themes -
metacity-theme-3.xml is now supported, and can include
version="> 3.2" type attributes on the root element or
any subelement.
- Add frame_x_center/frame_y_center variables
- Allow a theme to turn on title ellipsization
* Performance enhancements:
- Stream raw damage updates to ClutterX11TexturePixmap
to enable partial stage updates when windos change [Robert]
- Don't trap XErrors in meta_compositor_process_event [Adel]
* Add meta_prefs_override_preference_location(); this allows
a plugin like GNOME Shell to redirect preferences to a
plugin-specific location. [Owen]
* Support a _MUTTER_HINTS window property; this is a string
property holding key-value pairs with plugin-specific
interpretation [Tomas]
* Build with GSEAL_ENABLE [Florian, Javier]
* Add meta_display_get_leader_window() [Tomas]
* Add meta_display_sort_windows_by_stacking [Colin]
* Export
meta_display_get_last_user_time()
meta_display_xserver_time_is_before()
meta_window_foreach_ancestor(),
meta_window_foreach_transient()
meta_window_lower()
meta_window_raise()
meta_window_set_demands_attention()
meta_window_unset_demands_attention() [Colin]
* Bug fixes [Dan, Edward, Owen, Tomas]
* Build fixes [Owen, Dominique, Vincent]
Contributors:
Robert Bragg, Adel Gadllah, Tomas Frydrych, Javier Jardón,
Dominique Leuenberger, Florian Müllner, Edward Sheldrake,
Owen Taylor, Vincent Untz, Colin Walters, Dan Winship
Translations:
Xandru Armesto Fernandez (ast), Khaled Hosny (ar), Petr Kovar (cz),
Mario Blättermann, (de), Jorge González (es),
Inaki Larranaga Murgoitio [eu), Claude Paroz (fr), Luca Ferretti (it),
Gintautas Miliauskas (lt), Pavol Šimo (sk), Matej Urbančič (sl)
Fixed Bugs:
591842 - ellipsize titles when oversize
592503 - Add a flexible version mechanism
595496 - Use accessor functions instead direct access (use GSEAL GnomeGoal)
596659 - Fix handling of grabbed key events
613123 - Framework for plugin-specific per-window hint
613125 - Add meta_display_get_leader_window()
613127 - Keep num_workspaces key in sync with the actual workspace number
613136 - remove over-restrictive assert from meta_prefs_get_workspace_name()
613398 - Don't trap XErrors in meta_compositor_process_event
615586 - Allow redirecting preferences to a different GConf key
615672 - cant' compile mutter error: dereferencing pointer p does break
strict-aliasing rules
616050 - alt-tab infrastructure patches
616274 - mutter from git fails with gcc 4.5 (on new warning)
616546 - On dual screen maximized windows dragged to the second screen no
longer update their contents
618138 - Work around COGL bug causing flash for new windows
618613 - Fix crash with --sync option
2.29.1
======
* Support and require Clutter 1.2 (Owen)
* Add meta_display_get_keybinding_action() (Colin, Dan)
* Add meta_window_get_wm_class_instance() (Tomas)
* Remove workaround for bug fixed in intel driver Q2/2009 release (Robert)
* Build fixes (Owen, Brian, Nguyễn Thái Ngọc Duy)
Contributors:
Robert Bragg, Brian Cameron, Tomas Frydrych, Nguyễn Thái Ngọc Duy,
Owen Taylor, Colin Walters, Dan Winship
Translations:
Alexander Shopov (bg), Mario Blättermann (de), Bruno Brouard (fr),
Nils-Christoph Fiedler (nds), Piotr Drąg (pl), Aron Xu (zh_CN)
Fixed Bugs:
610862 Support and require Clutter 1.1
612506 mutter 2.29.0 fails to compile on Solaris
613100 [MetaDisplay] Expose meta_display_get_keybinding_action
613121 Remove workaround for multitexturing with old intel drivers
613128 [MetaWindow] Accessor for the instance part of WM_CLASS property
613278 meta_display_get_keybinding_action: strip out uninteresting modifiers
2.29.0
======
* Improve appearance of scaled down windows using mipmap emulation (Owen)
* Added signals: MetaDisplay::window-created, MetaDisplay::window-marked-urgent,
MetaDisplay::window-demands-attention, MetaWindow::unmanaged (Colin, Tomas)
* Added properties: MetaWindow:demands-attention, MetaWindow:urgent,
MetaWindow:maximized-horizontally, MetaWindow:maximized-vertically (Florian, Tomas)
* Fix nasty crash when workspace "struts" changed during a window move (Jon, Owen)
* Bug fixes (Dan, Maxim, Neil, Owen, Tomas)
* Build fixes (Colin, Emmanuele, Nickolas, Owen, Richard)
* Merge Metacity changes since 2.26. Includes themable sound support
via libcanberra (Owen)
Contributors
Emmanuele Bassi, Maxim Ermilov, Tomas Frydrych, Richard Hughes, Nickolas Lloyd,
Florian Müllner, Jon Nettleton, Neil Roberts, Owen Taylor, Colin Walters,
Dan Winship
Additional Metacity contributors:
Thomas Hindoe Paaboel Andersen, Peter Bloomfield, Matthias Clasen,
Matt Kraai, Claude Paroz, Lennart Poettering, Ray Strode, Thomas Thurman,
Vincent Untz, Tomislav Vujec, Tomeu Vizoso, Travis Watkins, 'alexisdm59'
Translations:
Khaled Hosny (ar), Petr Kovar (cz), Kjartan Maraas (nb), Djavan Fagundes (pt_BR),
Nils-Christoph Fiedler (nds), Matej Urbančič (sl), Vincent Untz
Fixed Bugs:
588065 Adds demands-attention signal to the window class
591913 Fails to skip current window on alt+tab when another window is asking for attention
592567 Dereferencing NULL in mutter_window_get_workspace()
597052 Add signal to MetaDisplay so we know when a window has demanded-attention
598289 Add "window-created" signal to MetaDisplay, "unmanaged" signal for MetaWindow
598473 "XXX specified twice for this theme" messages not in sync with metacity.
598600 "Visual Bell" option in Metacity causes Mutter to crash
600068 notifications for window urgency hint
601228 rdesktop does not get keypress signals
602349 [PATCH] trivial - fix compilation warning in mutter
602740 Remove XOR gc only used in removed reduced-resources mode
602870 Fix compilation with older libGL
604200 Compile issue: Use of deprecated clutter functions
606388 mutter fails to build when using ld with --no-add-needed
607125 Fails to build with latest introspection data
607398 Do not use CGL_* symbols
607746 reduce gconf roundtrips at startup
608800 alt-dragging gimp windows crashes gnome-shell
609350 Mutter does not support the COGL_DEBUG environment variable
609546 meta_workspace_set_builtin_struts(): optimize out non-changes
609585 Merge libcanberra usage from Metacity
609657 Use cogl multitexture API when drawing MutterShapedTexture
609665 Bug fixes from Fedora RPM
609710 screencast recording broke
610391 Fix crash on startup with list bindings
2.28.0
======
* New exported API:
meta_window_get_stable_sequence() [Colin]
meta_window_get_transient_for_as_xid() [Tomas]
MutterScreen::workareas-changed signal [Tomas]
* Fix a problem where changes processed from a Clutter event
callback wouldn't get handled before the screen was next
repainted, causing flashing [Owen]
* Remove MetaAltTabHandler as no longer needed [Dan]
* Bug fixes [Colin, Owen]
Contributors:
Tomas Frydrych, Owen Taylor, Colin Walters, Dan Winship
Translations:
Christian Kirbach (de), Claude Paroz (fr)
2.27.5
======
* Fix bug in GConf schemas where the overview activation key was specified as
'<Super_L>' not 'Super_L'.
Contributors:
Colin Walters
Translation:
Denis Arnaud (br)
2.27.4
======
* Big code cleanup: when talking about multiple monitors, call them
"monitors", not "xineramas". [Dan]
* Accessors added or made public:
meta_screen_get_n_monitors(), meta_screen_get_monitor_geometry()
meta_window_get_user_time() and MetaWindow:user-time property.
[Colin, Dan]
* Set _GNOME_WM_KEYBINDINGS=Metacity,Mutter on the _NET_SUPPORTING_WM_CHECK
window so that gnome-keybinding-properties can figure out to show the
Metacity keybindings when Mutter is running. [Owen]
* Bug and build fixes [Colin, Owen]
Contributors:
Owen Taylor, Colin Walters, Dan Winship
Translation:
Jorge González (es), Inaki Larranaga Murgoitio (eu), Gabor Kelemen (hu)
Bugs fixed:
592393 - Clicking on a minimized window in the overview doesn't focus the window
593399 - Add meta_display_get_grab_op()
593404 - Make MUTTER_DEBUG_XINERAMA override active Xinerama
593407 - Add 'skip-taskbar' accessor to MetaWindow.
593686 - Add meta_screen_get_monitors()
594067 - Export a _GNOME_WM_KEYBINDINGS property
2.27.3
======
* Key handling improvements:
- enforce that every key is handled no more than once.
- mutter_plugin_begin_modal() and mutter_plugin_begin_modal() allow
putting a plugin into a "modal" state where it has exclusive access
to key and pointer events.
- Add "tab_popup_select", "tab_pop_cancel" pseudo-keypress-handlers
that plugins can use to get notification when Alt-Tab ends
[Owen]
* Accessors added or made public:
meta_window_is_override_redirect(), meta_window_is_mapped(),
meta_display_xwindow_is_a_no_focus_window(),
meta_display_get_grab_op(), meta_window_is_skip_taskbar(),
meta_window_is_modal(), all of errors.h
[Colin, Owen, Michael, Steve, Tomas]
* Fix for various GTK+ deprecations [Javier]
* Bug fixes [Colin, Frédéric, Owen, Thomas, Tomas, Volker]
Contributors:
Javier Jardón, Steve Frécinaux, Tomas Frydrych, Michael Meeks,
Frédéric Péters, Volker Sobek, Owen Taylor, Thomas Thurman,
Colin Walters
Translation:
Fran Dieguez (gl), Gabor Kelemen (hu), Daniel Nylander (se)
Bugs fixed:
589457 - Fix up window property notification for "title"
590911 - Do not run plugin effects on WM startup
590978 - API to query whether window is in modal state
591367 - Be silent by default
591566 - install errors.h header ...
591788 - Add meta_window_is_override_redirect
591836 - mutter mishandles opacity
591913 - Fails to skip current window on alt+tab when another window is asking for attention
592393 - Clicking on a minimized window in the overview doesn't focus the window
592699 - Remove deprecated Encoding key from desktop files
592742 - Avoid accessing freed memory when being replaced
593399 - Add meta_display_get_grab_op()
593404 - Make MUTTER_DEBUG_XINERAMA override active Xinerama
593407 - Add 'skip-taskbar' accessor to MetaWindow.
----------------------------- Older Metacity News -----------------------------
2.26.0
======

View File

@ -1,7 +1,7 @@
AC_PREREQ(2.50)
m4_define([mutter_major_version], [2])
m4_define([mutter_minor_version], [91])
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [0])
m4_define([mutter_micro_version], [2])
m4_define([mutter_version],
@ -61,73 +61,7 @@ AC_CHECK_SIZEOF(__int64)
## byte order
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 "$enable_compile_warnings" != no ; then
if test "x$GCC" = "xyes"; then
case " $CFLAGS " in
*[\ \ ]-Wall[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wall" ;;
esac
# case " $CFLAGS " in
# *[\ \ ]-Wshadow[\ \ ]*) ;;
# *) CFLAGS="$CFLAGS -Wshadow" ;;
# esac
case " $CFLAGS " in
*[\ \ ]-Wchar-subscripts[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wmissing-declarations[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wnested-externs[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wnested-externs" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wpointer-arith[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wpointer-arith" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wcast-align[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wcast-align" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wsign-compare[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wsign-compare" ;;
esac
if test "$enable_compile_warnings" = error; then
case " $CFLAGS " in
*[\ \ ]-Werror[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Werror" ;;
esac
fi
fi
fi
changequote([,])dnl
GTK_MIN_VERSION=2.90.7
GTK_MIN_VERSION=2.91.7
CANBERRA_GTK=libcanberra-gtk3
CANBERRA_GTK_VERSION=0.26
@ -162,11 +96,6 @@ AC_ARG_ENABLE(startup-notification,
[disable mutter's startup notification support, for embedded/size-sensitive custom non-GNOME builds]),,
enable_startup_notification=auto)
AC_ARG_WITH(introspection,
AC_HELP_STRING([--without-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]),,
@ -280,24 +209,15 @@ else
AC_MSG_ERROR([no. Mutter requires Clutter version $CLUTTER_VERSION.])
fi
if test x$with_introspection != xno; then
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])
G_IR_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
AC_SUBST(G_IR_SCANNER)
G_IR_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
AC_SUBST(G_IR_COMPILER)
G_IR_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
AC_SUBST(G_IR_GENERATE)
GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
AC_SUBST(GIRDIR)
TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
AC_SUBST(TYPELIBDIR)
fi
INTROSPECTION_VERSION=0.9.5
GOBJECT_INTROSPECTION_CHECK([$INTROSPECTION_VERSION])
if test x$found_introspection != xno; then
AC_DEFINE(HAVE_INTROSPECTION, 1, [Define if GObject introspection is available])
MUTTER_PC_MODULES="$MUTTER_PC_MODULES gobject-introspection-1.0"
META_GIR=[Meta_]mutter_major_version[_]mutter_minor_version[_gir]
AC_SUBST(META_GIR)
fi
AM_CONDITIONAL(WITH_INTROSPECTION, test "$have_introspection" = "yes")
AC_MSG_CHECKING([Xcursor])
if $PKG_CONFIG xcursor; then
@ -518,13 +438,79 @@ AM_PATH_PYTHON([2.5])
# Use gnome-doc-utils:
GNOME_DOC_INIT([0.8.0])
#### Warnings (last since -Werror can disturb other tests)
# Stay command-line compatible with the gnome-common configure option. Here
# minimum/yes/maximum are the same, however.
AC_ARG_ENABLE(compile_warnings,
AS_HELP_STRING([--enable-compile-warnings=@<:@no/minimum/yes/maximum/error@:>@],[Turn on compiler warnings]),,
enable_compile_warnings=error)
changequote(,)dnl
if test "$enable_compile_warnings" != no ; then
if test "x$GCC" = "xyes"; then
case " $CFLAGS " in
*[\ \ ]-Wall[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wall" ;;
esac
# case " $CFLAGS " in
# *[\ \ ]-Wshadow[\ \ ]*) ;;
# *) CFLAGS="$CFLAGS -Wshadow" ;;
# esac
case " $CFLAGS " in
*[\ \ ]-Wchar-subscripts[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wchar-subscripts" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wmissing-declarations[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wmissing-declarations" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wmissing-prototypes[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wmissing-prototypes" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wnested-externs[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wnested-externs" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wpointer-arith[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wpointer-arith" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wcast-align[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wcast-align" ;;
esac
case " $CFLAGS " in
*[\ \ ]-Wsign-compare[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Wsign-compare" ;;
esac
if test "$enable_compile_warnings" = error; then
case " $CFLAGS " in
*[\ \ ]-Werror[\ \ ]*) ;;
*) CFLAGS="$CFLAGS -Werror" ;;
esac
fi
fi
fi
changequote([,])dnl
AC_CONFIG_FILES([
Makefile
doc/Makefile
doc/man/Makefile
src/Makefile
src/wm-tester/Makefile
src/libmutter-private.pc
src/libmutter.pc
src/mutter-plugins.pc
src/tools/Makefile
src/compositor/plugins/Makefile
@ -561,7 +547,7 @@ mutter-$VERSION
Solaris Xinerama: ${use_solaris_xinerama}
Startup notification: ${have_startup_notification}
libcanberra: ${have_libcanberra}
Introspection: ${have_introspection}
Introspection: ${found_introspection}
Session management: ${found_sm}
Shape extension: ${found_shape}
Xsync: ${found_xsync}
@ -574,7 +560,7 @@ if expr $MUTTER_MINOR_VERSION % 2 > /dev/null ; then
stable_version=`expr $MUTTER_MINOR_VERSION - 1`
echo "This is the UNSTABLE branch of mutter"
echo -n "Use 2.$stable_version.x for stable "
echo "(gnome-2-$stable_version branch in Subversion)"
echo "(gnome-2-$stable_version branch in git)"
else
echo "This is the stable branch of mutter"
fi

View File

@ -22,6 +22,24 @@ This document has separate sections for each format version. You may
want to read the document in reverse order, since the base features
are discussed under version 1.
New Features in Theme Format Version 3.3
========================================
Add two additional button background functions - left_single_background and
right_single_background - for button groups with just a single button.
There are now additional frame states to style left/right tiled windows
differently ("tiled_left", "tiled_right", "tiled_left_and_shaded",
"tiled_right_and_shaded").
New Features in Theme Format Version 3.2
========================================
A new window type 'attached' is added for modal dialogs which are
attached to their parent window. (When the attach_modal_dialogs preference
is turned on.) If no style is defined for the 'attached' window type,
the 'border' window type will be used instead.
New Features in Theme Format Version 3.1
========================================

View File

@ -6,6 +6,16 @@
<name xml:lang="en">mutter</name>
<shortdesc xml:lang="en">Window and compositing manager based on Clutter</shortdesc>
<description>Mutter is a window and compositing manager that displays and
manages your desktop via OpenGL. Mutter combines a sophisticated display engine
using the Clutter toolkit with solid window-management logic inherited from the
Metacity window manager.
While Mutter can be used stand-alone, it is primarily intended to be used as
the display core of a larger system such as GNOME Shell. For this reason,
Mutter is very extensible via plugins, which are used both to add fancy visual
effects and to rework the window management behaviors to meet the needs of the
environment.</description>
<!--
<homepage rdf:resource="http://www.gnome.org/" />
-->

View File

@ -22,6 +22,7 @@ dz
el
en_CA
en_GB
eo
es
et
eu
@ -82,6 +83,7 @@ te
th
tk
tr
ug
uk
vi
wa

View File

@ -1,5 +1,6 @@
# List of source files containing translatable strings.
# Please keep this file sorted alphabetically.
src/core/all-keybindings.h
src/core/bell.c
src/core/core.c
src/core/delete.c
@ -7,6 +8,7 @@ src/core/display.c
src/core/errors.c
src/core/keybindings.c
src/core/main.c
src/core/mutter.c
src/core/prefs.c
src/core/screen.c
src/core/session.c
@ -14,7 +16,6 @@ src/core/util.c
src/core/window.c
src/core/window-props.c
src/core/xprops.c
src/include/all-keybindings.h
src/mutter.desktop.in
src/mutter-wm.desktop.in
src/mutter.schemas.in

2923
po/ar.po

File diff suppressed because it is too large Load Diff

2175
po/as.po

File diff suppressed because it is too large Load Diff

1274
po/bg.po

File diff suppressed because it is too large Load Diff

3128
po/ca.po

File diff suppressed because it is too large Load Diff

1205
po/cs.po

File diff suppressed because it is too large Load Diff

1314
po/da.po

File diff suppressed because it is too large Load Diff

3180
po/de.po

File diff suppressed because it is too large Load Diff

598
po/el.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1826
po/eo.po Normal file

File diff suppressed because it is too large Load Diff

1744
po/es.po

File diff suppressed because it is too large Load Diff

2956
po/et.po

File diff suppressed because it is too large Load Diff

1418
po/eu.po

File diff suppressed because it is too large Load Diff

1264
po/fr.po

File diff suppressed because it is too large Load Diff

1374
po/gl.po

File diff suppressed because it is too large Load Diff

1536
po/gu.po

File diff suppressed because it is too large Load Diff

1346
po/he.po

File diff suppressed because it is too large Load Diff

1312
po/hu.po

File diff suppressed because it is too large Load Diff

4965
po/id.po

File diff suppressed because it is too large Load Diff

1378
po/it.po

File diff suppressed because it is too large Load Diff

5596
po/kn.po

File diff suppressed because it is too large Load Diff

3278
po/ko.po

File diff suppressed because it is too large Load Diff

2772
po/lv.po

File diff suppressed because it is too large Load Diff

1183
po/nb.po

File diff suppressed because it is too large Load Diff

2073
po/nl.po

File diff suppressed because it is too large Load Diff

1416
po/pa.po

File diff suppressed because it is too large Load Diff

1253
po/pl.po

File diff suppressed because it is too large Load Diff

1329
po/pt.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2853
po/ro.po

File diff suppressed because it is too large Load Diff

3650
po/ru.po

File diff suppressed because it is too large Load Diff

1351
po/sl.po

File diff suppressed because it is too large Load Diff

1580
po/sv.po

File diff suppressed because it is too large Load Diff

1263
po/ta.po

File diff suppressed because it is too large Load Diff

2597
po/tr.po

File diff suppressed because it is too large Load Diff

1947
po/ug.po Normal file

File diff suppressed because it is too large Load Diff

6177
po/uk.po

File diff suppressed because it is too large Load Diff

4122
po/vi.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,30 @@
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
.AUTOPARALLEL:
lib_LTLIBRARIES = libmutter-private.la
lib_LTLIBRARIES = libmutter.la
SUBDIRS=wm-tester tools compositor/plugins
INCLUDES=@MUTTER_CFLAGS@ -I $(srcdir)/include -I$(srcdir)/compositor -DMUTTER_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" -DMUTTER_DATADIR=\"$(datadir)\" -DG_LOG_DOMAIN=\"mutter\" -DSN_API_NOT_YET_FROZEN=1 -DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) -DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) -DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) -DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) -DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" -DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\"
INCLUDES= \
$(MUTTER_CFLAGS) \
-I$(srcdir) \
-I$(srcdir)/core \
-I$(srcdir)/ui \
-I$(srcdir)/compositor \
-DMUTTER_LIBEXECDIR=\"$(libexecdir)\" \
-DHOST_ALIAS=\"@HOST_ALIAS@\" \
-DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" \
-DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" \
-DMUTTER_DATADIR=\"$(datadir)\" \
-DG_LOG_DOMAIN=\"mutter\" \
-DSN_API_NOT_YET_FROZEN=1 \
-DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) \
-DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) \
-DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) \
-DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) \
-DMUTTER_PKGLIBDIR=\"$(pkglibdir)\" \
-DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\" \
-DGETTEXT_PACKAGE=\"$(GETTEXT_PACKAGE)\"
mutter_built_sources = \
mutter-marshal.h \
@ -13,21 +32,27 @@ mutter_built_sources = \
mutter-enum-types.h \
mutter-enum-types.c
mutter_SOURCES= \
libmutter_la_SOURCES = \
core/async-getprop.c \
core/async-getprop.h \
core/bell.c \
core/bell.h \
core/boxes.c \
core/boxes-private.h \
include/boxes.h \
meta/boxes.h \
compositor/cogl-utils.c \
compositor/cogl-utils.h \
compositor/compositor.c \
compositor/compositor-private.h \
compositor/meta-background-actor.c \
compositor/meta-background-actor.h \
compositor/meta-module.c \
compositor/meta-module.h \
compositor/meta-plugin.c \
compositor/meta-plugin-manager.c \
compositor/meta-plugin-manager.h \
compositor/meta-shadow-factory.c \
compositor/meta-shadow-factory-private.h \
compositor/meta-shaped-texture.c \
compositor/meta-shaped-texture.h \
compositor/meta-texture-tower.c \
@ -36,39 +61,40 @@ mutter_SOURCES= \
compositor/meta-window-actor-private.h \
compositor/meta-window-group.c \
compositor/meta-window-group.h \
compositor/shadow.c \
compositor/shadow.h \
compositor/tidy/tidy-texture-frame.c \
compositor/tidy/tidy-texture-frame.h \
include/compositor.h \
include/meta-plugin.h \
include/meta-window-actor.h \
include/compositor-mutter.h \
compositor/meta-window-shape.c \
compositor/meta-window-shape.h \
compositor/region-utils.c \
compositor/region-utils.h \
meta/compositor.h \
meta/meta-plugin.h \
meta/meta-shadow-factory.h \
meta/meta-window-actor.h \
meta/compositor-mutter.h \
core/above-tab-keycode.c \
core/constraints.c \
core/constraints.h \
core/core.c \
core/delete.c \
core/display.c \
core/display-private.h \
include/display.h \
meta/display.h \
ui/draw-workspace.c \
ui/draw-workspace.h \
core/edge-resistance.c \
core/edge-resistance.h \
core/errors.c \
include/errors.h \
meta/errors.h \
core/eventqueue.c \
core/eventqueue.h \
core/frame.c \
core/frame-private.h \
include/frame.h \
core/frame.h \
ui/gradient.c \
ui/gradient.h \
meta/gradient.h \
core/group-private.h \
core/group-props.c \
core/group-props.h \
core/group.c \
include/group.h \
meta/group.h \
core/iconcache.c \
core/iconcache.h \
core/keybindings.c \
@ -78,11 +104,11 @@ mutter_SOURCES= \
core/place.c \
core/place.h \
core/prefs.c \
include/prefs.h \
meta/prefs.h \
core/screen.c \
core/screen-private.h \
include/screen.h \
include/types.h \
meta/screen.h \
meta/types.h \
core/session.c \
core/session.h \
core/stack.c \
@ -90,19 +116,19 @@ mutter_SOURCES= \
core/stack-tracker.c \
core/stack-tracker.h \
core/util.c \
include/util.h \
meta/util.h \
core/window-props.c \
core/window-props.h \
core/window.c \
core/window-private.h \
include/window.h \
meta/window.h \
core/workspace.c \
core/workspace-private.h \
core/xprops.c \
include/xprops.h \
include/common.h \
include/core.h \
include/ui.h \
core/xprops.h \
meta/common.h \
core/core.h \
ui/ui.h \
inlinepixbufs.h \
ui/fixedtip.c \
ui/fixedtip.h \
@ -113,70 +139,55 @@ mutter_SOURCES= \
ui/metaaccellabel.c \
ui/metaaccellabel.h \
ui/resizepopup.c \
include/resizepopup.h \
ui/resizepopup.h \
ui/tabpopup.c \
include/tabpopup.h \
ui/tabpopup.h \
ui/tile-preview.c \
include/tile-preview.h \
ui/tile-preview.h \
ui/theme-parser.c \
ui/theme.c \
ui/theme.h \
meta/theme.h \
ui/theme-private.h \
ui/ui.c \
include/all-keybindings.h \
core/all-keybindings.h \
meta/preview-widget.h \
ui/preview-widget.c \
$(mutter_built_sources)
# by setting libmutter_private_la_CFLAGS, the files shared with
# mutter proper will be compiled with different names.
libmutter_private_la_CFLAGS =
libmutter_private_la_SOURCES= \
core/boxes.c \
include/boxes.h \
ui/gradient.c \
ui/gradient.h \
core/util.c \
include/util.h \
include/common.h \
ui/preview-widget.c \
ui/preview-widget.h \
ui/theme-parser.c \
ui/theme.c \
ui/theme.h
libmutter_private_la_LDFLAGS = -no-undefined
libmutter_private_la_LIBADD = @MUTTER_LIBS@
libmutter_la_LDFLAGS = -no-undefined
libmutter_la_LIBADD = $(MUTTER_LIBS)
# Headers installed for plugins; introspected information will
# be extracted into Mutter-<version>.gir
libmutterinclude_base_headers = \
include/boxes.h \
ui/gradient.h \
include/main.h \
include/util.h \
include/common.h \
ui/theme.h \
include/prefs.h \
include/window.h \
include/workspace.h \
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/meta-plugin.h \
include/meta-window-actor.h
meta/boxes.h \
meta/common.h \
meta/compositor-mutter.h \
meta/compositor.h \
meta/display.h \
meta/errors.h \
meta/gradient.h \
meta/group.h \
meta/keybindings.h \
meta/main.h \
meta/meta-plugin.h \
meta/meta-shadow-factory.h \
meta/meta-window-actor.h \
meta/prefs.h \
meta/screen.h \
meta/theme.h \
meta/types.h \
meta/util.h \
meta/window.h \
meta/workspace.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
meta/preview-widget.h \
meta/atomnames.h
libmutterincludedir = $(includedir)/mutter/mutter-private
libmutterincludedir = $(includedir)/mutter/meta
libmutterinclude_HEADERS = \
$(libmutterinclude_base_headers) \
@ -187,9 +198,14 @@ mutter_theme_viewer_SOURCES= \
bin_PROGRAMS=mutter mutter-theme-viewer
mutter_SOURCES = core/mutter.c
mutter_LDADD = $(MUTTER_LIBS) libmutter.la
if HAVE_INTROSPECTION
include $(INTROSPECTION_MAKEFILE)
api_version = $(MUTTER_MAJOR_VERSION).$(MUTTER_MINOR_VERSION)
if WITH_INTROSPECTION
# These files are in package-private directories, even though they may be used
# by plugins. If you're writing a plugin, use g-ir-compiler --add-include-path
# and g-ir-compiler --includedir.
@ -199,50 +215,32 @@ gir_DATA = Meta-$(api_version).gir
typelibdir = $(pkglibdir)
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) 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-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/$@
INTROSPECTION_GIRS = Meta-$(api_version).gir
Meta-$(api_version).gir: libmutter.la
@META_GIR@_INCLUDES = GObject-2.0 Gdk-3.0 Gtk-3.0 Clutter-1.0 xlib-2.0 xfixes-4.0
@META_GIR@_PACKAGES = clutter-1.0 gtk+-3.0
@META_GIR@_CFLAGS = $(INCLUDES)
@META_GIR@_LIBS = libmutter.la
@META_GIR@_FILES = \
mutter-enum-types.h \
$(libmutterinclude_base_headers) \
$(filter %.c,$(libmutter_la_SOURCES))
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
Meta-$(api_version).typelib: $(G_IR_COMPILER) Meta-$(api_version).gir
$(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@ $(EFENCE)
mutter_LDFLAGS=-export-dynamic
mutter_theme_viewer_LDADD= $(MUTTER_LIBS) libmutter.la
mutter_theme_viewer_LDADD= @MUTTER_LIBS@ libmutter-private.la
testboxes_SOURCES=include/util.h core/util.c include/boxes.h core/boxes.c core/testboxes.c
testgradient_SOURCES=ui/gradient.h ui/gradient.c ui/testgradient.c
testasyncgetprop_SOURCES=core/async-getprop.h core/async-getprop.c core/testasyncgetprop.c
testboxes_SOURCES = core/testboxes.c
testgradient_SOURCES = ui/testgradient.c
testasyncgetprop_SOURCES = core/testasyncgetprop.c
noinst_PROGRAMS=testboxes testgradient testasyncgetprop
testboxes_LDADD= @MUTTER_LIBS@
testgradient_LDADD= @MUTTER_LIBS@
testasyncgetprop_LDADD= @MUTTER_LIBS@
testboxes_LDADD = $(MUTTER_LIBS) libmutter.la
testgradient_LDADD = $(MUTTER_LIBS) libmutter.la
testasyncgetprop_LDADD = $(MUTTER_LIBS) libmutter.la
@INTLTOOL_DESKTOP_RULE@
@ -256,7 +254,7 @@ wmproperties_in_files=mutter-wm.desktop.in
wmproperties_files=$(wmproperties_in_files:.desktop.in=.desktop)
wmproperties_DATA = $(wmproperties_files)
schemadir = @GCONF_SCHEMA_FILE_DIR@
schemadir = $(GCONF_SCHEMA_FILE_DIR)
schema_in_files = mutter.schemas.in
schema_DATA = $(schema_in_files:.schemas.in=.schemas)
@ -291,7 +289,7 @@ inlinepixbufs.h: $(IMAGES)
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libmutter-private.pc mutter-plugins.pc
pkgconfig_DATA = libmutter.pc mutter-plugins.pc
EXTRA_DIST=$(desktopfiles_files) \
$(wmproperties_files) \
@ -299,7 +297,7 @@ EXTRA_DIST=$(desktopfiles_files) \
$(desktopfiles_in_files) \
$(wmproperties_in_files) \
$(schema_in_files) \
libmutter-private.pc.in \
libmutter.pc.in \
mutter-plugins.pc.in \
mutter-enum-types.h.in \
mutter-enum-types.c.in \

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

@ -0,0 +1,104 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Utilities for use with Cogl
*
* Copyright 2010 Red Hat, Inc.
* Copyright 2010 Intel Corporation
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "cogl-utils.h"
/**
* meta_create_color_texture_4ub:
* @red:
* @green:
* @blue:
* @alpha:
*
* Creates a texture that is a single pixel with the specified
* unpremultiplied color components.
*
* Return value: (transfer full): a newly created Cogl texture
*/
CoglHandle
meta_create_color_texture_4ub (guint8 red,
guint8 green,
guint8 blue,
guint8 alpha)
{
CoglColor color;
guint8 pixel[4];
cogl_color_set_from_4ub (&color, red, green, blue, alpha);
cogl_color_premultiply (&color);
pixel[0] = cogl_color_get_red_byte (&color);
pixel[1] = cogl_color_get_green_byte (&color);
pixel[2] = cogl_color_get_blue_byte (&color);
pixel[3] = cogl_color_get_alpha_byte (&color);
return cogl_texture_new_from_data (1, 1,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_RGBA_8888_PRE,
COGL_PIXEL_FORMAT_ANY,
4, pixel);
}
/* Based on gnome-shell/src/st/st-private.c:_st_create_texture_material.c */
/**
* meta_create_texture_material:
* @src_texture: (allow-none): texture to use initially for the layer
*
* Creates a material with a single layer. Using a common template
* allows sharing a shader for different uses in Mutter. To share the same
* shader with all other materials that are just texture plus opacity
* would require Cogl fixes.
* (See http://bugzilla.clutter-project.org/show_bug.cgi?id=2425)
*
* Return value: (transfer full): a newly created Cogl material
*/
CoglHandle
meta_create_texture_material (CoglHandle src_texture)
{
static CoglHandle texture_material_template = COGL_INVALID_HANDLE;
CoglHandle material;
/* We use a material that has a dummy texture as a base for all
texture materials. The idea is that only the Cogl texture object
would be different in the children so it is likely that Cogl will
be able to share GL programs between all the textures. */
if (G_UNLIKELY (texture_material_template == COGL_INVALID_HANDLE))
{
CoglHandle dummy_texture;
dummy_texture = meta_create_color_texture_4ub (0xff, 0xff, 0xff, 0xff);
texture_material_template = cogl_material_new ();
cogl_material_set_layer (texture_material_template, 0, dummy_texture);
cogl_handle_unref (dummy_texture);
}
material = cogl_material_copy (texture_material_template);
if (src_texture != COGL_INVALID_HANDLE)
cogl_material_set_layer (material, 0, src_texture);
return material;
}

View File

@ -1,7 +1,8 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2008 Iain Holmes
* Utilities for use with Cogl
*
* Copyright 2010 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@ -19,13 +20,15 @@
* 02111-1307, USA.
*/
#ifndef META_FRAME_H
#define META_FRAME_H
#ifndef __META_COGL_UTILS_H__
#define __META_COGL_UTILS_H__
#include <X11/Xlib.h>
#include <cogl/cogl.h>
#include "types.h"
CoglHandle meta_create_color_texture_4ub (guint8 red,
guint8 green,
guint8 blue,
guint8 alpha);
CoglHandle meta_create_texture_material (CoglHandle src_texture);
Window meta_frame_get_xwindow (MetaFrame *frame);
#endif
#endif /* __META_COGL_UTILS_H__ */

View File

@ -5,8 +5,8 @@
#include <X11/extensions/Xfixes.h>
#include "compositor.h"
#include "display.h"
#include <meta/compositor.h>
#include <meta/display.h>
#include "meta-plugin-manager.h"
#include <clutter/clutter.h>
@ -35,6 +35,7 @@ struct _MetaCompScreen
MetaScreen *screen;
ClutterActor *stage, *window_group, *overlay_group;
ClutterActor *background_actor;
ClutterActor *hidden_group;
GList *windows;
GHashTable *windows_by_xid;

View File

@ -4,17 +4,19 @@
#include <clutter/x11/clutter-x11.h>
#include "screen.h"
#include "errors.h"
#include "window.h"
#include <meta/screen.h>
#include <meta/errors.h>
#include <meta/window.h>
#include "compositor-private.h"
#include "compositor-mutter.h"
#include <meta/compositor-mutter.h>
#include "xprops.h"
#include "prefs.h"
#include <meta/prefs.h>
#include <meta/meta-shadow-factory.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 "meta-background-actor.h"
#include "window-private.h" /* to check window->hidden */
#include "display-private.h" /* for meta_display_lookup_x_window() */
#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
@ -33,7 +35,7 @@ composite_at_least_version (MetaDisplay *display, int maj, int min)
return (major > maj || (major == maj && minor >= min));
}
static void sync_actor_stacking (GList *windows);
static void sync_actor_stacking (MetaCompScreen *info);
static void
meta_finish_workspace_switch (MetaCompScreen *info)
@ -47,7 +49,7 @@ meta_finish_workspace_switch (MetaCompScreen *info)
/*
* Fix up stacking order in case the plugin messed it up.
*/
sync_actor_stacking (info->windows);
sync_actor_stacking (info);
/* printf ("... FINISHED DESKTOP SWITCH\n"); */
@ -86,7 +88,7 @@ add_win (MetaWindow *window)
meta_window_actor_new (window);
sync_actor_stacking (info->windows);
sync_actor_stacking (info);
}
static void
@ -135,6 +137,22 @@ process_property_notify (MetaCompositor *compositor,
{
MetaWindowActor *window_actor;
if (event->atom == compositor->atom_x_root_pixmap)
{
GSList *l;
for (l = meta_display_get_screens (compositor->display); l; l = l->next)
{
MetaScreen *screen = l->data;
if (event->window == meta_screen_get_xroot (screen))
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
meta_background_actor_update (META_BACKGROUND_ACTOR (info->background_actor));
return;
}
}
}
if (window == NULL)
return;
@ -235,6 +253,27 @@ meta_get_window_group_for_screen (MetaScreen *screen)
return info->window_group;
}
/**
* meta_get_background_actor_for_screen:
* @screen: a #MetaScreen
*
* Gets the actor that draws the root window background under the windows.
* The root window background automatically tracks the image or color set
* by the environment.
*
* Returns: (transfer none): The background actor corresponding to @screen
*/
ClutterActor *
meta_get_background_actor_for_screen (MetaScreen *screen)
{
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info)
return NULL;
return info->background_actor;
}
/**
* meta_get_window_actors:
* @screen: a #MetaScreen
@ -493,9 +532,14 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
XSelectInput (xdisplay, xwin, event_mask);
info->window_group = meta_window_group_new (screen);
info->background_actor = meta_background_actor_new (screen);
info->overlay_group = clutter_group_new ();
info->hidden_group = clutter_group_new ();
clutter_container_add (CLUTTER_CONTAINER (info->window_group),
info->background_actor,
NULL);
clutter_container_add (CLUTTER_CONTAINER (info->stage),
info->window_group,
info->overlay_group,
@ -506,18 +550,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
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");
meta_plugin_manager_initialize (info->plugin_mgr);
/*
* Delay the creation of the overlay window as long as we can, to avoid
@ -826,18 +859,73 @@ meta_compositor_switch_workspace (MetaCompositor *compositor,
}
static void
sync_actor_stacking (GList *windows)
sync_actor_stacking (MetaCompScreen *info)
{
GList *children;
GList *tmp;
GList *old;
gboolean reordered;
/* NB: The first entry in the list is stacked the lowest */
/* NB: The first entries in the lists are stacked the lowest */
for (tmp = g_list_last (windows); tmp != NULL; tmp = tmp->prev)
/* Restacking will trigger full screen redraws, so it's worth a
* little effort to make sure we actually need to restack before
* we go ahead and do it */
children = clutter_container_get_children (CLUTTER_CONTAINER (info->window_group));
reordered = FALSE;
old = children;
/* We allow for actors in the window group other than the actors we
* know about, but it's up to a plugin to try and keep them stacked correctly
* (we really need extra API to make that reliable.)
*/
/* Of the actors we know, the bottom actor should be the background actor */
while (old && old->data != info->background_actor && !META_IS_WINDOW_ACTOR (old->data))
old = old->next;
if (old == NULL || old->data != info->background_actor)
{
reordered = TRUE;
goto done_with_check;
}
/* Then the window actors should follow in sequence */
old = old->next;
for (tmp = info->windows; tmp != NULL; tmp = tmp->next)
{
while (old && !META_IS_WINDOW_ACTOR (old->data))
old = old->next;
/* old == NULL: someone reparented a window out of the window group,
* order undefined, always restack */
if (old == NULL || old->data != tmp->data)
{
reordered = TRUE;
goto done_with_check;
}
old = old->next;
}
done_with_check:
g_list_free (children);
if (!reordered)
return;
for (tmp = g_list_last (info->windows); tmp != NULL; tmp = tmp->prev)
{
MetaWindowActor *window_actor = tmp->data;
clutter_actor_lower_bottom (CLUTTER_ACTOR (window_actor));
}
clutter_actor_lower_bottom (info->background_actor);
}
void
@ -875,7 +963,10 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
if (old_window->hidden &&
!meta_window_actor_effect_in_progress (old_actor))
old_stack = g_list_delete_link (old_stack, old_stack);
{
old_stack = g_list_delete_link (old_stack, old_stack);
old_actor = NULL;
}
else
break;
}
@ -926,7 +1017,7 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
old_stack = g_list_remove (old_stack, actor);
}
sync_actor_stacking (info->windows);
sync_actor_stacking (info);
}
void
@ -983,6 +1074,8 @@ meta_compositor_sync_screen_size (MetaCompositor *compositor,
clutter_actor_set_size (info->stage, width, height);
meta_background_actor_screen_size_changed (META_BACKGROUND_ACTOR (info->background_actor));
meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
meta_screen_get_screen_number (screen),
width, height);
@ -1017,6 +1110,26 @@ meta_repaint_func (gpointer data)
return TRUE;
}
static void
on_shadow_factory_changed (MetaShadowFactory *factory,
MetaCompositor *compositor)
{
GSList *screens = meta_display_get_screens (compositor->display);
GList *l;
GSList *sl;
for (sl = screens; sl; sl = sl->next)
{
MetaScreen *screen = sl->data;
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
if (!info)
continue;
for (l = info->windows; l; l = l->next)
meta_window_actor_invalidate_shadow (l->data);
}
}
/**
* meta_compositor_new: (skip)
*
@ -1047,6 +1160,11 @@ meta_compositor_new (MetaDisplay *display)
XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
False, atoms);
g_signal_connect (meta_shadow_factory_get_default (),
"changed",
G_CALLBACK (on_shadow_factory_changed),
compositor);
compositor->atom_x_root_pixmap = atoms[0];
compositor->atom_x_set_root = atoms[1];
compositor->atom_net_wm_window_opacity = atoms[2];
@ -1069,3 +1187,47 @@ meta_get_overlay_window (MetaScreen *screen)
return info->output;
}
#define FLASH_TIME_MS 50
static void
flash_out_completed (ClutterAnimation *animation,
ClutterActor *flash)
{
clutter_actor_destroy (flash);
}
static void
flash_in_completed (ClutterAnimation *animation,
ClutterActor *flash)
{
clutter_actor_animate (flash, CLUTTER_EASE_IN_QUAD,
FLASH_TIME_MS,
"opacity", 0,
"signal-after::completed", flash_out_completed, flash,
NULL);
}
void
meta_compositor_flash_screen (MetaCompositor *compositor,
MetaScreen *screen)
{
ClutterActor *stage;
ClutterActor *flash;
ClutterColor black = { 0, 0, 0, 255 };
gfloat width, height;
stage = meta_get_stage_for_screen (screen);
clutter_actor_get_size (stage, &width, &height);
flash = clutter_rectangle_new_with_color (&black);
clutter_actor_set_size (flash, width, height);
clutter_actor_set_opacity (flash, 0);
clutter_container_add_actor (CLUTTER_CONTAINER (stage), flash);
clutter_actor_animate (flash, CLUTTER_EASE_OUT_QUAD,
FLASH_TIME_MS,
"opacity", 192,
"signal-after::completed", flash_in_completed, flash,
NULL);
}

View File

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

View File

@ -0,0 +1,58 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* meta-background-actor.h: Actor for painting the root window background
*
* Copyright 2010 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_BACKGROUND_ACTOR_H
#define META_BACKGROUND_ACTOR_H
#include <clutter/clutter.h>
#include <meta/screen.h>
/**
* MetaBackgroundActor:
*
* This class handles tracking and painting the root window background.
* By integrating with #MetaWindowGroup we can avoid painting parts of
* the background that are obscured by other windows.
*/
#define META_TYPE_BACKGROUND_ACTOR (meta_background_actor_get_type ())
#define META_BACKGROUND_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_BACKGROUND_ACTOR, MetaBackgroundActor))
#define META_BACKGROUND_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_BACKGROUND_ACTOR, MetaBackgroundActorClass))
#define META_IS_BACKGROUND_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_BACKGROUND_ACTOR))
#define META_IS_BACKGROUND_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_BACKGROUND_ACTOR))
#define META_BACKGROUND_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_BACKGROUND_ACTOR, MetaBackgroundActorClass))
typedef struct _MetaBackgroundActor MetaBackgroundActor;
typedef struct _MetaBackgroundActorClass MetaBackgroundActorClass;
typedef struct _MetaBackgroundActorPrivate MetaBackgroundActorPrivate;
GType meta_background_actor_get_type (void);
ClutterActor *meta_background_actor_new (MetaScreen *screen);
void meta_background_actor_update (MetaBackgroundActor *actor);
void meta_background_actor_set_visible_region (MetaBackgroundActor *self,
cairo_region_t *visible_region);
void meta_background_actor_screen_size_changed (MetaBackgroundActor *self);
#endif /* META_BACKGROUND_ACTOR_H */

View File

@ -21,7 +21,7 @@
* 02111-1307, USA.
*/
#include "meta-plugin.h"
#include <meta/meta-plugin.h>
#include "meta-module.h"
#include <gmodule.h>

View File

@ -24,20 +24,18 @@
#include "config.h"
#include "compositor-private.h"
#include "meta-plugin-manager.h"
#include "prefs.h"
#include "errors.h"
#include "workspace.h"
#include <meta/prefs.h>
#include <meta/errors.h>
#include <meta/workspace.h>
#include "meta-module.h"
#include "../core/window-private.h"
#include "window-private.h"
#include <string.h>
#include <stdlib.h>
#include <clutter/x11/clutter-x11.h>
/*
* There is only one instace of each module per the process.
*/
static GHashTable *plugin_modules = NULL;
static GSList *plugin_types;
/*
* We have one "default plugin manager" that acts for the first screen,
@ -45,270 +43,79 @@ static GHashTable *plugin_modules = NULL;
* plugin managers for each screen. (This is ugly. Probably we should
* have one plugin manager and only make the plugins per-screen.)
*/
static MetaPluginManager *default_plugin_manager;
static gboolean meta_plugin_manager_reload (MetaPluginManager *plugin_mgr);
struct MetaPluginManager
{
MetaScreen *screen;
GList /* MetaPlugin */ *plugins; /* TODO -- maybe use hash table */
GList *unload; /* Plugins that are disabled and pending unload */
guint idle_unload_id;
GList /* MetaPlugin */ *plugins; /* TODO -- maybe use hash table */
};
/*
* Checks that the plugin is compatible with the WM and sets up the plugin
* struct.
* Loads the given plugin.
*/
static MetaPlugin *
meta_plugin_load (MetaPluginManager *mgr,
MetaModule *module,
const gchar *params)
{
MetaPlugin *plugin = NULL;
GType plugin_type = meta_module_get_plugin_type (module);
if (!plugin_type)
{
g_warning ("Plugin type not registered !!!");
return NULL;
}
plugin = g_object_new (plugin_type,
"params", params,
NULL);
return plugin;
}
/*
* Attempst to unload a plugin; returns FALSE if plugin cannot be unloaded at
* present (e.g., and effect is in progress) and should be scheduled for
* removal later.
*/
static gboolean
meta_plugin_unload (MetaPlugin *plugin)
{
if (meta_plugin_running (plugin))
{
g_object_set (plugin, "disabled", TRUE, NULL);
return FALSE;
}
g_object_unref (plugin);
return TRUE;
}
/*
* Iddle callback to remove plugins that could not be removed directly and are
* pending for removal.
*/
static gboolean
meta_plugin_manager_idle_unload (MetaPluginManager *plugin_mgr)
{
GList *l = plugin_mgr->unload;
gboolean dont_remove = TRUE;
while (l)
{
MetaPlugin *plugin = l->data;
if (meta_plugin_unload (plugin))
{
/* Remove from list */
GList *p = l->prev;
GList *n = l->next;
if (!p)
plugin_mgr->unload = n;
else
p->next = n;
if (n)
n->prev = p;
g_list_free_1 (l);
l = n;
}
else
l = l->next;
}
if (!plugin_mgr->unload)
{
/* If no more unloads are pending, remove the handler as well */
dont_remove = FALSE;
plugin_mgr->idle_unload_id = 0;
}
return dont_remove;
}
/*
* Unloads all plugins
*/
static void
meta_plugin_manager_unload (MetaPluginManager *plugin_mgr)
{
GList *plugins = plugin_mgr->plugins;
while (plugins)
{
MetaPlugin *plugin = plugins->data;
/* If the plugin could not be removed, move it to the unload list */
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)
meta_plugin_manager_idle_unload,
plugin_mgr);
}
}
plugins = plugins->next;
}
g_list_free (plugin_mgr->plugins);
plugin_mgr->plugins = NULL;
}
static void
prefs_changed_callback (MetaPreference pref,
void *data)
{
MetaPluginManager *plugin_mgr = data;
if (pref == META_PREF_CLUTTER_PLUGINS)
{
meta_plugin_manager_reload (plugin_mgr);
}
}
static MetaModule *
meta_plugin_manager_get_module (const gchar *path)
{
MetaModule *module = g_hash_table_lookup (plugin_modules, path);
if (!module &&
(module = g_object_new (META_TYPE_MODULE, "path", path, NULL)))
{
g_hash_table_insert (plugin_modules, g_strdup (path), module);
}
return module;
}
/*
* Loads all plugins listed in gconf registry.
*/
gboolean
meta_plugin_manager_load (MetaPluginManager *plugin_mgr)
void
meta_plugin_manager_load (MetaPluginManager *plugin_mgr,
const gchar *plugin_name)
{
const gchar *dpath = MUTTER_PLUGIN_DIR "/";
GSList *plugins, *fallback = NULL;
gchar *path;
MetaModule *module;
GType plugin_type;
plugins = meta_prefs_get_clutter_plugins ();
if (g_path_is_absolute (plugin_name))
path = g_strdup (plugin_name);
else
path = g_strconcat (dpath, plugin_name, ".so", NULL);
if (!plugins)
module = g_object_new (META_TYPE_MODULE, "path", path, NULL);
if (!module || !g_type_module_use (G_TYPE_MODULE (module)))
{
/*
* If no plugins are specified, try to load the default plugin.
/* This is fatal under the assumption that a monitoring
* process like gnome-session will take over and handle
* our untimely exit.
*/
fallback = g_slist_append (fallback, "default");
plugins = fallback;
g_printerr ("Unable to load plugin module [%s]: %s",
path, g_module_error());
exit (1);
}
while (plugins)
{
gchar *plugin_string;
gchar *params;
plugin_type = meta_module_get_plugin_type (module);
meta_plugin_manager_register (plugin_mgr, plugin_type);
plugin_string = g_strdup (plugins->data);
if (plugin_string)
{
MetaModule *module;
gchar *path;
params = strchr (plugin_string, ':');
if (params)
{
*params = 0;
++params;
}
if (g_path_is_absolute (plugin_string))
path = g_strdup (plugin_string);
else
path = g_strconcat (dpath, plugin_string, ".so", NULL);
module = meta_plugin_manager_get_module (path);
if (module)
{
gboolean use_succeeded;
/*
* This dlopens the module and registers the plugin type with the
* GType system, if the module is not already loaded. When we
* create a plugin, the type system also calls g_type_module_use()
* to guarantee the module will not be unloaded during the plugin
* life time. Consequently we can unuse() the module again.
*/
use_succeeded = g_type_module_use (G_TYPE_MODULE (module));
if (use_succeeded)
{
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
g_warning ("Unable to load plugin module [%s]: %s",
path, g_module_error());
g_free (path);
g_free (plugin_string);
}
plugins = plugins->next;
}
if (fallback)
g_slist_free (fallback);
if (plugin_mgr->plugins != NULL)
{
meta_prefs_add_listener (prefs_changed_callback, plugin_mgr);
return TRUE;
}
return FALSE;
g_type_module_unuse (G_TYPE_MODULE (module));
g_free (path);
}
gboolean
/*
* Registers the given plugin type
*/
void
meta_plugin_manager_register (MetaPluginManager *plugin_mgr,
GType plugin_type)
{
MetaPlugin *plugin;
plugin_types = g_slist_prepend (plugin_types, GSIZE_TO_POINTER (plugin_type));
plugin = g_object_new (plugin_type, NULL);
plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, plugin);
}
void
meta_plugin_manager_initialize (MetaPluginManager *plugin_mgr)
{
GList *iter;
if (!plugin_mgr->plugins)
{
/*
* If no plugins are specified, load the default plugin.
*/
meta_plugin_manager_load (plugin_mgr, "default");
}
for (iter = plugin_mgr->plugins; iter; iter = iter->next)
{
MetaPlugin *plugin = (MetaPlugin*) iter->data;
@ -321,26 +128,6 @@ meta_plugin_manager_initialize (MetaPluginManager *plugin_mgr)
if (klass->start)
klass->start (plugin);
}
return TRUE;
}
/*
* Reloads all plugins
*/
static gboolean
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.
*/
/* 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);
}
static MetaPluginManager *
@ -348,15 +135,8 @@ meta_plugin_manager_new (MetaScreen *screen)
{
MetaPluginManager *plugin_mgr;
if (!plugin_modules)
{
plugin_modules = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
NULL);
}
plugin_mgr = g_new0 (MetaPluginManager, 1);
plugin_mgr->screen = screen;
plugin_mgr->screen = screen;
if (screen)
g_object_set_data (G_OBJECT (screen), "meta-plugin-manager", plugin_mgr);
@ -397,7 +177,20 @@ meta_plugin_manager_get (MetaScreen *screen)
}
else
{
return meta_plugin_manager_new (screen);
GSList *iter;
GType plugin_type;
MetaPlugin *plugin;
plugin_mgr = meta_plugin_manager_new (screen);
for (iter = plugin_types; iter; iter = iter->next)
{
plugin_type = (GType)GPOINTER_TO_SIZE (iter->data);
plugin = g_object_new (plugin_type, "screen", screen, NULL);
plugin_mgr->plugins = g_list_prepend (plugin_mgr->plugins, plugin);
}
return plugin_mgr;
}
}

View File

@ -24,11 +24,11 @@
#ifndef META_PLUGIN_MANAGER_H_
#define META_PLUGIN_MANAGER_H_
#include "types.h"
#include "screen.h"
#include <meta/types.h>
#include <meta/screen.h>
#define META_PLUGIN_FROM_MANAGER_
#include "meta-plugin.h"
#include <meta/meta-plugin.h>
#undef META_PLUGIN_FROM_MANAGER_
#define META_PLUGIN_MINIMIZE (1<<0)
@ -49,8 +49,12 @@ 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);
void meta_plugin_manager_load (MetaPluginManager *mgr,
const gchar *plugin_name);
void meta_plugin_manager_register (MetaPluginManager *mgr,
GType plugin_type);
void meta_plugin_manager_initialize (MetaPluginManager *mgr);
gboolean meta_plugin_manager_event_simple (MetaPluginManager *mgr,
MetaWindowActor *actor,
unsigned long event);

View File

@ -21,9 +21,10 @@
* 02111-1307, USA.
*/
#include "meta-plugin.h"
#include "screen.h"
#include "display.h"
#include <meta/meta-plugin.h>
#include "meta-plugin-manager.h"
#include <meta/screen.h>
#include <meta/display.h>
#include <string.h>
#include <X11/Xlib.h>
@ -43,7 +44,6 @@ enum
{
PROP_0,
PROP_SCREEN,
PROP_PARAMS,
PROP_FEATURES,
PROP_DISABLED,
PROP_DEBUG_MODE,
@ -52,7 +52,6 @@ enum
struct _MetaPluginPrivate
{
MetaScreen *screen;
gchar *params;
gulong features;
gint running;
@ -61,6 +60,46 @@ struct _MetaPluginPrivate
gboolean debug : 1;
};
static void
meta_plugin_set_features (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = plugin->priv;
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (plugin);
priv->features = 0;
/*
* Feature flags: identify events that the plugin can handle; a plugin can
* handle one or more events.
*/
if (klass->minimize)
priv->features |= META_PLUGIN_MINIMIZE;
if (klass->maximize)
priv->features |= META_PLUGIN_MAXIMIZE;
if (klass->unmaximize)
priv->features |= META_PLUGIN_UNMAXIMIZE;
if (klass->map)
priv->features |= META_PLUGIN_MAP;
if (klass->destroy)
priv->features |= META_PLUGIN_DESTROY;
if (klass->switch_workspace)
priv->features |= META_PLUGIN_SWITCH_WORKSPACE;
}
static void
meta_plugin_constructed (GObject *object)
{
meta_plugin_set_features (META_PLUGIN (object));
if (G_OBJECT_CLASS (meta_plugin_parent_class)->constructed)
G_OBJECT_CLASS (meta_plugin_parent_class)->constructed (object);
}
static void
meta_plugin_dispose (GObject *object)
{
@ -70,97 +109,9 @@ meta_plugin_dispose (GObject *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,
@ -174,10 +125,6 @@ meta_plugin_set_property (GObject *object,
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;
@ -203,9 +150,6 @@ meta_plugin_get_property (GObject *object,
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;
@ -227,6 +171,7 @@ meta_plugin_class_init (MetaPluginClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->constructed = meta_plugin_constructed;
gobject_class->finalize = meta_plugin_finalize;
gobject_class->dispose = meta_plugin_dispose;
gobject_class->set_property = meta_plugin_set_property;
@ -240,15 +185,6 @@ meta_plugin_class_init (MetaPluginClass *klass)
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",
@ -351,6 +287,14 @@ meta_plugin_get_window_group (MetaPlugin *plugin)
return meta_get_window_group_for_screen (priv->screen);
}
ClutterActor *
meta_plugin_get_background_actor (MetaPlugin *plugin)
{
MetaPluginPrivate *priv = META_PLUGIN (plugin)->priv;
return meta_get_background_actor_for_screen (priv->screen);
}
/**
* _meta_plugin_effect_started:
* @plugin: the plugin
@ -605,3 +549,18 @@ meta_plugin_get_screen (MetaPlugin *plugin)
return priv->screen;
}
/**
* meta_plugin_type_register:
* @plugin_type: a #MetaPlugin type
*
* Register @plugin_type as a compositor plugin type to be used.
* You must call this before calling meta_init().
*/
void
meta_plugin_type_register (GType plugin_type)
{
MetaPluginManager *plugin_manager;
plugin_manager = meta_plugin_manager_get_default ();
meta_plugin_manager_register (plugin_manager, plugin_type);
}

View File

@ -0,0 +1,67 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MetaShadowFactory:
*
* Create and cache shadow textures for arbitrary window shapes
*
* Copyright (C) 2010 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_SHADOW_FACTORY_PRIVATE_H__
#define __META_SHADOW_FACTORY_PRIVATE_H__
#include <cairo.h>
#include <clutter/clutter.h>
#include "meta-window-shape.h"
#include <meta/meta-shadow-factory.h>
/**
* MetaShadow:
* #MetaShadow holds a shadow texture along with information about how to
* apply that texture to draw a window texture. (E.g., it knows how big the
* unscaled borders are on each side of the shadow texture.)
*/
typedef struct _MetaShadow MetaShadow;
MetaShadow *meta_shadow_ref (MetaShadow *shadow);
void meta_shadow_unref (MetaShadow *shadow);
CoglHandle meta_shadow_get_texture (MetaShadow *shadow);
void meta_shadow_paint (MetaShadow *shadow,
int window_x,
int window_y,
int window_width,
int window_height,
guint8 opacity,
cairo_region_t *clip);
void meta_shadow_get_bounds (MetaShadow *shadow,
int window_x,
int window_y,
int window_width,
int window_height,
cairo_rectangle_int_t *bounds);
MetaShadowFactory *meta_shadow_factory_new (void);
MetaShadow *meta_shadow_factory_get_shadow (MetaShadowFactory *factory,
MetaWindowShape *shape,
int width,
int height,
const char *class_name,
gboolean focused);
#endif /* __META_SHADOW_FACTORY_PRIVATE_H__ */

View File

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

View File

@ -187,8 +187,10 @@ meta_shaped_texture_dirty_mask (MetaShapedTexture *stex)
cogl_texture_get_gl_texture (priv->mask_texture,
&mask_gl_tex, &mask_gl_target);
#ifdef GL_TEXTURE_RECTANGLE_ARB
if (mask_gl_target == GL_TEXTURE_RECTANGLE_ARB)
glDeleteTextures (1, &mask_gl_tex);
#endif
cogl_handle_unref (priv->mask_texture);
priv->mask_texture = COGL_INVALID_HANDLE;
@ -253,6 +255,7 @@ meta_shaped_texture_ensure_mask (MetaShapedTexture *stex)
cogl_texture_get_gl_texture (paint_tex, NULL, &paint_gl_target);
#ifdef GL_TEXTURE_RECTANGLE_ARB
if (paint_gl_target == GL_TEXTURE_RECTANGLE_ARB)
{
GLuint tex;
@ -275,6 +278,7 @@ meta_shaped_texture_ensure_mask (MetaShapedTexture *stex)
COGL_PIXEL_FORMAT_A_8);
}
else
#endif /* GL_TEXTURE_RECTANGLE_ARB */
priv->mask_texture = cogl_texture_new_from_data (tex_width, tex_height,
COGL_TEXTURE_NONE,
COGL_PIXEL_FORMAT_A_8,

View File

@ -31,6 +31,8 @@
#include <clutter/clutter.h>
#ifdef HAVE_GLX_TEXTURE_PIXMAP
#include <clutter/glx/clutter-glx.h>
#else
#include <clutter/x11/clutter-x11.h>
#endif /* HAVE_GLX_TEXTURE_PIXMAP */
G_BEGIN_DECLS

View File

@ -97,6 +97,7 @@ meta_texture_tower_free (MetaTextureTower *tower)
g_slice_free (MetaTextureTower, tower);
}
#ifdef GL_TEXTURE_RECTANGLE_ARB
static gboolean
texture_is_rectangle (CoglHandle texture)
{
@ -106,10 +107,12 @@ texture_is_rectangle (CoglHandle texture)
cogl_texture_get_gl_texture (texture, &gl_tex, &gl_target);
return gl_target == GL_TEXTURE_RECTANGLE_ARB;
}
#endif /* GL_TEXTURE_RECTANGLE_ARB */
static void
free_texture (CoglHandle texture)
{
#ifdef GL_TEXTURE_RECTANGLE_ARB
GLuint gl_tex;
GLenum gl_target;
@ -117,6 +120,7 @@ free_texture (CoglHandle texture)
if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
glDeleteTextures (1, &gl_tex);
#endif /* GL_TEXTURE_RECTANGLE_ARB */
cogl_handle_unref (texture);
}
@ -362,11 +366,13 @@ get_paint_level (int width, int height)
return (int)(0.5 + lambda);
}
#ifdef GL_TEXTURE_RECTANGLE_ARB
static gboolean
is_power_of_two (int x)
{
return (x & (x - 1)) == 0;
}
#endif /* GL_TEXTURE_RECTANGLE_ARB */
static void
texture_tower_create_texture (MetaTextureTower *tower,
@ -374,6 +380,7 @@ texture_tower_create_texture (MetaTextureTower *tower,
int width,
int height)
{
#ifdef GL_TEXTURE_RECTANGLE_ARB
if ((!is_power_of_two (width) || !is_power_of_two (height)) &&
texture_is_rectangle (tower->textures[level - 1]))
{
@ -396,6 +403,7 @@ texture_tower_create_texture (MetaTextureTower *tower,
TEXTURE_FORMAT);
}
else
#endif /* GL_TEXTURE_RECTANGLE_ARB */
{
tower->textures[level] = cogl_texture_new_with_size (width, height,
COGL_TEXTURE_NO_AUTO_MIPMAP,

View File

@ -6,7 +6,7 @@
#include <config.h>
#include <X11/extensions/Xdamage.h>
#include "compositor-mutter.h"
#include <meta/compositor-mutter.h>
MetaWindowActor *meta_window_actor_new (MetaWindow *window);
@ -28,6 +28,8 @@ void meta_window_actor_process_damage (MetaWindowActor *self,
XDamageNotifyEvent *event);
void meta_window_actor_pre_paint (MetaWindowActor *self);
void meta_window_actor_invalidate_shadow (MetaWindowActor *self);
gboolean meta_window_actor_effect_in_progress (MetaWindowActor *self);
void meta_window_actor_sync_actor_position (MetaWindowActor *self);
void meta_window_actor_sync_visibility (MetaWindowActor *self);

View File

@ -1,5 +1,7 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
#include <config.h>
#define _ISOC99_SOURCE /* for roundf */
#include <math.h>
@ -9,18 +11,27 @@
#include <X11/extensions/Xrender.h>
#include <clutter/x11/clutter-x11.h>
#include <gdk/gdk.h> /* for gdk_rectangle_union() */
#include "display.h"
#include "errors.h"
#include <meta/display.h>
#include <meta/errors.h>
#include "frame.h"
#include "window.h"
#include <meta/window.h>
#include "xprops.h"
#include "compositor-private.h"
#include "meta-shadow-factory-private.h"
#include "meta-shaped-texture.h"
#include "meta-window-actor-private.h"
#include "shadow.h"
#include "tidy/tidy-texture-frame.h"
enum {
POSITION_CHANGED,
SIZE_CHANGED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = {0};
struct _MetaWindowActorPrivate
{
@ -31,12 +42,27 @@ struct _MetaWindowActorPrivate
MetaScreen *screen;
ClutterActor *actor;
ClutterActor *shadow;
/* MetaShadowFactory only caches shadows that are actually in use;
* to avoid unnecessary recomputation we do two things: 1) we store
* both a focused and unfocused shadow for the window. If the window
* doesn't have different focused and unfocused shadow parameters,
* these will be the same. 2) when the shadow potentially changes we
* don't immediately unreference the old shadow, we just flag it as
* dirty and recompute it when we next need it (recompute_focused_shadow,
* recompute_unfocused_shadow.) Because of our extraction of
* size-invariant window shape, we'll often find that the new shadow
* is the same as the old shadow.
*/
MetaShadow *focused_shadow;
MetaShadow *unfocused_shadow;
Pixmap back_pixmap;
Damage damage;
guint8 opacity;
guint8 shadow_opacity;
gchar * desc;
@ -45,9 +71,16 @@ struct _MetaWindowActorPrivate
/* A rectangular region with the unshaped extends of the window
* texture */
cairo_region_t *bounding_region;
/* The region we should clip to when painting the shadow */
cairo_region_t *shadow_clip;
/* Extracted size-invariant shape used for shadows */
MetaWindowShape *shadow_shape;
gint freeze_count;
char * shadow_class;
/*
* These need to be counters rather than flags, since more plugins
* can implement same effect; the practicality of stacking effects
@ -70,7 +103,9 @@ struct _MetaWindowActorPrivate
guint received_damage : 1;
guint needs_pixmap : 1;
guint needs_reshape : 1;
guint needs_reshape : 1;
guint recompute_focused_shadow : 1;
guint recompute_unfocused_shadow : 1;
guint size_changed : 1;
guint needs_destroy : 1;
@ -87,8 +122,13 @@ enum
PROP_X_WINDOW,
PROP_X_WINDOW_ATTRIBUTES,
PROP_NO_SHADOW,
PROP_SHADOW_CLASS
};
#define DEFAULT_SHADOW_RADIUS 12
#define DEFAULT_SHADOW_X_OFFSET 0
#define DEFAULT_SHADOW_Y_OFFSET 8
static void meta_window_actor_dispose (GObject *object);
static void meta_window_actor_finalize (GObject *object);
static void meta_window_actor_constructed (GObject *object);
@ -101,11 +141,18 @@ static void meta_window_actor_get_property (GObject *object,
GValue *value,
GParamSpec *pspec);
static void meta_window_actor_paint (ClutterActor *actor);
#if CLUTTER_CHECK_VERSION(1, 5, 2)
static gboolean meta_window_actor_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume);
#endif
static void meta_window_actor_detach (MetaWindowActor *self);
static gboolean meta_window_actor_has_shadow (MetaWindowActor *self);
static void meta_window_actor_clear_shape_region (MetaWindowActor *self);
static void meta_window_actor_clear_bounding_region (MetaWindowActor *self);
static void meta_window_actor_clear_shadow_clip (MetaWindowActor *self);
static gboolean is_shaped (MetaDisplay *display,
Window xwindow);
@ -161,6 +208,7 @@ static void
meta_window_actor_class_init (MetaWindowActorClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
GParamSpec *pspec;
g_type_class_add_private (klass, sizeof (MetaWindowActorPrivate));
@ -171,6 +219,11 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
object_class->get_property = meta_window_actor_get_property;
object_class->constructed = meta_window_actor_constructed;
actor_class->paint = meta_window_actor_paint;
#if CLUTTER_CHECK_VERSION(1, 5, 2)
actor_class->get_paint_volume = meta_window_actor_get_paint_volume;
#endif
pspec = g_param_spec_object ("meta-window",
"MetaWindow",
"The displayed MetaWindow",
@ -216,11 +269,36 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
"No shadow",
"Do not add shaddow to this window",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
G_PARAM_READWRITE);
g_object_class_install_property (object_class,
PROP_NO_SHADOW,
pspec);
pspec = g_param_spec_string ("shadow-class",
"Name of the shadow class for this window.",
"NULL means to use the default shadow class for this window type",
NULL,
G_PARAM_READWRITE);
g_object_class_install_property (object_class,
PROP_SHADOW_CLASS,
pspec);
signals[POSITION_CHANGED] =
g_signal_new ("position-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
signals[SIZE_CHANGED] =
g_signal_new ("size-changed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
@ -232,6 +310,7 @@ meta_window_actor_init (MetaWindowActor *self)
META_TYPE_WINDOW_ACTOR,
MetaWindowActorPrivate);
priv->opacity = 0xff;
priv->shadow_class = NULL;
}
static void
@ -246,7 +325,6 @@ window_decorated_notify (MetaWindow *mw,
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window new_xwindow;
MetaCompScreen *info;
XWindowAttributes attrs;
/*
@ -262,8 +340,6 @@ window_decorated_notify (MetaWindow *mw,
meta_window_actor_detach (self);
info = meta_screen_get_compositor_data (screen);
/*
* First of all, clean up any resources we are currently using and will
* be replacing.
@ -291,24 +367,20 @@ window_decorated_notify (MetaWindow *mw,
g_object_set (self, "x-window-attributes", &attrs, NULL);
if (priv->shadow)
{
ClutterActor *p = clutter_actor_get_parent (priv->shadow);
if (CLUTTER_IS_CONTAINER (p))
clutter_container_remove_actor (CLUTTER_CONTAINER (p), priv->shadow);
else
clutter_actor_unparent (priv->shadow);
priv->shadow = NULL;
}
/*
* Recreate the contents.
*/
meta_window_actor_constructed (G_OBJECT (self));
}
static void
window_appears_focused_notify (MetaWindow *mw,
GParamSpec *arg1,
gpointer data)
{
clutter_actor_queue_redraw (CLUTTER_ACTOR (data));
}
static void
meta_window_actor_constructed (GObject *object)
{
@ -319,9 +391,6 @@ meta_window_actor_constructed (GObject *object)
Window xwindow = priv->xwindow;
Display *xdisplay = meta_display_get_xdisplay (display);
XRenderPictFormat *format;
MetaCompositor *compositor;
compositor = meta_display_get_compositor (display);
#ifdef HAVE_SHAPE
/* Listen for ShapeNotify events on the window */
@ -342,15 +411,6 @@ meta_window_actor_constructed (GObject *object)
if (format && format->type == PictTypeDirect && format->direct.alphaMask)
priv->argb32 = TRUE;
meta_window_actor_update_opacity (self);
if (meta_window_actor_has_shadow (self))
{
priv->shadow = meta_create_shadow_frame (compositor);
clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->shadow);
}
if (!priv->actor)
{
priv->actor = meta_shaped_texture_new ();
@ -368,6 +428,8 @@ meta_window_actor_constructed (GObject *object)
g_signal_connect (priv->window, "notify::decorated",
G_CALLBACK (window_decorated_notify), self);
g_signal_connect (priv->window, "notify::appears-focused",
G_CALLBACK (window_appears_focused_notify), self);
}
else
{
@ -378,7 +440,7 @@ meta_window_actor_constructed (GObject *object)
clutter_actor_raise_top (priv->actor);
}
meta_window_actor_update_opacity (self);
meta_window_actor_update_shape (self, priv->shaped);
}
@ -406,6 +468,31 @@ meta_window_actor_dispose (GObject *object)
meta_window_actor_clear_shape_region (self);
meta_window_actor_clear_bounding_region (self);
meta_window_actor_clear_shadow_clip (self);
if (priv->shadow_class != NULL)
{
g_free (priv->shadow_class);
priv->shadow_class = NULL;
}
if (priv->focused_shadow != NULL)
{
meta_shadow_unref (priv->focused_shadow);
priv->focused_shadow = NULL;
}
if (priv->unfocused_shadow != NULL)
{
meta_shadow_unref (priv->unfocused_shadow);
priv->unfocused_shadow = NULL;
}
if (priv->shadow_shape != NULL)
{
meta_window_shape_unref (priv->shadow_shape);
priv->shadow_shape = NULL;
}
if (priv->damage != None)
{
@ -418,6 +505,12 @@ meta_window_actor_dispose (GObject *object)
info->windows = g_list_remove (info->windows, (gconstpointer) self);
if (priv->window)
{
g_object_unref (priv->window);
priv->window = NULL;
}
/*
* Release the extra reference we took on the actor.
*/
@ -450,7 +543,11 @@ meta_window_actor_set_property (GObject *object,
switch (prop_id)
{
case PROP_META_WINDOW:
priv->window = g_value_get_object (value);
{
if (priv->window)
g_object_unref (priv->window);
priv->window = g_value_dup_object (value);
}
break;
case PROP_META_SCREEN:
priv->screen = g_value_get_pointer (value);
@ -463,36 +560,27 @@ meta_window_actor_set_property (GObject *object,
break;
case PROP_NO_SHADOW:
{
gboolean oldv = priv->no_shadow ? TRUE : FALSE;
gboolean newv = g_value_get_boolean (value);
if (oldv == newv)
if (newv == priv->no_shadow)
return;
priv->no_shadow = newv;
if (newv && priv->shadow)
{
clutter_container_remove_actor (CLUTTER_CONTAINER (object),
priv->shadow);
priv->shadow = NULL;
}
else if (!newv && !priv->shadow && meta_window_actor_has_shadow (self))
{
gfloat w, h;
MetaDisplay *display = meta_screen_get_display (priv->screen);
MetaCompositor *compositor;
meta_window_actor_invalidate_shadow (self);
}
break;
case PROP_SHADOW_CLASS:
{
const char *newv = g_value_get_string (value);
compositor = meta_display_get_compositor (display);
if (g_strcmp0 (newv, priv->shadow_class) == 0)
return;
clutter_actor_get_size (CLUTTER_ACTOR (self), &w, &h);
g_free (priv->shadow_class);
priv->shadow_class = g_strdup (newv);
priv->shadow = meta_create_shadow_frame (compositor);
clutter_actor_set_size (priv->shadow, w, h);
clutter_container_add_actor (CLUTTER_CONTAINER (self), priv->shadow);
}
meta_window_actor_invalidate_shadow (self);
}
break;
default:
@ -526,12 +614,166 @@ meta_window_actor_get_property (GObject *object,
case PROP_NO_SHADOW:
g_value_set_boolean (value, priv->no_shadow);
break;
case PROP_SHADOW_CLASS:
g_value_set_string (value, priv->shadow_class);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static const char *
meta_window_actor_get_shadow_class (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
if (priv->shadow_class != NULL)
return priv->shadow_class;
else
{
MetaWindowType window_type = meta_window_get_window_type (priv->window);
switch (window_type)
{
case META_WINDOW_DROPDOWN_MENU:
return "dropdown-menu";
case META_WINDOW_POPUP_MENU:
return "popup-menu";
default:
{
MetaFrameType frame_type = meta_window_get_frame_type (priv->window);
return meta_frame_type_to_string (frame_type);
}
}
}
}
static void
meta_window_actor_get_shadow_params (MetaWindowActor *self,
gboolean appears_focused,
MetaShadowParams *params)
{
const char *shadow_class = meta_window_actor_get_shadow_class (self);
meta_shadow_factory_get_params (meta_shadow_factory_get_default (),
shadow_class, appears_focused,
params);
}
static void
meta_window_actor_get_shape_bounds (MetaWindowActor *self,
cairo_rectangle_int_t *bounds)
{
MetaWindowActorPrivate *priv = self->priv;
/* We need to be defensive here because there are corner cases
* where getting the shape fails on a window being destroyed
* and similar.
*/
if (priv->shaped && priv->shape_region)
cairo_region_get_extents (priv->shape_region, bounds);
else if (priv->bounding_region)
cairo_region_get_extents (priv->bounding_region, bounds);
else
bounds->x = bounds->y = bounds->width = bounds->height = 0;
}
#if CLUTTER_CHECK_VERSION(1, 5, 2)
static void
meta_window_actor_get_shadow_bounds (MetaWindowActor *self,
gboolean appears_focused,
cairo_rectangle_int_t *bounds)
{
MetaWindowActorPrivate *priv = self->priv;
MetaShadow *shadow = appears_focused ? priv->focused_shadow : priv->unfocused_shadow;
cairo_rectangle_int_t shape_bounds;
MetaShadowParams params;
meta_window_actor_get_shape_bounds (self, &shape_bounds);
meta_window_actor_get_shadow_params (self, appears_focused, &params);
meta_shadow_get_bounds (shadow,
params.x_offset + shape_bounds.x,
params.y_offset + shape_bounds.y,
shape_bounds.width,
shape_bounds.height,
bounds);
}
#endif
static void
meta_window_actor_paint (ClutterActor *actor)
{
MetaWindowActor *self = META_WINDOW_ACTOR (actor);
MetaWindowActorPrivate *priv = self->priv;
gboolean appears_focused = meta_window_appears_focused (priv->window);
MetaShadow *shadow = appears_focused ? priv->focused_shadow : priv->unfocused_shadow;
if (shadow != NULL)
{
MetaShadowParams params;
cairo_rectangle_int_t shape_bounds;
meta_window_actor_get_shape_bounds (self, &shape_bounds);
meta_window_actor_get_shadow_params (self, appears_focused, &params);
meta_shadow_paint (shadow,
params.x_offset + shape_bounds.x,
params.y_offset + shape_bounds.y,
shape_bounds.width,
shape_bounds.height,
(clutter_actor_get_paint_opacity (actor) * params.opacity * priv->opacity) / (255 * 255),
priv->shadow_clip);
}
CLUTTER_ACTOR_CLASS (meta_window_actor_parent_class)->paint (actor);
}
#if CLUTTER_CHECK_VERSION(1, 5, 2)
static gboolean
meta_window_actor_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
MetaWindowActor *self = META_WINDOW_ACTOR (actor);
MetaWindowActorPrivate *priv = self->priv;
cairo_rectangle_int_t bounds;
gboolean appears_focused = meta_window_appears_focused (priv->window);
ClutterVertex origin;
/* The paint volume is computed before paint functions are called
* so our bounds might not be updated yet. Force an update. */
meta_window_actor_pre_paint (self);
meta_window_actor_get_shape_bounds (self, &bounds);
if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow)
{
cairo_rectangle_int_t shadow_bounds;
/* We could compute an full clip region as we do for the window
* texture, but the shadow is relatively cheap to draw, and
* a little more complex to clip, so we just catch the case where
* the shadow is completely obscured and doesn't need to be drawn
* at all.
*/
meta_window_actor_get_shadow_bounds (self, appears_focused, &shadow_bounds);
gdk_rectangle_union (&bounds, &shadow_bounds, &bounds);
}
origin.x = bounds.x;
origin.y = bounds.y;
origin.z = 0.0f;
clutter_paint_volume_set_origin (volume, &origin);
clutter_paint_volume_set_width (volume, bounds.width);
clutter_paint_volume_set_height (volume, bounds.height);
return TRUE;
}
#endif /* CLUTTER_CHECK_VERSION */
static gboolean
is_shaped (MetaDisplay *display, Window xwindow)
{
@ -560,10 +802,16 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
if (priv->no_shadow)
return FALSE;
/* Leaving out shadows for maximized and fullscreen windows is an effeciency
* win and also prevents the unsightly effect of the shadow of maximized
* window appearing on an adjacent window */
if ((meta_window_get_maximized (priv->window) == (META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL)) ||
meta_window_is_fullscreen (priv->window))
return FALSE;
/*
* Always put a shadow around windows with a frame - This should override
* the restriction about not putting a shadow around shaped windows
* as the frame might be the reason the window is shaped
* the restriction about not putting a shadow around ARGB windows.
*/
if (priv->window)
{
@ -576,7 +824,8 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
}
/*
* Do not add shadows to ARGB windows (since they are probably transparent)
* Do not add shadows to ARGB windows; eventually we should generate a
* shadow from the input shape for such windows.
*/
if (priv->argb32 || priv->opacity != 0xff)
{
@ -585,19 +834,8 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
return FALSE;
}
/*
* Never put a shadow around shaped windows
*/
if (priv->shaped)
{
meta_verbose ("Window 0x%x has no shadow as it is shaped\n",
(guint)priv->xwindow);
return FALSE;
}
/*
* Add shadows to override redirect windows (e.g., Gtk menus).
* This must have lower priority than window shape test.
*/
if (priv->attrs.override_redirect)
{
@ -681,6 +919,19 @@ meta_window_actor_get_texture (MetaWindowActor *self)
return self->priv->actor;
}
/**
* meta_window_actor_is_destroyed:
*
* Gets whether the X window that the actor was displaying has been destroyed
*
* Return value: %TRUE when the window is destroyed, otherwise %FALSE
*/
gboolean
meta_window_actor_is_destroyed (MetaWindowActor *self)
{
return self->priv->disposed;
}
gboolean
meta_window_actor_is_override_redirect (MetaWindowActor *self)
{
@ -1107,6 +1358,8 @@ meta_window_actor_sync_actor_position (MetaWindowActor *self)
window_rect.x, window_rect.y);
clutter_actor_set_size (CLUTTER_ACTOR (self),
window_rect.width, window_rect.height);
g_signal_emit (self, signals[POSITION_CHANGED], 0);
}
void
@ -1358,6 +1611,18 @@ meta_window_actor_clear_bounding_region (MetaWindowActor *self)
}
}
static void
meta_window_actor_clear_shadow_clip (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
if (priv->shadow_clip)
{
cairo_region_destroy (priv->shadow_clip);
priv->shadow_clip = NULL;
}
}
static void
meta_window_actor_update_bounding_region (MetaWindowActor *self,
int width,
@ -1366,9 +1631,28 @@ meta_window_actor_update_bounding_region (MetaWindowActor *self,
MetaWindowActorPrivate *priv = self->priv;
cairo_rectangle_int_t bounding_rectangle = { 0, 0, width, height };
if (priv->bounding_region != NULL)
{
cairo_rectangle_int_t old_bounding_rectangle;
cairo_region_get_extents (priv->bounding_region, &old_bounding_rectangle);
if (old_bounding_rectangle.width == width && old_bounding_rectangle.height == height)
return;
}
meta_window_actor_clear_bounding_region (self);
priv->bounding_region = cairo_region_create_rectangle (&bounding_rectangle);
/* When we're shaped, we use the shape region to generate the shadow; the shape
* region only changes when we get ShapeNotify event; but for unshaped windows
* we generate the shadow from the bounding region, so we need to recompute
* the shadow when the size changes.
*/
if (!priv->shaped)
meta_window_actor_invalidate_shadow (self);
g_signal_emit (self, signals[SIZE_CHANGED], 0);
}
static void
@ -1404,7 +1688,7 @@ meta_window_actor_get_obscured_region (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
if (!priv->argb32 && priv->back_pixmap)
if (!priv->argb32 && priv->opacity == 0xff && priv->back_pixmap)
{
if (priv->shaped)
return priv->shape_region;
@ -1497,30 +1781,12 @@ meta_window_actor_set_visible_region_beneath (MetaWindowActor *self,
cairo_region_t *beneath_region)
{
MetaWindowActorPrivate *priv = self->priv;
gboolean appears_focused = meta_window_appears_focused (priv->window);
if (priv->shadow)
if (appears_focused ? priv->focused_shadow : priv->unfocused_shadow)
{
cairo_rectangle_int_t shadow_rect;
ClutterActorBox box;
cairo_region_overlap_t overlap;
/* We could compute an full clip region as we do for the window
* texture, but the shadow is relatively cheap to draw, and
* a little more complex to clip, so we just catch the case where
* the shadow is completely obscured and doesn't need to be drawn
* at all.
*/
clutter_actor_get_allocation_box (priv->shadow, &box);
shadow_rect.x = roundf (box.x1);
shadow_rect.y = roundf (box.y1);
shadow_rect.width = roundf (box.x2 - box.x1);
shadow_rect.height = roundf (box.y2 - box.y1);
overlap = cairo_region_contains_rectangle (beneath_region, &shadow_rect);
tidy_texture_frame_set_needs_paint (TIDY_TEXTURE_FRAME (priv->shadow),
overlap != CAIRO_REGION_OVERLAP_OUT);
meta_window_actor_clear_shadow_clip (self);
priv->shadow_clip = cairo_region_copy (beneath_region);
}
}
@ -1538,8 +1804,7 @@ meta_window_actor_reset_visible_regions (MetaWindowActor *self)
meta_shaped_texture_set_clip_region (META_SHAPED_TEXTURE (priv->actor),
NULL);
if (priv->shadow)
tidy_texture_frame_set_needs_paint (TIDY_TEXTURE_FRAME (priv->shadow), TRUE);
meta_window_actor_clear_shadow_clip (self);
}
static void
@ -1552,7 +1817,6 @@ check_needs_pixmap (MetaWindowActor *self)
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
MetaCompositor *compositor;
Window xwindow = priv->xwindow;
gboolean full = FALSE;
if (!priv->needs_pixmap)
return;
@ -1613,21 +1877,18 @@ check_needs_pixmap (MetaWindowActor *self)
* do it here.
* See: http://bugzilla.clutter-project.org/show_bug.cgi?id=2236
*/
if (!clutter_glx_texture_pixmap_using_extension (
CLUTTER_GLX_TEXTURE_PIXMAP (priv->actor)))
#ifdef HAVE_GLX_TEXTURE_PIXMAP
if (G_UNLIKELY (!clutter_glx_texture_pixmap_using_extension (
CLUTTER_GLX_TEXTURE_PIXMAP (priv->actor))))
g_warning ("NOTE: Not using GLX TFP!\n");
#endif
g_object_get (priv->actor,
"pixmap-width", &pxm_width,
"pixmap-height", &pxm_height,
NULL);
if (priv->shadow)
clutter_actor_set_size (priv->shadow, pxm_width, pxm_height);
meta_window_actor_update_bounding_region (self, pxm_width, pxm_height);
full = TRUE;
}
meta_error_trap_pop (display);
@ -1635,6 +1896,79 @@ check_needs_pixmap (MetaWindowActor *self)
priv->needs_pixmap = FALSE;
}
static void
check_needs_shadow (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
MetaShadow *old_shadow = NULL;
MetaShadow **shadow_location;
gboolean recompute_shadow;
gboolean should_have_shadow;
gboolean appears_focused;
if (!priv->mapped)
return;
/* Calling meta_window_actor_has_shadow() here at every pre-paint is cheap
* and avoids the need to explicitly handle window type changes, which
* we would do if tried to keep track of when we might be adding or removing
* a shadow more explicitly. We only keep track of changes to the *shape* of
* the shadow with priv->recompute_shadow.
*/
should_have_shadow = meta_window_actor_has_shadow (self);
appears_focused = meta_window_appears_focused (priv->window);
if (appears_focused)
{
recompute_shadow = priv->recompute_focused_shadow;
priv->recompute_focused_shadow = FALSE;
shadow_location = &priv->focused_shadow;
}
else
{
recompute_shadow = priv->recompute_unfocused_shadow;
priv->recompute_unfocused_shadow = FALSE;
shadow_location = &priv->unfocused_shadow;
}
if (!should_have_shadow || recompute_shadow)
{
if (*shadow_location != NULL)
{
old_shadow = *shadow_location;
*shadow_location = NULL;
}
}
if (*shadow_location == NULL && should_have_shadow)
{
if (priv->shadow_shape == NULL)
{
if (priv->shaped && priv->shape_region)
priv->shadow_shape = meta_window_shape_new (priv->shape_region);
else if (priv->bounding_region)
priv->shadow_shape = meta_window_shape_new (priv->bounding_region);
}
if (priv->shadow_shape != NULL)
{
MetaShadowFactory *factory = meta_shadow_factory_get_default ();
const char *shadow_class = meta_window_actor_get_shadow_class (self);
cairo_rectangle_int_t shape_bounds;
meta_window_actor_get_shape_bounds (self, &shape_bounds);
*shadow_location = meta_shadow_factory_get_shadow (factory,
priv->shadow_shape,
shape_bounds.width, shape_bounds.height,
shadow_class, appears_focused);
}
}
if (old_shadow != NULL)
meta_shadow_unref (old_shadow);
}
static gboolean
is_frozen (MetaWindowActor *self)
{
@ -1733,6 +2067,7 @@ check_needs_reshape (MetaWindowActor *self)
#endif
priv->needs_reshape = FALSE;
meta_window_actor_invalidate_shadow (self);
}
void
@ -1743,6 +2078,11 @@ meta_window_actor_update_shape (MetaWindowActor *self,
priv->shaped = shaped;
priv->needs_reshape = TRUE;
if (priv->shadow_shape != NULL)
{
meta_window_shape_unref (priv->shadow_shape);
priv->shadow_shape = NULL;
}
clutter_actor_queue_redraw (priv->actor);
}
@ -1770,8 +2110,19 @@ meta_window_actor_pre_paint (MetaWindowActor *self)
priv->received_damage = FALSE;
}
check_needs_reshape (self);
check_needs_pixmap (self);
check_needs_reshape (self);
check_needs_shadow (self);
}
void
meta_window_actor_invalidate_shadow (MetaWindowActor *self)
{
MetaWindowActorPrivate *priv = self->priv;
priv->recompute_focused_shadow = TRUE;
priv->recompute_unfocused_shadow = TRUE;
clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
}
void
@ -1794,5 +2145,5 @@ meta_window_actor_update_opacity (MetaWindowActor *self)
opacity = 255;
self->priv->opacity = opacity;
clutter_actor_set_opacity (CLUTTER_ACTOR (self), opacity);
clutter_actor_set_opacity (self->priv->actor, opacity);
}

View File

@ -5,8 +5,11 @@
#define _ISOC99_SOURCE /* for roundf */
#include <math.h>
#include <gdk/gdk.h> /* for gdk_rectangle_intersect() */
#include "meta-window-actor-private.h"
#include "meta-window-group.h"
#include "meta-background-actor.h"
struct _MetaWindowGroupClass
{
@ -102,7 +105,9 @@ meta_window_group_paint (ClutterActor *actor)
{
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
cairo_region_t *visible_region;
GLboolean scissor_test;
cairo_rectangle_int_t screen_rect = { 0 };
cairo_rectangle_int_t scissor_rect;
GList *children, *l;
/* We walk the list from top to bottom (opposite of painting order),
@ -118,35 +123,67 @@ meta_window_group_paint (ClutterActor *actor)
* optimization, however.)
*/
meta_screen_get_size (window_group->screen, &screen_rect.width, &screen_rect.height);
visible_region = cairo_region_create_rectangle (&screen_rect);
/* When doing a partial stage paint, Clutter will set the GL scissor
* box to the clip rectangle for the partial repaint. We combine the screen
* rectangle with the scissor box to get the region we need to
* paint. (Strangely, the scissor box sometimes seems to be bigger
* than the stage ... Clutter should probably be clampimg)
*/
glGetBooleanv (GL_SCISSOR_TEST, &scissor_test);
if (scissor_test)
{
GLint scissor_box[4];
glGetIntegerv (GL_SCISSOR_BOX, scissor_box);
scissor_rect.x = scissor_box[0];
scissor_rect.y = screen_rect.height - (scissor_box[1] + scissor_box[3]);
scissor_rect.width = scissor_box[2];
scissor_rect.height = scissor_box[3];
gdk_rectangle_intersect (&scissor_rect, &screen_rect, &scissor_rect);
}
else
{
scissor_rect = screen_rect;
}
visible_region = cairo_region_create_rectangle (&scissor_rect);
for (l = children; l; l = l->next)
{
MetaWindowActor *window_actor;
gboolean x, y;
if (!META_IS_WINDOW_ACTOR (l->data) || !CLUTTER_ACTOR_IS_VISIBLE (l->data))
if (!CLUTTER_ACTOR_IS_VISIBLE (l->data))
continue;
window_actor = l->data;
if (!actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
continue;
/* Temporarily move to the coordinate system of the actor */
cairo_region_translate (visible_region, - x, - y);
meta_window_actor_set_visible_region (window_actor, visible_region);
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
if (META_IS_WINDOW_ACTOR (l->data))
{
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
if (obscured_region)
cairo_region_subtract (visible_region, obscured_region);
}
MetaWindowActor *window_actor = l->data;
gboolean x, y;
meta_window_actor_set_visible_region_beneath (window_actor, visible_region);
cairo_region_translate (visible_region, x, y);
if (!actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
continue;
/* Temporarily move to the coordinate system of the actor */
cairo_region_translate (visible_region, - x, - y);
meta_window_actor_set_visible_region (window_actor, visible_region);
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
{
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
if (obscured_region)
cairo_region_subtract (visible_region, obscured_region);
}
meta_window_actor_set_visible_region_beneath (window_actor, visible_region);
cairo_region_translate (visible_region, x, y);
}
else if (META_IS_BACKGROUND_ACTOR (l->data))
{
MetaBackgroundActor *background_actor = l->data;
meta_background_actor_set_visible_region (background_actor, visible_region);
}
}
cairo_region_destroy (visible_region);
@ -158,13 +195,17 @@ meta_window_group_paint (ClutterActor *actor)
*/
for (l = children; l; l = l->next)
{
MetaWindowActor *window_actor;
if (!META_IS_WINDOW_ACTOR (l->data))
continue;
window_actor = l->data;
meta_window_actor_reset_visible_regions (window_actor);
if (META_IS_WINDOW_ACTOR (l->data))
{
MetaWindowActor *window_actor = l->data;
window_actor = l->data;
meta_window_actor_reset_visible_regions (window_actor);
}
else if (META_IS_BACKGROUND_ACTOR (l->data))
{
MetaBackgroundActor *background_actor = l->data;
meta_background_actor_set_visible_region (background_actor, NULL);
}
}
g_list_free (children);

View File

@ -5,7 +5,7 @@
#include <clutter/clutter.h>
#include "screen.h"
#include <meta/screen.h>
/**
* MetaWindowGroup:

View File

@ -0,0 +1,254 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MetaWindowShape
*
* Extracted invariant window shape
*
* Copyright (C) 2010 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <string.h>
#include "meta-window-shape.h"
#include "region-utils.h"
struct _MetaWindowShape
{
guint ref_count;
int top, right, bottom, left;
int n_rectangles;
cairo_rectangle_int_t *rectangles;
guint hash;
};
MetaWindowShape *
meta_window_shape_new (cairo_region_t *region)
{
MetaWindowShape *shape;
MetaRegionIterator iter;
cairo_rectangle_int_t extents;
int max_yspan_y1 = 0;
int max_yspan_y2 = 0;
int max_xspan_x1 = -1;
int max_xspan_x2 = -1;
guint hash;
shape = g_slice_new0 (MetaWindowShape);
shape->ref_count = 1;
cairo_region_get_extents (region, &extents);
shape->n_rectangles = cairo_region_num_rectangles (region);
if (shape->n_rectangles == 0)
{
shape->rectangles = NULL;
shape->top = shape->right = shape->bottom = shape->left = 0;
shape->hash = 0;
return shape;
}
for (meta_region_iterator_init (&iter, region);
!meta_region_iterator_at_end (&iter);
meta_region_iterator_next (&iter))
{
int max_line_xspan_x1 = -1;
int max_line_xspan_x2 = -1;
if (iter.rectangle.width > max_line_xspan_x2 - max_line_xspan_x1)
{
max_line_xspan_x1 = iter.rectangle.x;
max_line_xspan_x2 = iter.rectangle.x + iter.rectangle.width;
}
if (iter.line_end)
{
if (iter.rectangle.height > max_yspan_y2 - max_yspan_y1)
{
max_yspan_y1 = iter.rectangle.y;
max_yspan_y2 = iter.rectangle.y + iter.rectangle.height;
}
if (max_xspan_x1 < 0) /* First line */
{
max_xspan_x1 = max_line_xspan_x1;
max_xspan_x2 = max_line_xspan_x2;
}
else
{
max_xspan_x1 = MAX (max_xspan_x1, max_line_xspan_x1);
max_xspan_x2 = MIN (max_xspan_x2, max_line_xspan_x2);
if (max_xspan_x2 < max_xspan_x1)
max_xspan_x2 = max_xspan_x1;
}
}
}
#if 0
g_print ("xspan: %d -> %d, yspan: %d -> %d\n",
max_xspan_x1, max_xspan_x2,
max_yspan_y1, max_yspan_y2);
#endif
shape->top = max_yspan_y1 - extents.y;
shape->right = extents.x + extents.width - max_xspan_x2;
shape->bottom = extents.y + extents.height - max_yspan_y2;
shape->left = max_xspan_x1 - extents.x;
shape->rectangles = g_new (cairo_rectangle_int_t, shape->n_rectangles);
hash = 0;
for (meta_region_iterator_init (&iter, region);
!meta_region_iterator_at_end (&iter);
meta_region_iterator_next (&iter))
{
int x1, x2, y1, y2;
x1 = iter.rectangle.x;
x2 = iter.rectangle.x + iter.rectangle.width;
y1 = iter.rectangle.y;
y2 = iter.rectangle.y + iter.rectangle.height;
if (x1 > max_xspan_x1)
x1 -= MIN (x1, max_xspan_x2 - 1) - max_xspan_x1;
if (x2 > max_xspan_x1)
x2 -= MIN (x2, max_xspan_x2 - 1) - max_xspan_x1;
if (y1 > max_yspan_y1)
y1 -= MIN (y1, max_yspan_y2 - 1) - max_yspan_y1;
if (y2 > max_yspan_y1)
y2 -= MIN (y2, max_yspan_y2 - 1) - max_yspan_y1;
shape->rectangles[iter.i].x = x1 - extents.x;
shape->rectangles[iter.i].y = y1 - extents.y;
shape->rectangles[iter.i].width = x2 - x1;
shape->rectangles[iter.i].height = y2 - y1;
#if 0
g_print ("%d: +%d+%dx%dx%d => +%d+%dx%dx%d\n",
iter.i, iter.rectangle.x, iter.rectangle.y, iter.rectangle.width, iter.rectangle.height,
shape->rectangles[iter.i].x, shape->rectangles[iter.i].y,
hape->rectangles[iter.i].width, shape->rectangles[iter.i].height);
#endif
hash = hash * 31 + x1 * 17 + x2 * 27 + y1 * 37 + y2 * 43;
}
shape->hash = hash;
#if 0
g_print ("%d %d %d %d: %#x\n\n", shape->top, shape->right, shape->bottom, shape->left, shape->hash);
#endif
return shape;
}
MetaWindowShape *
meta_window_shape_ref (MetaWindowShape *shape)
{
shape->ref_count++;
return shape;
}
void
meta_window_shape_unref (MetaWindowShape *shape)
{
shape->ref_count--;
if (shape->ref_count == 0)
{
g_free (shape->rectangles);
g_slice_free (MetaWindowShape, shape);
}
}
guint
meta_window_shape_hash (MetaWindowShape *shape)
{
return shape->hash;
}
gboolean
meta_window_shape_equal (MetaWindowShape *shape_a,
MetaWindowShape *shape_b)
{
if (shape_a->n_rectangles != shape_b->n_rectangles)
return FALSE;
return memcmp (shape_a->rectangles, shape_b->rectangles,
sizeof (cairo_rectangle_int_t) * shape_a->n_rectangles) == 0;
}
void
meta_window_shape_get_borders (MetaWindowShape *shape,
int *border_top,
int *border_right,
int *border_bottom,
int *border_left)
{
if (border_top)
*border_top = shape->top;
if (border_right)
*border_right = shape->right;
if (border_bottom)
*border_bottom = shape->bottom;
if (border_left)
*border_left = shape->left;
}
/**
* meta_window_shape_to_region:
* @shape: a #MetaWindowShape
* @center_width: size of the central region horizontally
* @center_height: size of the central region vertically
*
* Converts the shape to to a cairo_region_t using the given width
* and height for the central scaled region.
*
* Return value: a newly created region
*/
cairo_region_t *
meta_window_shape_to_region (MetaWindowShape *shape,
int center_width,
int center_height)
{
cairo_region_t *region;
int i;
region = cairo_region_create ();
for (i = 0; i < shape->n_rectangles; i++)
{
cairo_rectangle_int_t rect = shape->rectangles[i];
if (rect.x <= shape->left && rect.x + rect.width >= shape->left + 1)
rect.width += center_width;
else if (rect.x >= shape->left + 1)
rect.x += center_width;
if (rect.y <= shape->top && rect.y + rect.height >= shape->top + 1)
rect.height += center_height;
else if (rect.y >= shape->top + 1)
rect.y += center_height;
cairo_region_union_rectangle (region, &rect);
}
return region;
}

View File

@ -0,0 +1,60 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MetaWindowShape
*
* Extracted invariant window shape
*
* Copyright (C) 2010 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_WINDOW_SHAPE_H__
#define __META_WINDOW_SHAPE_H__
#include <cairo.h>
#include <glib.h>
/**
* MetaWindowShape:
* #MetaWindowShape represents a 9-sliced region with borders on all sides that
* are unscaled, and a constant central region that is scaled. For example,
* the regions representing two windows that are rounded rectangles,
* with the same corner radius but different sizes, have the
* same MetaWindowShape.
*
* #MetaWindowShape is designed to be used as part of a hash table key, so has
* efficient hash and equal functions.
*/
typedef struct _MetaWindowShape MetaWindowShape;
MetaWindowShape * meta_window_shape_new (cairo_region_t *region);
MetaWindowShape * meta_window_shape_ref (MetaWindowShape *shape);
void meta_window_shape_unref (MetaWindowShape *shape);
guint meta_window_shape_hash (MetaWindowShape *shape);
gboolean meta_window_shape_equal (MetaWindowShape *shape_a,
MetaWindowShape *shape_b);
void meta_window_shape_get_borders (MetaWindowShape *shape,
int *border_top,
int *border_right,
int *border_bottom,
int *border_left);
cairo_region_t *meta_window_shape_to_region (MetaWindowShape *shape,
int center_width,
int center_height);
#endif /* __META_WINDOW_SHAPE_H __*/

View File

@ -1,7 +1,7 @@
pkglibdir=@MUTTER_PLUGIN_DIR@
INCLUDES=@MUTTER_CFLAGS@ -I $(top_srcdir)/src/include -DMUTTER_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" -DMUTTER_DATADIR=\"$(datadir)\" -DG_LOG_DOMAIN=\"mutter\" -DSN_API_NOT_YET_FROZEN=1 -DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) -DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) -DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) -DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) -DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\"
INCLUDES=@MUTTER_CFLAGS@ -I $(top_srcdir)/src -DMUTTER_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\" -DMUTTER_LOCALEDIR=\"$(prefix)/@DATADIRNAME@/locale\" -DMUTTER_PKGDATADIR=\"$(pkgdatadir)\" -DMUTTER_DATADIR=\"$(datadir)\" -DG_LOG_DOMAIN=\"mutter\" -DSN_API_NOT_YET_FROZEN=1 -DMUTTER_MAJOR_VERSION=$(MUTTER_MAJOR_VERSION) -DMUTTER_MINOR_VERSION=$(MUTTER_MINOR_VERSION) -DMUTTER_MICRO_VERSION=$(MUTTER_MICRO_VERSION) -DMUTTER_PLUGIN_API_VERSION=$(MUTTER_PLUGIN_API_VERSION) -DMUTTER_PLUGIN_DIR=\"@MUTTER_PLUGIN_DIR@\"
default_la_CFLAGS = -fPIC
default_la_SOURCES = default.c

View File

@ -1,41 +0,0 @@
Plugins implement effects associated with WM events, such as window map,
minimizing, maximizing, unmaximizing, destruction and workspace switching. The
plugin API is documented in src/include/compositor-clutter-plugin.h; in
addition the simple plugin can be used as a reference implementation.
The API is intended to be generic, exposing no implementation details of the WM
to the plugins; this will facilitate reuse without modification with another WM
(there are plans to use the same plugin API with Matchbox 2).
Multiple plugins can implement the same effect and be loaded at the same time;
however, stacking arbitrary effects in this way might not work as expected;
this is particularly true of more complex effects, such as those for workspace
switching.
Plugins are installed in ${prefix}/lib/metacity/plugins/clutter; from there the
WM will load plugins listed in the clutter_plugins key in the Metacity gconf
general preferences group. Each entry in preferences has the format
'name: optional parameters'
where 'name' is the name of the library without the .so suffix.
As noted above, additional parameters can be passed to the plugin via the
preference key. In such case, the plugin name is immediately followed by a
colon, separating it from the parameters. Two common parameters should be
handled by all plugins:
'debug' indicates that the plugin is run in a debug mode (what exactly that
means is left to the plugin to determine).
'disable' parameter indicates which effects within the plugin should be
disabled; the format of the disable parameter is
'disable: effect1[, effect2];'
where effect1, etc., matches the effects listed in the
compositor-clutter-plugin.h file (currently one of 'map', 'destroy',
'maximize', 'unmaximize', 'switch-workspace'). Example 'disable:
minimize, maximize;'.

View File

@ -21,8 +21,8 @@
* 02111-1307, USA.
*/
#include "meta-plugin.h"
#include "window.h"
#include <meta/meta-plugin.h>
#include <meta/window.h>
#include <libintl.h>
#define _(x) dgettext (GETTEXT_PACKAGE, x)
@ -319,12 +319,10 @@ switch_workspace (MetaPlugin *plugin,
{
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 = meta_plugin_get_screen (plugin);
ClutterAnimation *animation;
stage = meta_plugin_get_stage (plugin);
@ -350,8 +348,6 @@ switch_workspace (MetaPlugin *plugin,
return;
}
n_workspaces = meta_screen_get_n_workspaces (screen);
l = g_list_last (meta_plugin_get_window_actors (plugin));
while (l)

View File

@ -0,0 +1,330 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Utilities for region manipulation
*
* Copyright (C) 2010 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include "region-utils.h"
#include <math.h>
/* MetaRegionBuilder */
/* Various algorithms in this file require unioning together a set of rectangles
* that are unsorted or overlap; unioning such a set of rectangles 1-by-1
* using cairo_region_union_rectangle() produces O(N^2) behavior (if the union
* adds or removes rectangles in the middle of the region, then it has to
* move all the rectangles after that.) To avoid this behavior, MetaRegionBuilder
* creates regions for small groups of rectangles and merges them together in
* a binary tree.
*
* Possible improvement: From a glance at the code, accumulating all the rectangles
* into a flat array and then calling the (not usefully documented)
* cairo_region_create_rectangles() would have the same behavior and would be
* simpler and a bit more efficient.
*/
/* Optimium performance seems to be with MAX_CHUNK_RECTANGLES=4; 8 is about 10% slower.
* But using 8 may be more robust to systems with slow malloc(). */
#define MAX_CHUNK_RECTANGLES 8
#define MAX_LEVELS 16
typedef struct
{
/* To merge regions in binary tree order, we need to keep track of
* the regions that we've already merged together at different
* levels of the tree. We fill in an array in the pattern:
*
* |a |
* |b |a |
* |c | |ab |
* |d |c |ab |
* |e | | |abcd|
*/
cairo_region_t *levels[MAX_LEVELS];
int n_levels;
} MetaRegionBuilder;
static void
meta_region_builder_init (MetaRegionBuilder *builder)
{
int i;
for (i = 0; i < MAX_LEVELS; i++)
builder->levels[i] = NULL;
builder->n_levels = 1;
}
static void
meta_region_builder_add_rectangle (MetaRegionBuilder *builder,
int x,
int y,
int width,
int height)
{
cairo_rectangle_int_t rect;
int i;
if (builder->levels[0] == NULL)
builder->levels[0] = cairo_region_create ();
rect.x = x;
rect.y = y;
rect.width = width;
rect.height = height;
cairo_region_union_rectangle (builder->levels[0], &rect);
if (cairo_region_num_rectangles (builder->levels[0]) >= MAX_CHUNK_RECTANGLES)
{
for (i = 1; i < builder->n_levels + 1; i++)
{
if (builder->levels[i] == NULL)
{
if (i < MAX_LEVELS)
{
builder->levels[i] = builder->levels[i - 1];
builder->levels[i - 1] = NULL;
if (i == builder->n_levels)
builder->n_levels++;
}
break;
}
else
{
cairo_region_union (builder->levels[i], builder->levels[i - 1]);
cairo_region_destroy (builder->levels[i - 1]);
builder->levels[i - 1] = NULL;
}
}
}
}
static cairo_region_t *
meta_region_builder_finish (MetaRegionBuilder *builder)
{
cairo_region_t *result = NULL;
int i;
for (i = 0; i < builder->n_levels; i++)
{
if (builder->levels[i])
{
if (result == NULL)
result = builder->levels[i];
else
{
cairo_region_union(result, builder->levels[i]);
cairo_region_destroy (builder->levels[i]);
}
}
}
if (result == NULL)
result = cairo_region_create ();
return result;
}
/* MetaRegionIterator */
void
meta_region_iterator_init (MetaRegionIterator *iter,
cairo_region_t *region)
{
iter->region = region;
iter->i = 0;
iter->n_rectangles = cairo_region_num_rectangles (region);
iter->line_start = TRUE;
if (iter->n_rectangles > 1)
{
cairo_region_get_rectangle (region, 0, &iter->rectangle);
cairo_region_get_rectangle (region, 1, &iter->next_rectangle);
iter->line_end = iter->next_rectangle.y != iter->rectangle.y;
}
else if (iter->n_rectangles > 0)
{
cairo_region_get_rectangle (region, 0, &iter->rectangle);
iter->line_end = TRUE;
}
}
gboolean
meta_region_iterator_at_end (MetaRegionIterator *iter)
{
return iter->i >= iter->n_rectangles;
}
void
meta_region_iterator_next (MetaRegionIterator *iter)
{
iter->i++;
iter->rectangle = iter->next_rectangle;
iter->line_start = iter->line_end;
if (iter->i + 1 < iter->n_rectangles)
{
cairo_region_get_rectangle (iter->region, iter->i + 1, &iter->next_rectangle);
iter->line_end = iter->next_rectangle.y != iter->rectangle.y;
}
else
{
iter->line_end = TRUE;
}
}
static void
add_expanded_rect (MetaRegionBuilder *builder,
int x,
int y,
int width,
int height,
int x_amount,
int y_amount,
gboolean flip)
{
if (flip)
meta_region_builder_add_rectangle (builder,
y - y_amount, x - x_amount,
height + 2 * y_amount, width + 2 * x_amount);
else
meta_region_builder_add_rectangle (builder,
x - x_amount, y - y_amount,
width + 2 * x_amount, height + 2 * y_amount);
}
static cairo_region_t *
expand_region (cairo_region_t *region,
int x_amount,
int y_amount,
gboolean flip)
{
MetaRegionBuilder builder;
int n;
int i;
meta_region_builder_init (&builder);
n = cairo_region_num_rectangles (region);
for (i = 0; i < n; i++)
{
cairo_rectangle_int_t rect;
cairo_region_get_rectangle (region, i, &rect);
add_expanded_rect (&builder,
rect.x, rect.y, rect.width, rect.height,
x_amount, y_amount, flip);
}
return meta_region_builder_finish (&builder);
}
/* This computes a (clipped version) of the inverse of the region
* and expands it by the given amount */
static cairo_region_t *
expand_region_inverse (cairo_region_t *region,
int x_amount,
int y_amount,
gboolean flip)
{
MetaRegionBuilder builder;
MetaRegionIterator iter;
cairo_rectangle_int_t extents;
int last_x;
meta_region_builder_init (&builder);
cairo_region_get_extents (region, &extents);
add_expanded_rect (&builder,
extents.x, extents.y - 1, extents.width, 1,
x_amount, y_amount, flip);
add_expanded_rect (&builder,
extents.x - 1, extents.y, 1, extents.height,
x_amount, y_amount, flip);
add_expanded_rect (&builder,
extents.x + extents.width, extents.y, 1, extents.height,
x_amount, y_amount, flip);
add_expanded_rect (&builder,
extents.x, extents.y + extents.height, extents.width, 1,
x_amount, y_amount, flip);
last_x = extents.x;
for (meta_region_iterator_init (&iter, region);
!meta_region_iterator_at_end (&iter);
meta_region_iterator_next (&iter))
{
if (iter.rectangle.x > last_x)
add_expanded_rect (&builder,
last_x, iter.rectangle.y,
iter.rectangle.x - last_x, iter.rectangle.height,
x_amount, y_amount, flip);
if (iter.line_end)
{
if (extents.x + extents.width > iter.rectangle.x + iter.rectangle.width)
add_expanded_rect (&builder,
iter.rectangle.x + iter.rectangle.width, iter.rectangle.y,
(extents.x + extents.width) - (iter.rectangle.x + iter.rectangle.width), iter.rectangle.height,
x_amount, y_amount, flip);
last_x = extents.x;
}
else
last_x = iter.rectangle.x + iter.rectangle.width;
}
return meta_region_builder_finish (&builder);
}
/**
* meta_make_border_region:
* @region: a #cairo_region_t
* @x_amount: distance from the border to extend horizontally
* @y_amount: distance from the border to extend vertically
* @flip: if true, the result is computed with x and y interchanged
*
* Computes the "border region" of a given region, which is roughly
* speaking the set of points near the boundary of the region. If we
* define the operation of growing a region as computing the set of
* points within a given manhattan distance of the region, then the
* border is 'grow(region) intersect grow(inverse(region))'.
*
* If we create an image by filling the region with a solid color,
* the border is the region affected by blurring the region.
*
* Return value: a new region which is the border of the given region
*/
cairo_region_t *
meta_make_border_region (cairo_region_t *region,
int x_amount,
int y_amount,
gboolean flip)
{
cairo_region_t *border_region;
cairo_region_t *inverse_region;
border_region = expand_region (region, x_amount, y_amount, flip);
inverse_region = expand_region_inverse (region, x_amount, y_amount, flip);
cairo_region_intersect (border_region, inverse_region);
cairo_region_destroy (inverse_region);
return border_region;
}

View File

@ -0,0 +1,76 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Utilities for region manipulation
*
* Copyright (C) 2010 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __META_REGION_UTILS_H__
#define __META_REGION_UTILS_H__
#include <clutter/clutter.h>
#include <cairo.h>
#include <glib.h>
/**
* MetaRegionIterator:
* @region: region being iterated
* @rectangle: current rectangle
* @line_start: whether the current rectangle starts a horizontal band
* @line_end: whether the current rectangle ends a horizontal band
*
* cairo_region_t is a yx banded region; sometimes its useful to iterate through
* such a region treating the start and end of each horizontal band in a distinct
* fashion.
*
* Usage:
*
* MetaRegionIterator iter;
* for (meta_region_iterator_init (&iter, region);
* !meta_region_iterator_at_end (&iter);
* meta_region_iterator_next (&iter))
* {
* [ Use iter.rectangle, iter.line_start, iter.line_end ]
* }
*/
typedef struct _MetaRegionIterator MetaRegionIterator;
struct _MetaRegionIterator {
cairo_region_t *region;
cairo_rectangle_int_t rectangle;
gboolean line_start;
gboolean line_end;
int i;
/*< private >*/
int n_rectangles;
cairo_rectangle_int_t next_rectangle;
};
void meta_region_iterator_init (MetaRegionIterator *iter,
cairo_region_t *region);
gboolean meta_region_iterator_at_end (MetaRegionIterator *iter);
void meta_region_iterator_next (MetaRegionIterator *iter);
cairo_region_t *meta_make_border_region (cairo_region_t *region,
int x_amount,
int y_amount,
gboolean flip);
#endif /* __META_REGION_UTILS_H__ */

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -51,7 +51,7 @@
#include <config.h>
#include "bell.h"
#include "screen-private.h"
#include "prefs.h"
#include <meta/prefs.h>
#ifdef HAVE_LIBCANBERRA
#include <canberra-gtk.h>
#endif
@ -149,7 +149,7 @@ bell_flash_screen (MetaDisplay *display,
#ifdef HAVE_XKB
static void
bell_flash_fullscreen (MetaDisplay *display,
XkbAnyEvent *xkb_ev)
XkbAnyEvent *xkb_ev)
{
XkbBellNotifyEvent *xkb_bell_ev = (XkbBellNotifyEvent *) xkb_ev;
MetaScreen *screen;
@ -159,7 +159,12 @@ bell_flash_fullscreen (MetaDisplay *display,
{
screen = meta_display_screen_for_xwindow (display, xkb_bell_ev->window);
if (screen)
bell_flash_screen (display, screen);
{
if (display->compositor)
meta_compositor_flash_screen (display->compositor, screen);
else
bell_flash_screen (display, screen);
}
}
else
{
@ -167,7 +172,10 @@ bell_flash_fullscreen (MetaDisplay *display,
while (screen_list)
{
screen = (MetaScreen *) screen_list->data;
bell_flash_screen (display, screen);
if (display->compositor)
meta_compositor_flash_screen (display->compositor, screen);
else
bell_flash_screen (display, screen);
screen_list = screen_list->next;
}
}

View File

@ -36,7 +36,7 @@
#include <X11/XKBlib.h>
#endif
#include "display-private.h"
#include "frame-private.h"
#include "frame.h"
#ifdef HAVE_XKB
/**

View File

@ -25,8 +25,8 @@
#define META_BOXES_PRIVATE_H
#include <glib-object.h>
#include "common.h"
#include "boxes.h"
#include <meta/common.h>
#include <meta/boxes.h>
#define BOX_LEFT(box) ((box).x) /* Leftmost pixel of rect */
#define BOX_RIGHT(box) ((box).x + (box).width) /* One pixel past right */

View File

@ -27,7 +27,7 @@
*/
#include "boxes-private.h"
#include "util.h"
#include <meta/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
@ -179,6 +179,16 @@ meta_rectangle_area (const MetaRectangle *rect)
return rect->width * rect->height;
}
/**
* meta_rectangle_intersect:
* @src1: a #MetaRectangle
* @src2: another #MetaRectangle
* @dest: (out caller-allocates): an empty #MetaRectangle, to be filled
* with the coordinates of the intersection.
*
* Returns: TRUE is some intersection exists and is not degenerate, FALSE
* otherwise.
*/
gboolean
meta_rectangle_intersect (const MetaRectangle *src1,
const MetaRectangle *src2,
@ -226,6 +236,13 @@ meta_rectangle_equal (const MetaRectangle *src1,
(src1->height == src2->height));
}
/**
* meta_rectangle_union:
* @rect1: a #MetaRectangle
* @rect2: another #MetaRectangle
* @dest: (out caller-allocates): an empty #MetaRectangle, to be filled
* with the coordinates of the bounding box.
*/
void
meta_rectangle_union (const MetaRectangle *rect1,
const MetaRectangle *rect2,
@ -340,7 +357,6 @@ meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect,
*/
/* First, the x direction */
int adjust = 0;
switch (gravity)
{
case NorthWestGravity:
@ -373,7 +389,6 @@ meta_rectangle_resize_with_gravity (const MetaRectangle *old_rect,
rect->width = new_width;
/* Next, the y direction */
adjust = 0;
switch (gravity)
{
case NorthWestGravity:

View File

@ -28,7 +28,7 @@
#include "constraints.h"
#include "workspace-private.h"
#include "place.h"
#include "prefs.h"
#include <meta/prefs.h>
#include <stdlib.h>
#include <math.h>
@ -142,6 +142,11 @@ typedef struct
GList *usable_screen_region;
GList *usable_monitor_region;
} ConstraintInfo;
static gboolean do_screen_and_monitor_relative_constraints (MetaWindow *window,
GList *region_spanning_rectangles,
ConstraintInfo *info,
gboolean check_only);
static gboolean constrain_modal_dialog (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
@ -776,7 +781,12 @@ constrain_modal_dialog (MetaWindow *window,
info->current.y = y;
info->current.x = x;
return TRUE;
/* The calculated position above may need adjustment to make sure the
* dialog does not end up partially off-screen */
return do_screen_and_monitor_relative_constraints (window,
info->usable_screen_region,
info,
check_only);
}
static gboolean
@ -796,7 +806,7 @@ constrain_maximization (MetaWindow *window,
/* Determine whether constraint applies; exit if it doesn't */
if ((!window->maximized_horizontally && !window->maximized_vertically) ||
META_WINDOW_TILED (window))
META_WINDOW_TILED_SIDE_BY_SIDE (window))
return TRUE;
/* Calculate target_size = maximized size of (window + frame) */
@ -880,7 +890,7 @@ constrain_tiling (MetaWindow *window,
return TRUE;
/* Determine whether constraint applies; exit if it doesn't */
if (!META_WINDOW_TILED (window))
if (!META_WINDOW_TILED_SIDE_BY_SIDE (window))
return TRUE;
/* Calculate target_size - as the tile previews need this as well, we
@ -968,7 +978,8 @@ constrain_size_increments (MetaWindow *window,
/* Determine whether constraint applies; exit if it doesn't */
if (META_WINDOW_MAXIMIZED (window) || window->fullscreen ||
META_WINDOW_TILED (window) || info->action_type == ACTION_MOVE)
META_WINDOW_TILED_SIDE_BY_SIDE (window) ||
info->action_type == ACTION_MOVE)
return TRUE;
/* Determine whether constraint is already satisfied; exit if it is */
@ -1099,7 +1110,8 @@ constrain_aspect_ratio (MetaWindow *window,
constraints_are_inconsistent = minr > maxr;
if (constraints_are_inconsistent ||
META_WINDOW_MAXIMIZED (window) || window->fullscreen ||
META_WINDOW_TILED (window) || info->action_type == ACTION_MOVE)
META_WINDOW_TILED_SIDE_BY_SIDE (window) ||
info->action_type == ACTION_MOVE)
return TRUE;
/* Determine whether constraint is already satisfied; exit if it is. We

View File

@ -25,9 +25,9 @@
#ifndef META_CONSTRAINTS_H
#define META_CONSTRAINTS_H
#include "util.h"
#include <meta/util.h>
#include "window-private.h"
#include "frame-private.h"
#include "frame.h"
typedef enum
{

View File

@ -25,10 +25,10 @@
#include <config.h>
#include "core.h"
#include "frame-private.h"
#include "frame.h"
#include "workspace-private.h"
#include "prefs.h"
#include "errors.h"
#include <meta/prefs.h>
#include <meta/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.
@ -117,65 +117,8 @@ meta_core_get (Display *xdisplay,
*((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
break;
case META_CORE_GET_FRAME_TYPE:
{
MetaFrameType base_type = META_FRAME_TYPE_LAST;
switch (window->type)
{
case META_WINDOW_NORMAL:
base_type = META_FRAME_TYPE_NORMAL;
break;
case META_WINDOW_DIALOG:
base_type = META_FRAME_TYPE_DIALOG;
break;
case META_WINDOW_MODAL_DIALOG:
base_type = META_FRAME_TYPE_MODAL_DIALOG;
break;
case META_WINDOW_MENU:
base_type = META_FRAME_TYPE_MENU;
break;
case META_WINDOW_UTILITY:
base_type = META_FRAME_TYPE_UTILITY;
break;
case META_WINDOW_DESKTOP:
case META_WINDOW_DOCK:
case META_WINDOW_TOOLBAR:
case META_WINDOW_SPLASHSCREEN:
case META_WINDOW_DROPDOWN_MENU:
case META_WINDOW_POPUP_MENU:
case META_WINDOW_TOOLTIP:
case META_WINDOW_NOTIFICATION:
case META_WINDOW_COMBO:
case META_WINDOW_DND:
case META_WINDOW_OVERRIDE_OTHER:
/* No frame */
base_type = META_FRAME_TYPE_LAST;
break;
}
if (base_type == META_FRAME_TYPE_LAST)
{
/* can't add border if undecorated */
*((MetaFrameType*)answer) = META_FRAME_TYPE_LAST;
}
else if (window->border_only)
{
/* override base frame type */
*((MetaFrameType*)answer) = META_FRAME_TYPE_BORDER;
}
else
{
*((MetaFrameType*)answer) = base_type;
}
break;
}
*((MetaFrameType*)answer) = meta_window_get_frame_type (window);
break;
case META_CORE_GET_MINI_ICON:
*((GdkPixbuf**)answer) = window->mini_icon;
break;

View File

@ -27,7 +27,7 @@
/* Don't include core headers here */
#include <gdk/gdkx.h>
#include "common.h"
#include <meta/common.h>
typedef enum
{

View File

@ -25,10 +25,10 @@
#define _XOPEN_SOURCE /* for kill() */
#include <config.h>
#include "util.h"
#include <meta/util.h>
#include "window-private.h"
#include "errors.h"
#include "workspace.h"
#include <meta/errors.h>
#include <meta/workspace.h>
#include <sys/types.h>
#include <sys/wait.h>
@ -103,8 +103,8 @@ delete_ping_timeout_func (MetaDisplay *display,
dialog_pid =
meta_show_dialog ("--question",
window_content, 0,
window->screen->number,
window_content, NULL,
window->screen->screen_name,
_("_Wait"), _("_Force Quit"), window->xwindow,
NULL, NULL);

View File

@ -34,11 +34,11 @@
#include <glib.h>
#include <X11/Xlib.h>
#include "eventqueue.h"
#include "common.h"
#include "boxes.h"
#include "display.h"
#include <meta/common.h>
#include <meta/boxes.h>
#include <meta/display.h>
#include "keybindings-private.h"
#include "prefs.h"
#include <meta/prefs.h>
#ifdef HAVE_STARTUP_NOTIFICATION
#include <libsn/sn.h>
@ -77,6 +77,13 @@ typedef enum {
*/
#define N_IGNORED_SERIALS 4
typedef enum {
META_TILE_NONE,
META_TILE_LEFT,
META_TILE_RIGHT,
META_TILE_MAXIMIZED
} MetaTileMode;
struct _MetaDisplay
{
GObject parent_instance;
@ -92,7 +99,7 @@ struct _MetaDisplay
* class is constructed.
*/
#define item(x) Atom atom_##x;
#include "atomnames.h"
#include <meta/atomnames.h>
#undef item
/* This is the actual window from focus events,
@ -179,6 +186,7 @@ struct _MetaDisplay
int grab_anchor_root_x;
int grab_anchor_root_y;
MetaRectangle grab_anchor_window_pos;
MetaTileMode grab_tile_mode;
int grab_latest_motion_x;
int grab_latest_motion_y;
gulong grab_mask;
@ -221,6 +229,7 @@ struct _MetaDisplay
KeySym *keymap;
int keysyms_per_keycode;
XModifierKeymap *modmap;
unsigned int above_tab_keycode;
unsigned int ignored_modifier_mask;
unsigned int num_lock_mask;
unsigned int scroll_lock_mask;
@ -433,4 +442,7 @@ void meta_display_remove_autoraise_callback (MetaDisplay *display);
void meta_display_overlay_key_activate (MetaDisplay *display);
/* In above-tab-keycode.c */
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
#endif

View File

@ -34,21 +34,21 @@
#include <config.h>
#include "display-private.h"
#include "util.h"
#include "main.h"
#include <meta/util.h>
#include <meta/main.h>
#include "screen-private.h"
#include "window-private.h"
#include "window-props.h"
#include "group-props.h"
#include "frame-private.h"
#include "errors.h"
#include "frame.h"
#include <meta/errors.h>
#include "keybindings-private.h"
#include "prefs.h"
#include <meta/prefs.h>
#include "resizepopup.h"
#include "xprops.h"
#include "workspace-private.h"
#include "bell.h"
#include "compositor.h"
#include <meta/compositor.h>
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#ifdef HAVE_SOLARIS_XINERAMA
@ -387,26 +387,6 @@ enable_compositor (MetaDisplay *display,
}
}
static void
disable_compositor (MetaDisplay *display)
{
GSList *list;
if (!display->compositor)
return;
for (list = display->screens; list != NULL; list = list->next)
{
MetaScreen *screen = list->data;
meta_compositor_unmanage_screen (screen->display->compositor,
screen);
}
meta_compositor_destroy (display->compositor);
display->compositor = NULL;
}
static void
meta_display_init (MetaDisplay *disp)
{
@ -437,7 +417,7 @@ meta_display_open (void)
/* A list of all atom names, so that we can intern them in one go. */
char *atom_names[] = {
#define item(x) #x,
#include "atomnames.h"
#include <meta/atomnames.h>
#undef item
};
Atom atoms[G_N_ELEMENTS(atom_names)];
@ -510,7 +490,7 @@ meta_display_open (void)
{
int i = 0;
#define item(x) the_display->atom_##x = atoms[i++];
#include "atomnames.h"
#include <meta/atomnames.h>
#undef item
}
@ -573,6 +553,7 @@ meta_display_open (void)
the_display->grab_window = NULL;
the_display->grab_screen = NULL;
the_display->grab_resize_popup = NULL;
the_display->grab_tile_mode = META_TILE_NONE;
the_display->grab_edge_resistance_data = NULL;
@ -839,8 +820,7 @@ meta_display_open (void)
/* We don't composite the windows here because they will be composited
faster with the call to meta_screen_manage_all_windows further down
the code */
if (1) /* meta_prefs_get_compositing_manager ()) FIXME */
enable_compositor (the_display, FALSE);
enable_compositor (the_display, FALSE);
meta_display_grab (the_display);
@ -1766,9 +1746,10 @@ event_callback (XEvent *event,
* 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.
* want to pass the key event to the compositor or GTK+ at all.
*/
bypass_compositor = meta_display_process_key_event (display, window, event);
if (meta_display_process_key_event (display, window, event))
filter_out_event = bypass_compositor = TRUE;
break;
case ButtonPress:
if (display->grab_op == META_GRAB_OP_COMPOSITOR)
@ -2543,12 +2524,6 @@ event_callback (XEvent *event,
meta_workspace_focus_default_window (screen->active_workspace, NULL, timestamp);
}
}
else if (event->xclient.message_type ==
display->atom__MUTTER_RESTART_MESSAGE)
{
meta_verbose ("Received restart request\n");
meta_restart ();
}
else if (event->xclient.message_type ==
display->atom__MUTTER_RELOAD_THEME_MESSAGE)
{
@ -2642,6 +2617,10 @@ event_callback (XEvent *event,
meta_bell_notify (display, xkb_ev);
}
break;
case XkbNewKeyboardNotify:
case XkbMapNotify:
meta_display_process_mapping_event (display, event);
break;
}
}
#endif
@ -3515,6 +3494,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
int root_x,
int root_y)
{
MetaWindow *grab_window = NULL;
Window grab_xwindow;
meta_topic (META_DEBUG_WINDOW_OPS,
@ -3544,14 +3524,25 @@ meta_display_begin_grab_op (MetaDisplay *display,
}
}
/* If window is a modal dialog attached to its parent,
* grab the parent instead for moving.
*/
if (meta_prefs_get_attach_modal_dialogs () &&
window && window->type == META_WINDOW_MODAL_DIALOG &&
meta_grab_op_is_moving (op))
grab_window = meta_window_get_transient_for (window);
if (grab_window == NULL)
grab_window = window;
/* FIXME:
* If we have no MetaWindow we do our best
* and try to do the grab on the RootWindow.
* This will fail if anyone else has any
* key grab on the RootWindow.
*/
if (window)
grab_xwindow = window->frame ? window->frame->xwindow : window->xwindow;
if (grab_window)
grab_xwindow = grab_window->frame ? grab_window->frame->xwindow : grab_window->xwindow;
else
grab_xwindow = screen->xroot;
@ -3573,9 +3564,9 @@ meta_display_begin_grab_op (MetaDisplay *display,
/* Grab keys for keyboard ops and mouse move/resizes; see #126497 */
if (grab_op_is_keyboard (op) || grab_op_is_mouse_only (op))
{
if (window)
if (grab_window)
display->grab_have_keyboard =
meta_window_grab_all_keys (window, timestamp);
meta_window_grab_all_keys (grab_window, timestamp);
else
display->grab_have_keyboard =
@ -3592,11 +3583,15 @@ meta_display_begin_grab_op (MetaDisplay *display,
}
display->grab_op = op;
display->grab_window = window;
display->grab_window = grab_window;
display->grab_screen = screen;
display->grab_xwindow = grab_xwindow;
display->grab_button = button;
display->grab_mask = modmask;
if (window)
display->grab_tile_mode = window->tile_mode;
else
display->grab_tile_mode = META_TILE_NONE;
display->grab_anchor_root_x = root_x;
display->grab_anchor_root_y = root_y;
display->grab_latest_motion_x = root_x;
@ -3793,6 +3788,7 @@ meta_display_end_grab_op (MetaDisplay *display,
display->grab_window = NULL;
display->grab_screen = NULL;
display->grab_xwindow = None;
display->grab_tile_mode = META_TILE_NONE;
display->grab_op = META_GRAB_OP_NONE;
if (display->grab_resize_popup)
@ -5184,15 +5180,6 @@ prefs_changed_callback (MetaPreference pref,
{
meta_bell_set_audible (display, meta_prefs_bell_is_audible ());
}
else if (pref == META_PREF_COMPOSITING_MANAGER)
{
gboolean cm = meta_prefs_get_compositing_manager ();
if (cm)
enable_compositor (display, TRUE);
else
disable_compositor (display);
}
else if (pref == META_PREF_ATTACH_MODAL_DIALOGS)
{
MetaDisplay *display = data;

View File

@ -23,7 +23,7 @@
*/
#include <config.h>
#include "errors.h"
#include <meta/errors.h>
#include "display-private.h"
#include <errno.h>
#include <stdlib.h>

View File

@ -24,9 +24,9 @@
*/
#include <config.h>
#include "frame-private.h"
#include "frame.h"
#include "bell.h"
#include "errors.h"
#include <meta/errors.h>
#include "keybindings-private.h"
#include <X11/extensions/Xrender.h>
@ -282,7 +282,7 @@ meta_frame_get_flags (MetaFrame *frame)
if (frame->window->shaded)
flags |= META_FRAME_SHADED;
if (frame->window->on_all_workspaces)
if (frame->window->on_all_workspaces_requested)
flags |= META_FRAME_STUCK;
/* FIXME: Should we have some kind of UI for windows that are just vertically
@ -291,6 +291,12 @@ meta_frame_get_flags (MetaFrame *frame)
if (META_WINDOW_MAXIMIZED (frame->window))
flags |= META_FRAME_MAXIMIZED;
if (META_WINDOW_TILED_LEFT (frame->window))
flags |= META_FRAME_TILED_LEFT;
if (META_WINDOW_TILED_RIGHT (frame->window))
flags |= META_FRAME_TILED_RIGHT;
if (frame->window->fullscreen)
flags |= META_FRAME_FULLSCREEN;

View File

@ -24,7 +24,6 @@
#ifndef META_FRAME_PRIVATE_H
#define META_FRAME_PRIVATE_H
#include "frame.h"
#include "window-private.h"
typedef struct _MetaFrameGeometry MetaFrameGeometry;
@ -68,7 +67,8 @@ void meta_window_ensure_frame (MetaWindow *window);
void meta_window_destroy_frame (MetaWindow *window);
void meta_frame_queue_draw (MetaFrame *frame);
MetaFrameFlags meta_frame_get_flags (MetaFrame *frame);
MetaFrameFlags meta_frame_get_flags (MetaFrame *frame);
Window meta_frame_get_xwindow (MetaFrame *frame);
/* These should ONLY be called from meta_window_move_resize_internal */
void meta_frame_calc_geometry (MetaFrame *frame,

View File

@ -24,7 +24,7 @@
#ifndef META_GROUP_PRIVATE_H
#define META_GROUP_PRIVATE_H
#include "group.h"
#include <meta/group.h>
struct _MetaGroup
{

View File

@ -24,7 +24,7 @@
#ifndef META_GROUP_PROPS_H
#define META_GROUP_PROPS_H
#include "group.h"
#include <meta/group.h>
#include "window-private.h"
void meta_group_reload_property (MetaGroup *group,

View File

@ -23,11 +23,11 @@
*/
#include <config.h>
#include "util.h"
#include <meta/util.h>
#include "group-private.h"
#include "group-props.h"
#include "window-private.h"
#include "window.h"
#include <meta/window.h>
static MetaGroup*
meta_group_new (MetaDisplay *display,

View File

@ -24,7 +24,7 @@
#include <config.h>
#include "iconcache.h"
#include "ui.h"
#include "errors.h"
#include <meta/errors.h>
#include <X11/Xatom.h>
@ -323,6 +323,40 @@ get_pixmap_geometry (MetaDisplay *display,
*d = depth;
}
static void
apply_foreground_background (GdkPixbuf *pixbuf)
{
int w, h;
int i, j;
guchar *pixels;
int stride;
w = gdk_pixbuf_get_width (pixbuf);
h = gdk_pixbuf_get_height (pixbuf);
pixels = gdk_pixbuf_get_pixels (pixbuf);
stride = gdk_pixbuf_get_rowstride (pixbuf);
i = 0;
while (i < h)
{
j = 0;
while (j < w)
{
guchar *p = pixels + i * stride + j * 4;
if (p[3] == 0)
p[0] = p[1] = p[2] = 0xff; /* white background */
else
p[0] = p[1] = p[2] = 0x00; /* black foreground */
p[3] = 0xff;
++j;
}
++i;
}
}
static GdkPixbuf*
apply_mask (GdkPixbuf *pixbuf,
GdkPixbuf *mask)
@ -352,16 +386,10 @@ apply_mask (GdkPixbuf *pixbuf,
j = 0;
while (j < w)
{
guchar *s = src + i * src_stride + j * 3;
guchar *s = src + i * src_stride + j * 4;
guchar *d = dest + i * dest_stride + j * 4;
/* s[0] == s[1] == s[2], they are 255 if the bit was set, 0
* otherwise
*/
if (s[0] == 0)
d[3] = 0; /* transparent */
else
d[3] = 255; /* opaque */
d[3] = s[3];
++j;
}
@ -385,25 +413,32 @@ try_pixmap_and_mask (MetaDisplay *display,
{
GdkPixbuf *unscaled = NULL;
GdkPixbuf *mask = NULL;
int w, h;
int w, h, d;
if (src_pixmap == None)
return FALSE;
meta_error_trap_push (display);
get_pixmap_geometry (display, src_pixmap, &w, &h, NULL);
get_pixmap_geometry (display, src_pixmap, &w, &h, &d);
unscaled = meta_gdk_pixbuf_get_from_pixmap (src_pixmap,
0, 0,
w, h);
/* A depth 1 pixmap has 0 background, and 1 foreground, but
* cairo and meta_gdk_pixbuf_get_from_pixmap consider it
* to be 0 transparent, 1 opaque */
if (d == 1)
apply_foreground_background (unscaled);
if (unscaled && src_mask != None)
{
get_pixmap_geometry (display, src_mask, &w, &h, NULL);
mask = meta_gdk_pixbuf_get_from_pixmap (src_mask,
0, 0,
w, h);
get_pixmap_geometry (display, src_mask, &w, &h, &d);
if (d == 1)
mask = meta_gdk_pixbuf_get_from_pixmap (src_mask,
0, 0,
w, h);
}
meta_error_trap_pop (display);

View File

@ -29,7 +29,7 @@
#ifndef META_KEYBINDINGS_PRIVATE_H
#define META_KEYBINDINGS_PRIVATE_H
#include "keybindings.h"
#include <meta/keybindings.h>
void meta_display_init_keys (MetaDisplay *display);
void meta_display_shutdown_keys (MetaDisplay *display);

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