Compare commits

...

319 Commits

Author SHA1 Message Date
2d57904bf4 Bump version to 2.29.0 2010-02-18 17:08:21 -05:00
8fa83e1be7 Fix fallback to builtin defaults for key bindings
The change to reduce GConf trips by using
gconf_client_all_entries() broke the fallback to builtin values
because update_binding() was no longer called for bindings not
found in GConf. Fix this by keeping track of the bindings we
find from GConf in a hash table, then looping through and setting
all the bindings at the end.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

svn path=/trunk/; revision=4165

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

svn path=/trunk/; revision=4141

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

* configure.in: Require libcanberra-gtk

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

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

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

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

  errno==0 && pwd!=NULL

Not:

  errno==0 || pwd==NULL

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

GL_TEXTURE_RECTANGLE_ARB - use _ARB name
glActiveTextureARB() - use get_proc_address

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Based on original patch by Jon Nettleton.

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

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

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

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

Similarly, add window-created which acts globally.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

https://bugzilla.gnome.org/show_bug.cgi?id=595882
2009-09-22 12:43:35 -04:00
f6f899f103 [release] 2.28.0 2009-09-22 15:41:33 +02:00
5b8919a246 Updated Kannada(kn) translation 2009-09-21 10:57:57 +05:30
fe1989979c Updated Czech translation 2009-09-21 03:15:22 +02:00
0895fa9331 Updating Assamese translations 2009-09-20 15:53:01 +05:30
b90fe0c52a Korean translation update 2009-09-20 09:34:59 +09:00
ab0e22159c Updated Catalan translation 2009-09-19 18:29:25 +02:00
6ac0afbce0 Updated Japanese translation 2009-09-20 00:56:16 +09:00
9532527e52 maithili update, translated by Sangeeta Kumari 2009-09-18 18:28:40 +05:30
Ani
defdf9f34c Updated Malayalam Translations 2009-09-17 23:44:05 +05:30
a7dce2dc4e Updated Hebrew translation 2009-09-17 20:01:46 +03:00
ea8c51f8f3 Added Ukrainian translation 2009-09-17 19:02:45 +03:00
1e66878447 Upadated Oriya Translation 2009-09-17 18:15:08 +05:30
6cfbdebf6a Upadted Oriya Translation 2009-09-16 19:17:46 +05:30
a4469dcc14 Updated Galician Translation 2009-09-16 14:56:21 +02:00
ac3eac7154 Bump version to 2.27.5 2009-09-15 17:30:07 -04:00
Ani
65ac9065fa Updated Malayalam Translations 2009-09-15 21:26:14 +05:30
5143e6763b hindi update by Rajesh Ranjan 2009-09-15 15:12:20 +05:30
5660a8e9f5 Updated Thai translation. 2009-09-15 14:38:08 +07:00
bc2b17df0b Updating Translation for Punjabi 2009-09-15 07:25:17 +05:30
Ani
f9e7c95348 Updaeted Malayalam Translations 2009-09-15 02:54:41 +05:30
c6afec4759 Updated breton translation 2009-09-14 06:32:03 +02:00
eb13498fff added br in LINGUAS file 2009-09-14 06:30:37 +02:00
163057f521 Updated Romanian translation 2009-09-14 00:10:52 +03:00
d8ff1f9873 Updated Danish translation 2009-09-13 03:45:00 +02:00
97b7760de8 Updated British English translation 2009-09-12 21:23:02 +01:00
acca0f6946 Updated Finnish translation 2009-09-12 22:27:52 +03:00
f3f6d67d46 Updated Slovenian translation 2009-09-12 09:52:02 +02:00
63773d5226 Updated Telugu Translations 2009-09-11 20:49:57 +05:30
4e4559fc8c Updated German translation 2009-09-10 21:14:43 +02:00
44d540d36c Updated Lithuanian translation. 2009-09-10 14:44:47 +03:00
c6253a6515 Corrected a bad spacing after a quotation mark in Brazilian Portuguese
translation
2009-09-09 10:06:28 -03:00
65a5ec2ef3 Updated Gujarati Translations 2009-09-09 15:50:22 +05:30
70e8b35944 Updated Marathi Translations 2009-09-09 12:54:03 +05:30
ddba25a674 Post-release bump to 2.27.2. 2009-09-08 23:12:45 +02:00
14e6cb6a8f 2.27.1 release 2009-09-08 23:06:42 +02:00
d4619150f3 Updated Serbian translation 2009-09-08 13:36:43 +00:00
5c1a1a2dd5 Fix Super_L specification for overlay_key
A recent commit fixed the schema association, which revealed that our
<Super_L> was wrong, should just be Super_L.
2009-09-07 14:27:09 -04:00
7cfa690aaf Updated Traditional Chinese translation(Hong Kong and Taiwan) 2009-09-06 15:01:55 +08:00
8d663ff055 Bump version to 2.27.4
Remove comment about Fibonacci micro numbering. We aren't going
to do that.
2009-09-04 19:00:03 -04:00
0b86343dd0 Export a _GNOME_WM_KEYBINDINGS property
We need a way to indicate to gnome-control-center that we want the
keybindings capplet to show the Window Manager keybindings for Metacity;
do this through a _GNOME_WM_KEYBINDING property we put on the
_NET_SUPPORTING_WM_CHECK window and set to Mutter,Metacity.

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

http://bugzilla.gnome.org/show_bug.cgi?id=594067
2009-09-04 18:25:39 -04:00
e127898312 Updated French translation 2009-09-04 21:32:33 +02:00
51f83f25e6 Updated Basque language 2009-09-04 11:56:53 +02:00
8f3da9f68a Use meta_window_set_user_time for setting user time consistently
This is a followup to making user-time a GObject property, this
way we get notifications.
2009-09-03 20:58:19 -04:00
4c1998f137 Annotate meta_screen_get_active_workspace as (transfer none) 2009-09-03 20:57:39 -04:00
84dc1c1b85 [MetaWindow] Make user-time a GObject property
Notification of changes are useful for code ordering windows.
2009-09-03 20:57:39 -04:00
326110e38d Fix owner and applyto for /apps/mutter/general/overlay_key schema
The owner field and the applyto key of
for /schemas//apps/mutter/general/overlay_key were still referencing
metacity not mutter, fix.
2009-09-03 14:48:20 -04:00
f63b81c52a Updated Portuguese translation 2009-09-03 01:08:03 +01:00
bd2e221da3 Fix broken META_IS_SCREEN macro
Should use META_TYPE_SCREEN not META_SCREEN_TYPE.
2009-09-01 09:38:40 -04:00
1fe673703f Updated Kannada(kn) translation 2009-09-01 11:33:20 +05:30
c10467d22e Add meta_screen_get_n_monitors() and meta_screen_get_monitor_geometry()
http://bugzilla.gnome.org/show_bug.cgi?id=593686
2009-08-31 18:57:29 -04:00
e21ec0a271 Fix the dependency for mutter-enum-types.h
mutter-enum-types.h is built from $(libmutterinclude_base_headers) not
the non-existent $(mutter_source_h)
2009-08-31 18:12:29 -04:00
3a1e492afc Refer to monitors as "monitors" rather than "xineramas"
http://bugzilla.gnome.org/show_bug.cgi?id=593686
2009-08-31 14:39:48 -04:00
e83c24c91b Add .AUTOPARALLEL flag to Makefile
This automatically enables parallelism with the patched make,
and flags us as maintaining a parallel build.
2009-08-30 20:21:02 -04:00
81183c71c1 Add public meta_window_get_user_time
Useful for sorting windows by interaction time.
2009-08-30 20:18:11 -04:00
979298ce57 Updated mailing list address. 2009-08-30 12:15:18 -04:00
66e727e1b2 Updated Turkish translation. 2009-08-30 18:10:53 +03:00
35b1dda3a3 Updated Spanish translation 2009-08-30 12:47:47 +02:00
6925779f59 Updating Estonian translation 2009-08-30 13:39:01 +03:00
125d7daf4a Hungarian translation updated 2009-08-29 14:27:23 +02:00
57c5ea4bd5 Hungarian translation updated 2009-08-29 14:26:10 +02:00
e75fbdb136 Hungarian translation updated 2009-08-29 14:25:03 +02:00
cb1020b26d Another update 2009-08-29 14:06:44 +02:00
e1945506f3 Hungarian translation updated 2009-08-29 13:59:56 +02:00
3a798112f2 Updated Italian translation 2009-08-28 09:55:24 +02:00
c5dd3e5542 Updated Basque language 2009-08-27 17:36:11 +02:00
2fa9cbfd9e Updating Estonian translation 2009-08-27 10:06:35 +03:00
23af4ee93e Updated Bengali India Translations 2009-08-26 15:42:33 +05:30
0317562605 Updated Spanish translation 2009-08-26 07:57:36 +02:00
1861e0b2cc Updated Swedish translation 2009-08-26 06:04:00 +02:00
e5974809e8 Updated Brazilian Portuguese translation 2009-08-25 15:21:02 -03:00
abfae17b9a Updated Polish translation 2009-08-25 17:47:45 +02:00
84b1a62ad2 Updated Tamil Translations 2009-08-25 17:27:29 +05:30
b6bcaec9bc Updated breton translation 2009-08-25 12:43:20 +02:00
f19ed84cc4 Added br in LINGUAS 2009-08-25 12:43:20 +02:00
6c5a946fda Updated Bulgarian translation 2009-08-24 22:52:12 +03:00
c6ffc9427e Add missing quotes in strings (Fixes #572046) 2009-08-24 19:49:29 +02:00
0f1e64f3b2 Updated Telugu Translations 2009-08-24 17:53:05 +05:30
1ce5ad3003 Added new entry for Telugu [te] in LINGUAS 2009-08-24 17:52:48 +05:30
64694955c0 Updated Arabic translation 2009-08-23 21:40:47 +03:00
97a90d8122 Updated Thai translation. 2009-08-23 15:50:57 +07:00
3cd2c08277 Update Korean translation 2009-08-23 04:14:10 +09:00
c37a2ca1c8 Updated Brazilian Portuguese translation. 2009-08-18 22:34:18 -04:00
80b38210b2 Updated Irish translation 2009-08-17 06:06:18 -06:00
e5dffb0097 Updated Finnish translation 2009-08-15 13:59:30 +03:00
deaa897928 Updated Bulgarian translation 2009-08-14 08:00:48 +03:00
3f9758e706 Updated Oriya Translation 2009-08-13 20:29:45 +05:30
3c25c265df Updated Gujarati Translations 2009-08-12 19:08:55 +05:30
a8529bd8d1 Updated Galician translation 2009-08-12 13:21:18 +02:00
ba03ca76c4 Updated Italian translation 2009-08-11 01:19:48 +02:00
71fd54ec9e Updated Spanish translation 2009-08-09 20:27:02 +02:00
a03343827e Updated German translation. 2009-08-08 01:47:24 +02:00
4fb7c642d5 Minor fix to Catalan translation 2009-08-07 18:57:23 +02:00
8a892d47e5 Updated Tamil translation 2009-07-29 13:48:28 +05:30
73abacc20b Updating Estonian translation 2009-07-23 19:00:46 +03:00
aea24279ba Updated Swedish translation 2009-07-22 15:12:43 +02:00
5c5968e742 Updated Traditional Chinese translation(Hong Kong and Taiwan) 2009-07-22 16:44:17 +08:00
3813ed9c2e Updated Hebrew translation 2009-07-22 00:57:22 +03:00
594897e9a5 Updated Ukrainian translation 2009-07-09 23:28:00 +03:00
40e9f6fa2c unset _NET_SUPPORTING_WM_CHECK when shutting down 2009-07-09 10:26:20 -04:00
35afd2a8fb update changelog 2009-07-09 10:23:03 -04:00
d9be1d7e32 Updated Spanish translation 2009-07-07 20:47:54 +02:00
b625ec30d9 Add a switch to disable autofullscreen'ing maximized windows without decorations 2009-07-06 07:51:45 -04:00
f5313268d7 Updated Hebrew translation 2009-07-04 15:47:15 +03:00
07dedee37b Updating Estonian translation 2009-06-25 14:31:10 +03:00
75f3127ba5 Updated Bengali India Translations 2009-06-24 15:56:42 +05:30
b13fae2556 Updating Estonian translation 2009-06-19 19:58:46 +03:00
2e9838699b Updated Simplified Chinese translation. 2009-06-06 17:27:37 +08:00
ba9c3f41c9 Updated Tamil translation 2009-05-25 17:50:14 +05:30
e35fae8f32 Updated Spanish translation 2009-05-23 19:58:37 +02:00
b0d5f3bd64 Updated Tamil translation 2009-05-23 17:53:59 +05:30
ed640bb181 Updated Tamil translation 2009-05-21 17:48:02 +05:30
a3511ba9e2 Updated Ukrainian translation 2009-04-28 14:06:23 +03:00
4c9c903648 Updating Estonian translation 2009-04-25 18:12:34 +03:00
d12aaddc34 Updated Italian transaltion 2009-04-24 22:17:24 +02:00
28955bb449 doap: Add desktop category 2009-04-23 19:35:51 +02:00
dcd7cae7cf Updated Slovenian translation 2009-04-22 12:18:20 +02:00
c954bb9456 Minor fixes to Catalan translation 2009-04-22 09:46:20 +02:00
be0b298d81 Updated Kannada Translation 2009-04-21 12:34:27 +05:30
409026044b Updated Spanish translation 2009-04-18 20:55:56 +02:00
0c311bdcf9 Updated zh_CN translation.
svn path=/trunk/; revision=4238
2009-04-10 03:22:43 +00:00
e81775e63d Updated Slovak translation by Pavol Šimo.
2009-04-04  Marcel Telka  <marcel@telka.sk>

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

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

	* pl.po: Updated Polish translation

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

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

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

	* lt.po: Updated Lithuanian translation.



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

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


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


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


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


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


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

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

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


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

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

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


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


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

	* hu.po: Translation updated.

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

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


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

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


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


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

	* eu.po: Updated Basque translation.


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

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

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


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


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


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


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

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

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


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


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


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


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


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


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


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


svn path=/trunk/; revision=4116
2009-02-05 01:13:01 +00:00
69 changed files with 13728 additions and 12462 deletions

31
.gitignore vendored
View File

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

View File

@ -1,10 +1,8 @@
AC_PREREQ(2.50)
m4_define([mutter_major_version], [2])
m4_define([mutter_minor_version], [27])
# Fibonacci sequence for micro version numbering:
# 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987
m4_define([mutter_micro_version], [3])
m4_define([mutter_minor_version], [29])
m4_define([mutter_micro_version], [0])
m4_define([mutter_version],
[mutter_major_version.mutter_minor_version.mutter_micro_version])
@ -162,6 +160,11 @@ AC_ARG_WITH(introspection,
[disable the use of GObject introspection]),,
with_introspection=auto)
AC_ARG_WITH(libcanberra,
AC_HELP_STRING([--without-libcanberra],
[disable the use of libcanberra for playing sounds]),,
with_libcanberra=auto)
AC_ARG_ENABLE(xsync,
AC_HELP_STRING([--disable-xsync],
[disable mutter's use of the XSync extension]),,
@ -214,6 +217,24 @@ else
echo "Building without libstartup-notification"
fi
have_libcanberra=no
AC_MSG_CHECKING([libcanberra-gtk])
if test x$with_libcanberra = xno ; then
AC_MSG_RESULT([disabled])
else
if $PKG_CONFIG --exists libcanberra-gtk; then
have_libcanberra=yes
AC_MSG_RESULT(yes)
MUTTER_PC_MODULES="$MUTTER_PC_MODULES libcanberra-gtk"
AC_DEFINE([HAVE_LIBCANBERRA], 1, [Building with libcanberra for playing sounds])
else
AC_MSG_RESULT(no)
if test x$with_libcanberra = xyes ; then
AC_MSG_ERROR([libcanberra forced and libcanberra-gtk was not found])
fi
fi
fi
XCOMPOSITE_VERSION=0.2
AC_MSG_CHECKING([Xcomposite >= $XCOMPOSITE_VERSION])
@ -416,7 +437,7 @@ fi
MUTTER_LIBS="$MUTTER_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
MUTTER_MESSAGE_LIBS="$MUTTER_MESSAGE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
MUTTER_WINDOW_DEMO_LIBS="$MUTTER_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS -lm"
MUTTER_PROPS_LIBS="$MUTTER_PROPS_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
found_sm=no
@ -534,6 +555,7 @@ mutter-$VERSION:
XFree86 Xinerama: ${use_xfree_xinerama}
Solaris Xinerama: ${use_solaris_xinerama}
Startup notification: ${have_startup_notification}
libcanberra: ${have_libcanberra}
Introspection: ${have_introspection}
Session management: ${found_sm}
Shape extension: ${found_shape}

View File

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

View File

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

4907
po/ar.po

File diff suppressed because it is too large Load Diff

1835
po/br.po Normal file

File diff suppressed because it is too large Load Diff

1504
po/cs.po

File diff suppressed because it is too large Load Diff

1637
po/de.po

File diff suppressed because it is too large Load Diff

1732
po/es.po

File diff suppressed because it is too large Load Diff

1012
po/eu.po

File diff suppressed because it is too large Load Diff

2498
po/fr.po

File diff suppressed because it is too large Load Diff

577
po/hu.po

File diff suppressed because it is too large Load Diff

515
po/nb.po

File diff suppressed because it is too large Load Diff

1814
po/nds.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

2132
po/sl.po

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,6 @@
# Flag build for parallelism; see https://savannah.gnu.org/patch/?6905
.AUTOPARALLEL:
lib_LTLIBRARIES = libmutter-private.la
SUBDIRS=wm-tester tools compositor/plugins
@ -13,10 +16,6 @@ mutter_built_sources = \
mutter_SOURCES= \
core/async-getprop.c \
core/async-getprop.h \
core/alttabhandler.c \
include/alttabhandler.h \
core/alttabhandlerdefault.c \
include/alttabhandlerdefault.h \
core/bell.c \
core/bell.h \
core/boxes.c \
@ -29,6 +28,8 @@ mutter_SOURCES= \
compositor/mutter-plugin-manager.c \
compositor/mutter-plugin-manager.h \
compositor/mutter-shaped-texture.c \
compositor/mutter-texture-tower.c \
compositor/mutter-texture-tower.h \
compositor/mutter-window.c \
compositor/mutter-window-private.h \
compositor/mutter-window-group.c \
@ -150,7 +151,6 @@ libmutterincludedir = $(includedir)/mutter/mutter-private
# Headers installed for plugins; introspected information will
# be extracted into Mutter-<version>.gir
libmutterinclude_base_headers = \
include/alttabhandler.h \
include/boxes.h \
ui/gradient.h \
include/main.h \
@ -214,6 +214,7 @@ Meta-$(api_version).gir: $(G_IR_SCANNER) mutter $(libmutterinclude_HEADERS) $(mu
--include=Clutter-1.0 \
--pkg=clutter-1.0 \
--pkg=gtk+-2.0 \
--include=xlib-2.0 \
--include=xfixes-4.0 \
--program=$$pwd/mutter \
$(filter %.c,$(mutter_SOURCES)) \
@ -328,7 +329,7 @@ mutter-marshal.c: Makefile mutter-marshal.list
mutter-enum-types.h: stamp-mutter-enum-types.h Makefile
@true
stamp-mutter-enum-types.h: $(mutter_source_h) mutter-enum-types.h.in
stamp-mutter-enum-types.h: $(libmutterinclude_base_headers) mutter-enum-types.h.in
$(AM_V_GEN) ( cd $(srcdir) && \
$(GLIB_MKENUMS) \
--template $(srcdir)/mutter-enum-types.h.in \

View File

@ -390,10 +390,10 @@ mutter_begin_modal_for_plugin (MetaScreen *screen,
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
{
XGrabKeyboard (xdpy, grab_window,
False, /* owner_events */
GrabModeAsync, GrabModeAsync,
timestamp);
result = XGrabKeyboard (xdpy, grab_window,
False, /* owner_events */
GrabModeAsync, GrabModeAsync,
timestamp);
if (result != Success)
goto fail;

View File

@ -459,6 +459,18 @@ mutter_plugin_set_stage_input_region (MutterPlugin *plugin,
mutter_set_stage_input_region (screen, region);
}
/**
* mutter_plugin_get_windows:
* @plugin: A #MutterPlugin
*
* This function returns all of the #MutterWindow objects referenced by Mutter, including
* override-redirect windows. The returned list is a snapshot of Mutter's current
* stacking order, with the topmost window last.
*
* The 'restacked' signal of #MetaScreen signals when this value has changed.
*
* Returns: (transfer none) (element-type MutterWindow): Windows in stacking order, topmost last
*/
GList *
mutter_plugin_get_windows (MutterPlugin *plugin)
{

View File

@ -26,19 +26,27 @@
#include <config.h>
#include "mutter-shaped-texture.h"
#include "mutter-texture-tower.h"
#include <clutter/clutter.h>
#include <cogl/cogl.h>
#include <string.h>
static void mutter_shaped_texture_dispose (GObject *object);
static void mutter_shaped_texture_finalize (GObject *object);
static void mutter_shaped_texture_notify (GObject *object,
GParamSpec *pspec);
static void mutter_shaped_texture_paint (ClutterActor *actor);
static void mutter_shaped_texture_pick (ClutterActor *actor,
const ClutterColor *color);
static void mutter_shaped_texture_update_area (ClutterX11TexturePixmap *texture,
int x,
int y,
int width,
int height);
static void mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex);
#ifdef HAVE_GLX_TEXTURE_PIXMAP
@ -55,6 +63,7 @@ G_DEFINE_TYPE (MutterShapedTexture, mutter_shaped_texture,
struct _MutterShapedTexturePrivate
{
MutterTextureTower *paint_tower;
CoglHandle mask_texture;
CoglHandle material;
CoglHandle material_unshaped;
@ -74,13 +83,17 @@ mutter_shaped_texture_class_init (MutterShapedTextureClass *klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
ClutterActorClass *actor_class = (ClutterActorClass *) klass;
ClutterX11TexturePixmapClass *x11_texture_class = (ClutterX11TexturePixmapClass *) klass;
gobject_class->dispose = mutter_shaped_texture_dispose;
gobject_class->finalize = mutter_shaped_texture_finalize;
gobject_class->notify = mutter_shaped_texture_notify;
actor_class->paint = mutter_shaped_texture_paint;
actor_class->pick = mutter_shaped_texture_pick;
x11_texture_class->update_area = mutter_shaped_texture_update_area;
g_type_class_add_private (klass, sizeof (MutterShapedTexturePrivate));
}
@ -93,6 +106,7 @@ mutter_shaped_texture_init (MutterShapedTexture *self)
priv->rectangles = g_array_new (FALSE, FALSE, sizeof (XRectangle));
priv->paint_tower = mutter_texture_tower_new ();
priv->mask_texture = COGL_INVALID_HANDLE;
}
@ -102,6 +116,10 @@ mutter_shaped_texture_dispose (GObject *object)
MutterShapedTexture *self = (MutterShapedTexture *) object;
MutterShapedTexturePrivate *priv = self->priv;
if (priv->paint_tower)
mutter_texture_tower_free (priv->paint_tower);
priv->paint_tower = NULL;
mutter_shaped_texture_dirty_mask (self);
if (priv->material != COGL_INVALID_HANDLE)
@ -138,6 +156,28 @@ mutter_shaped_texture_finalize (GObject *object)
G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->finalize (object);
}
static void
mutter_shaped_texture_notify (GObject *object,
GParamSpec *pspec)
{
if (G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->notify)
G_OBJECT_CLASS (mutter_shaped_texture_parent_class)->notify (object, pspec);
/* It seems like we could just do this out of update_area(), but unfortunately,
* clutter_glx_texture_pixmap() doesn't call through the vtable on the
* initial update_area, so we need to look for changes to the texture
* explicitly.
*/
if (strcmp (pspec->name, "cogl-texture") == 0)
{
MutterShapedTexture *stex = (MutterShapedTexture *) object;
MutterShapedTexturePrivate *priv = stex->priv;
mutter_texture_tower_set_base_texture (priv->paint_tower,
clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex)));
}
}
static void
mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex)
{
@ -151,7 +191,7 @@ mutter_shaped_texture_dirty_mask (MutterShapedTexture *stex)
cogl_texture_get_gl_texture (priv->mask_texture,
&mask_gl_tex, &mask_gl_target);
if (mask_gl_target == CGL_TEXTURE_RECTANGLE_ARB)
if (mask_gl_target == GL_TEXTURE_RECTANGLE_ARB)
glDeleteTextures (1, &mask_gl_tex);
cogl_texture_unref (priv->mask_texture);
@ -214,23 +254,23 @@ mutter_shaped_texture_ensure_mask (MutterShapedTexture *stex)
cogl_texture_get_gl_texture (paint_tex, NULL, &paint_gl_target);
if (paint_gl_target == CGL_TEXTURE_RECTANGLE_ARB)
if (paint_gl_target == GL_TEXTURE_RECTANGLE_ARB)
{
GLuint tex;
glGenTextures (1, &tex);
glBindTexture (CGL_TEXTURE_RECTANGLE_ARB, tex);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex);
glPixelStorei (GL_UNPACK_ROW_LENGTH, tex_width);
glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
glPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
glTexImage2D (CGL_TEXTURE_RECTANGLE_ARB, 0,
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0,
GL_ALPHA, tex_width, tex_height,
0, GL_ALPHA, GL_UNSIGNED_BYTE, mask_data);
priv->mask_texture
= cogl_texture_new_from_foreign (tex,
CGL_TEXTURE_RECTANGLE_ARB,
GL_TEXTURE_RECTANGLE_ARB,
tex_width, tex_height,
0, 0,
COGL_PIXEL_FORMAT_A_8);
@ -269,7 +309,30 @@ mutter_shaped_texture_paint (ClutterActor *actor)
if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex)))
clutter_actor_realize (CLUTTER_ACTOR (stex));
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
/* If mipmaps are supported, then the texture filter quality will
* still be HIGH here. In that case we just want to use the base
* texture. If mipmaps are not support then
* on_glx_texture_pixmap_pre_paint() will have reset the texture
* filter quality to MEDIUM, and we should use the MutterTextureTower
* mipmap emulation.
*
* http://bugzilla.openedhand.com/show_bug.cgi?id=1877 is an RFE
* for a better way of handling this.
*
* While it would be nice to have direct access to the 'can_mipmap'
* boolean in ClutterGLXTexturePixmap, since since MutterTextureTower
* creates the scaled down images on demand there is no substantial
* overhead from doing the work to create and update the tower and
* not using it, other than the memory allocated for the MutterTextureTower
* structure itself.
*/
if (clutter_texture_get_filter_quality (CLUTTER_TEXTURE (stex)) == CLUTTER_TEXTURE_QUALITY_HIGH)
paint_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (stex));
else
paint_tex = mutter_texture_tower_get_paint_texture (priv->paint_tower);
if (paint_tex == COGL_INVALID_HANDLE)
return;
tex_width = cogl_texture_get_width (paint_tex);
tex_height = cogl_texture_get_height (paint_tex);
@ -277,9 +340,6 @@ mutter_shaped_texture_paint (ClutterActor *actor)
if (tex_width == 0 || tex_height == 0) /* no contents yet */
return;
if (paint_tex == COGL_INVALID_HANDLE)
return;
if (priv->rectangles->len < 1)
{
/* If there are no rectangles use a single-layer texture */
@ -367,24 +427,34 @@ mutter_shaped_texture_paint (ClutterActor *actor)
}
else
{
float coords[MAX_RECTS * 8];
float coords[8];
float x1, y1, x2, y2;
for (i = 0; i < n_rects; i++)
{
GdkRectangle *rect = &rects[i];
coords[i * 8 + 0] = rect->x;
coords[i * 8 + 1] = rect->y;
coords[i * 8 + 2] = rect->x + rect->width;
coords[i * 8 + 3] = rect->y + rect->height;
coords[i * 8 + 4] = rect->x / (alloc.x2 - alloc.x1);
coords[i * 8 + 5] = rect->y / (alloc.y2 - alloc.y1);
coords[i * 8 + 6] = (rect->x + rect->width) / (alloc.x2 - alloc.x1);
coords[i * 8 + 7] = (rect->y + rect->height) / (alloc.y2 - alloc.y1);
}
x1 = rect->x;
y1 = rect->y;
x2 = rect->x + rect->width;
y2 = rect->y + rect->height;
coords[0] = rect->x / (alloc.x2 - alloc.x1);
coords[1] = rect->y / (alloc.y2 - alloc.y1);
coords[2] = (rect->x + rect->width) / (alloc.x2 - alloc.x1);
coords[3] = (rect->y + rect->height) / (alloc.y2 - alloc.y1);
coords[4] = coords[0];
coords[5] = coords[1];
coords[6] = coords[2];
coords[7] = coords[3];
cogl_rectangle_with_multitexture_coords (x1, y1, x2, y2,
&coords[0], 8);
}
g_free (rects);
cogl_rectangles_with_texture_coords (coords, n_rects);
return;
}
}
@ -438,6 +508,22 @@ mutter_shaped_texture_pick (ClutterActor *actor,
}
}
static void
mutter_shaped_texture_update_area (ClutterX11TexturePixmap *texture,
int x,
int y,
int width,
int height)
{
MutterShapedTexture *stex = (MutterShapedTexture *) texture;
MutterShapedTexturePrivate *priv = stex->priv;
CLUTTER_X11_TEXTURE_PIXMAP_CLASS (mutter_shaped_texture_parent_class)->update_area (texture,
x, y, width, height);
mutter_texture_tower_update_area (priv->paint_tower, x, y, width, height);
}
ClutterActor *
mutter_shaped_texture_new (void)
{

View File

@ -0,0 +1,837 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MutterTextureTower
*
* Mipmap emulation by creation of scaled down images
*
* Copyright (C) 2009 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <math.h>
#include <string.h>
#include "mutter-texture-tower.h"
#ifndef M_LOG2E
#define M_LOG2E 1.4426950408889634074
#endif
#if !CLUTTER_CHECK_VERSION(1,1,3)
static PFNGLACTIVETEXTUREARBPROC activeTexture;
static PFNGLGENFRAMEBUFFERSPROC genFramebuffers;
static PFNGLDELETEFRAMEBUFFERSPROC deleteFramebuffers;
static PFNGLBINDFRAMEBUFFERPROC bindFramebuffer;
static PFNGLFRAMEBUFFERTEXTURE2DPROC framebufferTexture2D;
#endif
#define MAX_TEXTURE_LEVELS 12
/* If the texture format in memory doesn't match this, then Mesa
* will do the conversion, so things will still work, but it might
* be slow depending on how efficient Mesa is. These should be the
* native formats unless the display is 16bpp. If conversions
* here are a bottleneck, investigate whether we are converting when
* storing window data *into* the texture before adding extra code
* to handle multiple texture formats.
*/
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_BGRA_8888_PRE
#else
#define TEXTURE_FORMAT COGL_PIXEL_FORMAT_ARGB_8888_PRE
#endif
typedef struct
{
guint16 x1;
guint16 y1;
guint16 x2;
guint16 y2;
} Box;
struct _MutterTextureTower
{
int n_levels;
CoglHandle textures[MAX_TEXTURE_LEVELS];
#if CLUTTER_CHECK_VERSION(1,1,3)
CoglHandle fbos[MAX_TEXTURE_LEVELS];
#else
GLuint fbos[MAX_TEXTURE_LEVELS];
#endif
Box invalid[MAX_TEXTURE_LEVELS];
};
/**
* mutter_texture_tower_new:
*
* Creates a new texture tower. The base texture has to be set with
* mutter_texture_tower_set_base_texture() before use.
*
* Return value: the new texture tower. Free with mutter_texture_tower_free()
*/
MutterTextureTower *
mutter_texture_tower_new (void)
{
MutterTextureTower *tower;
tower = g_slice_new0 (MutterTextureTower);
return tower;
}
/**
* mutter_texture_tower_free:
* @tower: a #MutterTextureTower
*
* Frees a texture tower created with mutter_texture_tower_new().
*/
void
mutter_texture_tower_free (MutterTextureTower *tower)
{
g_return_if_fail (tower != NULL);
mutter_texture_tower_set_base_texture (tower, COGL_INVALID_HANDLE);
g_slice_free (MutterTextureTower, tower);
}
static gboolean
texture_is_rectangle (CoglHandle texture)
{
GLuint gl_tex;
GLenum gl_target;
cogl_texture_get_gl_texture (texture, &gl_tex, &gl_target);
return gl_target == GL_TEXTURE_RECTANGLE_ARB;
}
static void
free_texture (CoglHandle texture)
{
GLuint gl_tex;
GLenum gl_target;
cogl_texture_get_gl_texture (texture, &gl_tex, &gl_target);
if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
glDeleteTextures (1, &gl_tex);
cogl_texture_unref (texture);
}
/**
* mutter_texture_tower_update_area:
* @tower: a MutterTextureTower
* @texture: the new texture used as a base for scaled down versions
*
* Sets the base texture that is the scaled texture that the
* scaled textures of the tower are derived from. The texture itself
* will be used as level 0 of the tower and will be referenced until
* unset or until the tower is freed.
*/
void
mutter_texture_tower_set_base_texture (MutterTextureTower *tower,
CoglHandle texture)
{
int i;
g_return_if_fail (tower != NULL);
if (texture == tower->textures[0])
return;
if (tower->textures[0] != COGL_INVALID_HANDLE)
{
for (i = 1; i < tower->n_levels; i++)
{
if (tower->textures[i] != COGL_INVALID_HANDLE)
{
free_texture (tower->textures[i]);
tower->textures[i] = COGL_INVALID_HANDLE;
}
#if CLUTTER_CHECK_VERSION(1,1,3)
if (tower->fbos[i] != COGL_INVALID_HANDLE)
{
cogl_handle_unref (tower->fbos[i]);
tower->fbos[i] = COGL_INVALID_HANDLE;
}
#else
if (tower->fbos[i] != 0)
{
(*deleteFramebuffers) (1, &tower->fbos[i]);
tower->fbos[i] = 0;
}
#endif
}
cogl_texture_unref (tower->textures[0]);
}
tower->textures[0] = texture;
if (tower->textures[0] != COGL_INVALID_HANDLE)
{
int width, height;
cogl_texture_ref (tower->textures[0]);
width = cogl_texture_get_width (tower->textures[0]);
height = cogl_texture_get_height (tower->textures[0]);
tower->n_levels = 1 + MAX ((int)(M_LOG2E * log (width)), (int)(M_LOG2E * log (height)));
tower->n_levels = MIN(tower->n_levels, MAX_TEXTURE_LEVELS);
mutter_texture_tower_update_area (tower, 0, 0, width, height);
}
else
{
tower->n_levels = 0;
}
}
/**
* mutter_texture_tower_update_area:
* @tower: a MutterTextureTower
* @x: X coordinate of upper left of rectangle that changed
* @y: Y coordinate of upper left of rectangle that changed
* @width: width of rectangle that changed
* @height: height rectangle that changed
*
* Mark a region of the base texture as having changed; the next
* time a scaled down version of the base texture is retrieved,
* the appropriate area of the scaled down texture will be updated.
*/
void
mutter_texture_tower_update_area (MutterTextureTower *tower,
int x,
int y,
int width,
int height)
{
int texture_width, texture_height;
Box invalid;
int i;
g_return_if_fail (tower != NULL);
texture_width = cogl_texture_get_width (tower->textures[0]);
texture_height = cogl_texture_get_height (tower->textures[0]);
invalid.x1 = x;
invalid.y1 = y;
invalid.x2 = x + width;
invalid.y2 = y + height;
for (i = 1; i < tower->n_levels; i++)
{
texture_width = MAX (1, texture_width / 2);
texture_height = MAX (1, texture_height / 2);
invalid.x1 = invalid.x1 / 2;
invalid.y1 = invalid.y1 / 2;
invalid.x2 = MIN (texture_width, (invalid.x2 + 1) / 2);
invalid.y2 = MIN (texture_height, (invalid.y2 + 1) / 2);
if (tower->invalid[i].x1 == tower->invalid[i].x2 ||
tower->invalid[i].y1 == tower->invalid[i].y2)
{
tower->invalid[i] = invalid;
}
else
{
tower->invalid[i].x1 = MIN (tower->invalid[i].x1, invalid.x1);
tower->invalid[i].y1 = MIN (tower->invalid[i].y1, invalid.y1);
tower->invalid[i].x2 = MAX (tower->invalid[i].x2, invalid.x2);
tower->invalid[i].y2 = MAX (tower->invalid[i].y2, invalid.y2);
}
}
}
/* It generally looks worse if we scale up a window texture by even a
* small amount than if we scale it down using bilinear filtering, so
* we always pick the *larger* adjacent level. */
#define LOD_BIAS (-0.49)
/* This determines the appropriate level of detail to use when drawing the
* texture, in a way that corresponds to what the GL specification does
* when mip-mapping. This is probably fancier and slower than what we need,
* but we do the computation only once each time we paint a window, and
* its easier to just use the equations from the specification than to
* come up with something simpler.
*
* If window is being painted at an angle from the viewer, then we have to
* pick a point in the texture; we use the middle of the texture (which is
* why the width/height are passed in.) This is not the normal case for
* Mutter.
*/
static int
get_paint_level (int width, int height)
{
CoglMatrix projection, modelview, pm;
float v[4];
double viewport_width, viewport_height;
double u0, v0;
double xc, yc, wc;
double dxdu_, dxdv_, dydu_, dydv_;
double det_, det_sq;
double rho_sq;
double lambda;
/* See
* http://www.opengl.org/registry/doc/glspec32.core.20090803.pdf
* Section 3.8.9, p. 1.6.2. Here we have
*
* u(x,y) = x_o;
* v(x,y) = y_o;
*
* Since we are mapping 1:1 from object coordinates into pixel
* texture coordinates, the clip coordinates are:
*
* (x_c) (x_o) (u)
* (y_c) = (M_projection)(M_modelview) (y_o) = (PM) (v)
* (z_c) (z_o) (0)
* (w_c) (w_o) (1)
*/
cogl_get_projection_matrix (&projection);
cogl_get_modelview_matrix (&modelview);
cogl_matrix_multiply (&pm, &projection, &modelview);
cogl_get_viewport (v);
viewport_width = v[2];
viewport_height = v[3];
u0 = width / 2.;
v0 = height / 2.;
xc = pm.xx * u0 + pm.xy * v0 + pm.xw;
yc = pm.yx * u0 + pm.yy * v0 + pm.yw;
wc = pm.wx * u0 + pm.wy * v0 + pm.ww;
/* We'll simplify the equations below for a bit of micro-optimization.
* The commented out code is the unsimplified version.
// Partial derivates of window coordinates:
//
// x_w = 0.5 * viewport_width * x_c / w_c + viewport_center_x
// y_w = 0.5 * viewport_height * y_c / w_c + viewport_center_y
//
// with respect to u, v, using
// d(a/b)/dx = da/dx * (1/b) - a * db/dx / (b^2)
dxdu = 0.5 * viewport_width * (pm.xx - pm.wx * (xc/wc)) / wc;
dxdv = 0.5 * viewport_width * (pm.xy - pm.wy * (xc/wc)) / wc;
dydu = 0.5 * viewport_height * (pm.yx - pm.wx * (yc/wc)) / wc;
dydv = 0.5 * viewport_height * (pm.yy - pm.wy * (yc/wc)) / wc;
// Compute the inverse partials as the matrix inverse
det = dxdu * dydv - dxdv * dydu;
dudx = dydv / det;
dudy = - dxdv / det;
dvdx = - dydu / det;
dvdy = dvdu / det;
// Scale factor; maximum of the distance in texels for a change of 1 pixel
// in the X direction or 1 pixel in the Y direction
rho = MAX (sqrt (dudx * dudx + dvdx * dvdx), sqrt(dudy * dudy + dvdy * dvdy));
// Level of detail
lambda = log2 (rho) + LOD_BIAS;
*/
/* dxdu * wc, etc */
dxdu_ = 0.5 * viewport_width * (pm.xx - pm.wx * (xc/wc));
dxdv_ = 0.5 * viewport_width * (pm.xy - pm.wy * (xc/wc));
dydu_ = 0.5 * viewport_height * (pm.yx - pm.wx * (yc/wc));
dydv_ = 0.5 * viewport_height * (pm.yy - pm.wy * (yc/wc));
/* det * wc^2 */
det_ = dxdu_ * dydv_ - dxdv_ * dydu_;
det_sq = det_ * det_;
if (det_sq == 0.0)
return -1;
/* (rho * det * wc)^2 */
rho_sq = MAX (dydv_ * dydv_ + dydu_ * dydu_, dxdv_ * dxdv_ + dxdu_ * dxdu_);
lambda = 0.5 * M_LOG2E * log (rho_sq * wc * wc / det_sq) + LOD_BIAS;
#if 0
g_print ("%g %g %g\n", 0.5 * viewport_width * pm.xx / pm.ww, 0.5 * viewport_height * pm.yy / pm.ww, lambda);
#endif
if (lambda <= 0.)
return 0;
else
return (int)(0.5 + lambda);
}
static gboolean
is_power_of_two (int x)
{
return (x & (x - 1)) == 0;
}
static void
texture_tower_create_texture (MutterTextureTower *tower,
int level,
int width,
int height)
{
if ((!is_power_of_two (width) || !is_power_of_two (height)) &&
texture_is_rectangle (tower->textures[level - 1]))
{
GLuint tex = 0;
glGenTextures (1, &tex);
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex);
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0,
GL_RGBA, width,height,
#if TEXTURE_FORMAT == COGL_PIXEL_FORMAT_BGRA_8888_PRE
0, GL_BGRA, GL_UNSIGNED_BYTE,
#else /* assume big endian */
0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
#endif
NULL);
tower->textures[level] = cogl_texture_new_from_foreign (tex, GL_TEXTURE_RECTANGLE_ARB,
width, height,
0, 0,
TEXTURE_FORMAT);
}
else
{
tower->textures[level] = cogl_texture_new_with_size (width, height,
COGL_TEXTURE_NO_AUTO_MIPMAP,
TEXTURE_FORMAT);
}
tower->invalid[level].x1 = 0;
tower->invalid[level].y1 = 0;
tower->invalid[level].x2 = width;
tower->invalid[level].y2 = height;
}
/* The COGL fbo (render-to-texture) support is pretty hard to use in
* Clutter 1.0; there's no way to save and restore the old projection
* matrix and viewport without ugly workarounds that require explicit
* access to the ClutterStage. In Clutter 1.2, the save/restore is
* automatic. For now, until we depend on Clutter 1.2, we use GL
* directly for render-to-texture. The main downside (other than
* a lot of verbosity) is that we have to save the state, reset anything
* that we think COGL might have left in a way we don't want it, then
* restore the old state.
*/
#if CLUTTER_CHECK_VERSION(1,1,3)
static gboolean
texture_tower_revalidate_fbo (MutterTextureTower *tower,
int level)
{
CoglHandle source_texture = tower->textures[level - 1];
int source_texture_width = cogl_texture_get_width (source_texture);
int source_texture_height = cogl_texture_get_height (source_texture);
CoglHandle dest_texture = tower->textures[level];
int dest_texture_width = cogl_texture_get_width (dest_texture);
int dest_texture_height = cogl_texture_get_height (dest_texture);
Box *invalid = &tower->invalid[level];
CoglMatrix modelview;
if (tower->fbos[level] == COGL_INVALID_HANDLE)
tower->fbos[level] = cogl_offscreen_new_to_texture (dest_texture);
if (tower->fbos[level] == COGL_INVALID_HANDLE)
return FALSE;
cogl_push_framebuffer (tower->fbos[level]);
cogl_ortho (0, dest_texture_width, dest_texture_height, 0, -1., 1.);
cogl_matrix_init_identity (&modelview);
cogl_set_modelview_matrix (&modelview);
cogl_set_source_texture (tower->textures[level - 1]);
cogl_rectangle_with_texture_coords (invalid->x1, invalid->y1,
invalid->x2, invalid->y2,
(2. * invalid->x1) / source_texture_width,
(2. * invalid->y1) / source_texture_height,
(2. * invalid->x2) / source_texture_width,
(2. * invalid->y2) / source_texture_height);
cogl_pop_framebuffer ();
return TRUE;
}
#else
static void
initialize_gl_functions (void)
{
static gboolean initialized = FALSE;
if (!initialized)
{
initialized = TRUE;
activeTexture = (PFNGLACTIVETEXTUREARBPROC) cogl_get_proc_address ("glActiveTextureARB");
genFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) cogl_get_proc_address ("glGenFramebuffersEXT");
deleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) cogl_get_proc_address ("glDeleteFramebuffersEXT");
bindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) cogl_get_proc_address ("glBindFramebufferEXT");
framebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) cogl_get_proc_address ("glFramebufferTexture2D");
}
}
static gboolean
texture_tower_revalidate_fbo (MutterTextureTower *tower,
int level)
{
CoglHandle source_texture = tower->textures[level - 1];
int source_texture_width = cogl_texture_get_width (source_texture);
int source_texture_height = cogl_texture_get_height (source_texture);
CoglHandle dest_texture = tower->textures[level];
int dest_texture_width = cogl_texture_get_width (dest_texture);
int dest_texture_height = cogl_texture_get_height (dest_texture);
ClutterActorBox source_box;
Box *dest_box;
GLuint source_gl_tex;
GLenum source_gl_target;
if (!cogl_features_available (COGL_FEATURE_OFFSCREEN))
return FALSE;
initialize_gl_functions ();
/* Create the frame-buffer object that renders to the texture, if
* it doesn't exist; just bind it for rendering if it does */
if (tower->fbos[level] == 0)
{
GLuint dest_gl_tex;
GLenum dest_gl_target;
cogl_texture_get_gl_texture (dest_texture, &dest_gl_tex, &dest_gl_target);
(*genFramebuffers) (1, &tower->fbos[level]);
(*bindFramebuffer) (GL_FRAMEBUFFER_EXT, tower->fbos[level]);
(*framebufferTexture2D) (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
dest_gl_target, dest_gl_tex, 0);
}
else
{
(*bindFramebuffer) (GL_FRAMEBUFFER_EXT, tower->fbos[level]);
}
/* Save the old state (other than the transformation matrices) */
glPushAttrib (GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT | GL_TEXTURE_BIT | GL_VIEWPORT_BIT);
/* And set up the state we need */
glDisable (GL_BLEND);
glDisable (GL_SCISSOR_TEST);
glDisable (GL_STENCIL_TEST);
glDisable (GL_CLIP_PLANE3);
glDisable (GL_CLIP_PLANE2);
glDisable (GL_CLIP_PLANE1);
glDisable (GL_CLIP_PLANE0);
cogl_texture_get_gl_texture (source_texture, &source_gl_tex, &source_gl_target);
(*activeTexture) (GL_TEXTURE0_ARB);
if (source_gl_target == GL_TEXTURE_2D)
glDisable (GL_TEXTURE_RECTANGLE_ARB);
else
glDisable (GL_TEXTURE_2D);
glEnable (source_gl_target);
glBindTexture (source_gl_target, source_gl_tex);
glTexParameteri (source_gl_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri (source_gl_target, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri (source_gl_target, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
/* In theory, we should loop over all the texture units supported
* by the GL implementation, but here we just assume that no more
* than three are used by Mutter and all GL implementations we care
* about will support at least 3.
*/
(*activeTexture) (GL_TEXTURE1_ARB);
glDisable (GL_TEXTURE_2D);
glDisable (GL_TEXTURE_RECTANGLE_ARB);
(*activeTexture) (GL_TEXTURE2_ARB);
glDisable (GL_TEXTURE_2D);
glDisable (GL_TEXTURE_RECTANGLE_ARB);
glViewport (0, 0, dest_texture_width, dest_texture_height);
/* Save the transformation matrices and set up new ones that map
* coordinates directly onto the destination texture */
glMatrixMode (GL_MODELVIEW);
glPushMatrix ();
glLoadIdentity ();
glMatrixMode (GL_PROJECTION);
glPushMatrix();
glLoadIdentity ();
glOrtho (0, dest_texture_width, 0, dest_texture_height, -1., 1.);
/* Draw */
dest_box = &tower->invalid[level];
if (texture_is_rectangle (source_texture))
{
source_box.x1 = 2 * dest_box->x1;
source_box.y1 = 2 * dest_box->y1;
source_box.x2 = 2 * dest_box->x2;
source_box.y2 = 2 * dest_box->y2;
}
else
{
source_box.x1 = (2. * dest_box->x1) / source_texture_width;
source_box.y1 = (2. * dest_box->y1) / source_texture_height;
source_box.x2 = (2. * dest_box->x2) / source_texture_width;
source_box.y2 = (2. * dest_box->y2) / source_texture_height;
}
glColor3f (0., 1., 1.);
glBegin (GL_QUADS);
glTexCoord2f (source_box.x1, source_box.y1);
glVertex2f (dest_box->x1, dest_box->y1);
glTexCoord2f (source_box.x2, source_box.y1);
glVertex2f (dest_box->x2, dest_box->y1);
glTexCoord2f (source_box.x2, source_box.y2);
glVertex2f (dest_box->x2, dest_box->y2);
glTexCoord2f (source_box.x1, source_box.y2);
glVertex2f (dest_box->x1, dest_box->y2);
glEnd ();
/* And restore everything back the way we found it */
glMatrixMode (GL_PROJECTION);
glPopMatrix ();
glMatrixMode (GL_MODELVIEW);
glPopMatrix ();
glPopAttrib ();
(*bindFramebuffer) (GL_FRAMEBUFFER_EXT, 0);
return TRUE;
}
#endif
static void
fill_copy (guchar *buf,
const guchar *source,
int width)
{
memcpy (buf, source, width * 4);
}
static void
fill_scale_down (guchar *buf,
const guchar *source,
int width)
{
while (width > 1)
{
buf[0] = (source[0] + source[4]) / 2;
buf[1] = (source[1] + source[5]) / 2;
buf[2] = (source[2] + source[6]) / 2;
buf[3] = (source[3] + source[7]) / 2;
buf += 4;
source += 8;
width -= 2;
}
if (width > 0)
{
buf[0] = source[0] / 2;
buf[1] = source[1] / 2;
buf[2] = source[2] / 2;
buf[3] = source[3] / 2;
}
}
static void
texture_tower_revalidate_client (MutterTextureTower *tower,
int level)
{
CoglHandle source_texture = tower->textures[level - 1];
int source_texture_width = cogl_texture_get_width (source_texture);
int source_texture_height = cogl_texture_get_height (source_texture);
guint source_rowstride;
guchar *source_data;
CoglHandle dest_texture = tower->textures[level];
int dest_texture_width = cogl_texture_get_width (dest_texture);
int dest_texture_height = cogl_texture_get_height (dest_texture);
int dest_x = tower->invalid[level].x1;
int dest_y = tower->invalid[level].y1;
int dest_width = tower->invalid[level].x2 - tower->invalid[level].x1;
int dest_height = tower->invalid[level].y2 - tower->invalid[level].y1;
guchar *dest_data;
guchar *source_tmp1 = NULL, *source_tmp2 = NULL;
int i, j;
source_rowstride = source_texture_width * 4;
source_data = g_malloc (source_texture_height * source_rowstride);
cogl_texture_get_data (source_texture, TEXTURE_FORMAT, source_rowstride,
source_data);
dest_data = g_malloc (dest_height * dest_width * 4);
if (dest_texture_height < source_texture_height)
{
source_tmp1 = g_malloc (dest_width * 4);
source_tmp2 = g_malloc (dest_width * 4);
}
for (i = 0; i < dest_height; i++)
{
guchar *dest_row = dest_data + i * dest_width * 4;
if (dest_texture_height < source_texture_height)
{
guchar *source1, *source2;
guchar *dest;
if (dest_texture_width < source_texture_width)
{
fill_scale_down (source_tmp1,
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 2 * 4,
dest_width * 2);
fill_scale_down (source_tmp2,
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 2 * 4,
dest_width * 2);
}
else
{
fill_copy (source_tmp1,
source_data + ((i + dest_y) * 2) * source_rowstride + dest_x * 4,
dest_width);
fill_copy (source_tmp2,
source_data + ((i + dest_y) * 2 + 1) * source_rowstride + dest_x * 4,
dest_width);
}
source1 = source_tmp1;
source2 = source_tmp2;
dest = dest_row;
for (j = 0; j < dest_width * 4; j++)
*(dest++) = (*(source1++) + *(source2++)) / 2;
}
else
{
if (dest_texture_width < source_texture_width)
fill_scale_down (dest_row,
source_data + (i + dest_y) * source_rowstride + dest_x * 2 * 4,
dest_width * 2);
else
fill_copy (dest_row,
source_data + (i + dest_y) * source_rowstride,
dest_width);
}
}
cogl_texture_set_region (dest_texture,
0, 0,
dest_x, dest_y,
dest_width, dest_height,
dest_width, dest_height,
TEXTURE_FORMAT,
4 * dest_width,
dest_data);
if (dest_height < source_texture_height)
{
g_free (source_tmp1);
g_free (source_tmp2);
}
g_free (source_data);
g_free (dest_data);
}
static void
texture_tower_revalidate (MutterTextureTower *tower,
int level)
{
if (!texture_tower_revalidate_fbo (tower, level))
texture_tower_revalidate_client (tower, level);
}
/**
* mutter_texture_tower_get_paint_texture:
* @tower: a MutterTextureTower
*
* Gets the texture from the tower that best matches the current
* rendering scale. (On the assumption here the texture is going to
* be rendered with vertex coordinates that correspond to its
* size in pixels, so a 200x200 texture will be rendered on the
* rectangle (0, 0, 200, 200).
*
* Return value: the COGL texture handle to use for painting, or
* %COGL_INVALID_HANDLE if no base texture has yet been set.
*/
CoglHandle
mutter_texture_tower_get_paint_texture (MutterTextureTower *tower)
{
int texture_width, texture_height;
int level;
g_return_val_if_fail (tower != NULL, COGL_INVALID_HANDLE);
if (tower->textures[0] == COGL_INVALID_HANDLE)
return COGL_INVALID_HANDLE;
texture_width = cogl_texture_get_width (tower->textures[0]);
texture_height = cogl_texture_get_height (tower->textures[0]);
level = get_paint_level(texture_width, texture_height);
if (level < 0) /* singular paint matrix, scaled to nothing */
return COGL_INVALID_HANDLE;
level = MIN (level, tower->n_levels - 1);
if (tower->textures[level] == COGL_INVALID_HANDLE ||
(tower->invalid[level].x2 != tower->invalid[level].x1 &&
tower->invalid[level].y2 != tower->invalid[level].y1))
{
int i;
for (i = 1; i <= level; i++)
{
/* Use "floor" convention here to be consistent with the NPOT texture extension */
texture_width = MAX (1, texture_width / 2);
texture_height = MAX (1, texture_height / 2);
if (tower->textures[i] == COGL_INVALID_HANDLE)
texture_tower_create_texture (tower, i, texture_width, texture_height);
}
for (i = 1; i <= level; i++)
{
if (tower->invalid[level].x2 != tower->invalid[level].x1 &&
tower->invalid[level].y2 != tower->invalid[level].y1)
texture_tower_revalidate (tower, i);
}
}
return tower->textures[level];
}

View File

@ -0,0 +1,69 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* MutterTextureTower
*
* Mipmap emulation by creation of scaled down images
*
* Copyright (C) 2009 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef __MUTTER_TEXTURE_TOWER_H__
#define __MUTTER_TEXTURE_TOWER_H__
#include <clutter/clutter.h>
G_BEGIN_DECLS
/**
* SECTION:MutterTextureTower
* @short_description: mipmap emulation by creation of scaled down images
*
* A #MutterTextureTower is used to get good looking scaled down images when
* we can't use the GL drivers mipmap support. There are two separate reasons
*
* - Some cards (including radeon cards <= r5xx) only support
* TEXTURE_RECTANGLE_ARB and not NPOT textures. Rectangular textures
* are defined not to support mipmapping.
* - Even when NPOT textures are available, the combination of NPOT
* textures, texture_from_pixmap, and mipmapping doesn't typically
* work, since the X server doesn't allocate pixmaps in the right
* layout for mipmapping.
*
* So, what we do is create the "mipmap" levels ourselves by successive
* power-of-two scaledowns, and when rendering pick the single texture
* that best matches the scale we are rendering at. (Since we aren't
* typically using perspective transforms, we'll frequently have a single
* scale for the entire texture.)
*/
typedef struct _MutterTextureTower MutterTextureTower;
MutterTextureTower *mutter_texture_tower_new (void);
void mutter_texture_tower_free (MutterTextureTower *tower);
void mutter_texture_tower_set_base_texture (MutterTextureTower *tower,
CoglHandle texture);
void mutter_texture_tower_update_area (MutterTextureTower *tower,
int x,
int y,
int width,
int height);
CoglHandle mutter_texture_tower_get_paint_texture (MutterTextureTower *tower);
G_BEGIN_DECLS
#endif /* __MUTTER_TEXTURE_TOWER_H__ */

View File

@ -722,6 +722,18 @@ const char *mutter_window_get_description (MutterWindow *self)
return self->priv->desc;
}
/**
* mutter_window_get_workspace:
* @self: #MutterWindow
*
* Returns the index of workspace on which this window is located; if the
* window is sticky, or is not currently located on any workspace, returns -1.
* This function is deprecated and should not be used in newly written code;
* meta_window_get_workspace() instead.
*
* Return value: (transfer none): index of workspace on which this window is
* located.
*/
gint
mutter_window_get_workspace (MutterWindow *self)
{
@ -738,6 +750,9 @@ mutter_window_get_workspace (MutterWindow *self)
workspace = meta_window_get_workspace (priv->window);
if (!workspace)
return -1;
return meta_workspace_index (workspace);
}

View File

@ -1,138 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Metacity Alt-Tab abstraction */
/*
* Copyright (C) 2009 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <config.h>
#include "alttabhandlerdefault.h"
#include "screen-private.h"
static GType handler_type = G_TYPE_INVALID;
GType meta_alt_tab_handler_default_get_type (void);
void
meta_alt_tab_handler_register (GType type)
{
handler_type = type;
}
MetaAltTabHandler *
meta_alt_tab_handler_new (MetaScreen *screen,
gboolean immediate)
{
if (handler_type == G_TYPE_INVALID)
handler_type = meta_alt_tab_handler_default_get_type ();
return g_object_new (handler_type,
"screen", screen,
"immediate", immediate,
NULL);
}
static void meta_alt_tab_handler_class_init (GObjectClass *object_class);
GType
meta_alt_tab_handler_get_type (void)
{
static volatile gsize g_define_type_id__volatile = 0;
if (g_once_init_enter (&g_define_type_id__volatile))
{
const GTypeInfo type_info =
{
sizeof (MetaAltTabHandlerInterface), /* class_size */
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc)meta_alt_tab_handler_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
0,
0, /* n_preallocs */
NULL
};
GType g_define_type_id =
g_type_register_static (G_TYPE_INTERFACE, "MetaAltTabHandler",
&type_info, 0);
g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT);
g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
}
return g_define_type_id__volatile;
}
static void
meta_alt_tab_handler_class_init (GObjectClass *object_class)
{
g_object_interface_install_property (object_class,
g_param_spec_object ("screen",
"Screen",
"MetaScreen this is the switcher for",
META_TYPE_SCREEN,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
g_object_interface_install_property (object_class,
g_param_spec_boolean ("immediate",
"Immediate mode",
"Whether or not to select windows immediately",
FALSE,
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
}
void
meta_alt_tab_handler_add_window (MetaAltTabHandler *handler,
MetaWindow *window)
{
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->add_window (handler, window);
}
void
meta_alt_tab_handler_show (MetaAltTabHandler *handler,
MetaWindow *initial_selection)
{
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->show (handler,
initial_selection);
}
void
meta_alt_tab_handler_destroy (MetaAltTabHandler *handler)
{
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->destroy (handler);
}
void
meta_alt_tab_handler_forward (MetaAltTabHandler *handler)
{
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->forward (handler);
}
void
meta_alt_tab_handler_backward (MetaAltTabHandler *handler)
{
META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->backward (handler);
}
MetaWindow *
meta_alt_tab_handler_get_selected (MetaAltTabHandler *handler)
{
return META_ALT_TAB_HANDLER_GET_INTERFACE (handler)->get_selected (handler);
}

View File

@ -1,223 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Metacity Alt-Tab abstraction: default implementation */
/*
* Copyright (C) 2009 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#include <config.h>
#include "alttabhandlerdefault.h"
#include "frame-private.h"
#include "window-private.h"
static void meta_alt_tab_handler_default_interface_init (MetaAltTabHandlerInterface *handler_iface);
G_DEFINE_TYPE_WITH_CODE (MetaAltTabHandlerDefault, meta_alt_tab_handler_default, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (META_TYPE_ALT_TAB_HANDLER,
meta_alt_tab_handler_default_interface_init))
enum {
PROP_SCREEN = 1,
PROP_IMMEDIATE
};
static void
meta_alt_tab_handler_default_init (MetaAltTabHandlerDefault *hd)
{
hd->entries = g_array_new (FALSE, FALSE, sizeof (MetaTabEntry));
}
static void
meta_alt_tab_handler_default_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (object);
switch (prop_id)
{
case PROP_SCREEN:
hd->screen = g_value_get_object (value);
break;
case PROP_IMMEDIATE:
hd->immediate_mode = g_value_get_boolean (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
meta_alt_tab_handler_default_finalize (GObject *object)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (object);
g_array_free (hd->entries, TRUE);
if (hd->tab_popup)
meta_ui_tab_popup_free (hd->tab_popup);
G_OBJECT_CLASS (meta_alt_tab_handler_default_parent_class)->finalize (object);
}
static void
meta_alt_tab_handler_default_add_window (MetaAltTabHandler *handler,
MetaWindow *window)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
MetaTabEntry entry;
MetaRectangle r;
entry.key = (MetaTabEntryKey) window;
entry.title = window->title;
entry.icon = window->icon;
entry.blank = FALSE;
entry.hidden = !meta_window_showing_on_its_workspace (window);
entry.demands_attention = window->wm_state_demands_attention;
if (hd->immediate_mode || !entry.hidden ||
!meta_window_get_icon_geometry (window, &r))
meta_window_get_outer_rect (window, &r);
entry.rect = r;
/* Find inside of highlight rectangle to be used when window is
* outlined for tabbing. This should be the size of the
* east/west frame, and the size of the south frame, on those
* sides. On the top it should be the size of the south frame
* edge.
*/
#define OUTLINE_WIDTH 5
/* Top side */
if (!entry.hidden &&
window->frame && window->frame->bottom_height > 0 &&
window->frame->child_y >= window->frame->bottom_height)
entry.inner_rect.y = window->frame->bottom_height;
else
entry.inner_rect.y = OUTLINE_WIDTH;
/* Bottom side */
if (!entry.hidden &&
window->frame && window->frame->bottom_height != 0)
entry.inner_rect.height = r.height
- entry.inner_rect.y - window->frame->bottom_height;
else
entry.inner_rect.height = r.height
- entry.inner_rect.y - OUTLINE_WIDTH;
/* Left side */
if (!entry.hidden && window->frame && window->frame->child_x != 0)
entry.inner_rect.x = window->frame->child_x;
else
entry.inner_rect.x = OUTLINE_WIDTH;
/* Right side */
if (!entry.hidden &&
window->frame && window->frame->right_width != 0)
entry.inner_rect.width = r.width
- entry.inner_rect.x - window->frame->right_width;
else
entry.inner_rect.width = r.width
- entry.inner_rect.x - OUTLINE_WIDTH;
g_array_append_val (hd->entries, entry);
}
static void
meta_alt_tab_handler_default_show (MetaAltTabHandler *handler,
MetaWindow *initial_selection)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
if (hd->tab_popup)
return;
hd->tab_popup = meta_ui_tab_popup_new ((MetaTabEntry *)hd->entries->data,
hd->screen->number,
hd->entries->len,
5, /* FIXME */
TRUE);
meta_ui_tab_popup_select (hd->tab_popup, (MetaTabEntryKey) initial_selection);
meta_ui_tab_popup_set_showing (hd->tab_popup, !hd->immediate_mode);
}
static void
meta_alt_tab_handler_default_destroy (MetaAltTabHandler *handler)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
if (hd->tab_popup)
{
meta_ui_tab_popup_free (hd->tab_popup);
hd->tab_popup = NULL;
}
}
static void
meta_alt_tab_handler_default_forward (MetaAltTabHandler *handler)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
if (hd->tab_popup)
meta_ui_tab_popup_forward (hd->tab_popup);
}
static void
meta_alt_tab_handler_default_backward (MetaAltTabHandler *handler)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
if (hd->tab_popup)
meta_ui_tab_popup_backward (hd->tab_popup);
}
static MetaWindow *
meta_alt_tab_handler_default_get_selected (MetaAltTabHandler *handler)
{
MetaAltTabHandlerDefault *hd = META_ALT_TAB_HANDLER_DEFAULT (handler);
if (hd->tab_popup)
return (MetaWindow *)meta_ui_tab_popup_get_selected (hd->tab_popup);
else
return NULL;
}
static void
meta_alt_tab_handler_default_class_init (MetaAltTabHandlerDefaultClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = meta_alt_tab_handler_default_set_property;
object_class->finalize = meta_alt_tab_handler_default_finalize;
g_object_class_override_property (object_class, PROP_SCREEN, "screen");
g_object_class_override_property (object_class, PROP_IMMEDIATE, "immediate");
}
static void
meta_alt_tab_handler_default_interface_init (MetaAltTabHandlerInterface *handler_iface)
{
handler_iface->add_window = meta_alt_tab_handler_default_add_window;
handler_iface->show = meta_alt_tab_handler_default_show;
handler_iface->destroy = meta_alt_tab_handler_default_destroy;
handler_iface->forward = meta_alt_tab_handler_default_forward;
handler_iface->backward = meta_alt_tab_handler_default_backward;
handler_iface->get_selected = meta_alt_tab_handler_default_get_selected;
}

View File

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

View File

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

View File

@ -27,6 +27,7 @@
#include "constraints.h"
#include "workspace-private.h"
#include "place.h"
#include "prefs.h"
#include <stdlib.h>
#include <math.h>
@ -93,7 +94,7 @@ typedef enum
{
PRIORITY_MINIMUM = 0, /* Dummy value used for loop start = min(all priorities) */
PRIORITY_ASPECT_RATIO = 0,
PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_XINERAMA = 0,
PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR = 0,
PRIORITY_ENTIRELY_VISIBLE_ON_WORKAREA = 1,
PRIORITY_SIZE_HINTS_INCREMENTS = 1,
PRIORITY_MAXIMIZATION = 2,
@ -127,17 +128,17 @@ typedef struct
int resize_gravity;
FixedDirections fixed_directions;
/* work_area_xinerama - current xinerama region minus struts
* entire_xinerama - current xienrama, including strut regions
/* work_area_monitor - current monitor region minus struts
* entire_monitor - current monitor, including strut regions
*/
MetaRectangle work_area_xinerama;
MetaRectangle entire_xinerama;
MetaRectangle work_area_monitor;
MetaRectangle entire_monitor;
/* Spanning rectangles for the non-covered (by struts) region of the
* screen and also for just the current xinerama
* screen and also for just the current monitor
*/
GList *usable_screen_region;
GList *usable_xinerama_region;
GList *usable_monitor_region;
} ConstraintInfo;
static gboolean constrain_maximization (MetaWindow *window,
@ -160,7 +161,7 @@ static gboolean constrain_aspect_ratio (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only);
static gboolean constrain_to_single_xinerama (MetaWindow *window,
static gboolean constrain_to_single_monitor (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only);
@ -214,7 +215,7 @@ static const Constraint all_constraints[] = {
{constrain_size_increments, "constrain_size_increments"},
{constrain_size_limits, "constrain_size_limits"},
{constrain_aspect_ratio, "constrain_aspect_ratio"},
{constrain_to_single_xinerama, "constrain_to_single_xinerama"},
{constrain_to_single_monitor, "constrain_to_single_monitor"},
{constrain_fully_onscreen, "constrain_fully_onscreen"},
{constrain_titlebar_visible, "constrain_titlebar_visible"},
{constrain_partially_onscreen, "constrain_partially_onscreen"},
@ -311,7 +312,7 @@ meta_window_constrain (MetaWindow *window,
*new = info.current;
/* We may need to update window->require_fully_onscreen,
* window->require_on_single_xinerama, and perhaps other quantities
* window->require_on_single_monitor, and perhaps other quantities
* if this was a user move or user move-and-resize operation.
*/
update_onscreen_requirements (window, &info);
@ -333,7 +334,7 @@ setup_constraint_info (ConstraintInfo *info,
const MetaRectangle *orig,
MetaRectangle *new)
{
const MetaXineramaScreenInfo *xinerama_info;
const MetaMonitorInfo *monitor_info;
MetaWorkspace *cur_workspace;
info->orig = *orig;
@ -387,15 +388,15 @@ setup_constraint_info (ConstraintInfo *info,
if (!info->is_user_action)
info->fixed_directions = FIXED_DIRECTION_NONE;
xinerama_info =
meta_screen_get_xinerama_for_rect (window->screen, &info->current);
meta_window_get_work_area_for_xinerama (window,
xinerama_info->number,
&info->work_area_xinerama);
monitor_info =
meta_screen_get_monitor_for_rect (window->screen, &info->current);
meta_window_get_work_area_for_monitor (window,
monitor_info->number,
&info->work_area_monitor);
if (!window->fullscreen || window->fullscreen_monitors[0] == -1)
{
info->entire_xinerama = xinerama_info->rect;
info->entire_monitor = monitor_info->rect;
}
else
{
@ -403,28 +404,29 @@ setup_constraint_info (ConstraintInfo *info,
long monitor;
monitor = window->fullscreen_monitors[i];
info->entire_xinerama =
window->screen->xinerama_infos[monitor].rect;
info->entire_monitor =
window->screen->monitor_infos[monitor].rect;
for (i = 1; i <= 3; i++)
{
monitor = window->fullscreen_monitors[i];
meta_rectangle_union (&info->entire_xinerama,
&window->screen->xinerama_infos[monitor].rect,
&info->entire_xinerama);
meta_rectangle_union (&info->entire_monitor,
&window->screen->monitor_infos[monitor].rect,
&info->entire_monitor);
}
}
cur_workspace = window->screen->active_workspace;
info->usable_screen_region =
meta_workspace_get_onscreen_region (cur_workspace);
info->usable_xinerama_region =
meta_workspace_get_onxinerama_region (cur_workspace,
xinerama_info->number);
info->usable_monitor_region =
meta_workspace_get_onmonitor_region (cur_workspace,
monitor_info->number);
/* Workaround braindead legacy apps that don't know how to
* fullscreen themselves properly.
*/
if (meta_rectangle_equal (new, &xinerama_info->rect) &&
if (meta_prefs_get_force_fullscreen() &&
meta_rectangle_equal (new, &monitor_info->rect) &&
window->has_fullscreen_func &&
!window->fullscreen)
{
@ -448,8 +450,8 @@ setup_constraint_info (ConstraintInfo *info,
" is_user_action : %s\n"
" resize_gravity : %s\n"
" fixed_directions: %s\n"
" work_area_xinerama: %d,%d +%d,%d\n"
" entire_xinerama : %d,%d +%d,%d\n",
" work_area_monitor: %d,%d +%d,%d\n"
" entire_monitor : %d,%d +%d,%d\n",
info->orig.x, info->orig.y, info->orig.width, info->orig.height,
info->current.x, info->current.y,
info->current.width, info->current.height,
@ -465,11 +467,11 @@ setup_constraint_info (ConstraintInfo *info,
(info->fixed_directions == FIXED_DIRECTION_X) ? "X fixed" :
(info->fixed_directions == FIXED_DIRECTION_Y) ? "Y fixed" :
"Freakin' Invalid Stupid",
info->work_area_xinerama.x, info->work_area_xinerama.y,
info->work_area_xinerama.width,
info->work_area_xinerama.height,
info->entire_xinerama.x, info->entire_xinerama.y,
info->entire_xinerama.width, info->entire_xinerama.height);
info->work_area_monitor.x, info->work_area_monitor.y,
info->work_area_monitor.width,
info->work_area_monitor.height,
info->entire_monitor.x, info->entire_monitor.y,
info->entire_monitor.width, info->entire_monitor.height);
}
static void
@ -493,25 +495,25 @@ place_window_if_needed(MetaWindow *window,
{
MetaRectangle placed_rect = info->orig;
MetaWorkspace *cur_workspace;
const MetaXineramaScreenInfo *xinerama_info;
const MetaMonitorInfo *monitor_info;
meta_window_place (window, info->fgeom, info->orig.x, info->orig.y,
&placed_rect.x, &placed_rect.y);
did_placement = TRUE;
/* placing the window may have changed the xinerama. Find the
* new xinerama and update the ConstraintInfo
/* placing the window may have changed the monitor. Find the
* new monitor and update the ConstraintInfo
*/
xinerama_info =
meta_screen_get_xinerama_for_rect (window->screen, &placed_rect);
info->entire_xinerama = xinerama_info->rect;
meta_window_get_work_area_for_xinerama (window,
xinerama_info->number,
&info->work_area_xinerama);
monitor_info =
meta_screen_get_monitor_for_rect (window->screen, &placed_rect);
info->entire_monitor = monitor_info->rect;
meta_window_get_work_area_for_monitor (window,
monitor_info->number,
&info->work_area_monitor);
cur_workspace = window->screen->active_workspace;
info->usable_xinerama_region =
meta_workspace_get_onxinerama_region (cur_workspace,
xinerama_info->number);
info->usable_monitor_region =
meta_workspace_get_onmonitor_region (cur_workspace,
monitor_info->number);
info->current.x = placed_rect.x;
@ -526,22 +528,23 @@ place_window_if_needed(MetaWindow *window,
if (window->placed || did_placement)
{
if (window->maximize_horizontally_after_placement ||
window->maximize_vertically_after_placement)
window->maximize_vertically_after_placement ||
window->fullscreen_after_placement)
{
/* define a sane saved_rect so that the user can unmaximize to
* something reasonable.
/* define a sane saved_rect so that the user can unmaximize or
* make unfullscreen to something reasonable.
*/
if (info->current.width >= info->work_area_xinerama.width)
if (info->current.width >= info->work_area_monitor.width)
{
info->current.width = .75 * info->work_area_xinerama.width;
info->current.x = info->work_area_xinerama.x +
.125 * info->work_area_xinerama.width;
info->current.width = .75 * info->work_area_monitor.width;
info->current.x = info->work_area_monitor.x +
.125 * info->work_area_monitor.width;
}
if (info->current.height >= info->work_area_xinerama.height)
if (info->current.height >= info->work_area_monitor.height)
{
info->current.height = .75 * info->work_area_xinerama.height;
info->current.y = info->work_area_xinerama.y +
.083 * info->work_area_xinerama.height;
info->current.height = .75 * info->work_area_monitor.height;
info->current.y = info->work_area_monitor.y +
.083 * info->work_area_monitor.height;
}
if (window->maximize_horizontally_after_placement ||
@ -556,6 +559,15 @@ place_window_if_needed(MetaWindow *window,
if (window->frame && !window->fullscreen)
meta_frame_calc_geometry (window->frame, info->fgeom);
if (window->fullscreen_after_placement)
{
window->saved_rect = info->current;
window->fullscreen = TRUE;
window->fullscreen_after_placement = FALSE;
g_object_notify (G_OBJECT (window), "fullscreen");
}
window->maximize_horizontally_after_placement = FALSE;
window->maximize_vertically_after_placement = FALSE;
}
@ -589,7 +601,7 @@ update_onscreen_requirements (MetaWindow *window,
return;
/* USABILITY NOTE: Naturally, I only want the require_fully_onscreen,
* require_on_single_xinerama, and require_titlebar_visible flags to
* require_on_single_monitor, and require_titlebar_visible flags to
* *become false* due to user interactions (which is allowed since
* certain constraints are ignored for user interactions regardless of
* the setting of these flags). However, whether to make these flags
@ -603,7 +615,7 @@ update_onscreen_requirements (MetaWindow *window,
* problematic case but this may need to be revisited.
*/
/* The require onscreen/on-single-xinerama and titlebar_visible
/* The require onscreen/on-single-monitor and titlebar_visible
* stuff is relative to the outer window, not the inner
*/
extend_by_frame (&info->current, info->fgeom);
@ -622,17 +634,17 @@ update_onscreen_requirements (MetaWindow *window,
window->require_fully_onscreen ? "TRUE" : "FALSE");
/* Update whether we want future constraint runs to require the
* window to be on a single xinerama.
* window to be on a single monitor.
*/
old = window->require_on_single_xinerama;
window->require_on_single_xinerama =
meta_rectangle_contained_in_region (info->usable_xinerama_region,
old = window->require_on_single_monitor;
window->require_on_single_monitor =
meta_rectangle_contained_in_region (info->usable_monitor_region,
&info->current);
if (old ^ window->require_on_single_xinerama)
if (old ^ window->require_on_single_monitor)
meta_topic (META_DEBUG_GEOMETRY,
"require_on_single_xinerama for %s toggled to %s\n",
"require_on_single_monitor for %s toggled to %s\n",
window->desc,
window->require_on_single_xinerama ? "TRUE" : "FALSE");
window->require_on_single_monitor ? "TRUE" : "FALSE");
/* Update whether we want future constraint runs to require the
* titlebar to be visible.
@ -735,7 +747,7 @@ constrain_maximization (MetaWindow *window,
/* Calculate target_size = maximized size of (window + frame) */
if (window->maximized_horizontally && window->maximized_vertically)
target_size = info->work_area_xinerama;
target_size = info->work_area_monitor;
else
{
/* Amount of maximization possible in a single direction depends
@ -757,7 +769,7 @@ constrain_maximization (MetaWindow *window,
target_size = info->current;
extend_by_frame (&target_size, info->fgeom);
meta_rectangle_expand_to_avoiding_struts (&target_size,
&info->entire_xinerama,
&info->entire_monitor,
direction,
active_workspace_struts);
}
@ -804,7 +816,7 @@ constrain_fullscreen (MetaWindow *window,
ConstraintPriority priority,
gboolean check_only)
{
MetaRectangle min_size, max_size, xinerama;
MetaRectangle min_size, max_size, monitor;
gboolean too_big, too_small, constraint_already_satisfied;
if (priority > PRIORITY_FULLSCREEN)
@ -814,22 +826,22 @@ constrain_fullscreen (MetaWindow *window,
if (!window->fullscreen)
return TRUE;
xinerama = info->entire_xinerama;
monitor = info->entire_monitor;
get_size_limits (window, info->fgeom, FALSE, &min_size, &max_size);
too_big = !meta_rectangle_could_fit_rect (&xinerama, &min_size);
too_small = !meta_rectangle_could_fit_rect (&max_size, &xinerama);
too_big = !meta_rectangle_could_fit_rect (&monitor, &min_size);
too_small = !meta_rectangle_could_fit_rect (&max_size, &monitor);
if (too_big || too_small)
return TRUE;
/* Determine whether constraint is already satisfied; exit if it is */
constraint_already_satisfied =
meta_rectangle_equal (&info->current, &xinerama);
meta_rectangle_equal (&info->current, &monitor);
if (check_only || constraint_already_satisfied)
return constraint_already_satisfied;
/*** Enforce constraint ***/
info->current = xinerama;
info->current = monitor;
return TRUE;
}
@ -1091,7 +1103,7 @@ constrain_aspect_ratio (MetaWindow *window,
}
static gboolean
do_screen_and_xinerama_relative_constraints (
do_screen_and_monitor_relative_constraints (
MetaWindow *window,
GList *region_spanning_rectangles,
ConstraintInfo *info,
@ -1107,7 +1119,7 @@ do_screen_and_xinerama_relative_constraints (
char spanning_region[1 + 28 * g_list_length (region_spanning_rectangles)];
meta_topic (META_DEBUG_GEOMETRY,
"screen/xinerama constraint; region_spanning_rectangles: %s\n",
"screen/monitor constraint; region_spanning_rectangles: %s\n",
meta_rectangle_region_to_string (region_spanning_rectangles, ", ",
spanning_region));
}
@ -1165,32 +1177,32 @@ do_screen_and_xinerama_relative_constraints (
}
static gboolean
constrain_to_single_xinerama (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only)
constrain_to_single_monitor (MetaWindow *window,
ConstraintInfo *info,
ConstraintPriority priority,
gboolean check_only)
{
if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_XINERAMA)
if (priority > PRIORITY_ENTIRELY_VISIBLE_ON_SINGLE_MONITOR)
return TRUE;
/* Exit early if we know the constraint won't apply--note that this constraint
* is only meant for normal windows (e.g. we don't want docks to be shoved
* "onscreen" by their own strut) and we can't apply it to frameless windows
* or else users will be unable to move windows such as XMMS across xineramas.
* or else users will be unable to move windows such as XMMS across monitors.
*/
if (window->type == META_WINDOW_DESKTOP ||
window->type == META_WINDOW_DOCK ||
window->screen->n_xinerama_infos == 1 ||
!window->require_on_single_xinerama ||
window->screen->n_monitor_infos == 1 ||
!window->require_on_single_monitor ||
!window->frame ||
info->is_user_action)
return TRUE;
/* Have a helper function handle the constraint for us */
return do_screen_and_xinerama_relative_constraints (window,
info->usable_xinerama_region,
info,
check_only);
return do_screen_and_monitor_relative_constraints (window,
info->usable_monitor_region,
info,
check_only);
}
static gboolean
@ -1214,10 +1226,10 @@ constrain_fully_onscreen (MetaWindow *window,
return TRUE;
/* Have a helper function handle the constraint for us */
return do_screen_and_xinerama_relative_constraints (window,
info->usable_screen_region,
info,
check_only);
return do_screen_and_monitor_relative_constraints (window,
info->usable_screen_region,
info,
check_only);
}
static gboolean
@ -1290,10 +1302,10 @@ constrain_titlebar_visible (MetaWindow *window,
horiz_amount_onscreen,
vert_amount_onscreen);
retval =
do_screen_and_xinerama_relative_constraints (window,
info->usable_screen_region,
info,
check_only);
do_screen_and_monitor_relative_constraints (window,
info->usable_screen_region,
info,
check_only);
meta_rectangle_expand_region_conditionally (info->usable_screen_region,
-horiz_amount_offscreen,
-horiz_amount_offscreen,
@ -1365,10 +1377,10 @@ constrain_partially_onscreen (MetaWindow *window,
horiz_amount_onscreen,
vert_amount_onscreen);
retval =
do_screen_and_xinerama_relative_constraints (window,
info->usable_screen_region,
info,
check_only);
do_screen_and_monitor_relative_constraints (window,
info->usable_screen_region,
info,
check_only);
meta_rectangle_expand_region_conditionally (info->usable_screen_region,
-horiz_amount_offscreen,
-horiz_amount_offscreen,

View File

@ -55,27 +55,16 @@ delete_ping_reply_func (MetaDisplay *display,
/* we do nothing */
}
static gboolean
delete_window_callback (gpointer w_p)
{
meta_window_kill ((MetaWindow*) w_p);
return FALSE; /* don't do it again */
}
static void
sigchld_handler (MetaNexus *nexus, guint arg1, gpointer arg2, gpointer user_data)
dialog_exited (GPid pid, int status, gpointer user_data)
{
MetaWindow *ours = (MetaWindow*) user_data;
if (GPOINTER_TO_INT (arg2) == ours->dialog_pid)
{
if (arg1 == 1 /* pressed "force quit" */)
g_idle_add_full (G_PRIORITY_DEFAULT,
delete_window_callback, user_data, NULL);
ours->dialog_pid = -1;
ours->dialog_pid = -1; /* forget it anyway */
}
/* exit status of 1 means the user pressed "Force Quit" */
if (WIFEXITED (status) && WEXITSTATUS (status) == 1)
meta_window_kill (ours);
}
static void
@ -86,7 +75,7 @@ delete_ping_timeout_func (MetaDisplay *display,
{
MetaWindow *window = user_data;
char *window_title;
gchar *window_content;
gchar *window_content, *tmp;
GPid dialog_pid;
meta_topic (META_DEBUG_PING,
@ -101,11 +90,14 @@ delete_ping_timeout_func (MetaDisplay *display,
window_title = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL);
window_content = g_strdup_printf(
_("<big><b><tt>%s</tt> is not responding.</b></big>\n\n"
"<i>You may choose to wait a short while for it to "
"continue or force the application to quit entirely.</i>"),
window_title);
/* Translators: %s is a window title */
tmp = g_strdup_printf (_("<tt>%s</tt> is not responding."),
window_title);
window_content = g_strdup_printf (
"<big><b>%s</b></big>\n\n<i>%s</i>",
tmp,
_("You may choose to wait a short while for it to "
"continue or force the application to quit entirely."));
g_free (window_title);
@ -117,13 +109,10 @@ delete_ping_timeout_func (MetaDisplay *display,
NULL, NULL);
g_free (window_content);
g_free (tmp);
window->dialog_pid = dialog_pid;
g_signal_connect (sigchld_nexus, "sigchld",
G_CALLBACK (sigchld_handler),
window);
g_child_watch_add (dialog_pid, dialog_exited, window);
}
void

View File

@ -150,6 +150,15 @@ struct _MetaDisplay
guint32 current_time;
/* We maintain a sequence counter, incremented for each #MetaWindow
* created. This is exposed by meta_window_get_stable_sequence()
* but is otherwise not used inside mutter.
*
* It can be useful to plugins which want to sort windows in a
* stable fashion.
*/
guint32 window_sequence_counter;
/* Pings which we're waiting for a reply from */
GSList *pending_pings;
@ -217,8 +226,8 @@ struct _MetaDisplay
MetaKeyCombo overlay_key_combo;
gboolean overlay_key_only_pressed;
/* Xinerama cache */
unsigned int xinerama_cache_invalidated : 1;
/* Monitor cache */
unsigned int monitor_cache_invalidated : 1;
/* Opening the display */
unsigned int display_opening : 1;
@ -349,6 +358,9 @@ void meta_display_register_x_window (MetaDisplay *display,
void meta_display_unregister_x_window (MetaDisplay *display,
Window xwindow);
void meta_display_notify_window_created (MetaDisplay *display,
MetaWindow *window);
GSList* meta_display_list_windows (MetaDisplay *display,
MetaListWindowsFlags flags);
@ -378,9 +390,8 @@ void meta_display_grab_focus_window_button (MetaDisplay *display,
void meta_display_ungrab_focus_window_button (MetaDisplay *display,
MetaWindow *window);
/* Next two functions are defined in edge-resistance.c */
void meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display);
void meta_display_cleanup_edges (MetaDisplay *display);
/* Next function is defined in edge-resistance.c */
void meta_display_cleanup_edges (MetaDisplay *display);
/* make a request to ensure the event serial has changed */
void meta_display_increment_event_serial (MetaDisplay *display);

View File

@ -129,6 +129,9 @@ enum
{
OVERLAY_KEY,
FOCUS_WINDOW,
WINDOW_CREATED,
WINDOW_DEMANDS_ATTENTION,
WINDOW_MARKED_URGENT,
LAST_SIGNAL
};
@ -148,8 +151,10 @@ static guint display_signals [LAST_SIGNAL] = { 0 };
*/
static MetaDisplay *the_display = NULL;
#ifdef WITH_VERBOSE_MODE
static void meta_spew_event (MetaDisplay *display,
XEvent *event);
#endif
static gboolean event_callback (XEvent *event,
gpointer data);
@ -226,6 +231,34 @@ meta_display_class_init (MetaDisplayClass *klass)
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
display_signals[WINDOW_CREATED] =
g_signal_new ("window-created",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, META_TYPE_WINDOW);
display_signals[WINDOW_DEMANDS_ATTENTION] =
g_signal_new ("window-demands-attention",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, META_TYPE_WINDOW);
display_signals[WINDOW_MARKED_URGENT] =
g_signal_new ("window-marked-urgent",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1,
META_TYPE_WINDOW);
g_object_class_install_property (object_class,
PROP_FOCUS_WINDOW,
g_param_spec_object ("focus-window",
@ -483,7 +516,7 @@ meta_display_open (void)
the_display->leader_window = None;
the_display->timestamp_pinging_window = None;
the_display->xinerama_cache_invalidated = TRUE;
the_display->monitor_cache_invalidated = TRUE;
the_display->groups_by_leader = NULL;
@ -722,6 +755,13 @@ meta_display_open (void)
the_display->leader_window,
the_display->atom__NET_WM_NAME,
"Mutter");
/* The GNOME keybindings capplet should include both the Mutter and Metacity
* keybindings */
meta_prop_set_utf8_string_hint (the_display,
the_display->leader_window,
the_display->atom__GNOME_WM_KEYBINDINGS,
"Mutter,Metacity");
meta_prop_set_utf8_string_hint (the_display,
the_display->leader_window,
@ -1528,7 +1568,7 @@ event_callback (XEvent *event,
bypass_compositor = FALSE;
filter_out_event = FALSE;
display->current_time = event_get_time (display, event);
display->xinerama_cache_invalidated = TRUE;
display->monitor_cache_invalidated = TRUE;
modified = event_get_modified_window (display, event);
@ -2549,7 +2589,7 @@ event_callback (XEvent *event,
{
case XkbBellNotify:
if (XSERVER_TIME_IS_BEFORE(display->last_bell_time,
xkb_ev->time - 1000))
xkb_ev->time - 100))
{
display->last_bell_time = xkb_ev->time;
meta_bell_notify (display, xkb_ev);
@ -3203,6 +3243,13 @@ meta_display_unregister_x_window (MetaDisplay *display,
remove_pending_pings_for_window (display, xwindow);
}
void
meta_display_notify_window_created (MetaDisplay *display,
MetaWindow *window)
{
g_signal_emit (display, display_signals[WINDOW_CREATED], 0, window);
}
/**
* meta_display_xwindow_is_a_no_focus_window:
* @display: A #MetaDisplay
@ -3591,18 +3638,6 @@ meta_display_begin_grab_op (MetaDisplay *display,
g_assert (display->grab_window != NULL || display->grab_screen != NULL);
g_assert (display->grab_op != META_GRAB_OP_NONE);
/* If this is a move or resize, cache the window edges for
* resistance/snapping
*/
if (meta_grab_op_is_resizing (display->grab_op) ||
meta_grab_op_is_moving (display->grab_op))
{
meta_topic (META_DEBUG_WINDOW_OPS,
"Computing edges to resist-movement or snap-to for %s.\n",
window->desc);
meta_display_compute_resistance_and_snapping_edges (display);
}
/* Save the old stacking */
if (GRAB_OP_IS_WINDOW_SWITCH (display->grab_op))
{
@ -4106,7 +4141,7 @@ meta_set_syncing (gboolean setting)
* How long, in milliseconds, we should wait after pinging a window
* before deciding it's not going to get back to us.
*/
#define PING_TIMEOUT_DELAY 2250
#define PING_TIMEOUT_DELAY 5000
/**
* Does whatever it is we decided to do when a window didn't respond
@ -4531,7 +4566,8 @@ meta_display_get_tab_list (MetaDisplay *display,
/* Check to see if it demands attention */
if (l_window->wm_state_demands_attention &&
l_window->workspace!=workspace)
l_window->workspace!=workspace &&
IN_TAB_CHAIN (l_window, type))
{
/* if it does, add it to the popup */
tab_list = g_list_prepend (tab_list, l_window);
@ -5111,9 +5147,9 @@ sanity_check_timestamps (MetaDisplay *display,
meta_warning ("%s appears to be one of the offending windows "
"with a timestamp of %u. Working around...\n",
window->desc, window->net_wm_user_time);
window->net_wm_user_time = timestamp;
meta_window_set_user_time (window, timestamp);
}
tmp = tmp->next;
}

View File

@ -63,6 +63,8 @@ struct MetaEdgeResistanceData
ResistanceDataForAnEdge bottom_data;
};
static void compute_resistance_and_snapping_edges (MetaDisplay *display);
/* !WARNING!: this function can return invalid indices (namely, either -1 or
* edges->len); this is by design, but you need to remember this.
*/
@ -340,12 +342,12 @@ apply_edge_resistance (MetaWindow *window,
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_WINDOW = 16;
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW = 0;
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_XINERAMA = 32;
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_XINERAMA = 0;
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_MONITOR = 32;
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_MONITOR = 0;
const int PIXEL_DISTANCE_THRESHOLD_TOWARDS_SCREEN = 32;
const int PIXEL_DISTANCE_THRESHOLD_AWAYFROM_SCREEN = 0;
const int TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW = 0;
const int TIMEOUT_RESISTANCE_LENGTH_MS_XINERAMA = 0;
const int TIMEOUT_RESISTANCE_LENGTH_MS_MONITOR = 0;
const int TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN = 0;
/* Quit if no movement was specified */
@ -423,8 +425,8 @@ apply_edge_resistance (MetaWindow *window,
case META_EDGE_WINDOW:
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_WINDOW;
break;
case META_EDGE_XINERAMA:
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_XINERAMA;
case META_EDGE_MONITOR:
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_MONITOR;
break;
case META_EDGE_SCREEN:
timeout_length_ms = TIMEOUT_RESISTANCE_LENGTH_MS_SCREEN;
@ -468,11 +470,11 @@ apply_edge_resistance (MetaWindow *window,
else
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_WINDOW;
break;
case META_EDGE_XINERAMA:
case META_EDGE_MONITOR:
if (movement_towards_edge (edge->side_type, increment))
threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_XINERAMA;
threshold = PIXEL_DISTANCE_THRESHOLD_TOWARDS_MONITOR;
else
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_XINERAMA;
threshold = PIXEL_DISTANCE_THRESHOLD_AWAYFROM_MONITOR;
break;
case META_EDGE_SCREEN:
if (movement_towards_edge (edge->side_type, increment))
@ -550,7 +552,9 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
gboolean modified;
int new_left, new_right, new_top, new_bottom;
g_assert (display->grab_edge_resistance_data != NULL);
if (display->grab_edge_resistance_data == NULL)
compute_resistance_and_snapping_edges (display);
edge_data = display->grab_edge_resistance_data;
if (auto_snap)
@ -671,7 +675,8 @@ meta_display_cleanup_edges (MetaDisplay *display)
MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data;
GHashTable *edges_to_be_freed;
g_assert (edge_data != NULL);
if (edge_data == NULL) /* Not currently cached */
return;
/* We first need to clean out any window edges */
edges_to_be_freed = g_hash_table_new_full (g_direct_hash, g_direct_equal,
@ -761,7 +766,7 @@ stupid_sort_requiring_extra_pointer_dereference (gconstpointer a,
static void
cache_edges (MetaDisplay *display,
GList *window_edges,
GList *xinerama_edges,
GList *monitor_edges,
GList *screen_edges)
{
MetaEdgeResistanceData *edge_data;
@ -776,7 +781,7 @@ cache_edges (MetaDisplay *display,
if (meta_is_verbose())
{
int max_edges = MAX (MAX( g_list_length (window_edges),
g_list_length (xinerama_edges)),
g_list_length (monitor_edges)),
g_list_length (screen_edges));
char big_buffer[(EDGE_LENGTH+2)*max_edges];
@ -784,9 +789,9 @@ cache_edges (MetaDisplay *display,
meta_topic (META_DEBUG_EDGE_RESISTANCE,
"Window edges for resistance : %s\n", big_buffer);
meta_rectangle_edge_list_to_string (xinerama_edges, ", ", big_buffer);
meta_rectangle_edge_list_to_string (monitor_edges, ", ", big_buffer);
meta_topic (META_DEBUG_EDGE_RESISTANCE,
"Xinerama edges for resistance: %s\n", big_buffer);
"Monitor edges for resistance: %s\n", big_buffer);
meta_rectangle_edge_list_to_string (screen_edges, ", ", big_buffer);
meta_topic (META_DEBUG_EDGE_RESISTANCE,
@ -807,7 +812,7 @@ cache_edges (MetaDisplay *display,
tmp = window_edges;
break;
case 1:
tmp = xinerama_edges;
tmp = monitor_edges;
break;
case 2:
tmp = screen_edges;
@ -875,7 +880,7 @@ cache_edges (MetaDisplay *display,
tmp = window_edges;
break;
case 1:
tmp = xinerama_edges;
tmp = monitor_edges;
break;
case 2:
tmp = screen_edges;
@ -938,8 +943,8 @@ initialize_grab_edge_resistance_data (MetaDisplay *display)
edge_data->bottom_data.keyboard_buildup = 0;
}
void
meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display)
static void
compute_resistance_and_snapping_edges (MetaDisplay *display)
{
GList *stacked_windows;
GList *cur_window_iter;
@ -952,6 +957,11 @@ meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display)
*/
GSList *rem_windows, *rem_win_stacking;
g_assert (display->grab_window != NULL);
meta_topic (META_DEBUG_WINDOW_OPS,
"Computing edges to resist-movement or snap-to for %s.\n",
display->grab_window->desc);
/*
* 1st: Get the list of relevant windows, from bottom to top
*/
@ -1110,12 +1120,12 @@ meta_display_compute_resistance_and_snapping_edges (MetaDisplay *display)
/*
* 5th: Cache the combination of these edges with the onscreen and
* xinerama edges in an array for quick access. Free the edges since
* monitor edges in an array for quick access. Free the edges since
* they've been cached elsewhere.
*/
cache_edges (display,
edges,
display->grab_screen->active_workspace->xinerama_edges,
display->grab_screen->active_workspace->monitor_edges,
display->grab_screen->active_workspace->screen_edges);
g_list_free (edges);

View File

@ -186,10 +186,10 @@ x_error_handler (Display *xdisplay,
display = meta_display_for_x_display (xdisplay);
/* Display can be NULL here because the compositing manager
* has its own Display, but Xlib only has one global error handler
/* Display can be NULL here Xlib only has one global error handler; and
* there might be other displays open in the process.
*/
if (display->error_traps > 0)
if (display && display->error_traps > 0)
{
/* we're in an error trap, chain to the trap handler
* saved from GDK
@ -228,21 +228,18 @@ x_io_error_handler (Display *xdisplay)
display = meta_display_for_x_display (xdisplay);
if (display == NULL)
meta_bug ("IO error received for unknown display?\n");
if (errno == EPIPE)
{
meta_warning (_("Lost connection to the display '%s';\n"
"most likely the X server was shut down or you killed/destroyed\n"
"the window manager.\n"),
display->name);
display ? display->name : DisplayString (xdisplay));
}
else
{
meta_warning (_("Fatal IO error %d (%s) on display '%s'.\n"),
errno, g_strerror (errno),
display->name);
display ? display->name : DisplayString (xdisplay));
}
/* Xlib would force an exit anyhow */

View File

@ -2047,15 +2047,11 @@ process_tab_grab (MetaDisplay *display,
action = META_KEYBINDING_ACTION_NONE;
/*
* There are currently two different ways of customizing Alt-Tab, you can either
* provide a replacement AltTabHandler object, or you can hook into the keybindings
* meta_keybindings_set_custom_handler() and call meta_display_begin_grab_op()
* yourself with one of the "tabbing" grab ops META_GRAB_OP_KEYBOARD_TABBING_NORMAL,
* etc. See meta_display_process_key_event() for the complete list. If screen->tab_handler
* is NULL, the latter mechanism is being used. We skip most of our normal
* processing and just make sure that the right custom handlers get called.
* If there is no tab_pop up object, i.e., there is some custom handler
* implementing Alt+Tab & Co., we call this custom handler; we do not
* mess about with the grab, as that is up to the handler to deal with.
*/
if (!screen->tab_handler)
if (!screen->tab_popup)
{
if (event->type == KeyRelease)
{
@ -2553,7 +2549,7 @@ handle_move_to_corner_backend (MetaDisplay *display,
int new_x, new_y;
int frame_width, frame_height;
meta_window_get_work_area_all_xineramas (window, &work_area);
meta_window_get_work_area_all_monitors (window, &work_area);
meta_window_get_outer_rect (window, &outer);
meta_window_get_position (window, &orig_x, &orig_y);
@ -2685,7 +2681,7 @@ handle_move_to_center (MetaDisplay *display,
int orig_x, orig_y;
int frame_width, frame_height;
meta_window_get_work_area_all_xineramas (window, &work_area);
meta_window_get_work_area_all_monitors (window, &work_area);
meta_window_get_outer_rect (window, &outer);
meta_window_get_position (window, &orig_x, &orig_y);

View File

@ -68,6 +68,7 @@
#include <fcntl.h>
#include <locale.h>
#include <time.h>
#include <unistd.h>
#include <clutter/clutter.h>
#include <clutter/x11/clutter-x11.h>
@ -124,11 +125,13 @@ log_handler (const gchar *log_domain,
static void
version (void)
{
const int latest_year = 2010;
g_print (_("mutter %s\n"
"Copyright (C) 2001-2008 Havoc Pennington, Red Hat, Inc., and others\n"
"Copyright (C) 2001-%d Havoc Pennington, Red Hat, Inc., and others\n"
"This is free software; see the source for copying conditions.\n"
"There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"),
VERSION);
VERSION, latest_year);
exit (0);
}
@ -226,6 +229,7 @@ typedef struct
gboolean sync;
gboolean composite;
gboolean no_composite;
gboolean no_force_fullscreen;
gboolean no_tab_popup;
gchar *introspect;
} MetaArguments;
@ -304,6 +308,12 @@ meta_parse_options (int *argc, char ***argv,
N_("Turn compositing off"),
NULL
},
{
"no-force-fullscreen", 0, COMPOSITE_OPTS_FLAGS, G_OPTION_ARG_NONE,
&my_args.no_force_fullscreen,
N_("Don't make fullscreen windows that are maximized and have no decorations"),
NULL
},
{
"mutter-plugins", 0, 0, G_OPTION_ARG_STRING,
&my_args.mutter_plugins,
@ -331,6 +341,7 @@ meta_parse_options (int *argc, char ***argv,
ctx = g_option_context_new (NULL);
g_option_context_add_main_entries (ctx, options, "mutter");
g_option_context_add_group (ctx, clutter_get_option_group_without_init ());
g_option_context_add_group (ctx, cogl_get_option_group ());
if (!g_option_context_parse (ctx, argc, argv, &error))
{
@ -436,37 +447,28 @@ meta_finalize (void)
meta_session_shutdown ();
}
static int sigterm_pipe_fds[2] = { -1, -1 };
static void
sigterm_handler (int signum)
{
meta_finalize ();
exit (meta_exit_code);
}
static guint sigchld_signal_id = 0;
static void
sigchld_handler (int signum, siginfo_t *info, void *context)
{
int stat;
if (info->si_code == CLD_EXITED)
if (sigterm_pipe_fds[1] >= 0)
{
g_signal_emit (sigchld_nexus, sigchld_signal_id, 0,
info->si_status,
GINT_TO_POINTER (info->si_pid));
int dummy;
dummy = write (sigterm_pipe_fds[1], "", 1);
close (sigterm_pipe_fds[1]);
sigterm_pipe_fds[1] = -1;
}
g_signal_handlers_disconnect_matched (sigchld_nexus,
G_SIGNAL_MATCH_DATA,
sigchld_signal_id,
0, NULL, NULL,
GINT_TO_POINTER (info->si_pid));
waitpid (info->si_pid, &stat, WNOHANG);
}
static gboolean
on_sigterm (void)
{
meta_quit (META_EXIT_SUCCESS);
return FALSE;
}
/**
* This is where the story begins. It parses commandline options and
* environment variables, sets up the screen, hands control off to
@ -489,8 +491,9 @@ main (int argc, char **argv)
"Pango", "GLib-GObject", "GThread"
};
guint i;
GIOChannel *channel;
GOptionContext *ctx;
if (!g_thread_supported ())
g_thread_init (NULL);
@ -512,29 +515,21 @@ main (int argc, char **argv)
g_strerror (errno));
#endif
if (pipe (sigterm_pipe_fds) != 0)
g_printerr ("Failed to create SIGTERM pipe: %s\n",
g_strerror (errno));
channel = g_io_channel_unix_new (sigterm_pipe_fds[0]);
g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
g_io_add_watch (channel, G_IO_IN, (GIOFunc) on_sigterm, NULL);
g_io_channel_set_close_on_unref (channel, TRUE);
g_io_channel_unref (channel);
act.sa_handler = &sigterm_handler;
if (sigaction (SIGTERM, &act, NULL) < 0)
g_printerr ("Failed to register SIGTERM handler: %s\n",
g_strerror (errno));
sigchld_nexus = g_object_new (META_TYPE_NEXUS, NULL);
sigchld_signal_id =
g_signal_new ("sigchld", META_TYPE_NEXUS,
G_SIGNAL_RUN_LAST,
0, NULL, NULL,
g_cclosure_marshal_VOID__UINT_POINTER,
G_TYPE_NONE,
2,
G_TYPE_UINT, G_TYPE_POINTER);
act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO;
act.sa_handler = SIG_DFL;
act.sa_sigaction = &sigchld_handler;
if (sigaction (SIGCHLD, &act, NULL) < 0)
g_printerr ("Failed to register SIGCHLD handler: %s\n",
g_strerror (errno));
if (g_getenv ("MUTTER_VERBOSE"))
meta_set_verbose (TRUE);
if (g_getenv ("MUTTER_DEBUG"))
@ -716,6 +711,9 @@ main (int argc, char **argv)
if (meta_args.composite || meta_args.no_composite)
meta_prefs_set_compositing_manager (meta_args.composite);
if (meta_args.no_force_fullscreen)
meta_prefs_set_force_fullscreen (FALSE);
if (meta_args.no_tab_popup)
{
meta_prefs_override_no_tab_popup (TRUE);

View File

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

View File

@ -52,6 +52,7 @@
#define KEY_COMPOSITOR "/apps/metacity/general/compositing_manager"
#define KEY_GNOME_ACCESSIBILITY "/desktop/gnome/interface/accessibility"
#define KEY_COMMAND_DIRECTORY "/apps/metacity/keybinding_commands"
#define KEY_COMMAND_PREFIX "/apps/metacity/keybinding_commands/command_"
#define KEY_TERMINAL_DIR "/desktop/gnome/applications/terminal"
@ -62,6 +63,7 @@
#define KEY_WINDOW_BINDINGS_PREFIX "/apps/metacity/window_keybindings"
#define KEY_LIST_BINDINGS_SUFFIX "_list"
#define KEY_WORKSPACE_NAME_DIRECTORY "/apps/metacity/workspace_names"
#define KEY_WORKSPACE_NAME_PREFIX "/apps/metacity/workspace_names/name_"
#define KEY_CLUTTER_PLUGINS "/apps/mutter/general/clutter_plugins"
@ -100,6 +102,7 @@ static char *cursor_theme = NULL;
static int cursor_size = 24;
static gboolean compositing_manager = FALSE;
static gboolean resize_with_right_button = FALSE;
static gboolean force_fullscreen = TRUE;
static MetaVisualBellType visual_bell_type = META_VISUAL_BELL_FULLSCREEN_FLASH;
static MetaButtonLayout button_layout;
@ -121,13 +124,23 @@ static gboolean no_tab_popup = FALSE;
#ifdef HAVE_GCONF
static gboolean handle_preference_update_enum (const gchar *key, GConfValue *value);
static gboolean update_key_binding (const char *name,
static char *binding_name (const char *gconf_key);
static gboolean update_key_binding (const char *key,
const char *value);
static gboolean find_and_update_list_binding (MetaKeyPref *bindings,
const char *name,
GSList *value);
static gboolean update_key_list_binding (const char *name,
GSList *value);
typedef enum
{
META_LIST_OF_STRINGS,
META_LIST_OF_GCONFVALUE_STRINGS
} MetaStringListType;
static gboolean find_and_update_list_binding (MetaKeyPref *bindings,
const char *key,
GSList *value,
MetaStringListType type_of_value);
static gboolean update_key_list_binding (const char *key,
GSList *value,
MetaStringListType type_of_value);
static gboolean update_command (const char *name,
const char *value);
static gboolean update_workspace_name (const char *name,
@ -142,14 +155,8 @@ static char* gconf_key_for_workspace_name (int i);
static void queue_changed (MetaPreference pref);
typedef enum
{
META_LIST_OF_STRINGS,
META_LIST_OF_GCONFVALUE_STRINGS
} MetaStringListType;
static gboolean update_list_binding (MetaKeyPref *binding,
GSList *value,
static gboolean update_list_binding (MetaKeyPref *binding,
GSList *value,
MetaStringListType type_of_value);
static void cleanup_error (GError **error);
@ -1146,7 +1153,7 @@ change_notify (GConfClient *client,
list = value ? gconf_value_get_list (value) : NULL;
if (update_key_list_binding (key, list))
if (update_key_list_binding (key, list, META_LIST_OF_GCONFVALUE_STRINGS))
queue_changed (META_PREF_KEYBINDINGS);
}
else
@ -1800,6 +1807,9 @@ meta_preference_to_string (MetaPreference pref)
case META_PREF_RESIZE_WITH_RIGHT_BUTTON:
return "RESIZE_WITH_RIGHT_BUTTON";
case META_PREF_FORCE_FULLSCREEN:
return "FORCE_FULLSCREEN";
case META_PREF_CLUTTER_PLUGINS:
return "CLUTTER_PLUGINS";
@ -1888,57 +1898,64 @@ init_special_bindings (void)
static void
init_bindings (void)
{
#ifdef HAVE_GCONF
int i = 0;
GError *err;
#ifdef HAVE_GCONF
const char *prefix[] = {
KEY_WINDOW_BINDINGS_PREFIX,
KEY_SCREEN_BINDINGS_PREFIX,
NULL
};
int i;
GSList *list, *l, *list_val;
const char *str_val;
const char *key;
GConfEntry *entry;
GConfValue *value;
GHashTable *to_update;
to_update = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
for (i = 0; prefix[i]; i++)
{
list = gconf_client_all_entries (default_client, prefix[i], NULL);
for (l = list; l; l = l->next)
{
entry = l->data;
key = gconf_entry_get_key (entry);
value = gconf_entry_get_value (entry);
if (g_str_has_suffix (key, KEY_LIST_BINDINGS_SUFFIX))
{
/* List bindings are used in addition to the normal bindings and never
* have defaults, so we just go ahead and set them immediately; there
* will be only a few of them, so don't worry about the linear scan
* in find_and_update_list_binding.
*/
list_val = gconf_client_get_list (default_client, key, GCONF_VALUE_STRING, NULL);
update_key_list_binding (key, list_val, META_LIST_OF_STRINGS);
g_slist_foreach (list_val, (GFunc)g_free, NULL);
g_slist_free (list_val);
}
else
{
str_val = gconf_value_get_string (value);
g_hash_table_insert (to_update, binding_name (key), g_strdup (str_val));
}
gconf_entry_free (entry);
}
g_slist_free (list);
}
i = 0;
while (key_bindings[i].name)
{
GSList *list_val, *tmp;
char *str_val;
char *key;
key = g_strconcat (key_bindings[i].per_window?
KEY_WINDOW_BINDINGS_PREFIX:
KEY_SCREEN_BINDINGS_PREFIX,
"/",
key_bindings[i].name, NULL);
err = NULL;
str_val = gconf_client_get_string (default_client, key, &err);
cleanup_error (&err);
update_binding (&key_bindings[i], str_val);
g_free (str_val);
g_free (key);
key = g_strconcat (key_bindings[i].per_window?
KEY_WINDOW_BINDINGS_PREFIX:
KEY_SCREEN_BINDINGS_PREFIX,
"/",
key_bindings[i].name,
KEY_LIST_BINDINGS_SUFFIX, NULL);
err = NULL;
list_val = gconf_client_get_list (default_client, key, GCONF_VALUE_STRING, &err);
cleanup_error (&err);
update_list_binding (&key_bindings[i], list_val, META_LIST_OF_STRINGS);
tmp = list_val;
while (tmp)
{
g_free (tmp->data);
tmp = tmp->next;
}
g_slist_free (list_val);
g_free (key);
update_binding (&key_bindings[i],
g_hash_table_lookup (to_update, key_bindings[i].name));
++i;
}
g_hash_table_destroy (to_update);
#else /* HAVE_GCONF */
int i = 0;
while (key_bindings[i].name)
@ -1960,28 +1977,23 @@ static void
init_commands (void)
{
#ifdef HAVE_GCONF
int i;
GError *err;
i = 0;
while (i < MAX_COMMANDS)
GSList *list, *l;
const char *str_val;
const char *key;
GConfEntry *entry;
GConfValue *value;
list = gconf_client_all_entries (default_client, KEY_COMMAND_DIRECTORY, NULL);
for (l = list; l; l = l->next)
{
char *str_val;
char *key;
key = meta_prefs_get_gconf_key_for_command (i);
err = NULL;
str_val = gconf_client_get_string (default_client, key, &err);
cleanup_error (&err);
entry = l->data;
key = gconf_entry_get_key (entry);
value = gconf_entry_get_value (entry);
str_val = gconf_value_get_string (value);
update_command (key, str_val);
g_free (str_val);
g_free (key);
++i;
gconf_entry_free (entry);
}
g_slist_free (list);
#else
int i;
for (i = 0; i < MAX_COMMANDS; i++)
@ -1993,30 +2005,23 @@ static void
init_workspace_names (void)
{
#ifdef HAVE_GCONF
int i;
GError *err;
i = 0;
while (i < MAX_REASONABLE_WORKSPACES)
GSList *list, *l;
const char *str_val;
const char *key;
GConfEntry *entry;
GConfValue *value;
list = gconf_client_all_entries (default_client, KEY_WORKSPACE_NAME_DIRECTORY, NULL);
for (l = list; l; l = l->next)
{
char *str_val;
char *key;
key = gconf_key_for_workspace_name (i);
err = NULL;
str_val = gconf_client_get_string (default_client, key, &err);
cleanup_error (&err);
entry = l->data;
key = gconf_entry_get_key (entry);
value = gconf_entry_get_value (entry);
str_val = gconf_value_get_string (value);
update_workspace_name (key, str_val);
g_assert (workspace_names[i] != NULL);
g_free (str_val);
g_free (key);
++i;
gconf_entry_free (entry);
}
g_slist_free (list);
#else
int i;
for (i = 0; i < MAX_REASONABLE_WORKSPACES; i++)
@ -2275,16 +2280,22 @@ update_list_binding (MetaKeyPref *binding,
return changed;
}
static const gchar*
relative_key (const gchar* key)
static char *
binding_name (const char *gconf_key)
{
const gchar* end;
end = strrchr (key, '/');
const char *start, *end;
++end;
if (*gconf_key == '/')
start = strrchr (gconf_key, '/') + 1;
else
start = gconf_key;
return end;
if (g_str_has_suffix (gconf_key, KEY_LIST_BINDINGS_SUFFIX))
end = gconf_key + strlen(gconf_key) - strlen (KEY_LIST_BINDINGS_SUFFIX);
else
end = gconf_key + strlen(gconf_key);
return g_strndup (start, end - start);
}
/* Return value is TRUE if a preference changed and we need to
@ -2292,22 +2303,19 @@ relative_key (const gchar* key)
*/
static gboolean
find_and_update_binding (MetaKeyPref *bindings,
const char *name,
const char *key,
const char *value)
{
const char *key;
char *name = binding_name (key);
int i;
if (*name == '/')
key = relative_key (name);
else
key = name;
i = 0;
while (bindings[i].name &&
strcmp (key, bindings[i].name) != 0)
strcmp (name, bindings[i].name) != 0)
++i;
g_free (name);
if (bindings[i].name)
return update_binding (&bindings[i], value);
else
@ -2315,46 +2323,40 @@ find_and_update_binding (MetaKeyPref *bindings,
}
static gboolean
update_key_binding (const char *name,
const char *value)
update_key_binding (const char *key,
const char *value)
{
return find_and_update_binding (key_bindings, name, value);
return find_and_update_binding (key_bindings, key, value);
}
static gboolean
find_and_update_list_binding (MetaKeyPref *bindings,
const char *name,
GSList *value)
find_and_update_list_binding (MetaKeyPref *bindings,
const char *key,
GSList *value,
MetaStringListType type_of_value)
{
const char *key;
char *name = binding_name (key);
int i;
gchar *name_without_suffix = g_strdup(name);
name_without_suffix[strlen(name_without_suffix) - strlen(KEY_LIST_BINDINGS_SUFFIX)] = 0;
if (*name_without_suffix == '/')
key = relative_key (name_without_suffix);
else
key = name_without_suffix;
i = 0;
while (bindings[i].name &&
strcmp (key, bindings[i].name) != 0)
strcmp (name, bindings[i].name) != 0)
++i;
g_free (name_without_suffix);
g_free (name);
if (bindings[i].name)
return update_list_binding (&bindings[i], value, META_LIST_OF_GCONFVALUE_STRINGS);
return update_list_binding (&bindings[i], value, type_of_value);
else
return FALSE;
}
static gboolean
update_key_list_binding (const char *name,
GSList *value)
update_key_list_binding (const char *key,
GSList *value,
MetaStringListType type_of_value)
{
return find_and_update_list_binding (key_bindings, name, value);
return find_and_update_list_binding (key_bindings, key, value, type_of_value);
}
static gboolean
@ -2792,6 +2794,12 @@ meta_prefs_get_mouse_button_menu (void)
return resize_with_right_button ? 2: 3;
}
gboolean
meta_prefs_get_force_fullscreen (void)
{
return force_fullscreen;
}
void
meta_prefs_set_compositing_manager (gboolean whether)
{
@ -2823,6 +2831,7 @@ meta_prefs_get_clutter_plugins (void)
void
meta_prefs_set_clutter_plugins (GSList *list)
{
#ifdef HAVE_GCONF
GError *err = NULL;
gconf_client_set_list (default_client,
@ -2837,6 +2846,7 @@ meta_prefs_set_clutter_plugins (GSList *list)
err->message);
g_error_free (err);
}
#endif
}
void
@ -2957,3 +2967,10 @@ init_button_layout(void)
};
#endif
void
meta_prefs_set_force_fullscreen (gboolean whether)
{
force_fullscreen = whether;
}

View File

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

View File

@ -38,7 +38,6 @@
#include "stack.h"
#include "xprops.h"
#include "compositor.h"
#include "alttabhandlerdefault.h"
#include "mutter-marshal.h"
#include "mutter-enum-types.h"
@ -86,6 +85,7 @@ enum
WORKSPACE_REMOVED,
WORKSPACE_SWITCHED,
STARTUP_SEQUENCE_CHANGED,
WORKAREAS_CHANGED,
LAST_SIGNAL
};
@ -218,6 +218,15 @@ meta_screen_class_init (MetaScreenClass *klass)
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
screen_signals[WORKAREAS_CHANGED] =
g_signal_new ("workareas-changed",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (MetaScreenClass, workareas_changed),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
g_object_class_install_property (object_class,
PROP_N_WORKSPACES,
pspec);
@ -255,6 +264,13 @@ set_wm_check_hint (MetaScreen *screen)
return Success;
}
static void
unset_wm_check_hint (MetaScreen *screen)
{
XDeleteProperty (screen->display->xdisplay, screen->xroot,
screen->display->atom__NET_SUPPORTING_WM_CHECK);
}
static int
set_supported_hint (MetaScreen *screen)
{
@ -299,7 +315,7 @@ set_wm_icon_size_hint (MetaScreen *screen)
}
static void
reload_xinerama_infos (MetaScreen *screen)
reload_monitor_infos (MetaScreen *screen)
{
MetaDisplay *display;
@ -319,35 +335,35 @@ reload_xinerama_infos (MetaScreen *screen)
display = screen->display;
if (screen->xinerama_infos)
g_free (screen->xinerama_infos);
if (screen->monitor_infos)
g_free (screen->monitor_infos);
screen->xinerama_infos = NULL;
screen->n_xinerama_infos = 0;
screen->last_xinerama_index = 0;
screen->monitor_infos = NULL;
screen->n_monitor_infos = 0;
screen->last_monitor_index = 0;
screen->display->xinerama_cache_invalidated = TRUE;
screen->display->monitor_cache_invalidated = TRUE;
if (g_getenv ("MUTTER_DEBUG_XINERAMA"))
{
meta_topic (META_DEBUG_XINERAMA,
"Pretending a single monitor has two Xinerama screens\n");
screen->xinerama_infos = g_new (MetaXineramaScreenInfo, 2);
screen->n_xinerama_infos = 2;
screen->monitor_infos = g_new (MetaMonitorInfo, 2);
screen->n_monitor_infos = 2;
screen->xinerama_infos[0].number = 0;
screen->xinerama_infos[0].rect = screen->rect;
screen->xinerama_infos[0].rect.width = screen->rect.width / 2;
screen->monitor_infos[0].number = 0;
screen->monitor_infos[0].rect = screen->rect;
screen->monitor_infos[0].rect.width = screen->rect.width / 2;
screen->xinerama_infos[1].number = 1;
screen->xinerama_infos[1].rect = screen->rect;
screen->xinerama_infos[1].rect.x = screen->rect.width / 2;
screen->xinerama_infos[1].rect.width = screen->rect.width / 2;
screen->monitor_infos[1].number = 1;
screen->monitor_infos[1].rect = screen->rect;
screen->monitor_infos[1].rect.x = screen->rect.width / 2;
screen->monitor_infos[1].rect.width = screen->rect.width / 2;
}
#ifdef HAVE_XFREE_XINERAMA
if (screen->n_xinerama_infos == 0 &&
if (screen->n_monitor_infos == 0 &&
XineramaIsActive (display->xdisplay))
{
XineramaScreenInfo *infos;
@ -363,25 +379,25 @@ reload_xinerama_infos (MetaScreen *screen)
if (n_infos > 0)
{
screen->xinerama_infos = g_new (MetaXineramaScreenInfo, n_infos);
screen->n_xinerama_infos = n_infos;
screen->monitor_infos = g_new (MetaMonitorInfo, n_infos);
screen->n_monitor_infos = n_infos;
i = 0;
while (i < n_infos)
{
screen->xinerama_infos[i].number = infos[i].screen_number;
screen->xinerama_infos[i].rect.x = infos[i].x_org;
screen->xinerama_infos[i].rect.y = infos[i].y_org;
screen->xinerama_infos[i].rect.width = infos[i].width;
screen->xinerama_infos[i].rect.height = infos[i].height;
screen->monitor_infos[i].number = infos[i].screen_number;
screen->monitor_infos[i].rect.x = infos[i].x_org;
screen->monitor_infos[i].rect.y = infos[i].y_org;
screen->monitor_infos[i].rect.width = infos[i].width;
screen->monitor_infos[i].rect.height = infos[i].height;
meta_topic (META_DEBUG_XINERAMA,
"Xinerama %d is %d,%d %d x %d\n",
screen->xinerama_infos[i].number,
screen->xinerama_infos[i].rect.x,
screen->xinerama_infos[i].rect.y,
screen->xinerama_infos[i].rect.width,
screen->xinerama_infos[i].rect.height);
"Monitor %d is %d,%d %d x %d\n",
screen->monitor_infos[i].number,
screen->monitor_infos[i].rect.x,
screen->monitor_infos[i].rect.y,
screen->monitor_infos[i].rect.width,
screen->monitor_infos[i].rect.height);
++i;
}
@ -389,7 +405,7 @@ reload_xinerama_infos (MetaScreen *screen)
meta_XFree (infos);
}
else if (screen->n_xinerama_infos > 0)
else if (screen->n_monitor_infos > 0)
{
meta_topic (META_DEBUG_XINERAMA,
"No XFree86 Xinerama extension or XFree86 Xinerama inactive on display %s\n",
@ -402,7 +418,7 @@ reload_xinerama_infos (MetaScreen *screen)
#ifdef HAVE_SOLARIS_XINERAMA
/* This code from GDK, Copyright (C) 2002 Sun Microsystems */
if (screen->n_xinerama_infos == 0 &&
if (screen->n_monitor_infos == 0 &&
XineramaGetState (screen->display->xdisplay,
screen->number))
{
@ -424,31 +440,31 @@ reload_xinerama_infos (MetaScreen *screen)
{
g_assert (n_monitors > 0);
screen->xinerama_infos = g_new (MetaXineramaScreenInfo, n_monitors);
screen->n_xinerama_infos = n_monitors;
screen->monitor_infos = g_new (MetaMonitorInfo, n_monitors);
screen->n_monitor_infos = n_monitors;
i = 0;
while (i < n_monitors)
{
screen->xinerama_infos[i].number = i;
screen->xinerama_infos[i].rect.x = monitors[i].x;
screen->xinerama_infos[i].rect.y = monitors[i].y;
screen->xinerama_infos[i].rect.width = monitors[i].width;
screen->xinerama_infos[i].rect.height = monitors[i].height;
screen->monitor_infos[i].number = i;
screen->monitor_infos[i].rect.x = monitors[i].x;
screen->monitor_infos[i].rect.y = monitors[i].y;
screen->monitor_infos[i].rect.width = monitors[i].width;
screen->monitor_infos[i].rect.height = monitors[i].height;
meta_topic (META_DEBUG_XINERAMA,
"Xinerama %d is %d,%d %d x %d\n",
screen->xinerama_infos[i].number,
screen->xinerama_infos[i].rect.x,
screen->xinerama_infos[i].rect.y,
screen->xinerama_infos[i].rect.width,
screen->xinerama_infos[i].rect.height);
"Monitor %d is %d,%d %d x %d\n",
screen->monitor_infos[i].number,
screen->monitor_infos[i].rect.x,
screen->monitor_infos[i].rect.y,
screen->monitor_infos[i].rect.width,
screen->monitor_infos[i].rect.height);
++i;
}
}
}
else if (screen->n_xinerama_infos == 0)
else if (screen->n_monitor_infos == 0)
{
meta_topic (META_DEBUG_XINERAMA,
"No Solaris Xinerama extension or Solaris Xinerama inactive on display %s\n",
@ -463,20 +479,20 @@ reload_xinerama_infos (MetaScreen *screen)
/* If no Xinerama, fill in the single screen info so
* we can use the field unconditionally
*/
if (screen->n_xinerama_infos == 0)
if (screen->n_monitor_infos == 0)
{
meta_topic (META_DEBUG_XINERAMA,
"No Xinerama screens, using default screen info\n");
screen->xinerama_infos = g_new (MetaXineramaScreenInfo, 1);
screen->n_xinerama_infos = 1;
screen->monitor_infos = g_new (MetaMonitorInfo, 1);
screen->n_monitor_infos = 1;
screen->xinerama_infos[0].number = 0;
screen->xinerama_infos[0].rect = screen->rect;
screen->monitor_infos[0].number = 0;
screen->monitor_infos[0].rect = screen->rect;
}
g_assert (screen->n_xinerama_infos > 0);
g_assert (screen->xinerama_infos != NULL);
g_assert (screen->n_monitor_infos > 0);
g_assert (screen->monitor_infos != NULL);
}
/* The guard window allows us to leave minimized windows mapped so
@ -687,7 +703,7 @@ meta_screen_new (MetaDisplay *display,
screen->wm_cm_selection_window = meta_create_offscreen_window (xdisplay,
xroot,
NoEventMask);
screen->work_area_idle = 0;
screen->work_area_later = 0;
screen->active_workspace = NULL;
screen->workspaces = NULL;
@ -698,40 +714,11 @@ meta_screen_new (MetaDisplay *display,
screen->compositor_data = NULL;
screen->guard_window = None;
{
XFontStruct *font_info;
XGCValues gc_values;
gulong value_mask = 0;
gc_values.subwindow_mode = IncludeInferiors;
value_mask |= GCSubwindowMode;
gc_values.function = GXinvert;
value_mask |= GCFunction;
gc_values.line_width = META_WIREFRAME_XOR_LINE_WIDTH;
value_mask |= GCLineWidth;
font_info = XLoadQueryFont (screen->display->xdisplay, "fixed");
if (font_info != NULL)
{
gc_values.font = font_info->fid;
value_mask |= GCFont;
XFreeFontInfo (NULL, font_info, 1);
}
else
meta_warning ("xserver doesn't have 'fixed' font.\n");
screen->root_xor_gc = XCreateGC (screen->display->xdisplay,
screen->xroot,
value_mask,
&gc_values);
}
screen->monitor_infos = NULL;
screen->n_monitor_infos = 0;
screen->last_monitor_index = 0;
screen->xinerama_infos = NULL;
screen->n_xinerama_infos = 0;
screen->last_xinerama_index = 0;
reload_xinerama_infos (screen);
reload_monitor_infos (screen);
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
@ -781,9 +768,9 @@ meta_screen_new (MetaDisplay *display,
screen->ui = meta_ui_new (screen->display->xdisplay,
screen->xscreen);
screen->tab_handler = NULL;
screen->tab_popup = NULL;
screen->ws_popup = NULL;
screen->stack = meta_stack_new (screen);
screen->stack_tracker = meta_stack_tracker_new (screen);
@ -822,7 +809,6 @@ meta_screen_free (MetaScreen *screen,
guint32 timestamp)
{
MetaDisplay *display;
XGCValues gc_values = { 0 };
display = screen->display;
@ -871,27 +857,16 @@ meta_screen_free (MetaScreen *screen,
meta_warning (_("Could not release screen %d on display \"%s\"\n"),
screen->number, screen->display->name);
unset_wm_check_hint (screen);
XDestroyWindow (screen->display->xdisplay,
screen->wm_sn_selection_window);
if (screen->work_area_idle != 0)
g_source_remove (screen->work_area_idle);
if (screen->work_area_later != 0)
g_source_remove (screen->work_area_later);
if (XGetGCValues (screen->display->xdisplay,
screen->root_xor_gc,
GCFont,
&gc_values))
{
XUnloadFont (screen->display->xdisplay,
gc_values.font);
}
XFreeGC (screen->display->xdisplay,
screen->root_xor_gc);
if (screen->xinerama_infos)
g_free (screen->xinerama_infos);
if (screen->monitor_infos)
g_free (screen->monitor_infos);
g_free (screen->screen_name);
@ -1516,58 +1491,146 @@ meta_screen_tab_popup_create (MetaScreen *screen,
MetaTabShowType show_type,
MetaWindow *initial_selection)
{
MetaTabEntry *entries;
GList *tab_list;
GList *tmp;
int len;
int i;
g_return_if_fail (screen->tab_handler == NULL);
screen->tab_handler = meta_alt_tab_handler_new (screen,
show_type == META_TAB_SHOW_INSTANTLY);
if (screen->tab_popup)
return;
tab_list = meta_display_get_tab_list (screen->display,
list_type,
screen,
screen->active_workspace);
for (tmp = tab_list; tmp; tmp = tmp->next)
meta_alt_tab_handler_add_window (screen->tab_handler, tmp->data);
meta_alt_tab_handler_show (screen->tab_handler, initial_selection);
len = g_list_length (tab_list);
entries = g_new (MetaTabEntry, len + 1);
entries[len].key = NULL;
entries[len].title = NULL;
entries[len].icon = NULL;
i = 0;
tmp = tab_list;
while (i < len)
{
MetaWindow *window;
MetaRectangle r;
window = tmp->data;
entries[i].key = (MetaTabEntryKey) window;
entries[i].title = window->title;
entries[i].icon = g_object_ref (window->icon);
entries[i].blank = FALSE;
entries[i].hidden = !meta_window_showing_on_its_workspace (window);
entries[i].demands_attention = window->wm_state_demands_attention;
if (show_type == META_TAB_SHOW_INSTANTLY ||
!entries[i].hidden ||
!meta_window_get_icon_geometry (window, &r))
meta_window_get_outer_rect (window, &r);
entries[i].rect = r;
/* Find inside of highlight rectangle to be used when window is
* outlined for tabbing. This should be the size of the
* east/west frame, and the size of the south frame, on those
* sides. On the top it should be the size of the south frame
* edge.
*/
#define OUTLINE_WIDTH 5
/* Top side */
if (!entries[i].hidden &&
window->frame && window->frame->bottom_height > 0 &&
window->frame->child_y >= window->frame->bottom_height)
entries[i].inner_rect.y = window->frame->bottom_height;
else
entries[i].inner_rect.y = OUTLINE_WIDTH;
/* Bottom side */
if (!entries[i].hidden &&
window->frame && window->frame->bottom_height != 0)
entries[i].inner_rect.height = r.height
- entries[i].inner_rect.y - window->frame->bottom_height;
else
entries[i].inner_rect.height = r.height
- entries[i].inner_rect.y - OUTLINE_WIDTH;
/* Left side */
if (!entries[i].hidden && window->frame && window->frame->child_x != 0)
entries[i].inner_rect.x = window->frame->child_x;
else
entries[i].inner_rect.x = OUTLINE_WIDTH;
/* Right side */
if (!entries[i].hidden &&
window->frame && window->frame->right_width != 0)
entries[i].inner_rect.width = r.width
- entries[i].inner_rect.x - window->frame->right_width;
else
entries[i].inner_rect.width = r.width
- entries[i].inner_rect.x - OUTLINE_WIDTH;
++i;
tmp = tmp->next;
}
if (!meta_prefs_get_no_tab_popup ())
screen->tab_popup = meta_ui_tab_popup_new (entries,
screen->number,
len,
5, /* FIXME */
TRUE);
for (i = 0; i < len; i++)
g_object_unref (entries[i].icon);
g_free (entries);
g_list_free (tab_list);
meta_ui_tab_popup_select (screen->tab_popup,
(MetaTabEntryKey) initial_selection);
if (show_type != META_TAB_SHOW_INSTANTLY)
meta_ui_tab_popup_set_showing (screen->tab_popup, TRUE);
}
void
meta_screen_tab_popup_forward (MetaScreen *screen)
{
g_return_if_fail (screen->tab_handler != NULL);
g_return_if_fail (screen->tab_popup != NULL);
meta_alt_tab_handler_forward (screen->tab_handler);
meta_ui_tab_popup_forward (screen->tab_popup);
}
void
meta_screen_tab_popup_backward (MetaScreen *screen)
{
g_return_if_fail (screen->tab_handler != NULL);
g_return_if_fail (screen->tab_popup != NULL);
meta_alt_tab_handler_backward (screen->tab_handler);
meta_ui_tab_popup_backward (screen->tab_popup);
}
MetaWindow *
meta_screen_tab_popup_get_selected (MetaScreen *screen)
{
g_return_val_if_fail (screen->tab_handler != NULL, NULL);
g_return_val_if_fail (screen->tab_popup != NULL, NULL);
return meta_alt_tab_handler_get_selected (screen->tab_handler);
return (MetaWindow *) meta_ui_tab_popup_get_selected (screen->tab_popup);
}
void
meta_screen_tab_popup_destroy (MetaScreen *screen)
{
if (!screen->tab_handler)
return;
meta_alt_tab_handler_destroy (screen->tab_handler);
g_object_unref (screen->tab_handler);
screen->tab_handler = NULL;
if (screen->tab_popup)
{
meta_ui_tab_popup_free (screen->tab_popup);
screen->tab_popup = NULL;
}
}
void
@ -1580,8 +1643,9 @@ meta_screen_workspace_popup_create (MetaScreen *screen,
MetaWorkspaceLayout layout;
int n_workspaces;
int current_workspace;
g_return_if_fail (screen->ws_popup == NULL);
if (screen->ws_popup || meta_prefs_get_no_tab_popup ())
return;
current_workspace = meta_workspace_index (screen->active_workspace);
n_workspaces = meta_screen_get_n_workspaces (screen);
@ -1703,61 +1767,61 @@ meta_screen_get_mouse_window (MetaScreen *screen,
return window;
}
const MetaXineramaScreenInfo*
meta_screen_get_xinerama_for_rect (MetaScreen *screen,
MetaRectangle *rect)
const MetaMonitorInfo*
meta_screen_get_monitor_for_rect (MetaScreen *screen,
MetaRectangle *rect)
{
int i;
int best_xinerama, xinerama_score;
int best_monitor, monitor_score;
if (screen->n_xinerama_infos == 1)
return &screen->xinerama_infos[0];
if (screen->n_monitor_infos == 1)
return &screen->monitor_infos[0];
best_xinerama = 0;
xinerama_score = 0;
best_monitor = 0;
monitor_score = 0;
for (i = 0; i < screen->n_xinerama_infos; i++)
for (i = 0; i < screen->n_monitor_infos; i++)
{
MetaRectangle dest;
if (meta_rectangle_intersect (&screen->xinerama_infos[i].rect,
if (meta_rectangle_intersect (&screen->monitor_infos[i].rect,
rect,
&dest))
{
int cur = meta_rectangle_area (&dest);
if (cur > xinerama_score)
if (cur > monitor_score)
{
xinerama_score = cur;
best_xinerama = i;
monitor_score = cur;
best_monitor = i;
}
}
}
return &screen->xinerama_infos[best_xinerama];
return &screen->monitor_infos[best_monitor];
}
const MetaXineramaScreenInfo*
meta_screen_get_xinerama_for_window (MetaScreen *screen,
MetaWindow *window)
const MetaMonitorInfo*
meta_screen_get_monitor_for_window (MetaScreen *screen,
MetaWindow *window)
{
MetaRectangle window_rect;
meta_window_get_outer_rect (window, &window_rect);
return meta_screen_get_xinerama_for_rect (screen, &window_rect);
return meta_screen_get_monitor_for_rect (screen, &window_rect);
}
const MetaXineramaScreenInfo*
meta_screen_get_xinerama_neighbor (MetaScreen *screen,
int which_xinerama,
MetaScreenDirection direction)
const MetaMonitorInfo*
meta_screen_get_monitor_neighbor (MetaScreen *screen,
int which_monitor,
MetaScreenDirection direction)
{
MetaXineramaScreenInfo* input = screen->xinerama_infos + which_xinerama;
MetaXineramaScreenInfo* current;
MetaMonitorInfo* input = screen->monitor_infos + which_monitor;
MetaMonitorInfo* current;
int i;
for (i = 0; i < screen->n_xinerama_infos; i++)
for (i = 0; i < screen->n_monitor_infos; i++)
{
current = screen->xinerama_infos + i;
current = screen->monitor_infos + i;
if ((direction == META_SCREEN_RIGHT &&
current->rect.x == input->rect.x + input->rect.width &&
@ -1780,110 +1844,110 @@ meta_screen_get_xinerama_neighbor (MetaScreen *screen,
}
void
meta_screen_get_natural_xinerama_list (MetaScreen *screen,
int** xineramas_list,
int* n_xineramas)
meta_screen_get_natural_monitor_list (MetaScreen *screen,
int** monitors_list,
int* n_monitors)
{
const MetaXineramaScreenInfo* current;
const MetaXineramaScreenInfo* tmp;
GQueue* xinerama_queue;
const MetaMonitorInfo* current;
const MetaMonitorInfo* tmp;
GQueue* monitor_queue;
int* visited;
int cur = 0;
int i;
*n_xineramas = screen->n_xinerama_infos;
*xineramas_list = g_new (int, screen->n_xinerama_infos);
*n_monitors = screen->n_monitor_infos;
*monitors_list = g_new (int, screen->n_monitor_infos);
/* we calculate a natural ordering by which to choose xineramas for
* window placement. We start at the current xinerama, and perform
* a breadth-first search of the xineramas starting from that
* xinerama. We choose preferentially left, then right, then down,
/* we calculate a natural ordering by which to choose monitors for
* window placement. We start at the current monitor, and perform
* a breadth-first search of the monitors starting from that
* monitor. We choose preferentially left, then right, then down,
* then up. The visitation order produced by this traversal is the
* natural xinerama ordering.
* natural monitor ordering.
*/
visited = g_new (int, screen->n_xinerama_infos);
for (i = 0; i < screen->n_xinerama_infos; i++)
visited = g_new (int, screen->n_monitor_infos);
for (i = 0; i < screen->n_monitor_infos; i++)
{
visited[i] = FALSE;
}
current = meta_screen_get_current_xinerama (screen);
xinerama_queue = g_queue_new ();
g_queue_push_tail (xinerama_queue, (gpointer) current);
current = meta_screen_get_current_monitor (screen);
monitor_queue = g_queue_new ();
g_queue_push_tail (monitor_queue, (gpointer) current);
visited[current->number] = TRUE;
while (!g_queue_is_empty (xinerama_queue))
while (!g_queue_is_empty (monitor_queue))
{
current = (const MetaXineramaScreenInfo*)
g_queue_pop_head (xinerama_queue);
current = (const MetaMonitorInfo*)
g_queue_pop_head (monitor_queue);
(*xineramas_list)[cur++] = current->number;
(*monitors_list)[cur++] = current->number;
/* enqueue each of the directions */
tmp = meta_screen_get_xinerama_neighbor (screen,
current->number,
META_SCREEN_LEFT);
tmp = meta_screen_get_monitor_neighbor (screen,
current->number,
META_SCREEN_LEFT);
if (tmp && !visited[tmp->number])
{
g_queue_push_tail (xinerama_queue,
(MetaXineramaScreenInfo*) tmp);
g_queue_push_tail (monitor_queue,
(MetaMonitorInfo*) tmp);
visited[tmp->number] = TRUE;
}
tmp = meta_screen_get_xinerama_neighbor (screen,
current->number,
META_SCREEN_RIGHT);
tmp = meta_screen_get_monitor_neighbor (screen,
current->number,
META_SCREEN_RIGHT);
if (tmp && !visited[tmp->number])
{
g_queue_push_tail (xinerama_queue,
(MetaXineramaScreenInfo*) tmp);
g_queue_push_tail (monitor_queue,
(MetaMonitorInfo*) tmp);
visited[tmp->number] = TRUE;
}
tmp = meta_screen_get_xinerama_neighbor (screen,
current->number,
META_SCREEN_UP);
tmp = meta_screen_get_monitor_neighbor (screen,
current->number,
META_SCREEN_UP);
if (tmp && !visited[tmp->number])
{
g_queue_push_tail (xinerama_queue,
(MetaXineramaScreenInfo*) tmp);
g_queue_push_tail (monitor_queue,
(MetaMonitorInfo*) tmp);
visited[tmp->number] = TRUE;
}
tmp = meta_screen_get_xinerama_neighbor (screen,
current->number,
META_SCREEN_DOWN);
tmp = meta_screen_get_monitor_neighbor (screen,
current->number,
META_SCREEN_DOWN);
if (tmp && !visited[tmp->number])
{
g_queue_push_tail (xinerama_queue,
(MetaXineramaScreenInfo*) tmp);
g_queue_push_tail (monitor_queue,
(MetaMonitorInfo*) tmp);
visited[tmp->number] = TRUE;
}
}
/* in case we somehow missed some set of xineramas, go through the
* visited list and add in any xineramas that were missed
/* in case we somehow missed some set of monitors, go through the
* visited list and add in any monitors that were missed
*/
for (i = 0; i < screen->n_xinerama_infos; i++)
for (i = 0; i < screen->n_monitor_infos; i++)
{
if (visited[i] == FALSE)
{
(*xineramas_list)[cur++] = i;
(*monitors_list)[cur++] = i;
}
}
g_free (visited);
g_queue_free (xinerama_queue);
g_queue_free (monitor_queue);
}
const MetaXineramaScreenInfo*
meta_screen_get_current_xinerama (MetaScreen *screen)
const MetaMonitorInfo*
meta_screen_get_current_monitor (MetaScreen *screen)
{
if (screen->n_xinerama_infos == 1)
return &screen->xinerama_infos[0];
if (screen->n_monitor_infos == 1)
return &screen->monitor_infos[0];
/* Sadly, we have to do it this way. Yuck.
*/
if (screen->display->xinerama_cache_invalidated)
if (screen->display->monitor_cache_invalidated)
{
Window root_return, child_return;
int win_x_return, win_y_return;
@ -1891,7 +1955,7 @@ meta_screen_get_current_xinerama (MetaScreen *screen)
int i;
MetaRectangle pointer_position;
screen->display->xinerama_cache_invalidated = FALSE;
screen->display->monitor_cache_invalidated = FALSE;
pointer_position.width = pointer_position.height = 1;
XQueryPointer (screen->display->xdisplay,
@ -1904,23 +1968,59 @@ meta_screen_get_current_xinerama (MetaScreen *screen)
&win_y_return,
&mask_return);
screen->last_xinerama_index = 0;
for (i = 0; i < screen->n_xinerama_infos; i++)
screen->last_monitor_index = 0;
for (i = 0; i < screen->n_monitor_infos; i++)
{
if (meta_rectangle_contains_rect (&screen->xinerama_infos[i].rect,
if (meta_rectangle_contains_rect (&screen->monitor_infos[i].rect,
&pointer_position))
{
screen->last_xinerama_index = i;
screen->last_monitor_index = i;
break;
}
}
meta_topic (META_DEBUG_XINERAMA,
"Rechecked current Xinerama, now %d\n",
screen->last_xinerama_index);
"Rechecked current monitor, now %d\n",
screen->last_monitor_index);
}
return &screen->xinerama_infos[screen->last_xinerama_index];
return &screen->monitor_infos[screen->last_monitor_index];
}
/**
* meta_screen_get_n_monitors:
* @screen: a #MetaScreen
*
* Gets the number of monitors that are joined together to form @screen.
*
* Return value: the number of monitors
*/
int
meta_screen_get_n_monitors (MetaScreen *screen)
{
g_return_val_if_fail (META_IS_SCREEN (screen), 0);
return screen->n_monitor_infos;
}
/**
* meta_screen_get_monitor_geometry:
* @screen: a #MetaScreen
* @monitor: the monitor number
* @geometry: (out): location to store the monitor geometry
*
* Stores the location and size of the indicated monitor in @geometry.
*/
void
meta_screen_get_monitor_geometry (MetaScreen *screen,
int monitor,
MetaRectangle *geometry)
{
g_return_if_fail (META_IS_SCREEN (screen));
g_return_if_fail (monitor >= 0 && monitor < screen->n_monitor_infos);
g_return_if_fail (geometry != NULL);
*geometry = screen->monitor_infos[monitor].rect;
}
#define _NET_WM_ORIENTATION_HORZ 0
@ -2145,7 +2245,7 @@ set_work_area_hint (MetaScreen *screen)
if (workspace->screen == screen)
{
meta_workspace_get_work_area_all_xineramas (workspace, &area);
meta_workspace_get_work_area_all_monitors (workspace, &area);
tmp[0] = area.x;
tmp[1] = area.y;
tmp[2] = area.width;
@ -2164,15 +2264,17 @@ set_work_area_hint (MetaScreen *screen)
(guchar*) data, num_workspaces*4);
g_free (data);
meta_error_trap_pop (screen->display, FALSE);
g_signal_emit (screen, screen_signals[WORKAREAS_CHANGED], 0);
}
static gboolean
set_work_area_idle_func (MetaScreen *screen)
set_work_area_later_func (MetaScreen *screen)
{
meta_topic (META_DEBUG_WORKAREA,
"Running work area idle function\n");
"Running work area hint computation function\n");
screen->work_area_idle = 0;
screen->work_area_later = 0;
set_work_area_hint (screen);
@ -2182,16 +2284,16 @@ set_work_area_idle_func (MetaScreen *screen)
void
meta_screen_queue_workarea_recalc (MetaScreen *screen)
{
/* Recompute work area in an idle */
if (screen->work_area_idle == 0)
/* Recompute work area later before redrawing */
if (screen->work_area_later == 0)
{
meta_topic (META_DEBUG_WORKAREA,
"Adding work area hint idle function\n");
screen->work_area_idle =
g_idle_add_full (META_PRIORITY_BEFORE_REDRAW,
(GSourceFunc) set_work_area_idle_func,
screen,
NULL);
"Adding work area hint computation function\n");
screen->work_area_later =
meta_later_add (META_LATER_BEFORE_REDRAW,
(GSourceFunc) set_work_area_later_func,
screen,
NULL);
}
}
@ -2513,7 +2615,7 @@ meta_screen_resize (MetaScreen *screen,
screen->rect.width = width;
screen->rect.height = height;
reload_xinerama_infos (screen);
reload_monitor_infos (screen);
set_desktop_geometry_hint (screen);
if (screen->display->compositor)
@ -3043,11 +3145,14 @@ meta_screen_set_cm_selection (MetaScreen *screen)
char selection[32];
Atom a;
screen->wm_cm_timestamp = meta_display_get_current_time_roundtrip (
screen->display);
g_snprintf (selection, sizeof(selection), "_NET_WM_CM_S%d", screen->number);
meta_verbose ("Setting selection: %s\n", selection);
a = XInternAtom (screen->display->xdisplay, selection, FALSE);
XSetSelectionOwner (screen->display->xdisplay, a,
screen->wm_cm_selection_window, CurrentTime);
screen->wm_cm_selection_window, screen->wm_cm_timestamp);
}
void
@ -3058,7 +3163,8 @@ meta_screen_unset_cm_selection (MetaScreen *screen)
g_snprintf (selection, sizeof(selection), "_NET_WM_CM_S%d", screen->number);
a = XInternAtom (screen->display->xdisplay, selection, FALSE);
XSetSelectionOwner (screen->display->xdisplay, a, None, CurrentTime);
XSetSelectionOwner (screen->display->xdisplay, a,
None, screen->wm_cm_timestamp);
}
GList *
@ -3078,6 +3184,11 @@ meta_screen_get_active_workspace_index (MetaScreen *screen)
return meta_workspace_index (active);
}
/**
* meta_screen_get_active_workspace:
*
* Returns: (transfer none): The current workspace
*/
MetaWorkspace *
meta_screen_get_active_workspace (MetaScreen *screen)
{

View File

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

View File

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

View File

@ -224,14 +224,14 @@ is_focused_foreach (MetaWindow *window,
}
static gboolean
windows_on_different_xinerama (MetaWindow *a,
MetaWindow *b)
windows_on_different_monitor (MetaWindow *a,
MetaWindow *b)
{
if (a->screen != b->screen)
return TRUE;
return meta_screen_get_xinerama_for_window (a->screen, a) !=
meta_screen_get_xinerama_for_window (b->screen, b);
return meta_screen_get_monitor_for_window (a->screen, a) !=
meta_screen_get_monitor_for_window (b->screen, b);
}
/* Get layer ignoring any transient or group relationships */
@ -275,8 +275,8 @@ get_standalone_layer (MetaWindow *window)
window == window->display->expected_focus_window ||
window->display->expected_focus_window == NULL ||
(window->display->expected_focus_window != NULL &&
windows_on_different_xinerama (window,
window->display->expected_focus_window))))
windows_on_different_monitor (window,
window->display->expected_focus_window))))
layer = META_LAYER_FULLSCREEN;
else if (window->wm_state_above)
layer = META_LAYER_TOP;

View File

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

View File

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

View File

@ -130,6 +130,12 @@ struct _MetaWindow
/* Whether we're fullscreen */
guint fullscreen : 1;
/* Whether the urgent flag of WM_HINTS is set */
guint wm_hints_urgent : 1;
/* Whether we have to fullscreen after placement */
guint fullscreen_after_placement : 1;
/* Area to cover when in fullscreen mode. If _NET_WM_FULLSCREEN_MONITORS has
* been overridden (via a client message), the window will cover the union of
* these monitors. If not, this is the single monitor which the window's
@ -139,8 +145,8 @@ struct _MetaWindow
/* Whether we're trying to constrain the window to be fully onscreen */
guint require_fully_onscreen : 1;
/* Whether we're trying to constrain the window to be on a single xinerama */
guint require_on_single_xinerama : 1;
/* Whether we're trying to constrain the window to be on a single monitor */
guint require_on_single_monitor : 1;
/* Whether we're trying to constrain the window's titlebar to be onscreen */
guint require_titlebar_visible : 1;
@ -246,6 +252,9 @@ struct _MetaWindow
/* Have we placed this window? */
guint placed : 1;
/* Must we force_save_user_window_placement? */
guint force_save_user_rect : 1;
/* Is this not a transient of the focus window which is being denied focus? */
guint denied_focus_and_not_transient : 1;
@ -316,6 +325,9 @@ struct _MetaWindow
*/
int unmaps_pending;
/* See docs for meta_window_get_stable_sequence() */
guint32 stable_sequence;
/* set to the most recent user-interaction event timestamp that we
know about for this window */
guint32 net_wm_user_time;
@ -377,6 +389,7 @@ struct _MetaWindowClass
void (*workspace_changed) (MetaWindow *window, int old_workspace);
void (*focus) (MetaWindow *window);
void (*raised) (MetaWindow *window);
void (*unmanaged) (MetaWindow *window);
};
/* These differ from window->has_foo_func in that they consider
@ -544,13 +557,13 @@ GList* meta_window_get_workspaces (MetaWindow *window);
gboolean meta_window_located_on_workspace (MetaWindow *window,
MetaWorkspace *workspace);
void meta_window_get_work_area_current_xinerama (MetaWindow *window,
MetaRectangle *area);
void meta_window_get_work_area_for_xinerama (MetaWindow *window,
int which_xinerama,
MetaRectangle *area);
void meta_window_get_work_area_all_xineramas (MetaWindow *window,
MetaRectangle *area);
void meta_window_get_work_area_current_monitor (MetaWindow *window,
MetaRectangle *area);
void meta_window_get_work_area_for_monitor (MetaWindow *window,
int which_monitor,
MetaRectangle *area);
void meta_window_get_work_area_all_monitors (MetaWindow *window,
MetaRectangle *area);
gboolean meta_window_same_application (MetaWindow *window,

View File

@ -604,6 +604,7 @@ reload_net_wm_state (MetaWindow *window,
window->shaded = FALSE;
window->maximized_horizontally = FALSE;
window->maximized_vertically = FALSE;
window->fullscreen = FALSE;
window->wm_state_modal = FALSE;
window->wm_state_skip_taskbar = FALSE;
window->wm_state_skip_pager = FALSE;
@ -632,13 +633,7 @@ reload_net_wm_state (MetaWindow *window,
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_SKIP_PAGER)
window->wm_state_skip_pager = TRUE;
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_FULLSCREEN)
{
if (!window->fullscreen)
{
window->fullscreen = TRUE;
g_object_notify (G_OBJECT (window), "fullscreen");
}
}
window->fullscreen_after_placement = TRUE;
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_ABOVE)
window->wm_state_above = TRUE;
else if (value->v.atom_list.atoms[i] == window->display->atom__NET_WM_STATE_BELOW)
@ -1350,8 +1345,10 @@ reload_wm_hints (MetaWindow *window,
gboolean initial)
{
Window old_group_leader;
gboolean old_urgent;
old_group_leader = window->xgroup_leader;
old_urgent = window->wm_hints_urgent;
/* Fill in defaults */
window->input = TRUE;
@ -1359,7 +1356,8 @@ reload_wm_hints (MetaWindow *window,
window->xgroup_leader = None;
window->wm_hints_pixmap = None;
window->wm_hints_mask = None;
window->wm_hints_urgent = FALSE;
if (value->type != META_PROP_VALUE_INVALID)
{
const XWMHints *hints = value->v.wm_hints;
@ -1378,7 +1376,10 @@ reload_wm_hints (MetaWindow *window,
if (hints->flags & IconMaskHint)
window->wm_hints_mask = hints->icon_mask;
if (hints->flags & XUrgencyHint)
window->wm_hints_urgent = TRUE;
meta_verbose ("Read WM_HINTS input: %d iconic: %d group leader: 0x%lx pixmap: 0x%lx mask: 0x%lx\n",
window->input, window->initially_iconic,
window->xgroup_leader,
@ -1394,6 +1395,21 @@ reload_wm_hints (MetaWindow *window,
meta_window_group_leader_changed (window);
}
/*
* Do not emit urgency notification on the inital property load
*/
if (!initial && (window->wm_hints_urgent != old_urgent))
g_object_notify (G_OBJECT (window), "urgent");
/*
* Do not emit signal for the initial property load, let the constructor to
* take care of it once the MetaWindow is fully constructed.
*
* Only emit if the property is both changed and set.
*/
if (!initial && window->wm_hints_urgent && !old_urgent)
g_signal_emit_by_name (window->display, "window-marked-urgent", window);
meta_icon_cache_property_changed (&window->icon_cache,
window->display,
XA_WM_HINTS);

View File

@ -45,6 +45,7 @@
#include "mutter-enum-types.h"
#include <X11/Xatom.h>
#include <X11/Xlibint.h> /* For display->resource_mask */
#include <string.h>
#ifdef HAVE_SHAPE
@ -72,6 +73,9 @@ static gboolean process_property_notify (MetaWindow *window,
static void meta_window_show (MetaWindow *window);
static void meta_window_hide (MetaWindow *window);
static gboolean meta_window_same_client (MetaWindow *window,
MetaWindow *other_window);
static void meta_window_save_rect (MetaWindow *window);
static void save_user_window_placement (MetaWindow *window);
static void force_save_user_window_placement (MetaWindow *window);
@ -116,8 +120,9 @@ static void meta_window_apply_session_info (MetaWindow *window,
static void unmaximize_window_before_freeing (MetaWindow *window);
static void unminimize_window_and_all_transient_parents (MetaWindow *window);
/* Idle handlers for the three queues. The "data" parameter in each case
* will be a GINT_TO_POINTER of the index into the queue arrays to use.
/* Idle handlers for the three queues (run with meta_later_add()). The
* "data" parameter in each case will be a GINT_TO_POINTER of the
* index into the queue arrays to use.
*
* TODO: Possibly there is still some code duplication among these, which we
* need to sort out at some point.
@ -136,7 +141,12 @@ enum {
PROP_MINI_ICON,
PROP_DECORATED,
PROP_FULLSCREEN,
PROP_WINDOW_TYPE
PROP_MAXIMIZED_HORIZONTALLY,
PROP_MAXIMIZED_VERTICALLY,
PROP_WINDOW_TYPE,
PROP_USER_TIME,
PROP_DEMANDS_ATTENTION,
PROP_URGENT
};
enum
@ -144,6 +154,7 @@ enum
WORKSPACE_CHANGED,
FOCUS,
RAISED,
UNMANAGED,
LAST_SIGNAL
};
@ -199,9 +210,24 @@ meta_window_get_property(GObject *object,
case PROP_FULLSCREEN:
g_value_set_boolean (value, win->fullscreen);
break;
case PROP_MAXIMIZED_HORIZONTALLY:
g_value_set_boolean (value, win->maximized_horizontally);
break;
case PROP_MAXIMIZED_VERTICALLY:
g_value_set_boolean (value, win->maximized_vertically);
break;
case PROP_WINDOW_TYPE:
g_value_set_enum (value, win->type);
break;
case PROP_USER_TIME:
g_value_set_uint (value, win->net_wm_user_time);
break;
case PROP_DEMANDS_ATTENTION:
g_value_set_boolean (value, win->wm_state_demands_attention);
break;
case PROP_URGENT:
g_value_set_boolean (value, win->wm_hints_urgent);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@ -259,7 +285,7 @@ meta_window_class_init (MetaWindowClass *klass)
PROP_DECORATED,
g_param_spec_boolean ("decorated",
"Decorated",
"Whether windos is decorated",
"Whether window is decorated",
TRUE,
G_PARAM_READABLE));
@ -267,7 +293,23 @@ meta_window_class_init (MetaWindowClass *klass)
PROP_FULLSCREEN,
g_param_spec_boolean ("fullscreen",
"Fullscreen",
"Whether windos is fullscreened",
"Whether window is fullscreened",
FALSE,
G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_MAXIMIZED_HORIZONTALLY,
g_param_spec_boolean ("maximized-horizontally",
"Maximized horizontally",
"Whether window is maximized horizontally",
FALSE,
G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_MAXIMIZED_VERTICALLY,
g_param_spec_boolean ("maximized-vertically",
"Maximizing vertically",
"Whether window is maximized vertically",
FALSE,
G_PARAM_READABLE));
@ -280,6 +322,32 @@ meta_window_class_init (MetaWindowClass *klass)
META_WINDOW_NORMAL,
G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_USER_TIME,
g_param_spec_uint ("user-time",
"User time",
"Timestamp of last user interaction",
0,
G_MAXUINT,
0,
G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_DEMANDS_ATTENTION,
g_param_spec_boolean ("demands-attention",
"Demands Attention",
"Whether the window has _NET_WM_STATE_DEMANDS_ATTENTION set",
FALSE,
G_PARAM_READABLE));
g_object_class_install_property (object_class,
PROP_URGENT,
g_param_spec_boolean ("urgent",
"Urgent",
"Whether the urgent flag of WM_HINTS is set",
FALSE,
G_PARAM_READABLE));
window_signals[WORKSPACE_CHANGED] =
g_signal_new ("workspace-changed",
G_TYPE_FROM_CLASS (object_class),
@ -307,6 +375,15 @@ meta_window_class_init (MetaWindowClass *klass)
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
window_signals[UNMANAGED] =
g_signal_new ("unmanaged",
G_TYPE_FROM_CLASS (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (MetaWindowClass, unmanaged),
NULL, NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE, 0);
}
static void
@ -663,6 +740,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
meta_icon_cache_init (&window->icon_cache);
window->wm_hints_pixmap = None;
window->wm_hints_mask = None;
window->wm_hints_urgent = FALSE;
window->frame = NULL;
window->has_focus = FALSE;
@ -673,9 +751,10 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->maximize_vertically_after_placement = FALSE;
window->minimize_after_placement = FALSE;
window->fullscreen = FALSE;
window->fullscreen_after_placement = FALSE;
window->fullscreen_monitors[0] = -1;
window->require_fully_onscreen = TRUE;
window->require_on_single_xinerama = TRUE;
window->require_on_single_monitor = TRUE;
window->require_titlebar_visible = TRUE;
window->on_all_workspaces = FALSE;
window->shaded = FALSE;
@ -696,6 +775,7 @@ meta_window_new_with_attrs (MetaDisplay *display,
meta_topic (META_DEBUG_PLACEMENT,
"Not placing window 0x%lx since it's already mapped\n",
xwindow);
window->force_save_user_rect = TRUE;
window->denied_focus_and_not_transient = FALSE;
window->unmanaging = FALSE;
window->is_in_queues = 0;
@ -707,6 +787,10 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->initial_timestamp_set = FALSE;
window->net_wm_user_time_set = FALSE;
window->user_time_window = None;
window->take_focus = FALSE;
window->delete_window = FALSE;
window->net_wm_ping = FALSE;
window->input = TRUE;
window->calc_placement = FALSE;
window->shaken_loose = FALSE;
window->have_focus_click_grab = FALSE;
@ -788,6 +872,10 @@ meta_window_new_with_attrs (MetaDisplay *display,
meta_display_register_x_window (display, &window->xwindow, window);
/* Assign this #MetaWindow a sequence number which can be used
* for sorting.
*/
window->stable_sequence = ++display->window_sequence_counter;
/* assign the window to its group, or create a new group if needed
*/
@ -1062,6 +1150,14 @@ meta_window_new_with_attrs (MetaDisplay *display,
window->constructing = FALSE;
meta_display_notify_window_created (display, window);
if (window->wm_state_demands_attention)
g_signal_emit_by_name (window->display, "window-demands-attention", window);
if (window->wm_hints_urgent)
g_signal_emit_by_name (window->display, "window-marked-urgent", window);
return window;
}
@ -1434,6 +1530,8 @@ meta_window_unmanage (MetaWindow *window,
meta_error_trap_pop (window->display, FALSE);
g_signal_emit (window, window_signals[UNMANAGED], 0);
g_object_unref (window);
}
@ -1687,7 +1785,7 @@ meta_window_calc_showing (MetaWindow *window)
implement_showing (window, meta_window_should_be_showing (window));
}
static guint queue_idle[NUMBER_OF_QUEUES] = {0, 0, 0};
static guint queue_later[NUMBER_OF_QUEUES] = {0, 0, 0};
static GSList *queue_pending[NUMBER_OF_QUEUES] = {NULL, NULL, NULL};
static int
@ -1725,7 +1823,7 @@ idle_calc_showing (gpointer data)
copy = g_slist_copy (queue_pending[queue_index]);
g_slist_free (queue_pending[queue_index]);
queue_pending[queue_index] = NULL;
queue_idle[queue_index] = 0;
queue_later[queue_index] = 0;
destroying_windows_disallowed += 1;
@ -1853,8 +1951,10 @@ idle_calc_showing (gpointer data)
return FALSE;
}
#ifdef WITH_VERBOSE_MODE
static const gchar* meta_window_queue_names[NUMBER_OF_QUEUES] =
{"calc_showing", "move_resize", "update_icon"};
#endif
static void
meta_window_unqueue (MetaWindow *window, guint queuebits)
@ -1883,10 +1983,10 @@ meta_window_unqueue (MetaWindow *window, guint queuebits)
* In that case, we should kill the function that deals with
* the queue, because there's nothing left for it to do.
*/
if (queue_pending[queuenum] == NULL && queue_idle[queuenum] != 0)
if (queue_pending[queuenum] == NULL && queue_later[queuenum] != 0)
{
g_source_remove (queue_idle[queuenum]);
queue_idle[queuenum] = 0;
meta_later_remove (queue_later[queuenum]);
queue_later[queuenum] = 0;
}
}
}
@ -1919,14 +2019,14 @@ meta_window_queue (MetaWindow *window, guint queuebits)
* I seem to be turning into a Perl programmer.
*/
const gint window_queue_idle_priority[NUMBER_OF_QUEUES] =
const MetaLaterType window_queue_later_when[NUMBER_OF_QUEUES] =
{
META_PRIORITY_BEFORE_REDRAW, /* CALC_SHOWING */
META_PRIORITY_RESIZE, /* MOVE_RESIZE */
META_PRIORITY_BEFORE_REDRAW /* UPDATE_ICON */
META_LATER_BEFORE_REDRAW, /* CALC_SHOWING */
META_LATER_RESIZE, /* MOVE_RESIZE */
META_LATER_BEFORE_REDRAW /* UPDATE_ICON */
};
const GSourceFunc window_queue_idle_handler[NUMBER_OF_QUEUES] =
const GSourceFunc window_queue_later_handler[NUMBER_OF_QUEUES] =
{
idle_calc_showing,
idle_move_resize,
@ -1959,11 +2059,11 @@ meta_window_queue (MetaWindow *window, guint queuebits)
* that. If not, we'll create one.
*/
if (queue_idle[queuenum] == 0)
queue_idle[queuenum] = g_idle_add_full
if (queue_later[queuenum] == 0)
queue_later[queuenum] = meta_later_add
(
window_queue_idle_priority[queuenum],
window_queue_idle_handler[queuenum],
window_queue_later_when[queuenum],
window_queue_later_handler[queuenum],
GUINT_TO_POINTER(queuenum),
NULL
);
@ -2118,6 +2218,9 @@ __window_is_terminal (MetaWindow *window)
/* mlterm ("multi lingual terminal emulator on X") */
else if (strcmp (window->res_class, "mlterm") == 0)
return TRUE;
/* Terminal -- XFCE Terminal */
else if (strcmp (window->res_class, "Terminal") == 0)
return TRUE;
return FALSE;
}
@ -2362,6 +2465,7 @@ meta_window_show (MetaWindow *window)
MetaWindow *focus_window;
gboolean toplevel_was_mapped;
gboolean toplevel_now_mapped;
gboolean notify_demands_attention = FALSE;
meta_topic (META_DEBUG_WINDOW_STATE,
"Showing window %s, shaded: %d iconic: %d placed: %d\n",
@ -2496,7 +2600,13 @@ meta_window_show (MetaWindow *window)
* which we are going to call ourselves here a few lines down.
*/
if (overlap)
window->wm_state_demands_attention = TRUE;
{
if (!window->wm_state_demands_attention)
{
window->wm_state_demands_attention = TRUE;
notify_demands_attention = TRUE;
}
}
}
/* Shaded means the frame is mapped but the window is not */
@ -2614,6 +2724,13 @@ meta_window_show (MetaWindow *window)
* See http://bugzilla.gnome.org/show_bug.cgi?id=573922
*/
window->initial_timestamp_set = FALSE;
if (notify_demands_attention)
{
g_object_notify (G_OBJECT (window), "demands-attention");
g_signal_emit_by_name (window->display, "window-demands-attention",
window);
}
}
static void
@ -2712,7 +2829,14 @@ meta_window_hide (MetaWindow *window)
invalidate_work_areas (window);
}
if (window->has_focus)
/* The check on expected_focus_window is a temporary workaround for
* https://bugzilla.gnome.org/show_bug.cgi?id=597352
* We may have already switched away from this window but not yet
* gotten FocusIn/FocusOut events. A more complete comprehensive
* fix for these type of issues is described in the bug.
*/
if (window->has_focus &&
window == window->display->expected_focus_window)
{
MetaWindow *not_this_one = NULL;
MetaWorkspace *my_workspace = meta_window_get_workspace (window);
@ -2914,6 +3038,8 @@ meta_window_maximize_internal (MetaWindow *window,
window->maximized_horizontally || maximize_horizontally;
window->maximized_vertically =
window->maximized_vertically || maximize_vertically;
if (maximize_horizontally || maximize_vertically)
window->force_save_user_rect = FALSE;
/* Fix for #336850: If the frame shape isn't reapplied, it is
* possible that the frame will retains its rounded corners. That
@ -2925,6 +3051,11 @@ meta_window_maximize_internal (MetaWindow *window,
recalc_window_features (window);
set_net_wm_state (window);
g_object_freeze_notify (G_OBJECT (window));
g_object_notify (G_OBJECT (window), "maximized-horizontally");
g_object_notify (G_OBJECT (window), "maximized-vertically");
g_object_thaw_notify (G_OBJECT (window));
}
void
@ -3093,6 +3224,10 @@ meta_window_unmaximize (MetaWindow *window,
window->display->grab_anchor_window_pos = target_rect;
}
/* Make sure user_rect is current.
*/
force_save_user_window_placement (window);
if (window->display->compositor)
{
MetaRectangle old_rect, new_rect;
@ -3125,6 +3260,11 @@ meta_window_unmaximize (MetaWindow *window,
recalc_window_features (window);
set_net_wm_state (window);
}
g_object_freeze_notify (G_OBJECT (window));
g_object_notify (G_OBJECT (window), "maximized-horizontally");
g_object_notify (G_OBJECT (window), "maximized-vertically");
g_object_thaw_notify (G_OBJECT (window));
}
void
@ -3170,6 +3310,7 @@ meta_window_make_fullscreen_internal (MetaWindow *window)
meta_window_save_rect (window);
window->fullscreen = TRUE;
window->force_save_user_rect = FALSE;
meta_stack_freeze (window->screen->stack);
meta_window_update_layer (window);
@ -3225,6 +3366,10 @@ meta_window_unmake_fullscreen (MetaWindow *window)
target_rect.width,
target_rect.height);
/* Make sure user_rect is current.
*/
force_save_user_window_placement (window);
meta_window_update_layer (window);
recalc_window_features (window);
@ -3241,10 +3386,10 @@ meta_window_update_fullscreen_monitors (MetaWindow *window,
unsigned long left,
unsigned long right)
{
if ((int)top < window->screen->n_xinerama_infos &&
(int)bottom < window->screen->n_xinerama_infos &&
(int)left < window->screen->n_xinerama_infos &&
(int)right < window->screen->n_xinerama_infos)
if ((int)top < window->screen->n_monitor_infos &&
(int)bottom < window->screen->n_monitor_infos &&
(int)left < window->screen->n_monitor_infos &&
(int)right < window->screen->n_monitor_infos)
{
window->fullscreen_monitors[0] = top;
window->fullscreen_monitors[1] = bottom;
@ -4039,7 +4184,7 @@ meta_window_move_resize_internal (MetaWindow *window,
if (need_configure_notify)
send_configure_notify (window);
if (!window->placed)
if (!window->placed && window->force_save_user_rect && !window->fullscreen)
force_save_user_window_placement (window);
else if (is_user_action)
save_user_window_placement (window);
@ -4182,7 +4327,7 @@ idle_move_resize (gpointer data)
copy = g_slist_copy (queue_pending[queue_index]);
g_slist_free (queue_pending[queue_index]);
queue_pending[queue_index] = NULL;
queue_idle[queue_index] = 0;
queue_later[queue_index] = 0;
destroying_windows_disallowed += 1;
@ -5067,8 +5212,7 @@ meta_window_configure_request (MetaWindow *window,
{
MetaWindow *active_window;
active_window = window->display->expected_focus_window;
if (meta_prefs_get_disable_workarounds () ||
!meta_prefs_get_raise_on_click ())
if (meta_prefs_get_disable_workarounds ())
{
meta_topic (META_DEBUG_STACK,
"%s sent an xconfigure stacking request; this is "
@ -5077,6 +5221,7 @@ meta_window_configure_request (MetaWindow *window,
}
else if (active_window &&
!meta_window_same_application (window, active_window) &&
!meta_window_same_client (window, active_window) &&
XSERVER_TIME_IS_BEFORE (window->net_wm_user_time,
active_window->net_wm_user_time))
{
@ -6244,7 +6389,7 @@ idle_update_icon (gpointer data)
copy = g_slist_copy (queue_pending[queue_index]);
g_slist_free (queue_pending[queue_index]);
queue_pending[queue_index] = NULL;
queue_idle[queue_index] = 0;
queue_later[queue_index] = 0;
destroying_windows_disallowed += 1;
@ -6788,7 +6933,7 @@ recalc_window_features (MetaWindow *window)
/* don't allow fullscreen if we can't resize, unless the size
* is entire screen size (kind of broken, because we
* actually fullscreen to xinerama head size not screen size)
* actually fullscreen to monitor size not screen size)
*/
if (window->size_hints.min_width == window->screen->rect.width &&
window->size_hints.min_height == window->screen->rect.height)
@ -7449,22 +7594,22 @@ update_move (MetaWindow *window,
return;
}
/* remaximize window on an other xinerama monitor if window has
* been shaken loose or it is still maximized (then move straight)
/* remaximize window on another monitor if window has been shaken
* loose or it is still maximized (then move straight)
*/
else if (window->shaken_loose || META_WINDOW_MAXIMIZED (window))
{
const MetaXineramaScreenInfo *wxinerama;
const MetaMonitorInfo *wmonitor;
MetaRectangle work_area;
int monitor;
wxinerama = meta_screen_get_xinerama_for_window (window->screen, window);
wmonitor = meta_screen_get_monitor_for_window (window->screen, window);
for (monitor = 0; monitor < window->screen->n_xinerama_infos; monitor++)
for (monitor = 0; monitor < window->screen->n_monitor_infos; monitor++)
{
meta_window_get_work_area_for_xinerama (window, monitor, &work_area);
meta_window_get_work_area_for_monitor (window, monitor, &work_area);
/* check if cursor is near the top of a xinerama work area */
/* check if cursor is near the top of a monitor work area */
if (x >= work_area.x &&
x < (work_area.x + work_area.width) &&
y >= work_area.y &&
@ -7473,7 +7618,7 @@ update_move (MetaWindow *window,
/* move the saved rect if window will become maximized on an
* other monitor so user isn't surprised on a later unmaximize
*/
if (wxinerama->number != monitor)
if (wmonitor->number != monitor)
{
window->saved_rect.x = work_area.x;
window->saved_rect.y = work_area.y;
@ -7955,24 +8100,24 @@ meta_window_set_gravity (MetaWindow *window,
}
static void
get_work_area_xinerama (MetaWindow *window,
MetaRectangle *area,
int which_xinerama)
get_work_area_monitor (MetaWindow *window,
MetaRectangle *area,
int which_monitor)
{
GList *tmp;
g_assert (which_xinerama >= 0);
g_assert (which_monitor >= 0);
/* Initialize to the whole xinerama */
*area = window->screen->xinerama_infos[which_xinerama].rect;
/* Initialize to the whole monitor */
*area = window->screen->monitor_infos[which_monitor].rect;
tmp = meta_window_get_workspaces (window);
while (tmp != NULL)
{
MetaRectangle workspace_work_area;
meta_workspace_get_work_area_for_xinerama (tmp->data,
which_xinerama,
&workspace_work_area);
meta_workspace_get_work_area_for_monitor (tmp->data,
which_monitor,
&workspace_work_area);
meta_rectangle_intersect (area,
&workspace_work_area,
area);
@ -7980,39 +8125,39 @@ get_work_area_xinerama (MetaWindow *window,
}
meta_topic (META_DEBUG_WORKAREA,
"Window %s xinerama %d has work area %d,%d %d x %d\n",
window->desc, which_xinerama,
"Window %s monitor %d has work area %d,%d %d x %d\n",
window->desc, which_monitor,
area->x, area->y, area->width, area->height);
}
void
meta_window_get_work_area_current_xinerama (MetaWindow *window,
MetaRectangle *area)
meta_window_get_work_area_current_monitor (MetaWindow *window,
MetaRectangle *area)
{
const MetaXineramaScreenInfo *xinerama = NULL;
xinerama = meta_screen_get_xinerama_for_window (window->screen,
window);
const MetaMonitorInfo *monitor = NULL;
monitor = meta_screen_get_monitor_for_window (window->screen,
window);
meta_window_get_work_area_for_xinerama (window,
xinerama->number,
area);
meta_window_get_work_area_for_monitor (window,
monitor->number,
area);
}
void
meta_window_get_work_area_for_xinerama (MetaWindow *window,
int which_xinerama,
MetaRectangle *area)
meta_window_get_work_area_for_monitor (MetaWindow *window,
int which_monitor,
MetaRectangle *area)
{
g_return_if_fail (which_xinerama >= 0);
g_return_if_fail (which_monitor >= 0);
get_work_area_xinerama (window,
area,
which_xinerama);
get_work_area_monitor (window,
area,
which_monitor);
}
void
meta_window_get_work_area_all_xineramas (MetaWindow *window,
MetaRectangle *area)
meta_window_get_work_area_all_monitors (MetaWindow *window,
MetaRectangle *area)
{
GList *tmp;
@ -8023,8 +8168,8 @@ meta_window_get_work_area_all_xineramas (MetaWindow *window,
while (tmp != NULL)
{
MetaRectangle workspace_work_area;
meta_workspace_get_work_area_all_xineramas (tmp->data,
&workspace_work_area);
meta_workspace_get_work_area_all_monitors (tmp->data,
&workspace_work_area);
meta_rectangle_intersect (area,
&workspace_work_area,
area);
@ -8050,6 +8195,23 @@ meta_window_same_application (MetaWindow *window,
group==other_group;
}
/* Generally meta_window_same_application() is a better idea
* of "sameness", since it handles the case where multiple apps
* want to look like the same app or the same app wants to look
* like multiple apps, but in the case of workarounds for legacy
* applications (which likely aren't setting the group properly
* anyways), it may be desirable to check this as well.
*/
static gboolean
meta_window_same_client (MetaWindow *window,
MetaWindow *other_window)
{
int resource_mask = window->display->xdisplay->resource_mask;
return ((window->xwindow & ~resource_mask) ==
(other_window->xwindow & ~resource_mask));
}
void
meta_window_refresh_resize_popup (MetaWindow *window)
{
@ -8456,6 +8618,26 @@ meta_window_stack_just_below (MetaWindow *window,
}
}
/**
* meta_window_get_user_time:
*
* The user time represents a timestamp for the last time the user
* interacted with this window. Note this property is only available
* for non-override-redirect windows.
*
* The property is set by Mutter initially upon window creation,
* and updated thereafter on input events (key and button presses) seen by Mutter,
* client updates to the _NET_WM_USER_TIME property (if later than the current time)
* and when focusing the window.
*
* Returns: The last time the user interacted with this window.
*/
guint32
meta_window_get_user_time (MetaWindow *window)
{
return window->net_wm_user_time;
}
void
meta_window_set_user_time (MetaWindow *window,
guint32 timestamp)
@ -8494,6 +8676,28 @@ meta_window_set_user_time (MetaWindow *window,
__window_is_terminal (window))
window->display->allow_terminal_deactivation = FALSE;
}
g_object_notify (G_OBJECT (window), "user-time");
}
/**
* meta_window_get_stable_sequence:
* @window: A #MetaWindow
*
* The stable sequence number is a monotonicially increasing
* unique integer assigned to each #MetaWindow upon creation.
*
* This number can be useful for sorting windows in a stable
* fashion.
*
* Returns: Internal sequence number for this window
*/
guint32
meta_window_get_stable_sequence (MetaWindow *window)
{
g_return_val_if_fail (META_IS_WINDOW (window), 0);
return window->stable_sequence;
}
/* Sets the demands_attention hint on a window, but only
@ -8508,6 +8712,10 @@ meta_window_set_demands_attention (MetaWindow *window)
gboolean obscured = FALSE;
MetaWorkspace *workspace = window->screen->active_workspace;
if (window->wm_state_demands_attention)
return;
if (workspace!=window->workspace)
{
/* windows on other workspaces are necessarily obscured */
@ -8551,6 +8759,9 @@ meta_window_set_demands_attention (MetaWindow *window)
window->wm_state_demands_attention = TRUE;
set_net_wm_state (window);
g_object_notify (G_OBJECT (window), "demands-attention");
g_signal_emit_by_name (window->display, "window-demands-attention",
window);
}
else
{
@ -8569,8 +8780,12 @@ meta_window_unset_demands_attention (MetaWindow *window)
meta_topic (META_DEBUG_WINDOW_OPS,
"Marking %s as not needing attention\n", window->desc);
window->wm_state_demands_attention = FALSE;
set_net_wm_state (window);
if (window->wm_state_demands_attention)
{
window->wm_state_demands_attention = FALSE;
set_net_wm_state (window);
g_object_notify (G_OBJECT (window), "demands-attention");
}
}
MetaFrame *
@ -8799,6 +9014,25 @@ meta_window_get_transient_for (MetaWindow *window)
return NULL;
}
/**
* meta_window_get_transient_for_as_xid:
* @window: a #MetaWindow
*
* Returns the XID of the window that is pointed to by the
* WM_TRANSIENT_FOR hint on this window (see XGetTransientForHint()
* or XSetTransientForHint()). Metacity keeps transient windows above their
* parents. A typical usage of this hint is for a dialog that wants to stay
* above its associated window.
*
* Return value: (transfer none): the window this window is transient for, or
* None if the WM_TRANSIENT_FOR hint is unset.
*/
Window
meta_window_get_transient_for_as_xid (MetaWindow *window)
{
return window->xtransient_for;
}
/**
* meta_window_get_pid:
* @window: a #MetaWindow

View File

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

View File

@ -33,6 +33,9 @@
#include <X11/Xatom.h>
#include <string.h>
#ifdef HAVE_LIBCANBERRA
#include <canberra-gtk.h>
#endif
enum {
PROP_0,
@ -170,16 +173,16 @@ meta_workspace_new (MetaScreen *screen)
meta_screen_foreach_window (screen, maybe_add_to_list, &workspace->mru_list);
workspace->work_areas_invalid = TRUE;
workspace->work_area_xinerama = NULL;
workspace->work_area_monitor = NULL;
workspace->work_area_screen.x = 0;
workspace->work_area_screen.y = 0;
workspace->work_area_screen.width = 0;
workspace->work_area_screen.height = 0;
workspace->screen_region = NULL;
workspace->xinerama_region = NULL;
workspace->monitor_region = NULL;
workspace->screen_edges = NULL;
workspace->xinerama_edges = NULL;
workspace->monitor_edges = NULL;
workspace->list_containing_self = g_list_prepend (NULL, workspace);
workspace->builtin_struts = NULL;
@ -263,7 +266,7 @@ meta_workspace_remove (MetaWorkspace *workspace)
workspace->screen->workspaces =
g_list_remove (workspace->screen->workspaces, workspace);
g_free (workspace->work_area_xinerama);
g_free (workspace->work_area_monitor);
g_list_free (workspace->mru_list);
g_list_free (workspace->list_containing_self);
@ -280,12 +283,12 @@ meta_workspace_remove (MetaWorkspace *workspace)
if (!workspace->work_areas_invalid)
{
workspace_free_all_struts (workspace);
for (i = 0; i < screen->n_xinerama_infos; i++)
meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]);
g_free (workspace->xinerama_region);
for (i = 0; i < screen->n_monitor_infos; i++)
meta_rectangle_free_list_and_elements (workspace->monitor_region[i]);
g_free (workspace->monitor_region);
meta_rectangle_free_list_and_elements (workspace->screen_region);
meta_rectangle_free_list_and_elements (workspace->screen_edges);
meta_rectangle_free_list_and_elements (workspace->xinerama_edges);
meta_rectangle_free_list_and_elements (workspace->monitor_edges);
}
g_object_unref (workspace);
@ -439,6 +442,69 @@ meta_workspace_queue_calc_showing (MetaWorkspace *workspace)
}
}
static void
workspace_switch_sound(MetaWorkspace *from,
MetaWorkspace *to)
{
#ifdef HAVE_LIBCANBERRA
MetaWorkspaceLayout layout;
int i, nw, x, y, fi, ti;
const char *e;
nw = meta_screen_get_n_workspaces(from->screen);
fi = meta_workspace_index(from);
ti = meta_workspace_index(to);
meta_screen_calc_workspace_layout(from->screen,
nw,
fi,
&layout);
for (i = 0; i < nw; i++)
if (layout.grid[i] == ti)
break;
if (i >= nw)
{
meta_bug("Failed to find destination workspace in layout\n");
goto finish;
}
y = i / layout.cols;
x = i % layout.cols;
/* We priorize horizontal over vertical movements here. The
rationale for this is that horizontal movements are probably more
interesting for sound effects because speakers are usually
positioned on a horizontal and not a vertical axis. i.e. your
spatial "Woosh!" effects will easily be able to encode horizontal
movement but not such much vertical movement. */
if (x < layout.current_col)
e = "desktop-switch-left";
else if (x > layout.current_col)
e = "desktop-switch-right";
else if (y < layout.current_row)
e = "desktop-switch-up";
else if (y > layout.current_row)
e = "desktop-switch-down";
else
{
meta_bug("Uh, origin and destination workspace at same logic position!\n");
goto finish;
}
ca_context_play(ca_gtk_context_get(), 1,
CA_PROP_EVENT_ID, e,
CA_PROP_EVENT_DESCRIPTION, "Desktop switched",
CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
NULL);
finish:
meta_screen_free_workspace_layout (&layout);
#endif /* HAVE_LIBCANBERRA */
}
/**
* meta_workspace_activate_with_focus:
* @workspace: a #MetaWorkspace
@ -478,6 +544,13 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
if (workspace->screen->active_workspace == workspace)
return;
/* Free any cached pointers to the workspaces's edges from
* a current resize or move operation */
meta_display_cleanup_edges (workspace->screen->display);
if (workspace->screen->active_workspace)
workspace_switch_sound (workspace->screen->active_workspace, workspace);
/* Note that old can be NULL; e.g. when starting up */
old = workspace->screen->active_workspace;
@ -638,7 +711,7 @@ meta_workspace_update_window_hints (MetaWorkspace *workspace)
* Gets windows contained on the workspace, including workspace->windows
* and also sticky windows. Override-redirect windows are not included.
*
* Return value: (transfer container): the list of windows.
* Return value: (transfer container) (element-type MetaWindow): the list of windows.
*/
GList*
meta_workspace_list_windows (MetaWorkspace *workspace)
@ -713,21 +786,26 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
"Invalidating work area for workspace %d\n",
meta_workspace_index (workspace));
g_free (workspace->work_area_xinerama);
workspace->work_area_xinerama = NULL;
/* If we are in the middle of a resize or move operation, we
* might have cached pointers to the workspace's edges */
if (workspace == workspace->screen->active_workspace)
meta_display_cleanup_edges (workspace->screen->display);
g_free (workspace->work_area_monitor);
workspace->work_area_monitor = NULL;
workspace_free_all_struts (workspace);
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]);
g_free (workspace->xinerama_region);
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
meta_rectangle_free_list_and_elements (workspace->monitor_region[i]);
g_free (workspace->monitor_region);
meta_rectangle_free_list_and_elements (workspace->screen_region);
meta_rectangle_free_list_and_elements (workspace->screen_edges);
meta_rectangle_free_list_and_elements (workspace->xinerama_edges);
workspace->xinerama_region = NULL;
meta_rectangle_free_list_and_elements (workspace->monitor_edges);
workspace->monitor_region = NULL;
workspace->screen_region = NULL;
workspace->screen_edges = NULL;
workspace->xinerama_edges = NULL;
workspace->monitor_edges = NULL;
workspace->work_areas_invalid = TRUE;
@ -780,10 +858,10 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
return;
g_assert (workspace->all_struts == NULL);
g_assert (workspace->xinerama_region == NULL);
g_assert (workspace->monitor_region == NULL);
g_assert (workspace->screen_region == NULL);
g_assert (workspace->screen_edges == NULL);
g_assert (workspace->xinerama_edges == NULL);
g_assert (workspace->monitor_edges == NULL);
/* STEP 1: Get the list of struts */
@ -803,18 +881,18 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
g_list_free (windows);
/* STEP 2: Get the maximal/spanning rects for the onscreen and
* on-single-xinerama regions
* on-single-monitor regions
*/
g_assert (workspace->xinerama_region == NULL);
g_assert (workspace->monitor_region == NULL);
g_assert (workspace->screen_region == NULL);
workspace->xinerama_region = g_new (GList*,
workspace->screen->n_xinerama_infos);
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
workspace->monitor_region = g_new (GList*,
workspace->screen->n_monitor_infos);
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
{
workspace->xinerama_region[i] =
workspace->monitor_region[i] =
meta_rectangle_get_minimal_spanning_set_for_region (
&workspace->screen->xinerama_infos[i].rect,
&workspace->screen->monitor_infos[i].rect,
workspace->all_struts);
}
workspace->screen_region =
@ -823,7 +901,7 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
workspace->all_struts);
/* STEP 3: Get the work areas (region-to-maximize-to) for the screen and
* xineramas.
* monitors.
*/
work_area = workspace->screen->rect; /* start with the screen */
if (workspace->screen_region == NULL)
@ -878,35 +956,35 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
workspace->work_area_screen.width,
workspace->work_area_screen.height);
/* Now find the work areas for each xinerama */
g_free (workspace->work_area_xinerama);
workspace->work_area_xinerama = g_new (MetaRectangle,
workspace->screen->n_xinerama_infos);
/* Now find the work areas for each monitor */
g_free (workspace->work_area_monitor);
workspace->work_area_monitor = g_new (MetaRectangle,
workspace->screen->n_monitor_infos);
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
{
work_area = workspace->screen->xinerama_infos[i].rect;
work_area = workspace->screen->monitor_infos[i].rect;
if (workspace->xinerama_region[i] == NULL)
if (workspace->monitor_region[i] == NULL)
/* FIXME: constraints.c untested with this, but it might be nice for
* a screen reader or magnifier.
*/
work_area = meta_rect (work_area.x, work_area.y, -1, -1);
else
meta_rectangle_clip_to_region (workspace->xinerama_region[i],
meta_rectangle_clip_to_region (workspace->monitor_region[i],
FIXED_DIRECTION_NONE,
&work_area);
workspace->work_area_xinerama[i] = work_area;
workspace->work_area_monitor[i] = work_area;
meta_topic (META_DEBUG_WORKAREA,
"Computed work area for workspace %d "
"xinerama %d: %d,%d %d x %d\n",
"monitor %d: %d,%d %d x %d\n",
meta_workspace_index (workspace),
i,
workspace->work_area_xinerama[i].x,
workspace->work_area_xinerama[i].y,
workspace->work_area_xinerama[i].width,
workspace->work_area_xinerama[i].height);
workspace->work_area_monitor[i].x,
workspace->work_area_monitor[i].y,
workspace->work_area_monitor[i].width,
workspace->work_area_monitor[i].height);
}
/* STEP 4: Make sure the screen_region is nonempty (separate from step 2
@ -920,17 +998,17 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
workspace->screen_region = g_list_prepend (NULL, nonempty_region);
}
/* STEP 5: Cache screen and xinerama edges for edge resistance and snapping */
/* STEP 5: Cache screen and monitor edges for edge resistance and snapping */
g_assert (workspace->screen_edges == NULL);
g_assert (workspace->xinerama_edges == NULL);
g_assert (workspace->monitor_edges == NULL);
workspace->screen_edges =
meta_rectangle_find_onscreen_edges (&workspace->screen->rect,
workspace->all_struts);
tmp = NULL;
for (i = 0; i < workspace->screen->n_xinerama_infos; i++)
tmp = g_list_prepend (tmp, &workspace->screen->xinerama_infos[i].rect);
workspace->xinerama_edges =
meta_rectangle_find_nonintersected_xinerama_edges (tmp,
for (i = 0; i < workspace->screen->n_monitor_infos; i++)
tmp = g_list_prepend (tmp, &workspace->screen->monitor_infos[i].rect);
workspace->monitor_edges =
meta_rectangle_find_nonintersected_monitor_edges (tmp,
workspace->all_struts);
g_list_free (tmp);
@ -950,6 +1028,23 @@ ensure_work_areas_validated (MetaWorkspace *workspace)
}
}
static gboolean
strut_lists_equal (GSList *l,
GSList *m)
{
for (; l && m; l = l->next, m = m->next)
{
MetaStrut *a = l->data;
MetaStrut *b = m->data;
if (a->side != b->side ||
!meta_rectangle_equal (&a->rect, &b->rect))
return FALSE;
}
return l == NULL && m == NULL;
}
/**
* meta_workspace_set_builtin_struts:
* @workspace: a #MetaWorkspace
@ -963,6 +1058,12 @@ void
meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
GSList *struts)
{
/* Reordering doesn't actually matter, so we don't catch all
* no-impact changes, but this is just a (possibly unnecessary
* anyways) optimization */
if (strut_lists_equal (struts, workspace->builtin_struts))
return;
workspace_free_builtin_struts (workspace);
workspace->builtin_struts = copy_strut_list (struts);
@ -970,21 +1071,21 @@ meta_workspace_set_builtin_struts (MetaWorkspace *workspace,
}
void
meta_workspace_get_work_area_for_xinerama (MetaWorkspace *workspace,
int which_xinerama,
MetaRectangle *area)
meta_workspace_get_work_area_for_monitor (MetaWorkspace *workspace,
int which_monitor,
MetaRectangle *area)
{
g_assert (which_xinerama >= 0);
g_assert (which_monitor >= 0);
ensure_work_areas_validated (workspace);
g_assert (which_xinerama < workspace->screen->n_xinerama_infos);
g_assert (which_monitor < workspace->screen->n_monitor_infos);
*area = workspace->work_area_xinerama[which_xinerama];
*area = workspace->work_area_monitor[which_monitor];
}
void
meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
MetaRectangle *area)
meta_workspace_get_work_area_all_monitors (MetaWorkspace *workspace,
MetaRectangle *area)
{
ensure_work_areas_validated (workspace);
@ -1000,12 +1101,12 @@ meta_workspace_get_onscreen_region (MetaWorkspace *workspace)
}
GList*
meta_workspace_get_onxinerama_region (MetaWorkspace *workspace,
int which_xinerama)
meta_workspace_get_onmonitor_region (MetaWorkspace *workspace,
int which_monitor)
{
ensure_work_areas_validated (workspace);
return workspace->xinerama_region[which_xinerama];
return workspace->monitor_region[which_monitor];
}
#ifdef WITH_VERBOSE_MODE
@ -1202,7 +1303,10 @@ focus_ancestor_or_mru_window (MetaWorkspace *workspace,
MetaWindow *ancestor;
ancestor = NULL;
meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor);
if (ancestor != NULL)
if (ancestor != NULL &&
(ancestor->on_all_workspaces ||
ancestor->workspace == workspace) &&
meta_window_showing_on_its_workspace (ancestor))
{
meta_topic (META_DEBUG_FOCUS,
"Focusing %s, ancestor of %s\n",

View File

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

View File

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

View File

@ -1,73 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Metacity Alt-Tab abstraction */
/*
* Copyright (C) 2009 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_ALT_TAB_HANDLER_H
#define META_ALT_TAB_HANDLER_H
#include <glib-object.h>
#include "types.h"
#define META_TYPE_ALT_TAB_HANDLER (meta_alt_tab_handler_get_type ())
#define META_ALT_TAB_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_ALT_TAB_HANDLER, MetaAltTabHandler))
#define META_ALT_TAB_HANDLER_GET_INTERFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), META_TYPE_ALT_TAB_HANDLER, MetaAltTabHandlerInterface))
typedef struct _MetaAltTabHandler MetaAltTabHandler;
typedef struct _MetaAltTabHandlerInterface MetaAltTabHandlerInterface;
struct _MetaAltTabHandlerInterface {
GTypeInterface g_iface;
void (*add_window) (MetaAltTabHandler *handler,
MetaWindow *window);
void (*show) (MetaAltTabHandler *handler,
MetaWindow *initial_selection);
void (*destroy) (MetaAltTabHandler *handler);
void (*forward) (MetaAltTabHandler *handler);
void (*backward) (MetaAltTabHandler *handler);
MetaWindow * (*get_selected) (MetaAltTabHandler *handler);
};
GType meta_alt_tab_handler_get_type (void);
void meta_alt_tab_handler_register (GType type);
MetaAltTabHandler *meta_alt_tab_handler_new (MetaScreen *screen,
gboolean immediate);
void meta_alt_tab_handler_add_window (MetaAltTabHandler *handler,
MetaWindow *window);
void meta_alt_tab_handler_show (MetaAltTabHandler *handler,
MetaWindow *initial_selection);
void meta_alt_tab_handler_destroy (MetaAltTabHandler *handler);
void meta_alt_tab_handler_forward (MetaAltTabHandler *handler);
void meta_alt_tab_handler_backward (MetaAltTabHandler *handler);
MetaWindow *meta_alt_tab_handler_get_selected (MetaAltTabHandler *handler);
#endif

View File

@ -1,55 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Metacity Alt-Tab abstraction: default implementation */
/*
* Copyright (C) 2009 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*/
#ifndef META_ALT_TAB_HANDLER_DEFAULT_H
#define META_ALT_TAB_HANDLER_DEFAULT_H
#include "alttabhandler.h"
#include "tabpopup.h"
#define META_TYPE_ALT_TAB_HANDLER_DEFAULT (meta_alt_tab_handler_default_get_type ())
#define META_ALT_TAB_HANDLER_DEFAULT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_ALT_TAB_HANDLER_DEFAULT, MetaAltTabHandlerDefault))
typedef struct _MetaAltTabHandlerDefault MetaAltTabHandlerDefault;
typedef struct _MetaAltTabHandlerDefaultClass MetaAltTabHandlerDefaultClass;
struct _MetaAltTabHandlerDefault {
GObject parent_instance;
MetaScreen *screen;
GArray *entries;
gboolean immediate_mode;
MetaTabPopup *tab_popup;
};
struct _MetaAltTabHandlerDefaultClass {
GObjectClass parent_class;
};
GType meta_alt_tab_handler_default_get_type (void);
#endif

View File

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

View File

@ -58,7 +58,7 @@ typedef enum
typedef enum
{
META_EDGE_WINDOW,
META_EDGE_XINERAMA,
META_EDGE_MONITOR,
META_EDGE_SCREEN
} MetaEdgeType;
@ -193,7 +193,7 @@ void meta_rectangle_expand_to_avoiding_struts (
* or
* meta_rectangle_find_onscreen_edges ()
* or
* meta_rectangle_find_nonintersected_xinerama_edges()
* meta_rectangle_find_nonintersected_monitor_edges()
*/
void meta_rectangle_free_list_and_elements (GList *filled_list);
@ -280,11 +280,11 @@ GList* meta_rectangle_remove_intersections_with_boxes_from_edges (
GList* meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,
const GSList *all_struts);
/* Finds edges between adjacent xineramas which are not covered by the given
/* Finds edges between adjacent monitors which are not covered by the given
* struts.
*/
GList* meta_rectangle_find_nonintersected_xinerama_edges (
const GList *xinerama_rects,
GList* meta_rectangle_find_nonintersected_monitor_edges (
const GList *monitor_rects,
const GSList *all_struts);
#endif /* META_BOXES_H */

View File

@ -317,8 +317,10 @@ struct _MetaButtonLayout
* coelesce multiple things together, the appropriate place to
* do it is usually META_PRIORITY_BEFORE_REDRAW.
*
* (FIXME: Use a Clutter paint() function instead, to prevent
* starving the repaints)
* Note that its usually better to use meta_later_add() rather
* than calling g_idle_add() directly; this will make sure things
* get run when added from a clutter event handler without
* waiting for another repaint cycle.
*
* If something has a priority lower than the redraw priority
* (such as a default priority idle), then it may be arbitrarily

View File

@ -59,9 +59,10 @@ typedef enum
META_PREF_CURSOR_SIZE,
META_PREF_COMPOSITING_MANAGER,
META_PREF_RESIZE_WITH_RIGHT_BUTTON,
META_PREF_FORCE_FULLSCREEN,
META_PREF_CLUTTER_PLUGINS,
META_PREF_LIVE_HIDDEN_WINDOWS,
META_PREF_NO_TAB_POPUP,
META_PREF_NO_TAB_POPUP
} MetaPreference;
typedef void (* MetaPrefsChangedFunc) (MetaPreference pref,
@ -115,6 +116,7 @@ void meta_prefs_change_workspace_name (int i,
const char* meta_prefs_get_cursor_theme (void);
int meta_prefs_get_cursor_size (void);
gboolean meta_prefs_get_compositing_manager (void);
gboolean meta_prefs_get_force_fullscreen (void);
/**
* Sets whether the compositor is turned on.
@ -123,6 +125,8 @@ gboolean meta_prefs_get_compositing_manager (void);
*/
void meta_prefs_set_compositing_manager (gboolean whether);
void meta_prefs_set_force_fullscreen (gboolean whether);
GSList * meta_prefs_get_clutter_plugins (void);
/**

View File

@ -30,7 +30,7 @@
#define META_TYPE_SCREEN (meta_screen_get_type ())
#define META_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_SCREEN, MetaScreen))
#define META_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_SCREEN, MetaScreenClass))
#define META_IS_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_SCREEN_TYPE))
#define META_IS_SCREEN(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_SCREEN))
#define META_IS_SCREEN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_SCREEN))
#define META_SCREEN_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_SCREEN, MetaScreenClass))
@ -75,4 +75,9 @@ int meta_screen_get_active_workspace_index (MetaScreen *screen);
MetaWorkspace * meta_screen_get_active_workspace (MetaScreen *screen);
int meta_screen_get_n_monitors (MetaScreen *screen);
void meta_screen_get_monitor_geometry (MetaScreen *screen,
int monitor,
MetaRectangle *geometry);
#endif

View File

@ -131,35 +131,25 @@ GPid meta_show_dialog (const char *type,
#endif /* !WITH_VERBOSE_MODE */
#include <glib-object.h>
#define META_TYPE_NEXUS (meta_nexus_get_type ())
#define META_NEXUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_NEXUS, MetaNexus))
#define META_NEXUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_NEXUS, MetaNexusClass))
#define META_IS_NEXUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_NEXUS))
#define META_IS_NEXUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_NEXUS))
#define META_NEXUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_NEXUS, MetaNexusClass))
typedef struct _MetaNexus
{
GObject parent_instance;
} MetaNexus;
typedef struct _MetaNexusClass
{
GObjectClass parent_class;
} MetaNexusClass;
GType meta_nexus_get_type (void) G_GNUC_CONST;
MetaNexus *meta_nexus_new ();
/**
* An object which exists purely to attach signals to; this is to receive
* signals when a child process exits. The signal is "sigchld" with no detail.
*
* \bug Eventually we should have a specialised type for objects like these.
*/
extern MetaNexus *sigchld_nexus;
* MetaLaterType:
* @META_LATER_RESIZE: call in a resize processing phase that is done
* before GTK+ repainting (including window borders) is done.
* @META_LATER_BEFORE_REDRAW: call before the stage is redrawn
* @META_LATER_IDLE: call at a very low priority (can be blocked
* by running animations or redrawing applications)
**/
typedef enum {
META_LATER_RESIZE,
META_LATER_BEFORE_REDRAW,
META_LATER_IDLE
} MetaLaterType;
guint meta_later_add (MetaLaterType when,
GSourceFunc func,
gpointer data,
GDestroyNotify notify);
void meta_later_remove (guint later_id);
#endif /* META_UTIL_H */

View File

@ -116,8 +116,11 @@ void meta_window_minimize (MetaWindow *window);
void meta_window_unminimize (MetaWindow *window);
const char *meta_window_get_title (MetaWindow *window);
MetaWindow *meta_window_get_transient_for (MetaWindow *window);
Window meta_window_get_transient_for_as_xid (MetaWindow *window);
void meta_window_delete (MetaWindow *window,
guint32 timestamp);
guint meta_window_get_stable_sequence (MetaWindow *window);
guint32 meta_window_get_user_time (MetaWindow *window);
int meta_window_get_pid (MetaWindow *window);
const char *meta_window_get_client_machine (MetaWindow *window);
gboolean meta_window_is_modal (MetaWindow *window);

View File

@ -51,8 +51,8 @@ GType meta_workspace_get_type (void);
int meta_workspace_index (MetaWorkspace *workspace);
MetaScreen *meta_workspace_get_screen (MetaWorkspace *workspace);
GList* meta_workspace_list_windows (MetaWorkspace *workspace);
void meta_workspace_get_work_area_all_xineramas (MetaWorkspace *workspace,
MetaRectangle *area);
void meta_workspace_get_work_area_all_monitors (MetaWorkspace *workspace,
MetaRectangle *area);
void meta_workspace_activate (MetaWorkspace *workspace, guint32 timestamp);
void meta_workspace_activate_with_focus (MetaWorkspace *workspace,
MetaWindow *focus_this,

View File

@ -5,10 +5,10 @@
<schema>
<key>/schemas/apps/mutter/general/overlay_key</key>
<applyto>/apps/metacity/general/overlay_key</applyto>
<owner>metacity</owner>
<applyto>/apps/mutter/general/overlay_key</applyto>
<owner>mutter</owner>
<type>string</type>
<default>&lt;Super_L&gt;</default>
<default>Super_L</default>
<locale name="C">
<short>Modifier to use for extended window management operations</short>
<long>

View File

@ -71,6 +71,8 @@ meta_fixed_tip_show (Display *xdisplay, int screen_number,
if (tip == NULL)
{
tip = gtk_window_new (GTK_WINDOW_POPUP);
gtk_window_set_type_hint (GTK_WINDOW(tip), GDK_WINDOW_TYPE_HINT_TOOLTIP);
{
GdkScreen *gdk_screen;
GdkRectangle monitor;

View File

@ -72,7 +72,7 @@ meta_preview_class_init (MetaPreviewClass *class)
GtkWidgetClass *widget_class;
widget_class = (GtkWidgetClass*) class;
parent_class = gtk_type_class (GTK_TYPE_BIN);
parent_class = g_type_class_peek (GTK_TYPE_BIN);
gobject_class->finalize = meta_preview_finalize;

View File

@ -1658,8 +1658,16 @@ parse_draw_op_element (GMarkupParseContext *context,
op->data.line.x1 = meta_draw_spec_new (info->theme, x1, NULL);
op->data.line.y1 = meta_draw_spec_new (info->theme, y1, NULL);
op->data.line.x2 = meta_draw_spec_new (info->theme, x2, NULL);
op->data.line.y2 = meta_draw_spec_new (info->theme, y2, NULL);
if (strcmp(x1, x2)==0)
op->data.line.x2 = NULL;
else
op->data.line.x2 = meta_draw_spec_new (info->theme, x2, NULL);
if (strcmp(y1, y2)==0)
op->data.line.y2 = NULL;
else
op->data.line.y2 = meta_draw_spec_new (info->theme, y2, NULL);
op->data.line.width = width_val;
op->data.line.dash_on_length = dash_on_val;
@ -3713,7 +3721,8 @@ text_handler (GMarkupParseContext *context,
{
set_error (error, context, G_MARKUP_ERROR,
G_MARKUP_ERROR_PARSE,
_("<name> specified twice for this theme"));
_("<%s> specified twice for this theme"),
"name");
return;
}
@ -3724,7 +3733,8 @@ text_handler (GMarkupParseContext *context,
{
set_error (error, context, G_MARKUP_ERROR,
G_MARKUP_ERROR_PARSE,
_("<author> specified twice for this theme"));
_("<%s> specified twice for this theme"),
"author");
return;
}
@ -3735,7 +3745,8 @@ text_handler (GMarkupParseContext *context,
{
set_error (error, context, G_MARKUP_ERROR,
G_MARKUP_ERROR_PARSE,
_("<copyright> specified twice for this theme"));
_("<%s> specified twice for this theme"),
"copyright");
return;
}
@ -3746,7 +3757,8 @@ text_handler (GMarkupParseContext *context,
{
set_error (error, context, G_MARKUP_ERROR,
G_MARKUP_ERROR_PARSE,
_("<date> specified twice for this theme"));
_("<%s> specified twice for this theme"),
"date");
return;
}
@ -3757,7 +3769,8 @@ text_handler (GMarkupParseContext *context,
{
set_error (error, context, G_MARKUP_ERROR,
G_MARKUP_ERROR_PARSE,
_("<description> specified twice for this theme"));
_("<%s> specified twice for this theme"),
"description");
return;
}

View File

@ -2645,6 +2645,7 @@ parse_size_unchecked (MetaDrawSpec *spec,
void
meta_draw_spec_free (MetaDrawSpec *spec)
{
if (!spec) return;
free_tokens (spec->tokens, spec->n_tokens);
g_slice_free (MetaDrawSpec, spec);
}
@ -3489,10 +3490,25 @@ meta_draw_op_draw_with_env (const MetaDrawOp *op,
x1 = parse_x_position_unchecked (op->data.line.x1, env);
y1 = parse_y_position_unchecked (op->data.line.y1, env);
x2 = parse_x_position_unchecked (op->data.line.x2, env);
y2 = parse_y_position_unchecked (op->data.line.y2, env);
gdk_draw_line (drawable, gc, x1, y1, x2, y2);
if (!op->data.line.x2 &&
!op->data.line.y2 &&
op->data.line.width==0)
gdk_draw_point (drawable, gc, x1, y1);
else
{
if (op->data.line.x2)
x2 = parse_x_position_unchecked (op->data.line.x2, env);
else
x2 = x1;
if (op->data.line.y2)
y2 = parse_y_position_unchecked (op->data.line.y2, env);
else
y2 = y1;
gdk_draw_line (drawable, gc, x1, y1, x2, y2);
}
g_object_unref (G_OBJECT (gc));
}
@ -5220,16 +5236,6 @@ meta_theme_draw_frame_by_name (MetaTheme *theme,
mini_icon, icon);
}
void
meta_theme_get_frame_borders (MetaTheme *theme,
MetaFrameType type,
@ -5526,6 +5532,15 @@ meta_theme_define_color_constant (MetaTheme *theme,
return TRUE;
}
/**
* Looks up a colour constant.
*
* \param theme the theme containing the constant
* \param name the name of the constant
* \param value [out] the string representation of the colour, or NULL if it
* doesn't exist
* \return TRUE if it exists, FALSE otherwise
*/
gboolean
meta_theme_lookup_color_constant (MetaTheme *theme,
const char *name,
@ -5572,6 +5587,13 @@ meta_gtk_widget_get_font_desc (GtkWidget *widget,
return font_desc;
}
/**
* Returns the height of the letters in a particular font.
*
* \param font_desc the font
* \param context the context of the font
* \return the height of the letters
*/
int
meta_pango_font_desc_get_text_height (const PangoFontDescription *font_desc,
PangoContext *context)
@ -6117,6 +6139,13 @@ meta_gtk_arrow_to_string (GtkArrowType arrow)
return "<unknown>";
}
/**
* Returns a fill_type from a string. The inverse of
* meta_image_fill_type_to_string().
*
* \param str a string representing a fill_type
* \result the fill_type, or -1 if it represents no fill_type.
*/
MetaImageFillType
meta_image_fill_type_from_string (const char *str)
{
@ -6128,6 +6157,13 @@ meta_image_fill_type_from_string (const char *str)
return -1;
}
/**
* Returns a string representation of a fill_type. The inverse of
* meta_image_fill_type_from_string().
*
* \param fill_type the fill type
* \result a string representing that type
*/
const char*
meta_image_fill_type_to_string (MetaImageFillType fill_type)
{
@ -6142,7 +6178,15 @@ meta_image_fill_type_to_string (MetaImageFillType fill_type)
return "<unknown>";
}
/* gtkstyle.c cut-and-pastage */
/**
* Takes a colour "a", scales the lightness and saturation by a certain amount,
* and sets "b" to the resulting colour.
* gtkstyle.c cut-and-pastage.
*
* \param a the starting colour
* \param b [out] the resulting colour
* \param k amount to scale lightness and saturation by
*/
static void
gtk_style_shade (GdkColor *a,
GdkColor *b,
@ -6177,6 +6221,13 @@ gtk_style_shade (GdkColor *a,
b->blue = blue * 65535.0;
}
/**
* Converts a red/green/blue triplet to a hue/lightness/saturation triplet.
*
* \param r on input, red; on output, hue
* \param g on input, green; on output, lightness
* \param b on input, blue; on output, saturation
*/
static void
rgb_to_hls (gdouble *r,
gdouble *g,
@ -6248,6 +6299,13 @@ rgb_to_hls (gdouble *r,
*b = s;
}
/**
* Converts a hue/lightness/saturation triplet to a red/green/blue triplet.
*
* \param h on input, hue; on output, red
* \param l on input, lightness; on output, green
* \param s on input, saturation; on output, blue
*/
static void
hls_to_rgb (gdouble *h,
gdouble *l,
@ -6536,6 +6594,14 @@ draw_bg_gradient_composite (const MetaTextureSpec *bg,
}
#endif
/**
* Returns the earliest version of the theme format which required support
* for a particular button. (For example, "shade" first appeared in v2, and
* "close" in v1.)
*
* \param type the button type
* \return the number of the theme format
*/
guint
meta_theme_earliest_version_with_button (MetaButtonType type)
{

View File

@ -69,7 +69,7 @@ meta_area_class_init (MetaAreaClass *class)
object_class = (GtkObjectClass*) class;
widget_class = (GtkWidgetClass*) class;
parent_class = gtk_type_class (gtk_misc_get_type ());
parent_class = g_type_class_peek (gtk_misc_get_type ());
gobject_class->finalize = meta_area_finalize;

View File

@ -656,7 +656,7 @@ meta_ui_window_should_not_cause_focus (Display *xdisplay,
/* we shouldn't cause focus if we're an override redirect
* toplevel which is not foreign
*/
if (window && gdk_window_get_type (window) == GDK_WINDOW_TEMP)
if (window && gdk_window_get_window_type (window) == GDK_WINDOW_TEMP)
return TRUE;
else
return FALSE;
@ -773,7 +773,7 @@ meta_ui_parse_accelerator (const char *accel,
*keycode = 0;
*mask = 0;
if (strcmp (accel, "disabled") == 0)
if (!accel[0] || strcmp (accel, "disabled") == 0)
return TRUE;
meta_ui_accelerator_parse (accel, &gdk_sym, &gdk_code, &gdk_mask);
@ -860,7 +860,7 @@ meta_ui_parse_modifier (const char *accel,
*mask = 0;
if (accel == NULL || strcmp (accel, "disabled") == 0)
if (accel == NULL || !accel[0] || strcmp (accel, "disabled") == 0)
return TRUE;
meta_ui_accelerator_parse (accel, &gdk_sym, &gdk_code, &gdk_mask);

View File

@ -79,7 +79,7 @@ get_size (Display *d, Drawable draw,
*yp = y;
if (widthp)
*widthp = width;
if (*heightp)
if (heightp)
*heightp = height;
}