Compare commits
78 Commits
3.10.0.1
...
wip/remove
Author | SHA1 | Date | |
---|---|---|---|
bb9501dbdf | |||
1db95bc32b | |||
93a8933282 | |||
5a63aaa5ac | |||
a3eb5e562a | |||
8a76383eca | |||
734deeb17c | |||
f8b4c28278 | |||
3e179c07bc | |||
56aae17b46 | |||
78741846a4 | |||
55180f5bb3 | |||
62b884dd42 | |||
3283018bfb | |||
55226ada8a | |||
ff790f7b39 | |||
899570d213 | |||
3b2506851c | |||
9b88059e55 | |||
59168b2c64 | |||
47144253e4 | |||
d8c66077f0 | |||
59a01137e1 | |||
ce3804ee04 | |||
f0bc53ce5a | |||
b8938e9d4d | |||
7116d9cedb | |||
66fb86fd0c | |||
59cfbb07c8 | |||
dc5bc3fea8 | |||
fbbc32422e | |||
fe8829f324 | |||
b4036e061a | |||
4ee9f3563b | |||
c652a54f59 | |||
61881477ac | |||
4373916d9d | |||
660d7df5ab | |||
b7e3f627f1 | |||
ca5d115715 | |||
21c46852cd | |||
10036832dd | |||
25b5ea8b4f | |||
20beaf7fe1 | |||
e72af50420 | |||
ef4417b717 | |||
cf943627e2 | |||
96543cb009 | |||
fbb2207f8c | |||
cce8a4341b | |||
b82784ee46 | |||
6b8959916c | |||
ecc1830296 | |||
497916aad7 | |||
e171a31ac5 | |||
a9a10aaa20 | |||
656d079ffc | |||
d801f699af | |||
89d01d2c17 | |||
ec284bc56a | |||
db2e00d41c | |||
0a616c9fcb | |||
fed3cd9e82 | |||
d0d8a3d4ea | |||
bdf5f88349 | |||
809dbe16d6 | |||
badebfae6b | |||
6693420005 | |||
0e3aab8691 | |||
55840c626c | |||
f0e5656717 | |||
8af0e10aa4 | |||
71f574bc52 | |||
2518d6138f | |||
36be084655 | |||
d863182810 | |||
85c2bc29e6 | |||
4eeeb1557a |
@ -8,3 +8,5 @@ EXTRA_DIST = HACKING MAINTAINERS rationales.txt
|
||||
DISTCLEANFILES = intltool-extract intltool-merge intltool-update po/stamp-it po/.intltool-merge-cache
|
||||
|
||||
DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
|
||||
|
39
NEWS
39
NEWS
@ -1,3 +1,42 @@
|
||||
3.11.2
|
||||
======
|
||||
* Fix resize operations using mouse-button-modifier [Lionel; #710251]
|
||||
* Misc. fixes and cleanups [Jasper, Rico, Florian; #711731]
|
||||
|
||||
Contributors:
|
||||
Lionel Landwerlin, Florian Müllner, Jasper St. Pierre, Rico Tzschichholz
|
||||
|
||||
3.11.1
|
||||
======
|
||||
* Don't require at least one output device to be connected [Giovanni; #709009]
|
||||
* Name the guard window [Andrew; #710346]
|
||||
* Use new UPower API [Bastien]
|
||||
* Expose min-backlight-step [Asad; #710380]
|
||||
* Don't focus the no-focus-window for globally active windows [Jasper; #710296]
|
||||
* Misc. fixes and cleanups [Jasper, Rico, Olav, Magdalen; #709776]
|
||||
|
||||
Contributors:
|
||||
Magdalen Berns, Giovanni Campagna, Asad Mehmood, Bastien Nocera,
|
||||
Jasper St. Pierre, Rico Tzschichholz, Olav Vitters, Andrew Walton
|
||||
|
||||
Translations:
|
||||
Reinout van Schouwen [nl]
|
||||
|
||||
3.10.1
|
||||
======
|
||||
* Don't apply fullscreen workarounds to CSD windows [Giovanni; #708718]
|
||||
* Fix hangs during DND operations [Adel; #709340]
|
||||
* Use nearest-pixel interpolation when possible [Hans; #708389]
|
||||
* Fix tile previews getting stuck on right click during drags [Lionel; #704759]
|
||||
* Misc bug fixes [Giovanni, Jasper; #708420]
|
||||
|
||||
Contributors:
|
||||
Giovanni Campagna, Adel Gadllah, Lionel Landwerlin, Hans Petter Jansson,
|
||||
Jasper St. Pierre
|
||||
|
||||
Translations:
|
||||
Khaled Hosny [ar], Reinout van Schouwen [nl], Carles Ferrando [ca@valencia]
|
||||
|
||||
3.10.0.1
|
||||
========
|
||||
* Fix bug when a window changed size twice in a single frame - this
|
||||
|
@ -1,8 +1,9 @@
|
||||
AC_PREREQ(2.50)
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
m4_define([mutter_major_version], [3])
|
||||
m4_define([mutter_minor_version], [10])
|
||||
m4_define([mutter_micro_version], [0.1])
|
||||
m4_define([mutter_minor_version], [11])
|
||||
m4_define([mutter_micro_version], [2])
|
||||
|
||||
m4_define([mutter_version],
|
||||
[mutter_major_version.mutter_minor_version.mutter_micro_version])
|
||||
@ -76,7 +77,7 @@ MUTTER_PC_MODULES="
|
||||
xcomposite >= 0.2 xfixes xrender xdamage xi >= 1.6.0
|
||||
$CLUTTER_PACKAGE >= 1.15.90
|
||||
cogl-1.0 >= 1.15.6
|
||||
upower-glib > 0.9.11
|
||||
upower-glib >= 0.99.0
|
||||
gnome-desktop-3.0
|
||||
"
|
||||
|
||||
|
@ -49,8 +49,8 @@ FIXXREF_OPTIONS=
|
||||
# Used for dependencies. The docs will be rebuilt if any of these change.
|
||||
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
|
||||
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
|
||||
HFILE_GLOB=$(top_srcdir)/src/*.h
|
||||
CFILE_GLOB=$(top_srcdir)/src/*.c
|
||||
HFILE_GLOB=$(top_srcdir)/src/*/*.h
|
||||
CFILE_GLOB=$(top_srcdir)/src/*/*.c
|
||||
|
||||
# Extra header to include when scanning, which are not under DOC_SOURCE_DIR
|
||||
# e.g. EXTRA_HFILES=$(top_srcdir}/contrib/extra.h
|
||||
|
@ -96,8 +96,6 @@ meta_compositor_hide_window
|
||||
meta_compositor_switch_workspace
|
||||
meta_compositor_maximize_window
|
||||
meta_compositor_unmaximize_window
|
||||
meta_compositor_window_mapped
|
||||
meta_compositor_window_unmapped
|
||||
meta_compositor_sync_window_geometry
|
||||
meta_compositor_set_updates_frozen
|
||||
meta_compositor_queue_frame_drawn
|
||||
@ -207,7 +205,6 @@ meta_key_binding_get_modifiers
|
||||
meta_key_binding_get_mask
|
||||
meta_key_binding_is_builtin
|
||||
meta_keybindings_set_custom_handler
|
||||
meta_keybindings_switch_window
|
||||
meta_screen_ungrab_all_keys
|
||||
meta_screen_grab_all_keys
|
||||
</SECTION>
|
||||
@ -389,6 +386,23 @@ MetaWindowActorPrivate
|
||||
meta_window_actor_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>meta-cullable</FILE>
|
||||
<TITLE>MetaCullable</TITLE>
|
||||
MetaCullable
|
||||
MetaCullableInterface
|
||||
meta_cullable_cull_out
|
||||
meta_cullable_reset_culling
|
||||
meta_cullable_cull_out_children
|
||||
meta_cullable_reset_culling_children
|
||||
<SUBSECTION Standard>
|
||||
META_TYPE_CULLABLE
|
||||
META_CULLABLE
|
||||
META_IS_CULLABLE
|
||||
META_CULLABLE_GET_IFACE
|
||||
meta_cullable_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>prefs</FILE>
|
||||
MetaPreference
|
||||
@ -542,7 +556,10 @@ meta_window_is_override_redirect
|
||||
meta_window_is_skip_taskbar
|
||||
meta_window_get_rect
|
||||
meta_window_get_input_rect
|
||||
meta_window_get_frame_rect
|
||||
meta_window_get_outer_rect
|
||||
meta_window_client_rect_to_frame_rect
|
||||
meta_window_frame_rect_to_client_rect
|
||||
meta_window_get_screen
|
||||
meta_window_get_display
|
||||
meta_window_get_xwindow
|
||||
|
@ -21,6 +21,7 @@ environment.</description>
|
||||
-->
|
||||
<mailing-list rdf:resource="http://mail.gnome.org/mailman/listinfo/gnome-shell-list" />
|
||||
<download-page rdf:resource="http://download.gnome.org/sources/mutter/" />
|
||||
<download-page rdf:resource="http://download.gnome.org/sources/mutter-wayland/" />
|
||||
<bug-database rdf:resource="http://bugzilla.gnome.org/browse.cgi?product=mutter" />
|
||||
|
||||
<category rdf:resource="http://api.gnome.org/doap-extensions#desktop" />
|
||||
|
2834
po/ca@valencia.po
2834
po/ca@valencia.po
File diff suppressed because it is too large
Load Diff
1197
po/zh_CN.po
1197
po/zh_CN.po
File diff suppressed because it is too large
Load Diff
@ -55,7 +55,8 @@ libmutter_la_SOURCES = \
|
||||
compositor/meta-background-actor.c \
|
||||
compositor/meta-background-actor-private.h \
|
||||
compositor/meta-background-group.c \
|
||||
compositor/meta-background-group-private.h \
|
||||
compositor/meta-cullable.c \
|
||||
compositor/meta-cullable.h \
|
||||
compositor/meta-module.c \
|
||||
compositor/meta-module.h \
|
||||
compositor/meta-plugin.c \
|
||||
@ -168,7 +169,9 @@ libmutter_la_SOURCES = \
|
||||
ui/theme.c \
|
||||
meta/theme.h \
|
||||
ui/theme-private.h \
|
||||
ui/ui.c \
|
||||
ui/ui.c
|
||||
|
||||
nodist_libmutter_la_SOURCES = \
|
||||
$(mutter_built_sources)
|
||||
|
||||
libmutter_la_LDFLAGS = -no-undefined
|
||||
@ -249,7 +252,7 @@ Meta-$(api_version).gir: libmutter.la
|
||||
@META_GIR@_FILES = \
|
||||
mutter-enum-types.h \
|
||||
$(libmutterinclude_base_headers) \
|
||||
$(filter %.c,$(libmutter_la_SOURCES))
|
||||
$(filter %.c,$(libmutter_la_SOURCES) $(nodist_libmutter_la_SOURCES))
|
||||
@META_GIR@_SCANNERFLAGS = --warn-all --warn-error
|
||||
|
||||
endif
|
||||
|
@ -17,8 +17,6 @@ struct _MetaCompositor
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
Atom atom_x_root_pixmap;
|
||||
Atom atom_net_wm_window_opacity;
|
||||
guint repaint_func_id;
|
||||
|
||||
ClutterActor *shadow_src;
|
||||
|
@ -42,15 +42,6 @@
|
||||
* the call, so it may be necessary to readjust the display based on the
|
||||
* old_rect to start the animation.
|
||||
*
|
||||
* meta_compositor_window_mapped() and meta_compositor_window_unmapped() are
|
||||
* notifications when the toplevel window (frame or client window) is mapped or
|
||||
* unmapped. That is, when the result of meta_window_toplevel_is_mapped()
|
||||
* changes. The main use of this is to drop resources when a window is unmapped.
|
||||
* A window will always be mapped before meta_compositor_show_window()
|
||||
* is called and will not be unmapped until after meta_compositor_hide_window()
|
||||
* is called. If the live_hidden_windows preference is set, windows will never
|
||||
* be unmapped.
|
||||
*
|
||||
* # Containers #
|
||||
*
|
||||
* There's two containers in the stage that are used to place window actors, here
|
||||
@ -175,31 +166,6 @@ process_damage (MetaCompositor *compositor,
|
||||
meta_window_actor_process_damage (window_actor, event);
|
||||
}
|
||||
|
||||
static void
|
||||
process_property_notify (MetaCompositor *compositor,
|
||||
XPropertyEvent *event,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
|
||||
if (window == NULL)
|
||||
return;
|
||||
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (window_actor == NULL)
|
||||
return;
|
||||
|
||||
/* Check for the opacity changing */
|
||||
if (event->atom == compositor->atom_net_wm_window_opacity)
|
||||
{
|
||||
meta_window_actor_update_opacity (window_actor);
|
||||
DEBUG_TRACE ("process_property_notify: net_wm_window_opacity\n");
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_TRACE ("process_property_notify: unknown\n");
|
||||
}
|
||||
|
||||
static Window
|
||||
get_output_window (MetaScreen *screen)
|
||||
{
|
||||
@ -685,15 +651,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
clutter_actor_add_child (info->stage, info->window_group);
|
||||
clutter_actor_add_child (info->stage, info->top_window_group);
|
||||
|
||||
info->plugin_mgr = meta_plugin_manager_new (screen);
|
||||
|
||||
/*
|
||||
* Delay the creation of the overlay window as long as we can, to avoid
|
||||
* blanking out the screen. This means that during the plugin loading, the
|
||||
* overlay window is not accessible; if the plugin needs to access it
|
||||
* directly, it should hook into the "show" signal on stage, and do
|
||||
* its stuff there.
|
||||
*/
|
||||
info->output = get_output_window (screen);
|
||||
XReparentWindow (xdisplay, xwin, info->output, 0, 0);
|
||||
|
||||
@ -714,6 +671,8 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
|
||||
info->pending_input_region = None;
|
||||
}
|
||||
|
||||
info->plugin_mgr = meta_plugin_manager_new (screen);
|
||||
|
||||
/* Map overlay window before redirecting windows offscreen so we catch their
|
||||
* contents until we show the stage.
|
||||
*/
|
||||
@ -756,7 +715,7 @@ meta_shape_cow_for_window (MetaScreen *screen,
|
||||
int width, height;
|
||||
MetaRectangle rect;
|
||||
|
||||
meta_window_get_outer_rect (metaWindow, &rect);
|
||||
meta_window_get_frame_rect (metaWindow, &rect);
|
||||
|
||||
window_bounds.x = rect.x;
|
||||
window_bounds.y = rect.y;
|
||||
@ -884,6 +843,18 @@ meta_compositor_window_shape_changed (MetaCompositor *compositor,
|
||||
meta_window_actor_update_shape (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_window_opacity_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor;
|
||||
window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_update_opacity (window_actor);
|
||||
}
|
||||
|
||||
/* Clutter makes the assumption that there is only one X window
|
||||
* per stage, which is a valid assumption to make for a generic
|
||||
* application toolkit. As such, it will ignore any events sent
|
||||
@ -990,28 +961,19 @@ meta_compositor_process_event (MetaCompositor *compositor,
|
||||
}
|
||||
}
|
||||
|
||||
switch (event->type)
|
||||
if (event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
|
||||
{
|
||||
case PropertyNotify:
|
||||
process_property_notify (compositor, (XPropertyEvent *) event, window);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (event->type == meta_display_get_damage_event_base (compositor->display) + XDamageNotify)
|
||||
/* Core code doesn't handle damage events, so we need to extract the MetaWindow
|
||||
* ourselves
|
||||
*/
|
||||
if (window == NULL)
|
||||
{
|
||||
/* Core code doesn't handle damage events, so we need to extract the MetaWindow
|
||||
* ourselves
|
||||
*/
|
||||
if (window == NULL)
|
||||
{
|
||||
Window xwin = ((XDamageNotifyEvent *) event)->drawable;
|
||||
window = meta_display_lookup_x_window (compositor->display, xwin);
|
||||
}
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
|
||||
process_damage (compositor, (XDamageNotifyEvent *) event, window);
|
||||
Window xwin = ((XDamageNotifyEvent *) event)->drawable;
|
||||
window = meta_display_lookup_x_window (compositor->display, xwin);
|
||||
}
|
||||
break;
|
||||
|
||||
DEBUG_TRACE ("meta_compositor_process_event (process_damage)\n");
|
||||
process_damage (compositor, (XDamageNotifyEvent *) event, window);
|
||||
}
|
||||
|
||||
/* Clutter needs to know about MapNotify events otherwise it will
|
||||
@ -1311,30 +1273,6 @@ meta_compositor_sync_stack (MetaCompositor *compositor,
|
||||
sync_actor_stacking (info);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_window_mapped (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_window_mapped\n");
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_mapped (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_window_unmapped (MetaCompositor *compositor,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
|
||||
DEBUG_TRACE ("meta_compositor_window_unmapped\n");
|
||||
if (!window_actor)
|
||||
return;
|
||||
|
||||
meta_window_actor_unmapped (window_actor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_compositor_sync_window_geometry (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
@ -1515,13 +1453,7 @@ on_shadow_factory_changed (MetaShadowFactory *factory,
|
||||
MetaCompositor *
|
||||
meta_compositor_new (MetaDisplay *display)
|
||||
{
|
||||
char *atom_names[] = {
|
||||
"_XROOTPMAP_ID",
|
||||
"_NET_WM_WINDOW_OPACITY",
|
||||
};
|
||||
Atom atoms[G_N_ELEMENTS(atom_names)];
|
||||
MetaCompositor *compositor;
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
|
||||
if (!composite_at_least_version (display, 0, 3))
|
||||
return NULL;
|
||||
@ -1533,18 +1465,11 @@ meta_compositor_new (MetaDisplay *display)
|
||||
if (g_getenv("META_DISABLE_MIPMAPS"))
|
||||
compositor->no_mipmaps = TRUE;
|
||||
|
||||
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
|
||||
XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
|
||||
False, atoms);
|
||||
|
||||
g_signal_connect (meta_shadow_factory_get_default (),
|
||||
"changed",
|
||||
G_CALLBACK (on_shadow_factory_changed),
|
||||
compositor);
|
||||
|
||||
compositor->atom_x_root_pixmap = atoms[0];
|
||||
compositor->atom_net_wm_window_opacity = atoms[1];
|
||||
|
||||
compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
|
||||
compositor,
|
||||
NULL);
|
||||
|
@ -6,9 +6,6 @@
|
||||
#include <meta/screen.h>
|
||||
#include <meta/meta-background-actor.h>
|
||||
|
||||
void meta_background_actor_set_clip_region (MetaBackgroundActor *self,
|
||||
cairo_region_t *clip_region);
|
||||
|
||||
cairo_region_t *meta_background_actor_get_clip_region (MetaBackgroundActor *self);
|
||||
|
||||
#endif /* META_BACKGROUND_ACTOR_PRIVATE_H */
|
||||
|
@ -41,20 +41,35 @@
|
||||
#include <meta/errors.h>
|
||||
#include <meta/meta-background.h>
|
||||
#include "meta-background-actor-private.h"
|
||||
#include "meta-cullable.h"
|
||||
|
||||
struct _MetaBackgroundActorPrivate
|
||||
{
|
||||
cairo_region_t *clip_region;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR);
|
||||
static void cullable_iface_init (MetaCullableInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (MetaBackgroundActor, meta_background_actor, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
|
||||
|
||||
static void
|
||||
set_clip_region (MetaBackgroundActor *self,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv = self->priv;
|
||||
|
||||
g_clear_pointer (&priv->clip_region, (GDestroyNotify) cairo_region_destroy);
|
||||
if (clip_region)
|
||||
priv->clip_region = cairo_region_copy (clip_region);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_dispose (GObject *object)
|
||||
{
|
||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (object);
|
||||
|
||||
meta_background_actor_set_clip_region (self, NULL);
|
||||
set_clip_region (self, NULL);
|
||||
|
||||
G_OBJECT_CLASS (meta_background_actor_parent_class)->dispose (object);
|
||||
}
|
||||
@ -104,26 +119,6 @@ meta_background_actor_get_preferred_height (ClutterActor *actor,
|
||||
*natural_height_p = height;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_background_actor_get_paint_volume (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
ClutterContent *content;
|
||||
gfloat width, height;
|
||||
|
||||
content = clutter_actor_get_content (actor);
|
||||
|
||||
if (!content)
|
||||
return FALSE;
|
||||
|
||||
clutter_content_get_preferred_size (content, &width, &height);
|
||||
|
||||
clutter_paint_volume_set_width (volume, width);
|
||||
clutter_paint_volume_set_height (volume, height);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_actor_class_init (MetaBackgroundActorClass *klass)
|
||||
{
|
||||
@ -136,7 +131,6 @@ meta_background_actor_class_init (MetaBackgroundActorClass *klass)
|
||||
|
||||
actor_class->get_preferred_width = meta_background_actor_get_preferred_width;
|
||||
actor_class->get_preferred_height = meta_background_actor_get_preferred_height;
|
||||
actor_class->get_paint_volume = meta_background_actor_get_paint_volume;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -166,31 +160,27 @@ meta_background_actor_new (void)
|
||||
return CLUTTER_ACTOR (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_background_actor_set_clip_region:
|
||||
* @self: a #MetaBackgroundActor
|
||||
* @clip_region: (allow-none): the area of the actor (in allocate-relative
|
||||
* coordinates) that is visible.
|
||||
*
|
||||
* Sets the area of the background that is unobscured by overlapping windows.
|
||||
* This is used to optimize and only paint the visible portions.
|
||||
*/
|
||||
void
|
||||
meta_background_actor_set_clip_region (MetaBackgroundActor *self,
|
||||
cairo_region_t *clip_region)
|
||||
static void
|
||||
meta_background_actor_cull_out (MetaCullable *cullable,
|
||||
cairo_region_t *unobscured_region,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
MetaBackgroundActorPrivate *priv;
|
||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (cullable);
|
||||
set_clip_region (self, clip_region);
|
||||
}
|
||||
|
||||
g_return_if_fail (META_IS_BACKGROUND_ACTOR (self));
|
||||
static void
|
||||
meta_background_actor_reset_culling (MetaCullable *cullable)
|
||||
{
|
||||
MetaBackgroundActor *self = META_BACKGROUND_ACTOR (cullable);
|
||||
set_clip_region (self, NULL);
|
||||
}
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
g_clear_pointer (&priv->clip_region,
|
||||
(GDestroyNotify)
|
||||
cairo_region_destroy);
|
||||
|
||||
if (clip_region)
|
||||
priv->clip_region = cairo_region_copy (clip_region);
|
||||
static void
|
||||
cullable_iface_init (MetaCullableInterface *iface)
|
||||
{
|
||||
iface->cull_out = meta_background_actor_cull_out;
|
||||
iface->reset_culling = meta_background_actor_reset_culling;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,11 +0,0 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
#ifndef META_BACKGROUND_GROUP_PRIVATE_H
|
||||
#define META_BACKGROUND_GROUP_PRIVATE_H
|
||||
|
||||
#include <meta/screen.h>
|
||||
#include <meta/meta-background-group.h>
|
||||
|
||||
void meta_background_group_set_clip_region (MetaBackgroundGroup *self,
|
||||
cairo_region_t *visible_region);
|
||||
#endif /* META_BACKGROUND_GROUP_PRIVATE_H */
|
@ -16,87 +16,43 @@
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include "compositor-private.h"
|
||||
#include "clutter-utils.h"
|
||||
#include "meta-background-actor-private.h"
|
||||
#include "meta-background-group-private.h"
|
||||
#include <meta/meta-background-group.h>
|
||||
#include "meta-cullable.h"
|
||||
|
||||
G_DEFINE_TYPE (MetaBackgroundGroup, meta_background_group, CLUTTER_TYPE_ACTOR);
|
||||
static void cullable_iface_init (MetaCullableInterface *iface);
|
||||
|
||||
struct _MetaBackgroundGroupPrivate
|
||||
{
|
||||
gpointer dummy;
|
||||
};
|
||||
|
||||
static void
|
||||
meta_background_group_dispose (GObject *object)
|
||||
{
|
||||
G_OBJECT_CLASS (meta_background_group_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_background_group_get_paint_volume (ClutterActor *actor,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
return clutter_paint_volume_set_from_allocation (volume, actor);
|
||||
}
|
||||
G_DEFINE_TYPE_WITH_CODE (MetaBackgroundGroup, meta_background_group, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
|
||||
|
||||
static void
|
||||
meta_background_group_class_init (MetaBackgroundGroupClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
}
|
||||
|
||||
actor_class->get_paint_volume = meta_background_group_get_paint_volume;
|
||||
object_class->dispose = meta_background_group_dispose;
|
||||
static void
|
||||
meta_background_group_cull_out (MetaCullable *cullable,
|
||||
cairo_region_t *unobscured_region,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
|
||||
}
|
||||
|
||||
g_type_class_add_private (klass, sizeof (MetaBackgroundGroupPrivate));
|
||||
static void
|
||||
meta_background_group_reset_culling (MetaCullable *cullable)
|
||||
{
|
||||
meta_cullable_reset_culling_children (cullable);
|
||||
}
|
||||
|
||||
static void
|
||||
cullable_iface_init (MetaCullableInterface *iface)
|
||||
{
|
||||
iface->cull_out = meta_background_group_cull_out;
|
||||
iface->reset_culling = meta_background_group_reset_culling;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_background_group_init (MetaBackgroundGroup *self)
|
||||
{
|
||||
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||
META_TYPE_BACKGROUND_GROUP,
|
||||
MetaBackgroundGroupPrivate);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_background_group_set_clip_region:
|
||||
* @self: a #MetaBackgroundGroup
|
||||
* @region: (allow-none): the parts of the background to paint
|
||||
*
|
||||
* Sets the area of the backgrounds that is unobscured by overlapping windows.
|
||||
* This is used to optimize and only paint the visible portions.
|
||||
*/
|
||||
void
|
||||
meta_background_group_set_clip_region (MetaBackgroundGroup *self,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
GList *children, *l;
|
||||
|
||||
children = clutter_actor_get_children (CLUTTER_ACTOR (self));
|
||||
for (l = children; l; l = l->next)
|
||||
{
|
||||
ClutterActor *actor = l->data;
|
||||
|
||||
if (META_IS_BACKGROUND_ACTOR (actor))
|
||||
{
|
||||
meta_background_actor_set_clip_region (META_BACKGROUND_ACTOR (actor), region);
|
||||
}
|
||||
else if (META_IS_BACKGROUND_GROUP (actor))
|
||||
{
|
||||
int x, y;
|
||||
|
||||
if (!meta_actor_is_untransformed (actor, &x, &y))
|
||||
continue;
|
||||
|
||||
cairo_region_translate (region, -x, -y);
|
||||
meta_background_group_set_clip_region (META_BACKGROUND_GROUP (actor), region);
|
||||
cairo_region_translate (region, x, y);
|
||||
}
|
||||
}
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
|
191
src/compositor/meta-cullable.c
Normal file
191
src/compositor/meta-cullable.c
Normal file
@ -0,0 +1,191 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Written by:
|
||||
* Owen Taylor <otaylor@redhat.com>
|
||||
* Ray Strode <rstrode@redhat.com>
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "meta-cullable.h"
|
||||
#include "clutter-utils.h"
|
||||
|
||||
G_DEFINE_INTERFACE (MetaCullable, meta_cullable, CLUTTER_TYPE_ACTOR);
|
||||
|
||||
/**
|
||||
* SECTION:meta-cullable
|
||||
* @title: MetaCullable
|
||||
* @short_description: CPU culling operations for efficient drawing
|
||||
*
|
||||
* When we are painting a stack of 5-10 large actors, the standard
|
||||
* bottom-to-top method of drawing every actor results in a tremendous
|
||||
* amount of overdraw. If these actors are painting textures like
|
||||
* windows, it can easily max out the available memory bandwidth on a
|
||||
* low-end graphics chipset. It's even worse if window textures are
|
||||
* being accessed over the AGP bus.
|
||||
*
|
||||
* #MetaCullable is our solution. The basic technique applied here is to
|
||||
* do a pre-pass before painting where we walk each actor from top to bottom
|
||||
* and ask each actor to "cull itself out". We pass in a region it can copy
|
||||
* to clip its drawing to, and the actor can subtract its fully opaque pixels
|
||||
* so that actors underneath know not to draw there as well.
|
||||
*/
|
||||
|
||||
/**
|
||||
* meta_cullable_cull_out_children:
|
||||
* @cullable: The #MetaCullable
|
||||
* @unobscured_region: The unobscured region, as passed into cull_out()
|
||||
* @clip_region: The clip region, as passed into cull_out()
|
||||
*
|
||||
* This is a helper method for actors that want to recurse over their
|
||||
* child actors, and cull them out.
|
||||
*
|
||||
* See #MetaCullable and meta_cullable_cull_out() for more details.
|
||||
*/
|
||||
void
|
||||
meta_cullable_cull_out_children (MetaCullable *cullable,
|
||||
cairo_region_t *unobscured_region,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
ClutterActor *actor = CLUTTER_ACTOR (cullable);
|
||||
ClutterActor *child;
|
||||
ClutterActorIter iter;
|
||||
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_prev (&iter, &child))
|
||||
{
|
||||
int x, y;
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
|
||||
continue;
|
||||
|
||||
/* If an actor has effects applied, then that can change the area
|
||||
* it paints and the opacity, so we no longer can figure out what
|
||||
* portion of the actor is obscured and what portion of the screen
|
||||
* it obscures, so we skip the actor.
|
||||
*
|
||||
* This has a secondary beneficial effect: if a ClutterOffscreenEffect
|
||||
* is applied to an actor, then our clipped redraws interfere with the
|
||||
* caching of the FBO - even if we only need to draw a small portion
|
||||
* of the window right now, ClutterOffscreenEffect may use other portions
|
||||
* of the FBO later. So, skipping actors with effects applied also
|
||||
* prevents these bugs.
|
||||
*
|
||||
* Theoretically, we should check clutter_actor_get_offscreen_redirect()
|
||||
* as well for the same reason, but omitted for simplicity in the
|
||||
* hopes that no-one will do that.
|
||||
*/
|
||||
if (clutter_actor_has_effects (child))
|
||||
continue;
|
||||
|
||||
if (!META_IS_CULLABLE (child))
|
||||
continue;
|
||||
|
||||
if (!meta_actor_is_untransformed (child, &x, &y))
|
||||
continue;
|
||||
|
||||
/* Temporarily move to the coordinate system of the actor */
|
||||
cairo_region_translate (unobscured_region, - x, - y);
|
||||
cairo_region_translate (clip_region, - x, - y);
|
||||
|
||||
meta_cullable_cull_out (META_CULLABLE (child), unobscured_region, clip_region);
|
||||
|
||||
cairo_region_translate (unobscured_region, x, y);
|
||||
cairo_region_translate (clip_region, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_cullable_reset_culling_children:
|
||||
* @cullable: The #MetaCullable
|
||||
*
|
||||
* This is a helper method for actors that want to recurse over their
|
||||
* child actors, and cull them out.
|
||||
*
|
||||
* See #MetaCullable and meta_cullable_reset_culling() for more details.
|
||||
*/
|
||||
void
|
||||
meta_cullable_reset_culling_children (MetaCullable *cullable)
|
||||
{
|
||||
ClutterActor *actor = CLUTTER_ACTOR (cullable);
|
||||
ClutterActor *child;
|
||||
ClutterActorIter iter;
|
||||
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
if (!META_IS_CULLABLE (child))
|
||||
continue;
|
||||
|
||||
meta_cullable_reset_culling (META_CULLABLE (child));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cullable_default_init (MetaCullableInterface *iface)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_cullable_cull_out:
|
||||
* @cullable: The #MetaCullable
|
||||
* @unobscured_region: The unobscured region, in @cullable's space.
|
||||
* @clip_region: The clip region, in @cullable's space.
|
||||
*
|
||||
* When #MetaWindowGroup is painted, we walk over its direct cullable
|
||||
* children from top to bottom and ask themselves to "cull out". Cullables
|
||||
* can use @unobscured_region and @clip_region to clip their drawing. Actors
|
||||
* interested in eliminating overdraw should copy the @clip_region and only
|
||||
* paint those parts, as everything else has been obscured by actors above it.
|
||||
*
|
||||
* Actors that may have fully opaque parts should also subtract out a region
|
||||
* that is fully opaque from @unobscured_region and @clip_region.
|
||||
*
|
||||
* @unobscured_region and @clip_region are extremely similar. The difference
|
||||
* is that @clip_region starts off with the stage's clip, if Clutter detects
|
||||
* that we're doing a clipped redraw. @unobscured_region, however, starts off
|
||||
* with the full stage size, so actors that may want to record what parts of
|
||||
* their window are unobscured for e.g. scheduling repaints can do so.
|
||||
*
|
||||
* Actors that have children can also use the meta_cullable_cull_out_children()
|
||||
* helper method to do a simple cull across all their children.
|
||||
*/
|
||||
void
|
||||
meta_cullable_cull_out (MetaCullable *cullable,
|
||||
cairo_region_t *unobscured_region,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
META_CULLABLE_GET_IFACE (cullable)->cull_out (cullable, unobscured_region, clip_region);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_cullable_reset_culling:
|
||||
* @cullable: The #MetaCullable
|
||||
*
|
||||
* Actors that copied data in their cull_out() implementation can now
|
||||
* reset their data, as the paint is now over. Additional paints may be
|
||||
* done by #ClutterClone or similar, and they should not be affected by
|
||||
* the culling operation.
|
||||
*/
|
||||
void
|
||||
meta_cullable_reset_culling (MetaCullable *cullable)
|
||||
{
|
||||
META_CULLABLE_GET_IFACE (cullable)->reset_culling (cullable);
|
||||
}
|
68
src/compositor/meta-cullable.h
Normal file
68
src/compositor/meta-cullable.h
Normal file
@ -0,0 +1,68 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2013 Red Hat
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Written by:
|
||||
* Owen Taylor <otaylor@redhat.com>
|
||||
* Ray Strode <rstrode@redhat.com>
|
||||
* Jasper St. Pierre <jstpierre@mecheye.net>
|
||||
*/
|
||||
|
||||
#ifndef __META_CULLABLE_H__
|
||||
#define __META_CULLABLE_H__
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define META_TYPE_CULLABLE (meta_cullable_get_type ())
|
||||
#define META_CULLABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_CULLABLE, MetaCullable))
|
||||
#define META_IS_CULLABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_CULLABLE))
|
||||
#define META_CULLABLE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), META_TYPE_CULLABLE, MetaCullableInterface))
|
||||
|
||||
typedef struct _MetaCullable MetaCullable;
|
||||
typedef struct _MetaCullableInterface MetaCullableInterface;
|
||||
|
||||
struct _MetaCullableInterface
|
||||
{
|
||||
GTypeInterface g_iface;
|
||||
|
||||
void (* cull_out) (MetaCullable *cullable,
|
||||
cairo_region_t *unobscured_region,
|
||||
cairo_region_t *clip_region);
|
||||
void (* reset_culling) (MetaCullable *cullable);
|
||||
};
|
||||
|
||||
GType meta_cullable_get_type (void);
|
||||
|
||||
void meta_cullable_cull_out (MetaCullable *cullable,
|
||||
cairo_region_t *unobscured_region,
|
||||
cairo_region_t *clip_region);
|
||||
void meta_cullable_reset_culling (MetaCullable *cullable);
|
||||
|
||||
/* Utility methods for implementations */
|
||||
void meta_cullable_cull_out_children (MetaCullable *cullable,
|
||||
cairo_region_t *unobscured_region,
|
||||
cairo_region_t *clip_region);
|
||||
void meta_cullable_reset_culling_children (MetaCullable *cullable);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __META_CULLABLE_H__ */
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <config.h>
|
||||
|
||||
#include <meta/meta-shaped-texture.h>
|
||||
#include "clutter-utils.h"
|
||||
#include "meta-texture-tower.h"
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
@ -71,6 +72,7 @@ struct _MetaShapedTexturePrivate
|
||||
|
||||
cairo_region_t *clip_region;
|
||||
cairo_region_t *opaque_region;
|
||||
cairo_region_t *input_shape_region;
|
||||
|
||||
guint tex_width, tex_height;
|
||||
|
||||
@ -209,6 +211,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
CoglTexture *paint_tex;
|
||||
ClutterActorBox alloc;
|
||||
cairo_region_t *blended_region = NULL;
|
||||
CoglPipelineFilter filter;
|
||||
|
||||
if (priv->clip_region && cairo_region_is_empty (priv->clip_region))
|
||||
return;
|
||||
@ -245,6 +248,22 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
|
||||
/* Use nearest-pixel interpolation if the texture is unscaled. This
|
||||
* improves performance, especially with software rendering.
|
||||
*/
|
||||
|
||||
filter = COGL_PIPELINE_FILTER_LINEAR;
|
||||
|
||||
if (!clutter_actor_is_in_clone_paint (actor))
|
||||
{
|
||||
int x_origin, y_origin;
|
||||
|
||||
if (meta_actor_is_untransformed (actor,
|
||||
&x_origin,
|
||||
&y_origin))
|
||||
filter = COGL_PIPELINE_FILTER_NEAREST;
|
||||
}
|
||||
|
||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
fb = cogl_get_draw_framebuffer ();
|
||||
|
||||
@ -273,6 +292,7 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
|
||||
opaque_pipeline = get_unblended_pipeline (ctx);
|
||||
cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex);
|
||||
cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter);
|
||||
|
||||
n_rects = cairo_region_num_rectangles (region);
|
||||
for (i = 0; i < n_rects; i++)
|
||||
@ -314,9 +334,11 @@ meta_shaped_texture_paint (ClutterActor *actor)
|
||||
{
|
||||
pipeline = get_masked_pipeline (ctx);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
|
||||
cogl_pipeline_set_layer_filters (pipeline, 1, filter, filter);
|
||||
}
|
||||
|
||||
cogl_pipeline_set_layer_texture (pipeline, 0, paint_tex);
|
||||
cogl_pipeline_set_layer_filters (pipeline, 0, filter, filter);
|
||||
|
||||
{
|
||||
CoglColor color;
|
||||
@ -373,45 +395,60 @@ meta_shaped_texture_pick (ClutterActor *actor,
|
||||
MetaShapedTexture *stex = (MetaShapedTexture *) actor;
|
||||
MetaShapedTexturePrivate *priv = stex->priv;
|
||||
|
||||
if (!clutter_actor_should_pick_paint (actor) ||
|
||||
(priv->clip_region && cairo_region_is_empty (priv->clip_region)))
|
||||
return;
|
||||
|
||||
/* If there is no region then use the regular pick */
|
||||
if (priv->mask_texture == NULL)
|
||||
if (priv->input_shape_region == NULL)
|
||||
CLUTTER_ACTOR_CLASS (meta_shaped_texture_parent_class)->pick (actor, color);
|
||||
else if (clutter_actor_should_pick_paint (actor))
|
||||
else
|
||||
{
|
||||
CoglTexture *paint_tex;
|
||||
ClutterActorBox alloc;
|
||||
guint tex_width, tex_height;
|
||||
int n_rects;
|
||||
float *rectangles;
|
||||
int i;
|
||||
CoglPipeline *pipeline;
|
||||
CoglContext *ctx;
|
||||
CoglFramebuffer *fb;
|
||||
CoglColor cogl_color;
|
||||
|
||||
paint_tex = COGL_TEXTURE (priv->texture);
|
||||
/* Note: We don't bother trying to intersect the pick and clip regions
|
||||
* since needing to copy the region, do the intersection, and probably
|
||||
* increase the number of rectangles seems more likely to have a negative
|
||||
* effect.
|
||||
*
|
||||
* NB: Most of the time when just using rectangles for picking then
|
||||
* picking shouldn't involve any rendering, and minimizing the number of
|
||||
* rectangles has more benefit than reducing the area of the pick
|
||||
* region.
|
||||
*/
|
||||
|
||||
if (paint_tex == NULL)
|
||||
return;
|
||||
n_rects = cairo_region_num_rectangles (priv->input_shape_region);
|
||||
rectangles = g_alloca (sizeof (float) * 4 * n_rects);
|
||||
|
||||
tex_width = cogl_texture_get_width (paint_tex);
|
||||
tex_height = cogl_texture_get_height (paint_tex);
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
cairo_rectangle_int_t rect;
|
||||
int pos = i * 4;
|
||||
|
||||
if (tex_width == 0 || tex_height == 0) /* no contents yet */
|
||||
return;
|
||||
cairo_region_get_rectangle (priv->input_shape_region, i, &rect);
|
||||
|
||||
rectangles[pos] = rect.x;
|
||||
rectangles[pos + 1] = rect.y;
|
||||
rectangles[pos + 2] = rect.x + rect.width;
|
||||
rectangles[pos + 3] = rect.y + rect.height;
|
||||
}
|
||||
|
||||
ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
|
||||
fb = cogl_get_draw_framebuffer ();
|
||||
|
||||
cogl_color_init_from_4ub (&cogl_color, color->red, color->green, color->blue, color->alpha);
|
||||
|
||||
pipeline = get_masked_pipeline (ctx);
|
||||
cogl_pipeline_set_layer_texture (pipeline, 1, priv->mask_texture);
|
||||
pipeline = cogl_pipeline_new (ctx);
|
||||
cogl_pipeline_set_color (pipeline, &cogl_color);
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &alloc);
|
||||
|
||||
cogl_framebuffer_draw_rectangle (fb, pipeline,
|
||||
0, 0,
|
||||
alloc.x2 - alloc.x1,
|
||||
alloc.y2 - alloc.y1);
|
||||
cogl_framebuffer_draw_rectangles (fb, pipeline,
|
||||
rectangles, n_rects);
|
||||
cogl_object_unref (pipeline);
|
||||
}
|
||||
}
|
||||
@ -670,6 +707,41 @@ meta_shaped_texture_get_texture (MetaShapedTexture *stex)
|
||||
return COGL_TEXTURE (stex->priv->texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_input_shape_region:
|
||||
* @stex: a #MetaShapedTexture
|
||||
* @shape_region: the region of the texture that should respond to
|
||||
* input.
|
||||
*
|
||||
* Determines what region of the texture should accept input. For
|
||||
* X based windows this is defined by the ShapeInput region of the
|
||||
* window.
|
||||
*/
|
||||
void
|
||||
meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *shape_region)
|
||||
{
|
||||
MetaShapedTexturePrivate *priv;
|
||||
|
||||
g_return_if_fail (META_IS_SHAPED_TEXTURE (stex));
|
||||
|
||||
priv = stex->priv;
|
||||
|
||||
if (priv->input_shape_region != NULL)
|
||||
{
|
||||
cairo_region_destroy (priv->input_shape_region);
|
||||
priv->input_shape_region = NULL;
|
||||
}
|
||||
|
||||
if (shape_region != NULL)
|
||||
{
|
||||
cairo_region_reference (shape_region);
|
||||
priv->input_shape_region = shape_region;
|
||||
}
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stex));
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_shaped_texture_set_clip_region:
|
||||
* @stex: a #MetaShapedTexture
|
||||
|
@ -55,14 +55,6 @@ void meta_window_actor_set_updates_frozen (MetaWindowActor *self,
|
||||
void meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
|
||||
gboolean no_delay_frame);
|
||||
|
||||
cairo_region_t *meta_window_actor_get_obscured_region (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_set_clip_region (MetaWindowActor *self,
|
||||
cairo_region_t *clip_region);
|
||||
void meta_window_actor_set_clip_region_beneath (MetaWindowActor *self,
|
||||
cairo_region_t *beneath_region);
|
||||
void meta_window_actor_reset_clip_regions (MetaWindowActor *self);
|
||||
|
||||
void meta_window_actor_set_unobscured_region (MetaWindowActor *self,
|
||||
cairo_region_t *unobscured_region);
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "meta-texture-rectangle.h"
|
||||
#include "region-utils.h"
|
||||
#include "monitor-private.h"
|
||||
#include "meta-cullable.h"
|
||||
|
||||
enum {
|
||||
POSITION_CHANGED,
|
||||
@ -45,7 +46,6 @@ static guint signals[LAST_SIGNAL] = {0};
|
||||
struct _MetaWindowActorPrivate
|
||||
{
|
||||
MetaWindow *window;
|
||||
Window xwindow;
|
||||
MetaScreen *screen;
|
||||
|
||||
ClutterActor *actor;
|
||||
@ -68,10 +68,10 @@ struct _MetaWindowActorPrivate
|
||||
|
||||
Damage damage;
|
||||
|
||||
guint8 opacity;
|
||||
|
||||
/* A region that matches the shape of the window, including frame bounds */
|
||||
cairo_region_t *shape_region;
|
||||
/* If the window has an input shape, a region that matches the shape */
|
||||
cairo_region_t *input_region;
|
||||
/* The opaque region, from _NET_WM_OPAQUE_REGION, intersected with
|
||||
* the shape region. */
|
||||
cairo_region_t *opaque_region;
|
||||
@ -109,7 +109,6 @@ struct _MetaWindowActorPrivate
|
||||
GList *frames;
|
||||
|
||||
guint visible : 1;
|
||||
guint mapped : 1;
|
||||
guint argb32 : 1;
|
||||
guint disposed : 1;
|
||||
guint redecorating : 1;
|
||||
@ -152,8 +151,6 @@ struct _FrameData
|
||||
enum
|
||||
{
|
||||
PROP_META_WINDOW = 1,
|
||||
PROP_META_SCREEN,
|
||||
PROP_X_WINDOW,
|
||||
PROP_NO_SHADOW,
|
||||
PROP_SHADOW_CLASS
|
||||
};
|
||||
@ -189,7 +186,10 @@ static void do_send_frame_timings (MetaWindowActor *self,
|
||||
gint refresh_interval,
|
||||
gint64 presentation_time);
|
||||
|
||||
G_DEFINE_TYPE (MetaWindowActor, meta_window_actor, CLUTTER_TYPE_ACTOR);
|
||||
static void cullable_iface_init (MetaCullableInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (MetaWindowActor, meta_window_actor, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
|
||||
|
||||
static void
|
||||
frame_data_free (FrameData *frame)
|
||||
@ -219,33 +219,12 @@ meta_window_actor_class_init (MetaWindowActorClass *klass)
|
||||
"MetaWindow",
|
||||
"The displayed MetaWindow",
|
||||
META_TYPE_WINDOW,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_META_WINDOW,
|
||||
pspec);
|
||||
|
||||
pspec = g_param_spec_pointer ("meta-screen",
|
||||
"MetaScreen",
|
||||
"MetaScreen",
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_META_SCREEN,
|
||||
pspec);
|
||||
|
||||
pspec = g_param_spec_ulong ("x-window",
|
||||
"Window",
|
||||
"Window",
|
||||
0,
|
||||
G_MAXULONG,
|
||||
0,
|
||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
|
||||
|
||||
g_object_class_install_property (object_class,
|
||||
PROP_X_WINDOW,
|
||||
pspec);
|
||||
|
||||
pspec = g_param_spec_boolean ("no-shadow",
|
||||
"No shadow",
|
||||
"Do not add shaddow to this window",
|
||||
@ -288,7 +267,6 @@ meta_window_actor_init (MetaWindowActor *self)
|
||||
priv = self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||
META_TYPE_WINDOW_ACTOR,
|
||||
MetaWindowActorPrivate);
|
||||
priv->opacity = 0xff;
|
||||
priv->shadow_class = NULL;
|
||||
}
|
||||
|
||||
@ -299,11 +277,9 @@ window_decorated_notify (MetaWindow *mw,
|
||||
{
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (data);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaFrame *frame = meta_window_get_frame (mw);
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
Window new_xwindow;
|
||||
|
||||
/*
|
||||
* Basically, we have to reconstruct the the internals of this object
|
||||
@ -311,11 +287,6 @@ window_decorated_notify (MetaWindow *mw,
|
||||
*/
|
||||
priv->redecorating = TRUE;
|
||||
|
||||
if (frame)
|
||||
new_xwindow = meta_frame_get_xwindow (frame);
|
||||
else
|
||||
new_xwindow = meta_window_get_xwindow (mw);
|
||||
|
||||
meta_window_actor_detach (self);
|
||||
|
||||
/*
|
||||
@ -330,8 +301,6 @@ window_decorated_notify (MetaWindow *mw,
|
||||
priv->damage = None;
|
||||
}
|
||||
|
||||
priv->xwindow = new_xwindow;
|
||||
|
||||
/*
|
||||
* Recreate the contents.
|
||||
*/
|
||||
@ -346,18 +315,30 @@ window_appears_focused_notify (MetaWindow *mw,
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (data));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_non_opaque (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaWindow *window = priv->window;
|
||||
|
||||
return priv->argb32 || (window->opacity != 0xFF);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_constructed (GObject *object)
|
||||
{
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (object);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaScreen *screen = priv->screen;
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Window xwindow = priv->xwindow;
|
||||
MetaWindow *window = priv->window;
|
||||
MetaScreen *screen = meta_window_get_screen (window);
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
XRenderPictFormat *format;
|
||||
Window xwindow;
|
||||
|
||||
xwindow = meta_window_get_toplevel_xwindow (window);
|
||||
|
||||
priv->screen = screen;
|
||||
priv->damage = XDamageCreate (xdisplay, xwindow,
|
||||
XDamageReportBoundingBox);
|
||||
|
||||
@ -380,19 +361,6 @@ meta_window_actor_constructed (GObject *object)
|
||||
* We will release it in dispose().
|
||||
*/
|
||||
g_object_ref (priv->actor);
|
||||
|
||||
g_signal_connect_object (window, "notify::decorated",
|
||||
G_CALLBACK (window_decorated_notify), self, 0);
|
||||
g_signal_connect_object (window, "notify::appears-focused",
|
||||
G_CALLBACK (window_appears_focused_notify), self, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* This is the case where existing window is gaining/loosing frame.
|
||||
* Just ensure the actor is top most (i.e., above shadow).
|
||||
*/
|
||||
clutter_actor_set_child_above_sibling (CLUTTER_ACTOR (self), priv->actor, NULL);
|
||||
}
|
||||
|
||||
meta_window_actor_update_opacity (self);
|
||||
@ -432,6 +400,7 @@ meta_window_actor_dispose (GObject *object)
|
||||
|
||||
g_clear_pointer (&priv->unobscured_region, cairo_region_destroy);
|
||||
g_clear_pointer (&priv->shape_region, cairo_region_destroy);
|
||||
g_clear_pointer (&priv->input_region, cairo_region_destroy);
|
||||
g_clear_pointer (&priv->opaque_region, cairo_region_destroy);
|
||||
g_clear_pointer (&priv->shadow_clip, cairo_region_destroy);
|
||||
|
||||
@ -484,17 +453,12 @@ meta_window_actor_set_property (GObject *object,
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_META_WINDOW:
|
||||
{
|
||||
if (priv->window)
|
||||
g_object_unref (priv->window);
|
||||
priv->window = g_value_dup_object (value);
|
||||
}
|
||||
break;
|
||||
case PROP_META_SCREEN:
|
||||
priv->screen = g_value_get_pointer (value);
|
||||
break;
|
||||
case PROP_X_WINDOW:
|
||||
priv->xwindow = g_value_get_ulong (value);
|
||||
priv->window = g_value_dup_object (value);
|
||||
|
||||
g_signal_connect_object (priv->window, "notify::decorated",
|
||||
G_CALLBACK (window_decorated_notify), self, 0);
|
||||
g_signal_connect_object (priv->window, "notify::appears-focused",
|
||||
G_CALLBACK (window_appears_focused_notify), self, 0);
|
||||
break;
|
||||
case PROP_NO_SHADOW:
|
||||
{
|
||||
@ -540,12 +504,6 @@ meta_window_actor_get_property (GObject *object,
|
||||
case PROP_META_WINDOW:
|
||||
g_value_set_object (value, priv->window);
|
||||
break;
|
||||
case PROP_META_SCREEN:
|
||||
g_value_set_pointer (value, priv->screen);
|
||||
break;
|
||||
case PROP_X_WINDOW:
|
||||
g_value_set_ulong (value, priv->xwindow);
|
||||
break;
|
||||
case PROP_NO_SHADOW:
|
||||
g_value_set_boolean (value, priv->no_shadow);
|
||||
break;
|
||||
@ -643,7 +601,7 @@ clip_shadow_under_window (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
return (priv->argb32 || priv->opacity != 0xff) && priv->window->frame;
|
||||
return is_non_opaque (self) && priv->window->frame;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -669,6 +627,7 @@ meta_window_actor_paint (ClutterActor *actor)
|
||||
MetaShadowParams params;
|
||||
cairo_rectangle_int_t shape_bounds;
|
||||
cairo_region_t *clip = priv->shadow_clip;
|
||||
MetaWindow *window = priv->window;
|
||||
|
||||
meta_window_actor_get_shape_bounds (self, &shape_bounds);
|
||||
meta_window_actor_get_shadow_params (self, appears_focused, ¶ms);
|
||||
@ -692,7 +651,7 @@ meta_window_actor_paint (ClutterActor *actor)
|
||||
params.y_offset + shape_bounds.y,
|
||||
shape_bounds.width,
|
||||
shape_bounds.height,
|
||||
(clutter_actor_get_paint_opacity (actor) * params.opacity * priv->opacity) / (255 * 255),
|
||||
(clutter_actor_get_paint_opacity (actor) * params.opacity * window->opacity) / (255 * 255),
|
||||
clip,
|
||||
clip_shadow_under_window (self)); /* clip_strictly - not just as an optimization */
|
||||
|
||||
@ -779,10 +738,10 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
* Do not add shadows to ARGB windows; eventually we should generate a
|
||||
* shadow from the input shape for such windows.
|
||||
* Do not add shadows to non-opaque windows; eventually we should generate
|
||||
* a shadow from the input shape for such windows.
|
||||
*/
|
||||
if (priv->argb32 || priv->opacity != 0xff)
|
||||
if (is_non_opaque (self))
|
||||
return FALSE;
|
||||
|
||||
/*
|
||||
@ -813,20 +772,6 @@ meta_window_actor_has_shadow (MetaWindowActor *self)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_actor_get_x_window: (skip)
|
||||
* @self: a #MetaWindowActor
|
||||
*
|
||||
*/
|
||||
Window
|
||||
meta_window_actor_get_x_window (MetaWindowActor *self)
|
||||
{
|
||||
if (!self)
|
||||
return None;
|
||||
|
||||
return self->priv->xwindow;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_actor_get_meta_window:
|
||||
* @self: a #MetaWindowActor
|
||||
@ -973,7 +918,7 @@ queue_send_frame_messages_timeout (MetaWindowActor *self)
|
||||
}
|
||||
|
||||
interval = (int)(1000000 / refresh_rate) * 6;
|
||||
offset = MAX (0, current_time - priv->frame_drawn_time + interval) / 1000;
|
||||
offset = MAX (0, priv->frame_drawn_time + interval - current_time) / 1000;
|
||||
|
||||
/* The clutter master clock source has already been added with META_PRIORITY_REDRAW,
|
||||
* so the timer will run *after* the clutter frame handling, if a frame is ready
|
||||
@ -994,7 +939,7 @@ meta_window_actor_damage_all (MetaWindowActor *self)
|
||||
|
||||
texture = meta_shaped_texture_get_texture (META_SHAPED_TEXTURE (priv->actor));
|
||||
|
||||
if (!priv->mapped || priv->needs_pixmap)
|
||||
if (priv->needs_pixmap)
|
||||
return;
|
||||
|
||||
redraw_queued = meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor),
|
||||
@ -1083,7 +1028,7 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self,
|
||||
{
|
||||
queue_send_frame_messages_timeout (self);
|
||||
}
|
||||
else if (priv->mapped && !priv->needs_pixmap)
|
||||
else
|
||||
{
|
||||
const cairo_rectangle_int_t clip = { 0, 0, 1, 1 };
|
||||
clutter_actor_queue_redraw_with_clip (priv->actor, &clip);
|
||||
@ -1115,9 +1060,6 @@ meta_window_actor_queue_create_pixmap (MetaWindowActor *self)
|
||||
|
||||
priv->needs_pixmap = TRUE;
|
||||
|
||||
if (!priv->mapped)
|
||||
return;
|
||||
|
||||
if (is_frozen (self))
|
||||
return;
|
||||
|
||||
@ -1331,7 +1273,7 @@ meta_window_actor_should_unredirect (MetaWindowActor *self)
|
||||
if (meta_window_requested_dont_bypass_compositor (metaWindow))
|
||||
return FALSE;
|
||||
|
||||
if (priv->opacity != 0xff)
|
||||
if (metaWindow->opacity != 0xFF)
|
||||
return FALSE;
|
||||
|
||||
if (metaWindow->shape_region != NULL)
|
||||
@ -1362,7 +1304,7 @@ meta_window_actor_set_redirected (MetaWindowActor *self, gboolean state)
|
||||
MetaDisplay *display = meta_window_get_display (metaWindow);
|
||||
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
Window xwin = meta_window_actor_get_x_window (self);
|
||||
Window xwin = meta_window_get_toplevel_xwindow (metaWindow);
|
||||
|
||||
if (state)
|
||||
{
|
||||
@ -1616,22 +1558,10 @@ meta_window_actor_new (MetaWindow *window)
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
MetaWindowActor *self;
|
||||
MetaWindowActorPrivate *priv;
|
||||
MetaFrame *frame;
|
||||
Window top_window;
|
||||
ClutterActor *window_group;
|
||||
|
||||
frame = meta_window_get_frame (window);
|
||||
if (frame)
|
||||
top_window = meta_frame_get_xwindow (frame);
|
||||
else
|
||||
top_window = meta_window_get_xwindow (window);
|
||||
|
||||
meta_verbose ("add window: Meta %p, xwin 0x%x\n", window, (guint)top_window);
|
||||
|
||||
self = g_object_new (META_TYPE_WINDOW_ACTOR,
|
||||
"meta-window", window,
|
||||
"x-window", top_window,
|
||||
"meta-screen", screen,
|
||||
"meta-window", window,
|
||||
NULL);
|
||||
|
||||
priv = self->priv;
|
||||
@ -1639,10 +1569,6 @@ meta_window_actor_new (MetaWindow *window)
|
||||
priv->last_width = -1;
|
||||
priv->last_height = -1;
|
||||
|
||||
priv->mapped = meta_window_toplevel_is_mapped (priv->window);
|
||||
if (priv->mapped)
|
||||
meta_window_actor_queue_create_pixmap (self);
|
||||
|
||||
meta_window_actor_set_updates_frozen (self,
|
||||
meta_window_updates_are_frozen (priv->window));
|
||||
|
||||
@ -1676,34 +1602,6 @@ meta_window_actor_new (MetaWindow *window)
|
||||
return self;
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_actor_mapped (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
g_return_if_fail (!priv->mapped);
|
||||
|
||||
priv->mapped = TRUE;
|
||||
|
||||
meta_window_actor_queue_create_pixmap (self);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_actor_unmapped (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
g_return_if_fail (priv->mapped);
|
||||
|
||||
priv->mapped = FALSE;
|
||||
|
||||
if (meta_window_actor_effect_in_progress (self))
|
||||
return;
|
||||
|
||||
meta_window_actor_detach (self);
|
||||
priv->needs_pixmap = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_actor_get_obscured_region:
|
||||
* @self: a #MetaWindowActor
|
||||
@ -1714,12 +1612,13 @@ meta_window_actor_unmapped (MetaWindowActor *self)
|
||||
* Return value: (transfer none): the area obscured by the window,
|
||||
* %NULL is the same as an empty region.
|
||||
*/
|
||||
cairo_region_t *
|
||||
static cairo_region_t *
|
||||
meta_window_actor_get_obscured_region (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaWindow *window = priv->window;
|
||||
|
||||
if (priv->back_pixmap && priv->opacity == 0xff && !priv->window->shaded)
|
||||
if (priv->back_pixmap && window->opacity != 0xFF && !priv->window->shaded)
|
||||
return priv->opaque_region;
|
||||
else
|
||||
return NULL;
|
||||
@ -1803,7 +1702,7 @@ meta_window_actor_set_unobscured_region (MetaWindowActor *self,
|
||||
* not drawn in this frame.
|
||||
* This will be set before painting then unset afterwards.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
meta_window_actor_set_clip_region (MetaWindowActor *self,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
@ -1825,7 +1724,7 @@ meta_window_actor_set_clip_region (MetaWindowActor *self,
|
||||
* shadow hid by the window itself. This will be set before painting
|
||||
* then unset afterwards.
|
||||
*/
|
||||
void
|
||||
static void
|
||||
meta_window_actor_set_clip_region_beneath (MetaWindowActor *self,
|
||||
cairo_region_t *beneath_region)
|
||||
{
|
||||
@ -1845,16 +1744,38 @@ meta_window_actor_set_clip_region_beneath (MetaWindowActor *self,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_actor_reset_clip_regions:
|
||||
* @self: a #MetaWindowActor
|
||||
*
|
||||
* Unsets the regions set by meta_window_actor_set_clip_region() and
|
||||
* meta_window_actor_set_clip_region_beneath()
|
||||
*/
|
||||
void
|
||||
meta_window_actor_reset_clip_regions (MetaWindowActor *self)
|
||||
static void
|
||||
meta_window_actor_cull_out (MetaCullable *cullable,
|
||||
cairo_region_t *unobscured_region,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (self->priv->screen);
|
||||
|
||||
/* Don't do any culling for the unredirected window */
|
||||
if (self == info->unredirected_window)
|
||||
return;
|
||||
|
||||
meta_window_actor_set_unobscured_region (self, unobscured_region);
|
||||
meta_window_actor_set_clip_region (self, clip_region);
|
||||
|
||||
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self)) == 0xff)
|
||||
{
|
||||
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (self);
|
||||
if (obscured_region)
|
||||
{
|
||||
cairo_region_subtract (unobscured_region, obscured_region);
|
||||
cairo_region_subtract (clip_region, obscured_region);
|
||||
}
|
||||
}
|
||||
|
||||
meta_window_actor_set_clip_region_beneath (self, clip_region);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_reset_culling (MetaCullable *cullable)
|
||||
{
|
||||
MetaWindowActor *self = META_WINDOW_ACTOR (cullable);
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
|
||||
meta_shaped_texture_set_clip_region (META_SHAPED_TEXTURE (priv->actor),
|
||||
@ -1862,6 +1783,13 @@ meta_window_actor_reset_clip_regions (MetaWindowActor *self)
|
||||
g_clear_pointer (&priv->shadow_clip, cairo_region_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
cullable_iface_init (MetaCullableInterface *iface)
|
||||
{
|
||||
iface->cull_out = meta_window_actor_cull_out;
|
||||
iface->reset_culling = meta_window_actor_reset_culling;
|
||||
}
|
||||
|
||||
static void
|
||||
check_needs_pixmap (MetaWindowActor *self)
|
||||
{
|
||||
@ -1870,15 +1798,12 @@ check_needs_pixmap (MetaWindowActor *self)
|
||||
MetaDisplay *display = meta_screen_get_display (screen);
|
||||
Display *xdisplay = meta_display_get_xdisplay (display);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (screen);
|
||||
Window xwindow = meta_window_get_toplevel_xwindow (priv->window);
|
||||
MetaCompositor *compositor;
|
||||
Window xwindow = priv->xwindow;
|
||||
|
||||
if (!priv->needs_pixmap)
|
||||
return;
|
||||
|
||||
if (!priv->mapped)
|
||||
return;
|
||||
|
||||
if (xwindow == meta_screen_get_xroot (screen) ||
|
||||
xwindow == clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage)))
|
||||
return;
|
||||
@ -1936,7 +1861,7 @@ check_needs_pixmap (MetaWindowActor *self)
|
||||
if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture))))
|
||||
g_warning ("NOTE: Not using GLX TFP!\n");
|
||||
|
||||
/* ::size-changed is supposed to refer to meta_window_get_outer_rect().
|
||||
/* ::size-changed is supposed to refer to meta_window_get_frame_rect().
|
||||
* Emitting it here works pretty much OK because a new value of the
|
||||
* *input* rect (which is the outer rect with the addition of invisible
|
||||
* borders) forces a new pixmap and we get here. In the rare case where
|
||||
@ -1964,9 +1889,6 @@ check_needs_shadow (MetaWindowActor *self)
|
||||
gboolean should_have_shadow;
|
||||
gboolean appears_focused;
|
||||
|
||||
if (!priv->mapped)
|
||||
return;
|
||||
|
||||
/* Calling meta_window_actor_has_shadow() here at every pre-paint is cheap
|
||||
* and avoids the need to explicitly handle window type changes, which
|
||||
* we would do if tried to keep track of when we might be adding or removing
|
||||
@ -2032,7 +1954,7 @@ meta_window_actor_process_damage (MetaWindowActor *self,
|
||||
if (meta_window_is_fullscreen (priv->window) && g_list_last (info->windows)->data == self && !priv->unredirected)
|
||||
{
|
||||
MetaRectangle window_rect;
|
||||
meta_window_get_outer_rect (priv->window, &window_rect);
|
||||
meta_window_get_frame_rect (priv->window, &window_rect);
|
||||
|
||||
if (window_rect.x == event->area.x &&
|
||||
window_rect.y == event->area.y &&
|
||||
@ -2070,7 +1992,7 @@ meta_window_actor_process_damage (MetaWindowActor *self,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!priv->mapped || priv->needs_pixmap)
|
||||
if (priv->needs_pixmap)
|
||||
return;
|
||||
|
||||
redraw_queued = meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor),
|
||||
@ -2256,9 +2178,46 @@ meta_window_actor_update_shape_region (MetaWindowActor *self,
|
||||
priv->shape_region = region;
|
||||
|
||||
g_clear_pointer (&priv->shadow_shape, meta_window_shape_unref);
|
||||
|
||||
meta_window_actor_invalidate_shadow (self);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_update_input_region (MetaWindowActor *self,
|
||||
cairo_rectangle_int_t *client_area)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaShapedTexture *stex = META_SHAPED_TEXTURE (priv->actor);
|
||||
cairo_region_t *region = NULL;
|
||||
|
||||
if (priv->window->frame != NULL && priv->window->input_region != NULL)
|
||||
{
|
||||
region = meta_frame_get_frame_bounds (priv->window->frame);
|
||||
|
||||
cairo_region_subtract_rectangle (region, client_area);
|
||||
|
||||
/* input_region is in client window coordinates, so translate the
|
||||
* input region into that coordinate system and back */
|
||||
cairo_region_translate (region, -client_area->x, -client_area->y);
|
||||
cairo_region_union (region, priv->window->input_region);
|
||||
cairo_region_translate (region, client_area->x, client_area->y);
|
||||
}
|
||||
else if (priv->window->input_region != NULL)
|
||||
{
|
||||
region = cairo_region_reference (priv->window->input_region);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If we don't have a shape on the server, that means that
|
||||
* we have an implicit shape of one rectangle covering the
|
||||
* entire window. */
|
||||
region = cairo_region_create_rectangle (client_area);
|
||||
}
|
||||
|
||||
meta_shaped_texture_set_input_shape_region (stex, region);
|
||||
cairo_region_destroy (region);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_actor_update_opaque_region (MetaWindowActor *self)
|
||||
{
|
||||
@ -2302,9 +2261,6 @@ check_needs_reshape (MetaWindowActor *self)
|
||||
MetaFrameBorders borders;
|
||||
cairo_rectangle_int_t client_area;
|
||||
|
||||
if (!priv->mapped)
|
||||
return;
|
||||
|
||||
if (!priv->needs_reshape)
|
||||
return;
|
||||
|
||||
@ -2319,10 +2275,10 @@ check_needs_reshape (MetaWindowActor *self)
|
||||
client_area.height = priv->window->rect.height;
|
||||
|
||||
meta_window_actor_update_shape_region (self, &client_area);
|
||||
meta_window_actor_update_input_region (self, &client_area);
|
||||
meta_window_actor_update_opaque_region (self);
|
||||
|
||||
priv->needs_reshape = FALSE;
|
||||
meta_window_actor_invalidate_shadow (self);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2567,23 +2523,9 @@ void
|
||||
meta_window_actor_update_opacity (MetaWindowActor *self)
|
||||
{
|
||||
MetaWindowActorPrivate *priv = self->priv;
|
||||
MetaDisplay *display = meta_screen_get_display (priv->screen);
|
||||
MetaCompositor *compositor = meta_display_get_compositor (display);
|
||||
Window xwin = meta_window_get_xwindow (priv->window);
|
||||
gulong value;
|
||||
guint8 opacity;
|
||||
MetaWindow *window = priv->window;
|
||||
|
||||
if (meta_prop_get_cardinal (display, xwin,
|
||||
compositor->atom_net_wm_window_opacity,
|
||||
&value))
|
||||
{
|
||||
opacity = (guint8)((gfloat)value * 255.0 / ((gfloat)0xffffffff));
|
||||
}
|
||||
else
|
||||
opacity = 255;
|
||||
|
||||
self->priv->opacity = opacity;
|
||||
clutter_actor_set_opacity (self->priv->actor, opacity);
|
||||
clutter_actor_set_opacity (self->priv->actor, window->opacity);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -11,8 +11,8 @@
|
||||
#include "compositor-private.h"
|
||||
#include "meta-window-actor-private.h"
|
||||
#include "meta-window-group.h"
|
||||
#include "meta-background-actor-private.h"
|
||||
#include "meta-background-group-private.h"
|
||||
#include "window-private.h"
|
||||
#include "meta-cullable.h"
|
||||
|
||||
struct _MetaWindowGroupClass
|
||||
{
|
||||
@ -26,7 +26,10 @@ struct _MetaWindowGroup
|
||||
MetaScreen *screen;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_ACTOR);
|
||||
static void cullable_iface_init (MetaCullableInterface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (MetaWindowGroup, meta_window_group, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (META_TYPE_CULLABLE, cullable_iface_init));
|
||||
|
||||
/* Help macros to scale from OpenGL <-1,1> coordinates system to
|
||||
* window coordinates ranging [0,window-size]. Borrowed from clutter-utils.c
|
||||
@ -86,6 +89,27 @@ painting_untransformed (MetaWindowGroup *window_group,
|
||||
return meta_actor_vertices_are_untransformed (vertices, width, height, x_origin, y_origin);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_group_cull_out (MetaCullable *cullable,
|
||||
cairo_region_t *unobscured_region,
|
||||
cairo_region_t *clip_region)
|
||||
{
|
||||
meta_cullable_cull_out_children (cullable, unobscured_region, clip_region);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_group_reset_culling (MetaCullable *cullable)
|
||||
{
|
||||
meta_cullable_reset_culling_children (cullable);
|
||||
}
|
||||
|
||||
static void
|
||||
cullable_iface_init (MetaCullableInterface *iface)
|
||||
{
|
||||
iface->cull_out = meta_window_group_cull_out;
|
||||
iface->reset_culling = meta_window_group_reset_culling;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_window_group_paint (ClutterActor *actor)
|
||||
{
|
||||
@ -94,13 +118,13 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
cairo_rectangle_int_t visible_rect, clip_rect;
|
||||
int paint_x_offset, paint_y_offset;
|
||||
int paint_x_origin, paint_y_origin;
|
||||
int actor_x_origin, actor_y_origin;
|
||||
int paint_x_offset, paint_y_offset;
|
||||
|
||||
MetaWindowGroup *window_group = META_WINDOW_GROUP (actor);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen);
|
||||
ClutterActor *stage = clutter_actor_get_stage (actor);
|
||||
MetaCompScreen *info = meta_screen_get_compositor_data (window_group->screen);
|
||||
|
||||
/* Start off by treating all windows as completely unobscured, so damage anywhere
|
||||
* in a window queues redraws, but confine it more below. */
|
||||
@ -134,9 +158,6 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
return;
|
||||
}
|
||||
|
||||
paint_x_offset = paint_x_origin - actor_x_origin;
|
||||
paint_y_offset = paint_y_origin - actor_y_origin;
|
||||
|
||||
visible_rect.x = visible_rect.y = 0;
|
||||
visible_rect.width = clutter_actor_get_width (CLUTTER_ACTOR (stage));
|
||||
visible_rect.height = clutter_actor_get_height (CLUTTER_ACTOR (stage));
|
||||
@ -154,134 +175,54 @@ meta_window_group_paint (ClutterActor *actor)
|
||||
|
||||
clip_region = cairo_region_create_rectangle (&clip_rect);
|
||||
|
||||
paint_x_offset = paint_x_origin - actor_x_origin;
|
||||
paint_y_offset = paint_y_origin - actor_y_origin;
|
||||
cairo_region_translate (clip_region, -paint_x_offset, -paint_y_offset);
|
||||
|
||||
if (info->unredirected_window != NULL)
|
||||
{
|
||||
cairo_rectangle_int_t unredirected_rect;
|
||||
MetaWindow *window = meta_window_actor_get_meta_window (info->unredirected_window);
|
||||
|
||||
meta_window_get_outer_rect (window, (MetaRectangle *)&unredirected_rect);
|
||||
meta_window_get_frame_rect (window, (MetaRectangle *)&unredirected_rect);
|
||||
cairo_region_subtract_rectangle (unobscured_region, &unredirected_rect);
|
||||
cairo_region_subtract_rectangle (clip_region, &unredirected_rect);
|
||||
}
|
||||
|
||||
/* We walk the list from top to bottom (opposite of painting order),
|
||||
* and subtract the opaque area of each window out of the visible
|
||||
* region that we pass to the windows below.
|
||||
*/
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_prev (&iter, &child))
|
||||
{
|
||||
if (!CLUTTER_ACTOR_IS_VISIBLE (child))
|
||||
continue;
|
||||
|
||||
if (info->unredirected_window != NULL &&
|
||||
child == CLUTTER_ACTOR (info->unredirected_window))
|
||||
continue;
|
||||
|
||||
/* If an actor has effects applied, then that can change the area
|
||||
* it paints and the opacity, so we no longer can figure out what
|
||||
* portion of the actor is obscured and what portion of the screen
|
||||
* it obscures, so we skip the actor.
|
||||
*
|
||||
* This has a secondary beneficial effect: if a ClutterOffscreenEffect
|
||||
* is applied to an actor, then our clipped redraws interfere with the
|
||||
* caching of the FBO - even if we only need to draw a small portion
|
||||
* of the window right now, ClutterOffscreenEffect may use other portions
|
||||
* of the FBO later. So, skipping actors with effects applied also
|
||||
* prevents these bugs.
|
||||
*
|
||||
* Theoretically, we should check clutter_actor_get_offscreen_redirect()
|
||||
* as well for the same reason, but omitted for simplicity in the
|
||||
* hopes that no-one will do that.
|
||||
*/
|
||||
if (clutter_actor_has_effects (child))
|
||||
continue;
|
||||
|
||||
if (META_IS_WINDOW_ACTOR (child))
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
|
||||
int x, y;
|
||||
|
||||
if (!meta_actor_is_untransformed (CLUTTER_ACTOR (window_actor), &x, &y))
|
||||
continue;
|
||||
|
||||
x += paint_x_offset;
|
||||
y += paint_y_offset;
|
||||
|
||||
|
||||
/* Temporarily move to the coordinate system of the actor */
|
||||
cairo_region_translate (unobscured_region, - x, - y);
|
||||
cairo_region_translate (clip_region, - x, - y);
|
||||
|
||||
meta_window_actor_set_unobscured_region (window_actor, unobscured_region);
|
||||
meta_window_actor_set_clip_region (window_actor, clip_region);
|
||||
|
||||
if (clutter_actor_get_paint_opacity (CLUTTER_ACTOR (window_actor)) == 0xff)
|
||||
{
|
||||
cairo_region_t *obscured_region = meta_window_actor_get_obscured_region (window_actor);
|
||||
if (obscured_region)
|
||||
{
|
||||
cairo_region_subtract (unobscured_region, obscured_region);
|
||||
cairo_region_subtract (clip_region, obscured_region);
|
||||
}
|
||||
}
|
||||
|
||||
meta_window_actor_set_clip_region_beneath (window_actor, clip_region);
|
||||
|
||||
cairo_region_translate (unobscured_region, x, y);
|
||||
cairo_region_translate (clip_region, x, y);
|
||||
}
|
||||
else if (META_IS_BACKGROUND_ACTOR (child) ||
|
||||
META_IS_BACKGROUND_GROUP (child))
|
||||
{
|
||||
int x, y;
|
||||
|
||||
if (!meta_actor_is_untransformed (child, &x, &y))
|
||||
continue;
|
||||
|
||||
x += paint_x_offset;
|
||||
y += paint_y_offset;
|
||||
|
||||
cairo_region_translate (clip_region, - x, - y);
|
||||
|
||||
if (META_IS_BACKGROUND_GROUP (child))
|
||||
meta_background_group_set_clip_region (META_BACKGROUND_GROUP (child), clip_region);
|
||||
else
|
||||
meta_background_actor_set_clip_region (META_BACKGROUND_ACTOR (child), clip_region);
|
||||
|
||||
cairo_region_translate (clip_region, x, y);
|
||||
}
|
||||
}
|
||||
meta_cullable_cull_out (META_CULLABLE (window_group), unobscured_region, clip_region);
|
||||
|
||||
cairo_region_destroy (unobscured_region);
|
||||
cairo_region_destroy (clip_region);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (meta_window_group_parent_class)->paint (actor);
|
||||
|
||||
/* Now that we are done painting, unset the visible regions (they will
|
||||
* mess up painting clones of our actors)
|
||||
*/
|
||||
clutter_actor_iter_init (&iter, actor);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
if (META_IS_WINDOW_ACTOR (child))
|
||||
{
|
||||
MetaWindowActor *window_actor = META_WINDOW_ACTOR (child);
|
||||
meta_window_actor_reset_clip_regions (window_actor);
|
||||
}
|
||||
else if (META_IS_BACKGROUND_ACTOR (child))
|
||||
{
|
||||
MetaBackgroundActor *background_actor = META_BACKGROUND_ACTOR (child);
|
||||
meta_background_actor_set_clip_region (background_actor, NULL);
|
||||
}
|
||||
}
|
||||
meta_cullable_reset_culling (META_CULLABLE (window_group));
|
||||
}
|
||||
|
||||
/* Adapted from clutter_actor_update_default_paint_volume() */
|
||||
static gboolean
|
||||
meta_window_group_get_paint_volume (ClutterActor *actor,
|
||||
meta_window_group_get_paint_volume (ClutterActor *self,
|
||||
ClutterPaintVolume *volume)
|
||||
{
|
||||
return clutter_paint_volume_set_from_allocation (volume, actor);
|
||||
ClutterActorIter iter;
|
||||
ClutterActor *child;
|
||||
|
||||
clutter_actor_iter_init (&iter, self);
|
||||
while (clutter_actor_iter_next (&iter, &child))
|
||||
{
|
||||
const ClutterPaintVolume *child_volume;
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_MAPPED (child))
|
||||
continue;
|
||||
|
||||
child_volume = clutter_actor_get_transformed_paint_volume (child, self);
|
||||
if (child_volume == NULL)
|
||||
return FALSE;
|
||||
|
||||
clutter_paint_volume_union (volume, child_volume);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -11,29 +11,9 @@
|
||||
* MetaWindowGroup:
|
||||
*
|
||||
* This class is a subclass of ClutterActor with special handling for
|
||||
* MetaWindowActor/MetaBackgroundActor/MetaBackgroundGroup when painting
|
||||
* children.
|
||||
*
|
||||
* When we are painting a stack of 5-10 maximized windows, the
|
||||
* standard bottom-to-top method of drawing every actor results in a
|
||||
* tremendous amount of overdraw and can easily max out the available
|
||||
* memory bandwidth on a low-end graphics chipset. It's even worse if
|
||||
* window textures are being accessed over the AGP bus.
|
||||
*
|
||||
* The basic technique applied here is to do a pre-pass before painting
|
||||
* where we walk window from top to bottom and compute the visible area
|
||||
* at each step by subtracting out the windows above it. The visible
|
||||
* area is passed to MetaWindowActor which uses it to clip the portion of
|
||||
* the window which drawn and avoid redrawing the shadow if it is completely
|
||||
* obscured.
|
||||
*
|
||||
* A caveat is that this is ineffective if applications are using ARGB
|
||||
* visuals, since we have no way of knowing whether a window obscures
|
||||
* the windows behind it or not. Alternate approaches using the depth
|
||||
* or stencil buffer rather than client side regions might be able to
|
||||
* handle alpha windows, but the combination of glAlphaFunc and stenciling
|
||||
* tends not to be efficient except on newer cards. (And on newer cards
|
||||
* we have lots of memory and bandwidth.)
|
||||
* #MetaCullable when painting children. It uses code similar to
|
||||
* meta_cullable_cull_out_children(), but also has additional special
|
||||
* cases for the undirected window, and similar.
|
||||
*/
|
||||
|
||||
#define META_TYPE_WINDOW_GROUP (meta_window_group_get_type ())
|
||||
|
@ -118,8 +118,6 @@ typedef struct
|
||||
{
|
||||
MetaRectangle orig;
|
||||
MetaRectangle current;
|
||||
MetaFrameBorders *borders;
|
||||
gboolean must_free_borders;
|
||||
ActionType action_type;
|
||||
gboolean is_user_action;
|
||||
|
||||
@ -195,7 +193,6 @@ static gboolean constrain_partially_onscreen (MetaWindow *window,
|
||||
|
||||
static void setup_constraint_info (ConstraintInfo *info,
|
||||
MetaWindow *window,
|
||||
MetaFrameBorders *orig_borders,
|
||||
MetaMoveResizeFlags flags,
|
||||
int resize_gravity,
|
||||
const MetaRectangle *orig,
|
||||
@ -204,13 +201,12 @@ static void place_window_if_needed (MetaWindow *window,
|
||||
ConstraintInfo *info);
|
||||
static void update_onscreen_requirements (MetaWindow *window,
|
||||
ConstraintInfo *info);
|
||||
static void extend_by_frame (MetaRectangle *rect,
|
||||
const MetaFrameBorders *borders);
|
||||
static void unextend_by_frame (MetaRectangle *rect,
|
||||
const MetaFrameBorders *borders);
|
||||
static inline void get_size_limits (const MetaWindow *window,
|
||||
const MetaFrameBorders *borders,
|
||||
gboolean include_frame,
|
||||
static void extend_by_frame (MetaWindow *window,
|
||||
MetaRectangle *rect);
|
||||
static void unextend_by_frame (MetaWindow *window,
|
||||
MetaRectangle *rect);
|
||||
static inline void get_size_limits (MetaWindow *window,
|
||||
gboolean include_frame,
|
||||
MetaRectangle *min_size,
|
||||
MetaRectangle *max_size);
|
||||
|
||||
@ -280,7 +276,6 @@ do_all_constraints (MetaWindow *window,
|
||||
|
||||
void
|
||||
meta_window_constrain (MetaWindow *window,
|
||||
MetaFrameBorders *orig_borders,
|
||||
MetaMoveResizeFlags flags,
|
||||
int resize_gravity,
|
||||
const MetaRectangle *orig,
|
||||
@ -303,7 +298,6 @@ meta_window_constrain (MetaWindow *window,
|
||||
|
||||
setup_constraint_info (&info,
|
||||
window,
|
||||
orig_borders,
|
||||
flags,
|
||||
resize_gravity,
|
||||
orig,
|
||||
@ -333,19 +327,11 @@ meta_window_constrain (MetaWindow *window,
|
||||
* if this was a user move or user move-and-resize operation.
|
||||
*/
|
||||
update_onscreen_requirements (window, &info);
|
||||
|
||||
/* Ew, what an ugly way to do things. Destructors (in a real OOP language,
|
||||
* not gobject-style--gobject would be more pain than it's worth) or
|
||||
* smart pointers would be so much nicer here. *shrug*
|
||||
*/
|
||||
if (info.must_free_borders)
|
||||
g_free (info.borders);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_constraint_info (ConstraintInfo *info,
|
||||
MetaWindow *window,
|
||||
MetaFrameBorders *orig_borders,
|
||||
MetaMoveResizeFlags flags,
|
||||
int resize_gravity,
|
||||
const MetaRectangle *orig,
|
||||
@ -357,18 +343,6 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
info->orig = *orig;
|
||||
info->current = *new;
|
||||
|
||||
/* Create a fake frame geometry if none really exists */
|
||||
if (orig_borders && !window->fullscreen)
|
||||
{
|
||||
info->borders = orig_borders;
|
||||
info->must_free_borders = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
info->borders = g_new0 (MetaFrameBorders, 1);
|
||||
info->must_free_borders = TRUE;
|
||||
}
|
||||
|
||||
if (flags & META_IS_MOVE_ACTION && flags & META_IS_RESIZE_ACTION)
|
||||
info->action_type = ACTION_MOVE_AND_RESIZE;
|
||||
else if (flags & META_IS_RESIZE_ACTION)
|
||||
@ -447,12 +421,14 @@ setup_constraint_info (ConstraintInfo *info,
|
||||
|
||||
/* Workaround braindead legacy apps that don't know how to
|
||||
* fullscreen themselves properly - don't get fooled by
|
||||
* windows which hide their titlebar when maximized; that's
|
||||
* not the same as fullscreen, even if there are no struts
|
||||
* making the workarea smaller than the monitor.
|
||||
* windows which hide their titlebar when maximized or which are
|
||||
* client decorated; that's not the same as fullscreen, even
|
||||
* if there are no struts making the workarea smaller than
|
||||
* the monitor.
|
||||
*/
|
||||
if (meta_prefs_get_force_fullscreen() &&
|
||||
!window->hide_titlebar_when_maximized &&
|
||||
window->decorated &&
|
||||
meta_rectangle_equal (new, &monitor_info->rect) &&
|
||||
window->has_fullscreen_func &&
|
||||
!window->fullscreen)
|
||||
@ -517,11 +493,12 @@ place_window_if_needed(MetaWindow *window,
|
||||
!window->minimized &&
|
||||
!window->fullscreen)
|
||||
{
|
||||
MetaRectangle placed_rect = info->orig;
|
||||
MetaRectangle placed_rect;
|
||||
MetaWorkspace *cur_workspace;
|
||||
const MetaMonitorInfo *monitor_info;
|
||||
|
||||
meta_window_place (window, info->borders, info->orig.x, info->orig.y,
|
||||
meta_window_get_frame_rect (window, &placed_rect);
|
||||
meta_window_place (window, info->orig.x, info->orig.y,
|
||||
&placed_rect.x, &placed_rect.y);
|
||||
did_placement = TRUE;
|
||||
|
||||
@ -539,6 +516,7 @@ place_window_if_needed(MetaWindow *window,
|
||||
meta_workspace_get_onmonitor_region (cur_workspace,
|
||||
monitor_info->number);
|
||||
|
||||
meta_window_frame_rect_to_client_rect (window, &placed_rect, &placed_rect);
|
||||
|
||||
info->current.x = placed_rect.x;
|
||||
info->current.y = placed_rect.y;
|
||||
@ -584,10 +562,6 @@ place_window_if_needed(MetaWindow *window,
|
||||
(window->maximize_vertically_after_placement ?
|
||||
META_MAXIMIZE_VERTICAL : 0), &info->current);
|
||||
|
||||
/* maximization may have changed frame geometry */
|
||||
if (!window->fullscreen)
|
||||
meta_frame_calc_borders (window->frame, info->borders);
|
||||
|
||||
if (window->fullscreen_after_placement)
|
||||
{
|
||||
window->saved_rect = info->current;
|
||||
@ -647,7 +621,7 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
/* 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->borders);
|
||||
extend_by_frame (window, &info->current);
|
||||
|
||||
/* Update whether we want future constraint runs to require the
|
||||
* window to be on fully onscreen.
|
||||
@ -680,10 +654,13 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
*/
|
||||
if (window->frame && window->decorated)
|
||||
{
|
||||
MetaFrameBorders borders;
|
||||
MetaRectangle titlebar_rect;
|
||||
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
|
||||
titlebar_rect = info->current;
|
||||
titlebar_rect.height = info->borders->visible.top;
|
||||
titlebar_rect.height = borders.visible.top;
|
||||
old = window->require_titlebar_visible;
|
||||
window->require_titlebar_visible =
|
||||
meta_rectangle_overlaps_with_region (info->usable_screen_region,
|
||||
@ -696,39 +673,33 @@ update_onscreen_requirements (MetaWindow *window,
|
||||
}
|
||||
|
||||
/* Don't forget to restore the position of the window */
|
||||
unextend_by_frame (&info->current, info->borders);
|
||||
unextend_by_frame (window, &info->current);
|
||||
}
|
||||
|
||||
static void
|
||||
extend_by_frame (MetaRectangle *rect,
|
||||
const MetaFrameBorders *borders)
|
||||
extend_by_frame (MetaWindow *window,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
rect->x -= borders->visible.left;
|
||||
rect->y -= borders->visible.top;
|
||||
rect->width += borders->visible.left + borders->visible.right;
|
||||
rect->height += borders->visible.top + borders->visible.bottom;
|
||||
meta_window_client_rect_to_frame_rect (window, rect, rect);
|
||||
}
|
||||
|
||||
static void
|
||||
unextend_by_frame (MetaRectangle *rect,
|
||||
const MetaFrameBorders *borders)
|
||||
unextend_by_frame (MetaWindow *window,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
rect->x += borders->visible.left;
|
||||
rect->y += borders->visible.top;
|
||||
rect->width -= borders->visible.left + borders->visible.right;
|
||||
rect->height -= borders->visible.top + borders->visible.bottom;
|
||||
meta_window_frame_rect_to_client_rect (window, rect, rect);
|
||||
}
|
||||
|
||||
static inline void
|
||||
get_size_limits (const MetaWindow *window,
|
||||
const MetaFrameBorders *borders,
|
||||
gboolean include_frame,
|
||||
get_size_limits (MetaWindow *window,
|
||||
gboolean include_frame,
|
||||
MetaRectangle *min_size,
|
||||
MetaRectangle *max_size)
|
||||
{
|
||||
/* We pack the results into MetaRectangle structs just for convienience; we
|
||||
* don't actually use the position of those rects.
|
||||
*/
|
||||
min_size->x = min_size->y = max_size->x = max_size->y = 0;
|
||||
min_size->width = window->size_hints.min_width;
|
||||
min_size->height = window->size_hints.min_height;
|
||||
max_size->width = window->size_hints.max_width;
|
||||
@ -736,22 +707,8 @@ get_size_limits (const MetaWindow *window,
|
||||
|
||||
if (include_frame)
|
||||
{
|
||||
int fw = borders->visible.left + borders->visible.right;
|
||||
int fh = borders->visible.top + borders->visible.bottom;
|
||||
|
||||
min_size->width += fw;
|
||||
min_size->height += fh;
|
||||
/* Do check to avoid overflow (e.g. max_size->width & max_size->height
|
||||
* may be set to G_MAXINT by meta_set_normal_hints()).
|
||||
*/
|
||||
if (max_size->width < (G_MAXINT - fw))
|
||||
max_size->width += fw;
|
||||
else
|
||||
max_size->width = G_MAXINT;
|
||||
if (max_size->height < (G_MAXINT - fh))
|
||||
max_size->height += fh;
|
||||
else
|
||||
max_size->height = G_MAXINT;
|
||||
meta_window_client_rect_to_frame_rect (window, min_size, min_size);
|
||||
meta_window_client_rect_to_frame_rect (window, max_size, max_size);
|
||||
}
|
||||
}
|
||||
|
||||
@ -763,18 +720,28 @@ constrain_modal_dialog (MetaWindow *window,
|
||||
{
|
||||
int x, y;
|
||||
MetaWindow *parent = meta_window_get_transient_for (window);
|
||||
MetaRectangle child_rect, parent_rect;
|
||||
gboolean constraint_already_satisfied;
|
||||
|
||||
if (!meta_window_is_attached_dialog (window))
|
||||
return TRUE;
|
||||
|
||||
x = parent->rect.x + (parent->rect.width / 2 - info->current.width / 2);
|
||||
y = parent->rect.y + (parent->rect.height / 2 - info->current.height / 2);
|
||||
if (parent->frame)
|
||||
{
|
||||
x += parent->frame->rect.x;
|
||||
y += parent->frame->rect.y;
|
||||
}
|
||||
/* We want to center the dialog on the parent, including the decorations
|
||||
for both of them. info->current is in client X window coordinates, so we need
|
||||
to convert them to frame coordinates, apply the centering and then
|
||||
convert back to client.
|
||||
*/
|
||||
|
||||
child_rect = info->current;
|
||||
extend_by_frame (window, &child_rect);
|
||||
|
||||
meta_window_get_frame_rect (parent, &parent_rect);
|
||||
|
||||
child_rect.x = parent_rect.x + (parent_rect.width / 2 - child_rect.width / 2);
|
||||
child_rect.y = parent_rect.y + (parent_rect.height / 2 - child_rect.height / 2);
|
||||
unextend_by_frame (window, &child_rect);
|
||||
x = child_rect.x;
|
||||
y = child_rect.y;
|
||||
|
||||
constraint_already_satisfied = (x == info->current.x) && (y == info->current.y);
|
||||
|
||||
@ -839,19 +806,19 @@ constrain_maximization (MetaWindow *window,
|
||||
active_workspace_struts = window->screen->active_workspace->all_struts;
|
||||
|
||||
target_size = info->current;
|
||||
extend_by_frame (&target_size, info->borders);
|
||||
extend_by_frame (window, &target_size);
|
||||
meta_rectangle_expand_to_avoiding_struts (&target_size,
|
||||
&info->entire_monitor,
|
||||
direction,
|
||||
active_workspace_struts);
|
||||
}
|
||||
/* Now make target_size = maximized size of client window */
|
||||
unextend_by_frame (&target_size, info->borders);
|
||||
unextend_by_frame (window, &target_size);
|
||||
|
||||
/* Check min size constraints; max size constraints are ignored for maximized
|
||||
* windows, as per bug 327543.
|
||||
*/
|
||||
get_size_limits (window, info->borders, FALSE, &min_size, &max_size);
|
||||
get_size_limits (window, FALSE, &min_size, &max_size);
|
||||
hminbad = target_size.width < min_size.width && window->maximized_horizontally;
|
||||
vminbad = target_size.height < min_size.height && window->maximized_vertically;
|
||||
if (hminbad || vminbad)
|
||||
@ -905,12 +872,12 @@ constrain_tiling (MetaWindow *window,
|
||||
* use an external function for the actual calculation
|
||||
*/
|
||||
meta_window_get_current_tile_area (window, &target_size);
|
||||
unextend_by_frame (&target_size, info->borders);
|
||||
unextend_by_frame (window, &target_size);
|
||||
|
||||
/* Check min size constraints; max size constraints are ignored as for
|
||||
* maximized windows.
|
||||
*/
|
||||
get_size_limits (window, info->borders, FALSE, &min_size, &max_size);
|
||||
get_size_limits (window, FALSE, &min_size, &max_size);
|
||||
hminbad = target_size.width < min_size.width;
|
||||
vminbad = target_size.height < min_size.height;
|
||||
if (hminbad || vminbad)
|
||||
@ -953,7 +920,7 @@ constrain_fullscreen (MetaWindow *window,
|
||||
|
||||
monitor = info->entire_monitor;
|
||||
|
||||
get_size_limits (window, info->borders, FALSE, &min_size, &max_size);
|
||||
get_size_limits (window, FALSE, &min_size, &max_size);
|
||||
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)
|
||||
@ -1062,7 +1029,7 @@ constrain_size_limits (MetaWindow *window,
|
||||
return TRUE;
|
||||
|
||||
/* Determine whether constraint is already satisfied; exit if it is */
|
||||
get_size_limits (window, info->borders, FALSE, &min_size, &max_size);
|
||||
get_size_limits (window, FALSE, &min_size, &max_size);
|
||||
/* We ignore max-size limits for maximized windows; see #327543 */
|
||||
if (window->maximized_horizontally)
|
||||
max_size.width = MAX (max_size.width, info->current.width);
|
||||
@ -1254,8 +1221,8 @@ do_screen_and_monitor_relative_constraints (
|
||||
|
||||
/* Determine whether constraint applies; exit if it doesn't */
|
||||
how_far_it_can_be_smushed = info->current;
|
||||
get_size_limits (window, info->borders, TRUE, &min_size, &max_size);
|
||||
extend_by_frame (&info->current, info->borders);
|
||||
get_size_limits (window, TRUE, &min_size, &max_size);
|
||||
extend_by_frame (window, &info->current);
|
||||
|
||||
if (info->action_type != ACTION_MOVE)
|
||||
{
|
||||
@ -1275,7 +1242,7 @@ do_screen_and_monitor_relative_constraints (
|
||||
&info->current);
|
||||
if (exit_early || constraint_satisfied || check_only)
|
||||
{
|
||||
unextend_by_frame (&info->current, info->borders);
|
||||
unextend_by_frame (window, &info->current);
|
||||
return constraint_satisfied;
|
||||
}
|
||||
|
||||
@ -1299,7 +1266,7 @@ do_screen_and_monitor_relative_constraints (
|
||||
info->fixed_directions,
|
||||
&info->current);
|
||||
|
||||
unextend_by_frame (&info->current, info->borders);
|
||||
unextend_by_frame (window, &info->current);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -1412,8 +1379,11 @@ constrain_titlebar_visible (MetaWindow *window,
|
||||
*/
|
||||
if (window->frame)
|
||||
{
|
||||
bottom_amount = info->current.height + info->borders->visible.bottom;
|
||||
vert_amount_onscreen = info->borders->visible.top;
|
||||
MetaFrameBorders borders;
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
|
||||
bottom_amount = info->current.height + borders.visible.bottom;
|
||||
vert_amount_onscreen = borders.visible.top;
|
||||
}
|
||||
else
|
||||
bottom_amount = vert_amount_offscreen;
|
||||
@ -1487,8 +1457,11 @@ constrain_partially_onscreen (MetaWindow *window,
|
||||
*/
|
||||
if (window->frame)
|
||||
{
|
||||
bottom_amount = info->current.height + info->borders->visible.bottom;
|
||||
vert_amount_onscreen = info->borders->visible.top;
|
||||
MetaFrameBorders borders;
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
|
||||
bottom_amount = info->current.height + borders.visible.bottom;
|
||||
vert_amount_onscreen = borders.visible.top;
|
||||
}
|
||||
else
|
||||
bottom_amount = vert_amount_offscreen;
|
||||
|
@ -39,7 +39,6 @@ typedef enum
|
||||
} MetaMoveResizeFlags;
|
||||
|
||||
void meta_window_constrain (MetaWindow *window,
|
||||
MetaFrameBorders *orig_borders,
|
||||
MetaMoveResizeFlags flags,
|
||||
int resize_gravity,
|
||||
const MetaRectangle *orig,
|
||||
|
@ -171,6 +171,7 @@ meta_core_queue_frame_resize (Display *xdisplay,
|
||||
MetaWindow *window = get_window (xdisplay, frame_xwindow);
|
||||
|
||||
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
|
||||
meta_window_frame_size_changed (window);
|
||||
}
|
||||
|
||||
void
|
||||
@ -279,8 +280,7 @@ meta_core_lower_beneath_grab_window (Display *xdisplay,
|
||||
return;
|
||||
|
||||
changes.stack_mode = Below;
|
||||
changes.sibling = grab_window->frame ? grab_window->frame->xwindow
|
||||
: grab_window->xwindow;
|
||||
changes.sibling = meta_window_get_toplevel_xwindow (grab_window);
|
||||
|
||||
meta_stack_tracker_record_lower_below (screen->stack_tracker,
|
||||
xwindow,
|
||||
@ -469,26 +469,6 @@ meta_core_change_workspace (Display *xdisplay,
|
||||
new_workspace));
|
||||
}
|
||||
|
||||
int
|
||||
meta_core_get_num_workspaces (Screen *xscreen)
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
screen = meta_screen_for_x_screen (xscreen);
|
||||
|
||||
return meta_screen_get_n_workspaces (screen);
|
||||
}
|
||||
|
||||
int
|
||||
meta_core_get_active_workspace (Screen *xscreen)
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
screen = meta_screen_for_x_screen (xscreen);
|
||||
|
||||
return meta_workspace_index (screen->active_workspace);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_show_window_menu (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
|
@ -153,8 +153,6 @@ void meta_core_change_workspace (Display *xdisplay,
|
||||
Window frame_xwindow,
|
||||
int new_workspace);
|
||||
|
||||
int meta_core_get_num_workspaces (Screen *xscreen);
|
||||
int meta_core_get_active_workspace (Screen *xscreen);
|
||||
int meta_core_get_frame_workspace (Display *xdisplay,
|
||||
Window frame_xwindow);
|
||||
const char* meta_core_get_workspace_name_with_index (Display *xdisplay,
|
||||
|
@ -51,7 +51,6 @@
|
||||
#include <meta/compositor.h>
|
||||
#include <meta/compositor-mutter.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/cursorfont.h>
|
||||
#include "mutter-enum-types.h"
|
||||
#include "meta-idle-monitor-private.h"
|
||||
|
||||
@ -118,12 +117,6 @@ typedef struct
|
||||
guint ping_timeout_id;
|
||||
} MetaPingData;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaDisplay *display;
|
||||
Window xwindow;
|
||||
} MetaAutoRaiseData;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaDisplay *display;
|
||||
@ -1586,23 +1579,10 @@ reset_ignored_crossing_serials (MetaDisplay *display)
|
||||
static gboolean
|
||||
window_raise_with_delay_callback (void *data)
|
||||
{
|
||||
MetaWindow *window;
|
||||
MetaAutoRaiseData *auto_raise;
|
||||
MetaWindow *window = data;
|
||||
|
||||
auto_raise = data;
|
||||
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"In autoraise callback for window 0x%lx\n",
|
||||
auto_raise->xwindow);
|
||||
|
||||
auto_raise->display->autoraise_timeout_id = 0;
|
||||
auto_raise->display->autoraise_window = NULL;
|
||||
|
||||
window = meta_display_lookup_x_window (auto_raise->display,
|
||||
auto_raise->xwindow);
|
||||
|
||||
if (window == NULL)
|
||||
return FALSE;
|
||||
window->display->autoraise_timeout_id = 0;
|
||||
window->display->autoraise_window = NULL;
|
||||
|
||||
/* If we aren't already on top, check whether the pointer is inside
|
||||
* the window and raise the window if so.
|
||||
@ -1611,6 +1591,7 @@ window_raise_with_delay_callback (void *data)
|
||||
{
|
||||
int x, y, root_x, root_y;
|
||||
Window root, child;
|
||||
MetaRectangle frame_rect;
|
||||
unsigned int mask;
|
||||
gboolean same_screen;
|
||||
gboolean point_in_window;
|
||||
@ -1622,9 +1603,8 @@ window_raise_with_delay_callback (void *data)
|
||||
&root_x, &root_y, &x, &y, &mask);
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
point_in_window =
|
||||
(window->frame && POINT_IN_RECT (root_x, root_y, window->frame->rect)) ||
|
||||
(window->frame == NULL && POINT_IN_RECT (root_x, root_y, window->rect));
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
point_in_window = POINT_IN_RECT (root_x, root_y, frame_rect);
|
||||
if (same_screen && point_in_window)
|
||||
meta_window_raise (window);
|
||||
else
|
||||
@ -1639,7 +1619,8 @@ window_raise_with_delay_callback (void *data)
|
||||
static void
|
||||
meta_display_mouse_mode_focus (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
guint32 timestamp) {
|
||||
guint32 timestamp)
|
||||
{
|
||||
if (window->type != META_WINDOW_DESKTOP)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
@ -1678,7 +1659,8 @@ meta_display_mouse_mode_focus (MetaDisplay *display,
|
||||
}
|
||||
|
||||
static gboolean
|
||||
window_focus_on_pointer_rest_callback (gpointer data) {
|
||||
window_focus_on_pointer_rest_callback (gpointer data)
|
||||
{
|
||||
MetaFocusData *focus_data;
|
||||
MetaDisplay *display;
|
||||
MetaScreen *screen;
|
||||
@ -1723,9 +1705,9 @@ window_focus_on_pointer_rest_callback (gpointer data) {
|
||||
goto out;
|
||||
|
||||
window =
|
||||
meta_stack_get_default_focus_window_at_point (screen->stack,
|
||||
screen->active_workspace,
|
||||
None, root_x, root_y);
|
||||
meta_stack_get_default_focus_window_at_point (screen->stack,
|
||||
screen->active_workspace,
|
||||
None, root_x, root_y);
|
||||
|
||||
if (window == NULL)
|
||||
goto out;
|
||||
@ -1733,7 +1715,7 @@ window_focus_on_pointer_rest_callback (gpointer data) {
|
||||
timestamp = meta_display_get_current_time_roundtrip (display);
|
||||
meta_display_mouse_mode_focus (display, window, timestamp);
|
||||
|
||||
out:
|
||||
out:
|
||||
display->focus_timeout_id = 0;
|
||||
return FALSE;
|
||||
}
|
||||
@ -1742,17 +1724,11 @@ void
|
||||
meta_display_queue_autoraise_callback (MetaDisplay *display,
|
||||
MetaWindow *window)
|
||||
{
|
||||
MetaAutoRaiseData *auto_raise_data;
|
||||
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Queuing an autoraise timeout for %s with delay %d\n",
|
||||
window->desc,
|
||||
meta_prefs_get_auto_raise_delay ());
|
||||
|
||||
auto_raise_data = g_new (MetaAutoRaiseData, 1);
|
||||
auto_raise_data->display = window->display;
|
||||
auto_raise_data->xwindow = window->xwindow;
|
||||
|
||||
if (display->autoraise_timeout_id != 0)
|
||||
g_source_remove (display->autoraise_timeout_id);
|
||||
|
||||
@ -1760,8 +1736,7 @@ meta_display_queue_autoraise_callback (MetaDisplay *display,
|
||||
g_timeout_add_full (G_PRIORITY_DEFAULT,
|
||||
meta_prefs_get_auto_raise_delay (),
|
||||
window_raise_with_delay_callback,
|
||||
auto_raise_data,
|
||||
g_free);
|
||||
window, NULL);
|
||||
display->autoraise_window = window;
|
||||
}
|
||||
|
||||
@ -2126,6 +2101,19 @@ handle_window_focus_event (MetaDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
window_has_xwindow (MetaWindow *window,
|
||||
Window xwindow)
|
||||
{
|
||||
if (window->xwindow == xwindow)
|
||||
return TRUE;
|
||||
|
||||
if (window->frame && window->frame->xwindow == xwindow)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* event_callback:
|
||||
* @event: The event that just happened
|
||||
@ -2181,7 +2169,7 @@ event_callback (XEvent *event,
|
||||
|
||||
if (event->xany.serial > display->focus_serial &&
|
||||
display->focus_window &&
|
||||
display->focus_window->xwindow != display->server_focus_window)
|
||||
!window_has_xwindow (display->focus_window, display->server_focus_window))
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed\n",
|
||||
display->focus_window->desc);
|
||||
@ -2304,7 +2292,7 @@ event_callback (XEvent *event,
|
||||
XIEnterEvent *enter_event = (XIEnterEvent *) input_event;
|
||||
|
||||
if (window && !window->override_redirect &&
|
||||
((input_event->type == XI_KeyPress) || (input_event->type == XI_ButtonPress)))
|
||||
((input_event->evtype == XI_KeyPress) || (input_event->evtype == XI_ButtonPress)))
|
||||
{
|
||||
if (CurrentTime == display->current_time)
|
||||
{
|
||||
@ -2349,6 +2337,7 @@ event_callback (XEvent *event,
|
||||
|
||||
if ((window &&
|
||||
meta_grab_op_is_mouse (display->grab_op) &&
|
||||
(device_event->mods.effective & display->window_grab_modifiers) &&
|
||||
display->grab_button != device_event->detail &&
|
||||
display->grab_window == window) ||
|
||||
grab_op_is_keyboard (display->grab_op))
|
||||
@ -2435,15 +2424,15 @@ event_callback (XEvent *event,
|
||||
{
|
||||
gboolean north, south;
|
||||
gboolean west, east;
|
||||
int root_x, root_y;
|
||||
MetaRectangle frame_rect;
|
||||
MetaGrabOp op;
|
||||
|
||||
meta_window_get_position (window, &root_x, &root_y);
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
|
||||
west = device_event->root_x < (root_x + 1 * window->rect.width / 3);
|
||||
east = device_event->root_x > (root_x + 2 * window->rect.width / 3);
|
||||
north = device_event->root_y < (root_y + 1 * window->rect.height / 3);
|
||||
south = device_event->root_y > (root_y + 2 * window->rect.height / 3);
|
||||
west = device_event->root_x < (frame_rect.x + 1 * frame_rect.width / 3);
|
||||
east = device_event->root_x > (frame_rect.x + 2 * frame_rect.width / 3);
|
||||
north = device_event->root_y < (frame_rect.y + 1 * frame_rect.height / 3);
|
||||
south = device_event->root_y > (frame_rect.y + 2 * frame_rect.height / 3);
|
||||
|
||||
if (north && west)
|
||||
op = META_GRAB_OP_RESIZING_NW;
|
||||
@ -3858,85 +3847,6 @@ meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
|
||||
return is_a_no_focus_window;
|
||||
}
|
||||
|
||||
Cursor
|
||||
meta_display_create_x_cursor (MetaDisplay *display,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
Cursor xcursor;
|
||||
guint glyph = XC_num_glyphs;
|
||||
const char *name = NULL;
|
||||
|
||||
switch (cursor)
|
||||
{
|
||||
case META_CURSOR_DEFAULT:
|
||||
glyph = XC_left_ptr;
|
||||
break;
|
||||
case META_CURSOR_NORTH_RESIZE:
|
||||
glyph = XC_top_side;
|
||||
break;
|
||||
case META_CURSOR_SOUTH_RESIZE:
|
||||
glyph = XC_bottom_side;
|
||||
break;
|
||||
case META_CURSOR_WEST_RESIZE:
|
||||
glyph = XC_left_side;
|
||||
break;
|
||||
case META_CURSOR_EAST_RESIZE:
|
||||
glyph = XC_right_side;
|
||||
break;
|
||||
case META_CURSOR_SE_RESIZE:
|
||||
glyph = XC_bottom_right_corner;
|
||||
break;
|
||||
case META_CURSOR_SW_RESIZE:
|
||||
glyph = XC_bottom_left_corner;
|
||||
break;
|
||||
case META_CURSOR_NE_RESIZE:
|
||||
glyph = XC_top_right_corner;
|
||||
break;
|
||||
case META_CURSOR_NW_RESIZE:
|
||||
glyph = XC_top_left_corner;
|
||||
break;
|
||||
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
|
||||
glyph = XC_fleur;
|
||||
break;
|
||||
case META_CURSOR_BUSY:
|
||||
glyph = XC_watch;
|
||||
break;
|
||||
case META_CURSOR_DND_IN_DRAG:
|
||||
name = "dnd-none";
|
||||
break;
|
||||
case META_CURSOR_DND_MOVE:
|
||||
name = "dnd-move";
|
||||
break;
|
||||
case META_CURSOR_DND_COPY:
|
||||
name = "dnd-copy";
|
||||
break;
|
||||
case META_CURSOR_DND_UNSUPPORTED_TARGET:
|
||||
name = "dnd-none";
|
||||
break;
|
||||
case META_CURSOR_POINTING_HAND:
|
||||
glyph = XC_hand2;
|
||||
break;
|
||||
case META_CURSOR_CROSSHAIR:
|
||||
glyph = XC_crosshair;
|
||||
break;
|
||||
case META_CURSOR_IBEAM:
|
||||
glyph = XC_xterm;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
glyph = 0; /* silence compiler */
|
||||
break;
|
||||
}
|
||||
|
||||
if (name != NULL)
|
||||
xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
|
||||
else
|
||||
xcursor = XCreateFontCursor (display->xdisplay, glyph);
|
||||
|
||||
return xcursor;
|
||||
}
|
||||
|
||||
static Cursor
|
||||
xcursor_for_op (MetaDisplay *display,
|
||||
MetaGrabOp op)
|
||||
@ -4098,7 +4008,7 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
* key grab on the RootWindow.
|
||||
*/
|
||||
if (grab_window)
|
||||
grab_xwindow = grab_window->frame ? grab_window->frame->xwindow : grab_window->xwindow;
|
||||
grab_xwindow = meta_window_get_toplevel_xwindow (grab_window);
|
||||
else
|
||||
grab_xwindow = screen->xroot;
|
||||
|
||||
@ -4626,6 +4536,7 @@ meta_display_queue_retheme_all_windows (MetaDisplay *display)
|
||||
MetaWindow *window = tmp->data;
|
||||
|
||||
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
|
||||
meta_window_frame_size_changed (window);
|
||||
if (window->frame)
|
||||
{
|
||||
meta_frame_queue_draw (window->frame);
|
||||
@ -5807,25 +5718,6 @@ meta_display_request_take_focus (MetaDisplay *display,
|
||||
meta_topic (META_DEBUG_FOCUS, "WM_TAKE_FOCUS(%s, %u)\n",
|
||||
window->desc, timestamp);
|
||||
|
||||
if (window != display->focus_window)
|
||||
{
|
||||
/* The "Globally Active Input" window case, where the window
|
||||
* doesn't want us to call XSetInputFocus on it, but does
|
||||
* want us to send a WM_TAKE_FOCUS.
|
||||
*
|
||||
* We can't just set display->focus_window to @window, since we
|
||||
* we don't know when (or even if) the window will actually take
|
||||
* focus, so we could end up being wrong for arbitrarily long.
|
||||
* But we also can't leave it set to the current window, or else
|
||||
* bug #597352 would come back. So we focus the no_focus_window
|
||||
* now (and set display->focus_window to that), send the
|
||||
* WM_TAKE_FOCUS, and then just forget about @window
|
||||
* until/unless we get a FocusIn.
|
||||
*/
|
||||
meta_display_focus_the_no_focus_window (display,
|
||||
window->screen,
|
||||
timestamp);
|
||||
}
|
||||
meta_window_send_icccm_message (window,
|
||||
display->atom_WM_TAKE_FOCUS,
|
||||
timestamp);
|
||||
|
@ -985,7 +985,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
{
|
||||
MetaRectangle *new_rect;
|
||||
new_rect = g_new (MetaRectangle, 1);
|
||||
meta_window_get_outer_rect (cur_window, new_rect);
|
||||
meta_window_get_frame_rect (cur_window, new_rect);
|
||||
obscuring_windows = g_slist_prepend (obscuring_windows, new_rect);
|
||||
window_stacking =
|
||||
g_slist_prepend (window_stacking, GINT_TO_POINTER (stack_position));
|
||||
@ -1010,7 +1010,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
|
||||
{
|
||||
MetaRectangle cur_rect;
|
||||
MetaWindow *cur_window = cur_window_iter->data;
|
||||
meta_window_get_outer_rect (cur_window, &cur_rect);
|
||||
meta_window_get_frame_rect (cur_window, &cur_rect);
|
||||
|
||||
/* Check if we want to use this window's edges for edge
|
||||
* resistance (note that dock edges are considered screen edges
|
||||
@ -1151,7 +1151,7 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
|
||||
MetaRectangle old_outer, proposed_outer, new_outer;
|
||||
gboolean is_resize;
|
||||
|
||||
meta_window_get_outer_rect (window, &old_outer);
|
||||
meta_window_get_frame_rect (window, &old_outer);
|
||||
|
||||
proposed_outer = old_outer;
|
||||
proposed_outer.x += (*new_x - old_x);
|
||||
@ -1237,7 +1237,7 @@ meta_window_edge_resistance_for_resize (MetaWindow *window,
|
||||
int proposed_outer_width, proposed_outer_height;
|
||||
gboolean is_resize;
|
||||
|
||||
meta_window_get_outer_rect (window, &old_outer);
|
||||
meta_window_get_frame_rect (window, &old_outer);
|
||||
proposed_outer_width = old_outer.width + (*new_width - old_width);
|
||||
proposed_outer_height = old_outer.height + (*new_height - old_height);
|
||||
meta_rectangle_resize_with_gravity (&old_outer,
|
||||
|
@ -68,6 +68,7 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
|
||||
frame->mapped = FALSE;
|
||||
frame->is_flashing = FALSE;
|
||||
frame->borders_cached = FALSE;
|
||||
|
||||
meta_verbose ("Framing window %s: visual %s default, depth %d default depth %d\n",
|
||||
window->desc,
|
||||
@ -327,9 +328,23 @@ meta_frame_calc_borders (MetaFrame *frame,
|
||||
if (frame == NULL)
|
||||
meta_frame_borders_clear (borders);
|
||||
else
|
||||
meta_ui_get_frame_borders (frame->window->screen->ui,
|
||||
frame->xwindow,
|
||||
borders);
|
||||
{
|
||||
if (!frame->borders_cached)
|
||||
{
|
||||
meta_ui_get_frame_borders (frame->window->screen->ui,
|
||||
frame->xwindow,
|
||||
&frame->cached_borders);
|
||||
frame->borders_cached = TRUE;
|
||||
}
|
||||
|
||||
*borders = frame->cached_borders;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_frame_clear_cached_borders (MetaFrame *frame)
|
||||
{
|
||||
frame->borders_cached = FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
@ -41,6 +41,8 @@ struct _MetaFrame
|
||||
*/
|
||||
MetaRectangle rect;
|
||||
|
||||
MetaFrameBorders cached_borders; /* valid if borders_cached is set */
|
||||
|
||||
/* position of client, size of frame */
|
||||
int child_x;
|
||||
int child_y;
|
||||
@ -50,6 +52,7 @@ struct _MetaFrame
|
||||
guint mapped : 1;
|
||||
guint need_reapply_frame_shape : 1;
|
||||
guint is_flashing : 1; /* used by the visual bell flash */
|
||||
guint borders_cached : 1;
|
||||
};
|
||||
|
||||
void meta_window_ensure_frame (MetaWindow *window);
|
||||
@ -68,6 +71,8 @@ gboolean meta_frame_sync_to_window (MetaFrame *frame,
|
||||
gboolean need_move,
|
||||
gboolean need_resize);
|
||||
|
||||
void meta_frame_clear_cached_borders (MetaFrame *frame);
|
||||
|
||||
cairo_region_t *meta_frame_get_frame_bounds (MetaFrame *frame);
|
||||
|
||||
void meta_frame_get_mask (MetaFrame *frame,
|
||||
|
@ -1277,7 +1277,7 @@ meta_window_grab_keys (MetaWindow *window)
|
||||
}
|
||||
|
||||
meta_window_change_keygrabs (window,
|
||||
window->frame ? window->frame->xwindow : window->xwindow,
|
||||
meta_window_get_toplevel_xwindow (window),
|
||||
TRUE);
|
||||
|
||||
window->keys_grabbed = TRUE;
|
||||
@ -1580,7 +1580,7 @@ meta_window_grab_all_keys (MetaWindow *window,
|
||||
window->desc);
|
||||
meta_window_focus (window, timestamp);
|
||||
|
||||
grabwindow = window->frame ? window->frame->xwindow : window->xwindow;
|
||||
grabwindow = meta_window_get_toplevel_xwindow (window);
|
||||
|
||||
meta_topic (META_DEBUG_KEYBINDINGS,
|
||||
"Grabbing all keys on window %s\n", window->desc);
|
||||
@ -1835,7 +1835,6 @@ invoke_handler_by_name (MetaDisplay *display,
|
||||
invoke_handler (display, screen, handler, window, event, NULL);
|
||||
}
|
||||
|
||||
/* now called from only one place, may be worth merging */
|
||||
static gboolean
|
||||
process_event (MetaKeyBinding *bindings,
|
||||
int n_bindings,
|
||||
@ -1843,7 +1842,6 @@ process_event (MetaKeyBinding *bindings,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
XIDeviceEvent *event,
|
||||
KeySym keysym,
|
||||
gboolean on_window)
|
||||
{
|
||||
int i;
|
||||
@ -1861,7 +1859,6 @@ process_event (MetaKeyBinding *bindings,
|
||||
MetaKeyHandler *handler = bindings[i].handler;
|
||||
|
||||
if ((!on_window && handler->flags & META_KEY_BINDING_PER_WINDOW) ||
|
||||
event->evtype != XI_KeyPress ||
|
||||
bindings[i].keycode != event->detail ||
|
||||
((event->mods.effective & 0xff & ~(display->ignored_modifier_mask)) !=
|
||||
bindings[i].mask) ||
|
||||
@ -1928,7 +1925,7 @@ process_overlay_key (MetaDisplay *display,
|
||||
*/
|
||||
if (process_event (display->key_bindings,
|
||||
display->n_key_bindings,
|
||||
display, screen, NULL, event, keysym,
|
||||
display, screen, NULL, event,
|
||||
FALSE))
|
||||
{
|
||||
/* As normally, after we've handled a global key
|
||||
@ -2192,7 +2189,7 @@ meta_display_process_key_event (MetaDisplay *display,
|
||||
/* Do the normal keybindings */
|
||||
return process_event (display->key_bindings,
|
||||
display->n_key_bindings,
|
||||
display, screen, window, event, keysym,
|
||||
display, screen, window, event,
|
||||
!all_keys_grabbed && window);
|
||||
}
|
||||
|
||||
@ -3140,6 +3137,20 @@ handle_maximize_horizontally (MetaDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_always_on_top (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *window,
|
||||
XIDeviceEvent *event,
|
||||
MetaKeyBinding *binding,
|
||||
gpointer dummy)
|
||||
{
|
||||
if (window->wm_state_above == FALSE)
|
||||
meta_window_make_above (window);
|
||||
else
|
||||
meta_window_unmake_above (window);
|
||||
}
|
||||
|
||||
/* Move a window to a corner; to_bottom/to_right are FALSE for the
|
||||
* top or left edge, or TRUE for the bottom/right edge. xchange/ychange
|
||||
* are FALSE if that dimension is not to be changed, TRUE otherwise.
|
||||
@ -3157,17 +3168,17 @@ handle_move_to_corner_backend (MetaDisplay *display,
|
||||
gpointer dummy)
|
||||
{
|
||||
MetaRectangle work_area;
|
||||
MetaRectangle outer;
|
||||
MetaRectangle frame_rect;
|
||||
int orig_x, orig_y;
|
||||
int new_x, new_y;
|
||||
|
||||
meta_window_get_work_area_all_monitors (window, &work_area);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
meta_window_get_position (window, &orig_x, &orig_y);
|
||||
|
||||
if (xchange) {
|
||||
new_x = work_area.x + (to_right ?
|
||||
work_area.width - outer.width :
|
||||
work_area.width - frame_rect.width :
|
||||
0);
|
||||
} else {
|
||||
new_x = orig_x;
|
||||
@ -3175,7 +3186,7 @@ handle_move_to_corner_backend (MetaDisplay *display,
|
||||
|
||||
if (ychange) {
|
||||
new_y = work_area.y + (to_bottom ?
|
||||
work_area.height - outer.height :
|
||||
work_area.height - frame_rect.height :
|
||||
0);
|
||||
} else {
|
||||
new_y = orig_y;
|
||||
@ -3284,12 +3295,12 @@ handle_move_to_center (MetaDisplay *display,
|
||||
gpointer dummy)
|
||||
{
|
||||
MetaRectangle work_area;
|
||||
MetaRectangle outer;
|
||||
MetaRectangle frame_rect;
|
||||
int orig_x, orig_y;
|
||||
int frame_width, frame_height;
|
||||
|
||||
meta_window_get_work_area_all_monitors (window, &work_area);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
meta_window_get_position (window, &orig_x, &orig_y);
|
||||
|
||||
frame_width = (window->frame ? window->frame->child_x : 0);
|
||||
@ -3297,8 +3308,8 @@ handle_move_to_center (MetaDisplay *display,
|
||||
|
||||
meta_window_move_resize (window,
|
||||
TRUE,
|
||||
work_area.x + (work_area.width +frame_width -outer.width )/2,
|
||||
work_area.y + (work_area.height+frame_height-outer.height)/2,
|
||||
work_area.x + (work_area.width +frame_width -frame_rect.width )/2,
|
||||
work_area.y + (work_area.height+frame_height-frame_rect.height)/2,
|
||||
window->rect.width,
|
||||
window->rect.height);
|
||||
}
|
||||
@ -3991,8 +4002,8 @@ handle_raise_or_lower (MetaDisplay *display,
|
||||
|
||||
if (above->mapped)
|
||||
{
|
||||
meta_window_get_outer_rect (window, &win_rect);
|
||||
meta_window_get_outer_rect (above, &above_rect);
|
||||
meta_window_get_frame_rect (window, &win_rect);
|
||||
meta_window_get_frame_rect (above, &above_rect);
|
||||
|
||||
/* Check if obscured */
|
||||
if (meta_rectangle_intersect (&win_rect, &above_rect, &tmp))
|
||||
@ -4132,28 +4143,6 @@ meta_keybindings_set_custom_handler (const gchar *name,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_keybindings_switch_window: (skip)
|
||||
* @display: a #MetaDisplay
|
||||
* @screen: a #MetaScreen
|
||||
* @event_window: a #MetaWindow
|
||||
* @event: a #XIDeviceEvent
|
||||
* @binding: a #MetaKeyBinding
|
||||
*
|
||||
*/
|
||||
void
|
||||
meta_keybindings_switch_window (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *event_window,
|
||||
XIDeviceEvent *event,
|
||||
MetaKeyBinding *binding)
|
||||
{
|
||||
gint backwards = (binding->handler->flags & META_KEY_BINDING_IS_REVERSED) != 0;
|
||||
|
||||
do_choose_window (display, screen, event_window, event, binding,
|
||||
backwards, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
init_builtin_key_bindings (MetaDisplay *display)
|
||||
{
|
||||
@ -4675,6 +4664,13 @@ init_builtin_key_bindings (MetaDisplay *display)
|
||||
META_KEYBINDING_ACTION_MAXIMIZE_HORIZONTALLY,
|
||||
handle_maximize_horizontally, 0);
|
||||
|
||||
add_builtin_keybinding (display,
|
||||
"always-on-top",
|
||||
common_keybindings,
|
||||
META_KEY_BINDING_PER_WINDOW,
|
||||
META_KEYBINDING_ACTION_ALWAYS_ON_TOP,
|
||||
handle_always_on_top, 0);
|
||||
|
||||
add_builtin_keybinding (display,
|
||||
"move-to-corner-nw",
|
||||
common_keybindings,
|
||||
|
@ -37,7 +37,9 @@
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
|
||||
#include "meta-cursor-tracker-private.h"
|
||||
#include "screen-private.h"
|
||||
@ -69,6 +71,106 @@ enum {
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
static void
|
||||
translate_meta_cursor (MetaCursor cursor,
|
||||
guint *glyph_out,
|
||||
const char **name_out)
|
||||
{
|
||||
guint glyph = XC_num_glyphs;
|
||||
const char *name = NULL;
|
||||
|
||||
switch (cursor)
|
||||
{
|
||||
case META_CURSOR_DEFAULT:
|
||||
glyph = XC_left_ptr;
|
||||
break;
|
||||
case META_CURSOR_NORTH_RESIZE:
|
||||
glyph = XC_top_side;
|
||||
break;
|
||||
case META_CURSOR_SOUTH_RESIZE:
|
||||
glyph = XC_bottom_side;
|
||||
break;
|
||||
case META_CURSOR_WEST_RESIZE:
|
||||
glyph = XC_left_side;
|
||||
break;
|
||||
case META_CURSOR_EAST_RESIZE:
|
||||
glyph = XC_right_side;
|
||||
break;
|
||||
case META_CURSOR_SE_RESIZE:
|
||||
glyph = XC_bottom_right_corner;
|
||||
break;
|
||||
case META_CURSOR_SW_RESIZE:
|
||||
glyph = XC_bottom_left_corner;
|
||||
break;
|
||||
case META_CURSOR_NE_RESIZE:
|
||||
glyph = XC_top_right_corner;
|
||||
break;
|
||||
case META_CURSOR_NW_RESIZE:
|
||||
glyph = XC_top_left_corner;
|
||||
break;
|
||||
case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
|
||||
glyph = XC_fleur;
|
||||
break;
|
||||
case META_CURSOR_BUSY:
|
||||
glyph = XC_watch;
|
||||
break;
|
||||
case META_CURSOR_DND_IN_DRAG:
|
||||
name = "dnd-none";
|
||||
break;
|
||||
case META_CURSOR_DND_MOVE:
|
||||
name = "dnd-move";
|
||||
break;
|
||||
case META_CURSOR_DND_COPY:
|
||||
name = "dnd-copy";
|
||||
break;
|
||||
case META_CURSOR_DND_UNSUPPORTED_TARGET:
|
||||
name = "dnd-none";
|
||||
break;
|
||||
case META_CURSOR_POINTING_HAND:
|
||||
glyph = XC_hand2;
|
||||
break;
|
||||
case META_CURSOR_CROSSHAIR:
|
||||
glyph = XC_crosshair;
|
||||
break;
|
||||
case META_CURSOR_IBEAM:
|
||||
glyph = XC_xterm;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
glyph = 0; /* silence compiler */
|
||||
break;
|
||||
}
|
||||
|
||||
*glyph_out = glyph;
|
||||
*name_out = name;
|
||||
}
|
||||
|
||||
static Cursor
|
||||
load_cursor_on_server (MetaDisplay *display,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
Cursor xcursor;
|
||||
guint glyph;
|
||||
const char *name;
|
||||
|
||||
translate_meta_cursor (cursor, &glyph, &name);
|
||||
|
||||
if (name != NULL)
|
||||
xcursor = XcursorLibraryLoadCursor (display->xdisplay, name);
|
||||
else
|
||||
xcursor = XCreateFontCursor (display->xdisplay, glyph);
|
||||
|
||||
return xcursor;
|
||||
}
|
||||
|
||||
Cursor
|
||||
meta_display_create_x_cursor (MetaDisplay *display,
|
||||
MetaCursor cursor)
|
||||
{
|
||||
return load_cursor_on_server (display, cursor);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_tracker_init (MetaCursorTracker *self)
|
||||
{
|
||||
|
@ -287,6 +287,7 @@ idle_monitor_watch_free (MetaIdleMonitorWatch *watch)
|
||||
return;
|
||||
|
||||
monitor = watch->monitor;
|
||||
g_object_ref (monitor);
|
||||
|
||||
if (watch->idle_source_id)
|
||||
{
|
||||
@ -304,6 +305,7 @@ idle_monitor_watch_free (MetaIdleMonitorWatch *watch)
|
||||
g_hash_table_remove (monitor->alarms, (gpointer) watch->xalarm);
|
||||
}
|
||||
|
||||
g_object_unref (monitor);
|
||||
g_slice_free (MetaIdleMonitorWatch, watch);
|
||||
}
|
||||
|
||||
@ -840,6 +842,8 @@ on_bus_acquired (GDBusConnection *connection,
|
||||
for (iter = devices; iter; iter = iter->next)
|
||||
on_device_added (device_manager, iter->data, manager);
|
||||
|
||||
g_slist_free (devices);
|
||||
|
||||
g_signal_connect_object (device_manager, "device-added",
|
||||
G_CALLBACK (on_device_added), manager, 0);
|
||||
g_signal_connect_object (device_manager, "device-removed",
|
||||
|
@ -99,8 +99,9 @@ static gboolean meta_monitor_config_assign_crtcs (MetaConfiguration *config,
|
||||
GPtrArray *crtcs,
|
||||
GPtrArray *outputs);
|
||||
|
||||
static void power_client_changed_cb (UpClient *client,
|
||||
gpointer user_data);
|
||||
static void power_client_changed_cb (UpClient *client,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data);
|
||||
|
||||
static void
|
||||
free_output_key (MetaOutputKey *key)
|
||||
@ -232,7 +233,7 @@ meta_monitor_config_init (MetaMonitorConfig *self)
|
||||
self->up_client = up_client_new ();
|
||||
self->lid_is_closed = up_client_get_lid_is_closed (self->up_client);
|
||||
|
||||
g_signal_connect_object (self->up_client, "changed",
|
||||
g_signal_connect_object (self->up_client, "notify::lid-is-closed",
|
||||
G_CALLBACK (power_client_changed_cb), self, 0);
|
||||
}
|
||||
|
||||
@ -816,6 +817,22 @@ meta_monitor_config_match_current (MetaMonitorConfig *self,
|
||||
return ok;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager)
|
||||
{
|
||||
MetaOutput *outputs;
|
||||
unsigned n_outputs;
|
||||
unsigned int i;
|
||||
|
||||
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
|
||||
|
||||
for (i = 0; i < n_outputs; i++)
|
||||
if (outputs[i].hotplug_mode_update)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static MetaConfiguration *
|
||||
meta_monitor_config_get_stored (MetaMonitorConfig *self,
|
||||
MetaOutput *outputs,
|
||||
@ -824,6 +841,9 @@ meta_monitor_config_get_stored (MetaMonitorConfig *self,
|
||||
MetaConfiguration key;
|
||||
MetaConfiguration *stored;
|
||||
|
||||
if (n_outputs == 0)
|
||||
return NULL;
|
||||
|
||||
make_config_key (&key, outputs, n_outputs, -1);
|
||||
stored = g_hash_table_lookup (self->configs, &key);
|
||||
|
||||
@ -1231,6 +1251,12 @@ meta_monitor_config_make_default (MetaMonitorConfig *self,
|
||||
outputs = meta_monitor_manager_get_outputs (manager, &n_outputs);
|
||||
meta_monitor_manager_get_screen_limits (manager, &max_width, &max_height);
|
||||
|
||||
if (n_outputs == 0)
|
||||
{
|
||||
meta_verbose ("No output connected, not applying configuration\n");
|
||||
return;
|
||||
}
|
||||
|
||||
default_config = make_default_config (self, outputs, n_outputs, max_width, max_height);
|
||||
|
||||
if (default_config != NULL)
|
||||
@ -1335,8 +1361,9 @@ turn_off_laptop_display (MetaMonitorConfig *self,
|
||||
}
|
||||
|
||||
static void
|
||||
power_client_changed_cb (UpClient *client,
|
||||
gpointer user_data)
|
||||
power_client_changed_cb (UpClient *client,
|
||||
GParamSpec *pspec,
|
||||
gpointer user_data)
|
||||
{
|
||||
MetaMonitorManager *manager = meta_monitor_manager_get ();
|
||||
MetaMonitorConfig *self = user_data;
|
||||
|
@ -116,6 +116,9 @@ struct _MetaOutput
|
||||
*/
|
||||
gboolean is_primary;
|
||||
gboolean is_presentation;
|
||||
|
||||
/* get a new preferred mode on hotplug events, to handle dynamic guest resizing */
|
||||
gboolean hotplug_mode_update;
|
||||
};
|
||||
|
||||
struct _MetaCRTC
|
||||
@ -383,6 +386,7 @@ void meta_output_info_free (MetaOutputInfo *info);
|
||||
|
||||
void meta_monitor_manager_free_output_array (MetaOutput *old_outputs,
|
||||
int n_old_outputs);
|
||||
gboolean meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager);
|
||||
|
||||
/* Returns true if transform causes width and height to be inverted
|
||||
This is true for the odd transforms in the enum */
|
||||
|
@ -311,6 +311,29 @@ read_output_edid (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
output_get_hotplug_mode_update (MetaMonitorManagerXrandr *manager_xrandr,
|
||||
XID output_id)
|
||||
{
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
XRRPropertyInfo *info;
|
||||
gboolean result = FALSE;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
info = XRRQueryOutputProperty (manager_xrandr->xdisplay, output_id,
|
||||
display->atom_hotplug_mode_update);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
if (info)
|
||||
{
|
||||
result = TRUE;
|
||||
XFree (info);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
{
|
||||
@ -430,8 +453,10 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
XRRFreeCrtcInfo (crtc);
|
||||
}
|
||||
|
||||
meta_error_trap_push (meta_get_display ());
|
||||
primary_output = XRRGetOutputPrimary (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay));
|
||||
meta_error_trap_pop (meta_get_display ());
|
||||
|
||||
n_actual_outputs = 0;
|
||||
for (i = 0; i < (unsigned)resources->noutput; i++)
|
||||
@ -484,6 +509,8 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager)
|
||||
meta_output->width_mm = output->mm_width;
|
||||
meta_output->height_mm = output->mm_height;
|
||||
meta_output->subpixel_order = COGL_SUBPIXEL_ORDER_UNKNOWN;
|
||||
meta_output->hotplug_mode_update =
|
||||
output_get_hotplug_mode_update (manager_xrandr, meta_output->output_id);
|
||||
|
||||
meta_output->n_modes = output->nmode;
|
||||
meta_output->modes = g_new0 (MetaMonitorMode *, meta_output->n_modes);
|
||||
@ -668,10 +695,11 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
unsigned int n_outputs)
|
||||
{
|
||||
MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager);
|
||||
MetaDisplay *display = meta_get_display ();
|
||||
unsigned i;
|
||||
int width, height, width_mm, height_mm;
|
||||
|
||||
meta_display_grab (meta_get_display ());
|
||||
meta_display_grab (display);
|
||||
|
||||
/* First compute the new size of the screen (framebuffer) */
|
||||
width = 0; height = 0;
|
||||
@ -765,10 +793,10 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
*/
|
||||
width_mm = (width / DPI_FALLBACK) * 25.4 + 0.5;
|
||||
height_mm = (height / DPI_FALLBACK) * 25.4 + 0.5;
|
||||
meta_error_trap_push (meta_get_display ());
|
||||
meta_error_trap_push (display);
|
||||
XRRSetScreenSize (manager_xrandr->xdisplay, DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
width, height, width_mm, height_mm);
|
||||
meta_error_trap_pop (meta_get_display ());
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
for (i = 0; i < n_crtcs; i++)
|
||||
{
|
||||
@ -825,7 +853,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
goto next;
|
||||
}
|
||||
|
||||
meta_error_trap_push (meta_get_display ());
|
||||
meta_error_trap_push (display);
|
||||
ok = XRRSetCrtcConfig (manager_xrandr->xdisplay,
|
||||
manager_xrandr->resources,
|
||||
(XID)crtc->crtc_id,
|
||||
@ -834,7 +862,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
(XID)mode->mode_id,
|
||||
wl_transform_to_xrandr (crtc_info->transform),
|
||||
outputs, n_outputs);
|
||||
meta_error_trap_pop (meta_get_display ());
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
if (ok != Success)
|
||||
{
|
||||
@ -875,9 +903,11 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
|
||||
if (output_info->is_primary)
|
||||
{
|
||||
meta_error_trap_push (display);
|
||||
XRRSetOutputPrimary (manager_xrandr->xdisplay,
|
||||
DefaultRootWindow (manager_xrandr->xdisplay),
|
||||
(XID)output_info->output->output_id);
|
||||
meta_error_trap_pop (display);
|
||||
}
|
||||
|
||||
output_set_presentation_xrandr (manager_xrandr,
|
||||
@ -903,7 +933,7 @@ meta_monitor_manager_xrandr_apply_configuration (MetaMonitorManager *manager,
|
||||
output->is_primary = FALSE;
|
||||
}
|
||||
|
||||
meta_display_ungrab (meta_get_display ());
|
||||
meta_display_ungrab (display);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -971,6 +1001,16 @@ meta_monitor_manager_xrandr_set_crtc_gamma (MetaMonitorManager *manager,
|
||||
XRRFreeGamma (gamma);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_monitor_manager_xrandr_rebuild_derived (MetaMonitorManager *manager)
|
||||
{
|
||||
/* This will be a no-op if the change was from our side, as
|
||||
we already called it in the DBus method handler */
|
||||
meta_monitor_config_update_current (manager->config, manager);
|
||||
|
||||
meta_monitor_manager_rebuild_derived (manager);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
|
||||
XEvent *event)
|
||||
@ -980,6 +1020,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
|
||||
MetaCRTC *old_crtcs;
|
||||
MetaMonitorMode *old_modes;
|
||||
int n_old_outputs;
|
||||
gboolean new_config;
|
||||
|
||||
if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify)
|
||||
return FALSE;
|
||||
@ -995,31 +1036,36 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManager *manager,
|
||||
manager->serial++;
|
||||
meta_monitor_manager_xrandr_read_current (manager);
|
||||
|
||||
/* Check if the current intended configuration has the same outputs
|
||||
as the new real one, or if the event is a result of an XRandR call.
|
||||
If so, we can go straight to rebuild the logical config and tell
|
||||
the outside world.
|
||||
Otherwise, this event was caused by hotplug, so give a chance to
|
||||
MetaMonitorConfig.
|
||||
new_config = manager_xrandr->resources->timestamp >=
|
||||
manager_xrandr->resources->configTimestamp;
|
||||
if (meta_monitor_manager_has_hotplug_mode_update (manager))
|
||||
|
||||
Note that we need to check both the timestamps and the list of
|
||||
outputs, because the X server might emit spurious events with
|
||||
new configTimestamps (bug 702804), and the driver may have
|
||||
changed the EDID for some other reason (old broken qxl and vbox
|
||||
drivers...).
|
||||
*/
|
||||
if (manager_xrandr->resources->timestamp >= manager_xrandr->resources->configTimestamp ||
|
||||
meta_monitor_config_match_current (manager->config, manager))
|
||||
{
|
||||
/* This will be a no-op if the change was from our side, as
|
||||
we already called it in the DBus method handler */
|
||||
meta_monitor_config_update_current (manager->config, manager);
|
||||
|
||||
meta_monitor_manager_rebuild_derived (manager);
|
||||
/* Check if the current intended configuration is a result of an
|
||||
XRandR call. Otherwise, hotplug_mode_update tells us to get
|
||||
a new preferred mode on hotplug events to handle dynamic
|
||||
guest resizing. */
|
||||
if (new_config)
|
||||
meta_monitor_manager_xrandr_rebuild_derived (manager);
|
||||
else
|
||||
meta_monitor_config_make_default (manager->config, manager);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!meta_monitor_config_apply_stored (manager->config, manager))
|
||||
/* Check if the current intended configuration has the same outputs
|
||||
as the new real one, or if the event is a result of an XRandR call.
|
||||
If so, we can go straight to rebuild the logical config and tell
|
||||
the outside world.
|
||||
Otherwise, this event was caused by hotplug, so give a chance to
|
||||
MetaMonitorConfig.
|
||||
|
||||
Note that we need to check both the timestamps and the list of
|
||||
outputs, because the X server might emit spurious events with new
|
||||
configTimestamps (bug 702804), and the driver may have changed
|
||||
the EDID for some other reason (old qxl and vbox drivers). */
|
||||
if (new_config || meta_monitor_config_match_current (manager->config, manager))
|
||||
meta_monitor_manager_xrandr_rebuild_derived (manager);
|
||||
else if (!meta_monitor_config_apply_stored (manager->config, manager))
|
||||
meta_monitor_config_make_default (manager->config, manager);
|
||||
}
|
||||
|
||||
|
@ -806,6 +806,9 @@ meta_monitor_manager_handle_get_resources (MetaDBusDisplayConfig *skeleton,
|
||||
g_variant_new_take_string (make_display_name (manager, output)));
|
||||
g_variant_builder_add (&properties, "{sv}", "backlight",
|
||||
g_variant_new_int32 (output->backlight));
|
||||
g_variant_builder_add (&properties, "{sv}", "min-backlight-step",
|
||||
g_variant_new_int32 ((output->backlight_max - output->backlight_min) ?
|
||||
100 / (output->backlight_max - output->backlight_min) : -1));
|
||||
g_variant_builder_add (&properties, "{sv}", "primary",
|
||||
g_variant_new_boolean (output->is_primary));
|
||||
g_variant_builder_add (&properties, "{sv}", "presentation",
|
||||
|
299
src/core/place.c
299
src/core/place.c
@ -47,34 +47,18 @@ northwestcmp (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
MetaWindow *aw = (gpointer) a;
|
||||
MetaWindow *bw = (gpointer) b;
|
||||
MetaRectangle a_frame;
|
||||
MetaRectangle b_frame;
|
||||
int from_origin_a;
|
||||
int from_origin_b;
|
||||
int ax, ay, bx, by;
|
||||
|
||||
/* we're interested in the frame position for cascading,
|
||||
* not meta_window_get_position()
|
||||
*/
|
||||
if (aw->frame)
|
||||
{
|
||||
ax = aw->frame->rect.x;
|
||||
ay = aw->frame->rect.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
ax = aw->rect.x;
|
||||
ay = aw->rect.y;
|
||||
}
|
||||
|
||||
if (bw->frame)
|
||||
{
|
||||
bx = bw->frame->rect.x;
|
||||
by = bw->frame->rect.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
bx = bw->rect.x;
|
||||
by = bw->rect.y;
|
||||
}
|
||||
meta_window_get_frame_rect (aw, &a_frame);
|
||||
meta_window_get_frame_rect (bw, &b_frame);
|
||||
ax = a_frame.x;
|
||||
ay = a_frame.y;
|
||||
bx = b_frame.x;
|
||||
by = b_frame.y;
|
||||
|
||||
/* probably there's a fast good-enough-guess we could use here. */
|
||||
from_origin_a = sqrt (ax * ax + ay * ay);
|
||||
@ -90,7 +74,6 @@ northwestcmp (gconstpointer a, gconstpointer b)
|
||||
|
||||
static void
|
||||
find_next_cascade (MetaWindow *window,
|
||||
MetaFrameBorders *borders,
|
||||
/* visible windows on relevant workspaces */
|
||||
GList *windows,
|
||||
int x,
|
||||
@ -102,6 +85,7 @@ find_next_cascade (MetaWindow *window,
|
||||
GList *sorted;
|
||||
int cascade_x, cascade_y;
|
||||
int x_threshold, y_threshold;
|
||||
MetaRectangle frame_rect;
|
||||
int window_width, window_height;
|
||||
int cascade_stage;
|
||||
MetaRectangle work_area;
|
||||
@ -120,10 +104,13 @@ find_next_cascade (MetaWindow *window,
|
||||
* manually cascade.
|
||||
*/
|
||||
#define CASCADE_FUZZ 15
|
||||
if (borders)
|
||||
if (window->frame)
|
||||
{
|
||||
x_threshold = MAX (borders->visible.left, CASCADE_FUZZ);
|
||||
y_threshold = MAX (borders->visible.top, CASCADE_FUZZ);
|
||||
MetaFrameBorders borders;
|
||||
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
x_threshold = MAX (borders.visible.left, CASCADE_FUZZ);
|
||||
y_threshold = MAX (borders.visible.top, CASCADE_FUZZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -143,30 +130,25 @@ find_next_cascade (MetaWindow *window,
|
||||
cascade_y = MAX (0, work_area.y);
|
||||
|
||||
/* Find first cascade position that's not used. */
|
||||
|
||||
window_width = window->frame ? window->frame->rect.width : window->rect.width;
|
||||
window_height = window->frame ? window->frame->rect.height : window->rect.height;
|
||||
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
window_width = frame_rect.width;
|
||||
window_height = frame_rect.height;
|
||||
|
||||
cascade_stage = 0;
|
||||
tmp = sorted;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *w;
|
||||
MetaRectangle w_frame_rect;
|
||||
int wx, wy;
|
||||
|
||||
w = tmp->data;
|
||||
|
||||
/* we want frame position, not window position */
|
||||
if (w->frame)
|
||||
{
|
||||
wx = w->frame->rect.x;
|
||||
wy = w->frame->rect.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
wx = w->rect.x;
|
||||
wy = w->rect.y;
|
||||
}
|
||||
meta_window_get_frame_rect (w, &w_frame_rect);
|
||||
wx = w_frame_rect.x;
|
||||
wy = w_frame_rect.y;
|
||||
|
||||
if (ABS (wx - cascade_x) < x_threshold &&
|
||||
ABS (wy - cascade_y) < y_threshold)
|
||||
@ -223,22 +205,12 @@ find_next_cascade (MetaWindow *window,
|
||||
|
||||
g_list_free (sorted);
|
||||
|
||||
/* Convert coords to position of window, not position of frame. */
|
||||
if (borders == NULL)
|
||||
{
|
||||
*new_x = cascade_x;
|
||||
*new_y = cascade_y;
|
||||
}
|
||||
else
|
||||
{
|
||||
*new_x = cascade_x + borders->visible.left;
|
||||
*new_y = cascade_y + borders->visible.top;
|
||||
}
|
||||
*new_x = cascade_x;
|
||||
*new_y = cascade_y;
|
||||
}
|
||||
|
||||
static void
|
||||
find_most_freespace (MetaWindow *window,
|
||||
MetaFrameBorders *borders,
|
||||
/* visible windows on relevant workspaces */
|
||||
MetaWindow *focus_window,
|
||||
int x,
|
||||
@ -250,29 +222,25 @@ find_most_freespace (MetaWindow *window,
|
||||
int max_area;
|
||||
int max_width, max_height, left, right, top, bottom;
|
||||
int left_space, right_space, top_space, bottom_space;
|
||||
int frame_size_left, frame_size_top;
|
||||
MetaRectangle work_area;
|
||||
MetaRectangle avoid;
|
||||
MetaRectangle outer;
|
||||
|
||||
frame_size_left = borders ? borders->visible.left : 0;
|
||||
frame_size_top = borders ? borders->visible.top : 0;
|
||||
MetaRectangle frame_rect;
|
||||
|
||||
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);
|
||||
meta_window_get_frame_rect (focus_window, &avoid);
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
|
||||
/* Find the areas of choosing the various sides of the focus window */
|
||||
max_width = MIN (avoid.width, outer.width);
|
||||
max_height = MIN (avoid.height, outer.height);
|
||||
max_width = MIN (avoid.width, frame_rect.width);
|
||||
max_height = MIN (avoid.height, frame_rect.height);
|
||||
left_space = avoid.x - work_area.x;
|
||||
right_space = work_area.width - (avoid.x + avoid.width - work_area.x);
|
||||
top_space = avoid.y - work_area.y;
|
||||
bottom_space = work_area.height - (avoid.y + avoid.height - work_area.y);
|
||||
left = MIN (left_space, outer.width);
|
||||
right = MIN (right_space, outer.width);
|
||||
top = MIN (top_space, outer.height);
|
||||
bottom = MIN (bottom_space, outer.height);
|
||||
left = MIN (left_space, frame_rect.width);
|
||||
right = MIN (right_space, frame_rect.width);
|
||||
top = MIN (top_space, frame_rect.height);
|
||||
bottom = MIN (bottom_space, frame_rect.height);
|
||||
|
||||
/* Find out which side of the focus_window can show the most of the window */
|
||||
side = META_LEFT;
|
||||
@ -304,39 +272,56 @@ find_most_freespace (MetaWindow *window,
|
||||
switch (side)
|
||||
{
|
||||
case META_LEFT:
|
||||
*new_y = avoid.y + frame_size_top;
|
||||
if (left_space > outer.width)
|
||||
*new_x = avoid.x - outer.width + frame_size_left;
|
||||
*new_y = avoid.y;
|
||||
if (left_space > frame_rect.width)
|
||||
*new_x = avoid.x - frame_rect.width;
|
||||
else
|
||||
*new_x = work_area.x + frame_size_left;
|
||||
*new_x = work_area.x;
|
||||
break;
|
||||
case META_RIGHT:
|
||||
*new_y = avoid.y + frame_size_top;
|
||||
if (right_space > outer.width)
|
||||
*new_x = avoid.x + avoid.width + frame_size_left;
|
||||
*new_y = avoid.y;
|
||||
if (right_space > frame_rect.width)
|
||||
*new_x = avoid.x + avoid.width;
|
||||
else
|
||||
*new_x = work_area.x + work_area.width - outer.width + frame_size_left;
|
||||
*new_x = work_area.x + work_area.width - frame_rect.width;
|
||||
break;
|
||||
case META_TOP:
|
||||
*new_x = avoid.x + frame_size_left;
|
||||
if (top_space > outer.height)
|
||||
*new_y = avoid.y - outer.height + frame_size_top;
|
||||
*new_x = avoid.x;
|
||||
if (top_space > frame_rect.height)
|
||||
*new_y = avoid.y - frame_rect.height;
|
||||
else
|
||||
*new_y = work_area.y + frame_size_top;
|
||||
*new_y = work_area.y;
|
||||
break;
|
||||
case META_BOTTOM:
|
||||
*new_x = avoid.x + frame_size_left;
|
||||
if (bottom_space > outer.height)
|
||||
*new_y = avoid.y + avoid.height + frame_size_top;
|
||||
*new_x = avoid.x;
|
||||
if (bottom_space > frame_rect.height)
|
||||
*new_y = avoid.y + avoid.height;
|
||||
else
|
||||
*new_y = work_area.y + work_area.height - outer.height + frame_size_top;
|
||||
*new_y = work_area.y + work_area.height - frame_rect.height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
window_overlaps_focus_window (MetaWindow *window)
|
||||
{
|
||||
MetaWindow *focus_window;
|
||||
MetaRectangle window_frame, focus_frame, overlap;
|
||||
|
||||
focus_window = window->display->focus_window;
|
||||
if (focus_window == NULL)
|
||||
return FALSE;
|
||||
|
||||
meta_window_get_frame_rect (window, &window_frame);
|
||||
meta_window_get_frame_rect (focus_window, &focus_frame);
|
||||
|
||||
return meta_rectangle_intersect (&window_frame,
|
||||
&focus_frame,
|
||||
&overlap);
|
||||
}
|
||||
|
||||
static void
|
||||
avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
|
||||
MetaFrameBorders *borders,
|
||||
int *x,
|
||||
int *y)
|
||||
{
|
||||
@ -355,18 +340,17 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
|
||||
*/
|
||||
|
||||
MetaWindow *focus_window;
|
||||
MetaRectangle overlap;
|
||||
|
||||
focus_window = window->display->focus_window;
|
||||
|
||||
/* denied_focus_and_not_transient is only set when focus_window != NULL */
|
||||
|
||||
if (window->denied_focus_and_not_transient &&
|
||||
window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
|
||||
meta_window_same_application (window, focus_window) &&
|
||||
meta_rectangle_intersect (&window->rect,
|
||||
&focus_window->rect,
|
||||
&overlap))
|
||||
window_overlaps_focus_window (window))
|
||||
{
|
||||
find_most_freespace (window, borders, focus_window, *x, *y, x, y);
|
||||
find_most_freespace (window, focus_window, *x, *y, x, y);
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Dialog window %s was denied focus but may be modal "
|
||||
"to the focus window; had to move it to avoid the "
|
||||
@ -409,7 +393,7 @@ rectangle_overlaps_some_window (MetaRectangle *rect,
|
||||
case META_WINDOW_UTILITY:
|
||||
case META_WINDOW_TOOLBAR:
|
||||
case META_WINDOW_MENU:
|
||||
meta_window_get_outer_rect (other, &other_rect);
|
||||
meta_window_get_frame_rect (other, &other_rect);
|
||||
|
||||
if (meta_rectangle_intersect (rect, &other_rect, &dest))
|
||||
return TRUE;
|
||||
@ -427,20 +411,14 @@ leftmost_cmp (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
MetaWindow *aw = (gpointer) a;
|
||||
MetaWindow *bw = (gpointer) b;
|
||||
MetaRectangle a_frame;
|
||||
MetaRectangle b_frame;
|
||||
int ax, bx;
|
||||
|
||||
/* we're interested in the frame position for cascading,
|
||||
* not meta_window_get_position()
|
||||
*/
|
||||
if (aw->frame)
|
||||
ax = aw->frame->rect.x;
|
||||
else
|
||||
ax = aw->rect.x;
|
||||
|
||||
if (bw->frame)
|
||||
bx = bw->frame->rect.x;
|
||||
else
|
||||
bx = bw->rect.x;
|
||||
meta_window_get_frame_rect (aw, &a_frame);
|
||||
meta_window_get_frame_rect (bw, &b_frame);
|
||||
ax = a_frame.x;
|
||||
bx = b_frame.x;
|
||||
|
||||
if (ax < bx)
|
||||
return -1;
|
||||
@ -455,20 +433,14 @@ topmost_cmp (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
MetaWindow *aw = (gpointer) a;
|
||||
MetaWindow *bw = (gpointer) b;
|
||||
MetaRectangle a_frame;
|
||||
MetaRectangle b_frame;
|
||||
int ay, by;
|
||||
|
||||
/* we're interested in the frame position for cascading,
|
||||
* not meta_window_get_position()
|
||||
*/
|
||||
if (aw->frame)
|
||||
ay = aw->frame->rect.y;
|
||||
else
|
||||
ay = aw->rect.y;
|
||||
|
||||
if (bw->frame)
|
||||
by = bw->frame->rect.y;
|
||||
else
|
||||
by = bw->rect.y;
|
||||
meta_window_get_frame_rect (aw, &a_frame);
|
||||
meta_window_get_frame_rect (bw, &b_frame);
|
||||
ay = a_frame.y;
|
||||
by = b_frame.y;
|
||||
|
||||
if (ay < by)
|
||||
return -1;
|
||||
@ -506,7 +478,6 @@ center_tile_rect_in_area (MetaRectangle *rect,
|
||||
*/
|
||||
static gboolean
|
||||
find_first_fit (MetaWindow *window,
|
||||
MetaFrameBorders *borders,
|
||||
/* visible windows on relevant workspaces */
|
||||
GList *windows,
|
||||
int monitor,
|
||||
@ -540,15 +511,8 @@ find_first_fit (MetaWindow *window,
|
||||
right_sorted = g_list_copy (windows);
|
||||
right_sorted = g_list_sort (right_sorted, topmost_cmp);
|
||||
right_sorted = g_list_sort (right_sorted, leftmost_cmp);
|
||||
|
||||
rect.width = window->rect.width;
|
||||
rect.height = window->rect.height;
|
||||
|
||||
if (borders)
|
||||
{
|
||||
rect.width += borders->visible.left + borders->visible.right;
|
||||
rect.height += borders->visible.top + borders->visible.bottom;
|
||||
}
|
||||
|
||||
meta_window_get_frame_rect (window, &rect);
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
{
|
||||
@ -570,11 +534,6 @@ find_first_fit (MetaWindow *window,
|
||||
{
|
||||
*new_x = rect.x;
|
||||
*new_y = rect.y;
|
||||
if (borders)
|
||||
{
|
||||
*new_x += borders->visible.left;
|
||||
*new_y += borders->visible.top;
|
||||
}
|
||||
|
||||
retval = TRUE;
|
||||
|
||||
@ -586,23 +545,18 @@ find_first_fit (MetaWindow *window,
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *w = tmp->data;
|
||||
MetaRectangle outer_rect;
|
||||
MetaRectangle frame_rect;
|
||||
|
||||
meta_window_get_outer_rect (w, &outer_rect);
|
||||
meta_window_get_frame_rect (w, &frame_rect);
|
||||
|
||||
rect.x = outer_rect.x;
|
||||
rect.y = outer_rect.y + outer_rect.height;
|
||||
rect.x = frame_rect.x;
|
||||
rect.y = frame_rect.y + frame_rect.height;
|
||||
|
||||
if (meta_rectangle_contains_rect (&work_area, &rect) &&
|
||||
!rectangle_overlaps_some_window (&rect, below_sorted))
|
||||
{
|
||||
*new_x = rect.x;
|
||||
*new_y = rect.y;
|
||||
if (borders)
|
||||
{
|
||||
*new_x += borders->visible.left;
|
||||
*new_y += borders->visible.top;
|
||||
}
|
||||
|
||||
retval = TRUE;
|
||||
|
||||
@ -617,23 +571,18 @@ find_first_fit (MetaWindow *window,
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *w = tmp->data;
|
||||
MetaRectangle outer_rect;
|
||||
MetaRectangle frame_rect;
|
||||
|
||||
meta_window_get_outer_rect (w, &outer_rect);
|
||||
meta_window_get_frame_rect (w, &frame_rect);
|
||||
|
||||
rect.x = outer_rect.x + outer_rect.width;
|
||||
rect.y = outer_rect.y;
|
||||
rect.x = frame_rect.x + frame_rect.width;
|
||||
rect.y = frame_rect.y;
|
||||
|
||||
if (meta_rectangle_contains_rect (&work_area, &rect) &&
|
||||
!rectangle_overlaps_some_window (&rect, right_sorted))
|
||||
{
|
||||
*new_x = rect.x;
|
||||
*new_y = rect.y;
|
||||
if (borders)
|
||||
{
|
||||
*new_x += borders->visible.left;
|
||||
*new_y += borders->visible.top;
|
||||
}
|
||||
|
||||
retval = TRUE;
|
||||
|
||||
@ -652,7 +601,6 @@ find_first_fit (MetaWindow *window,
|
||||
|
||||
void
|
||||
meta_window_place (MetaWindow *window,
|
||||
MetaFrameBorders *borders,
|
||||
int x,
|
||||
int y,
|
||||
int *new_x,
|
||||
@ -661,13 +609,6 @@ meta_window_place (MetaWindow *window,
|
||||
GList *windows;
|
||||
const MetaMonitorInfo *xi;
|
||||
|
||||
/* frame member variables should NEVER be used in here, only
|
||||
* MetaFrameBorders. But remember borders == NULL
|
||||
* for undecorated windows. Also, this function should
|
||||
* NEVER have side effects other than computing the
|
||||
* placement coordinates.
|
||||
*/
|
||||
|
||||
meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
|
||||
|
||||
windows = NULL;
|
||||
@ -756,7 +697,7 @@ meta_window_place (MetaWindow *window,
|
||||
{
|
||||
meta_topic (META_DEBUG_PLACEMENT,
|
||||
"Not placing window with PPosition or USPosition set\n");
|
||||
avoid_being_obscured_as_second_modal_dialog (window, borders, &x, &y);
|
||||
avoid_being_obscured_as_second_modal_dialog (window, &x, &y);
|
||||
goto done_no_constraints;
|
||||
}
|
||||
}
|
||||
@ -775,29 +716,27 @@ meta_window_place (MetaWindow *window,
|
||||
|
||||
if (parent)
|
||||
{
|
||||
int w;
|
||||
MetaRectangle frame_rect, parent_frame_rect;
|
||||
|
||||
meta_window_get_position (parent, &x, &y);
|
||||
w = parent->rect.width;
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
meta_window_get_frame_rect (parent, &parent_frame_rect);
|
||||
|
||||
y = parent_frame_rect.y;
|
||||
|
||||
/* center of parent */
|
||||
x = x + w / 2;
|
||||
x = parent_frame_rect.x + parent_frame_rect.width / 2;
|
||||
/* center of child over center of parent */
|
||||
x -= window->rect.width / 2;
|
||||
x -= frame_rect.width / 2;
|
||||
|
||||
/* "visually" center window over parent, leaving twice as
|
||||
* much space below as on top.
|
||||
*/
|
||||
y += (parent->rect.height - window->rect.height)/3;
|
||||
|
||||
/* put top of child's frame, not top of child's client */
|
||||
if (borders)
|
||||
y += borders->visible.top;
|
||||
y += (parent_frame_rect.height - frame_rect.height)/3;
|
||||
|
||||
meta_topic (META_DEBUG_PLACEMENT, "Centered window %s over transient parent\n",
|
||||
window->desc);
|
||||
|
||||
avoid_being_obscured_as_second_modal_dialog (window, borders, &x, &y);
|
||||
avoid_being_obscured_as_second_modal_dialog (window, &x, &y);
|
||||
|
||||
goto done;
|
||||
}
|
||||
@ -813,6 +752,9 @@ meta_window_place (MetaWindow *window,
|
||||
{
|
||||
/* Center on current monitor */
|
||||
int w, h;
|
||||
MetaRectangle frame_rect;
|
||||
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
|
||||
/* Warning, this function is a round trip! */
|
||||
xi = meta_screen_get_current_monitor_info (window->screen);
|
||||
@ -820,8 +762,8 @@ meta_window_place (MetaWindow *window,
|
||||
w = xi->rect.width;
|
||||
h = xi->rect.height;
|
||||
|
||||
x = (w - window->rect.width) / 2;
|
||||
y = (h - window->rect.height) / 2;
|
||||
x = (w - frame_rect.width) / 2;
|
||||
y = (h - frame_rect.height) / 2;
|
||||
|
||||
x += xi->rect.x;
|
||||
y += xi->rect.y;
|
||||
@ -865,7 +807,7 @@ meta_window_place (MetaWindow *window,
|
||||
x = xi->rect.x;
|
||||
y = xi->rect.y;
|
||||
|
||||
if (find_first_fit (window, borders, windows,
|
||||
if (find_first_fit (window, windows,
|
||||
xi->number,
|
||||
x, y, &x, &y))
|
||||
goto done_check_denied_focus;
|
||||
@ -878,17 +820,17 @@ meta_window_place (MetaWindow *window,
|
||||
!window->fullscreen)
|
||||
{
|
||||
MetaRectangle workarea;
|
||||
MetaRectangle outer;
|
||||
MetaRectangle frame_rect;
|
||||
|
||||
meta_window_get_work_area_for_monitor (window,
|
||||
xi->number,
|
||||
&workarea);
|
||||
meta_window_get_outer_rect (window, &outer);
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
|
||||
/* If the window is bigger than the screen, then automaximize. Do NOT
|
||||
* auto-maximize the directions independently. See #419810.
|
||||
*/
|
||||
if (outer.width >= workarea.width && outer.height >= workarea.height)
|
||||
if (frame_rect.width >= workarea.width && frame_rect.height >= workarea.height)
|
||||
{
|
||||
window->maximize_horizontally_after_placement = TRUE;
|
||||
window->maximize_vertically_after_placement = TRUE;
|
||||
@ -899,7 +841,7 @@ meta_window_place (MetaWindow *window,
|
||||
* fully overlapping window (e.g. starting multiple terminals)
|
||||
* */
|
||||
if (x == xi->rect.x && y == xi->rect.y)
|
||||
find_next_cascade (window, borders, windows, x, y, &x, &y);
|
||||
find_next_cascade (window, windows, x, y, &x, &y);
|
||||
|
||||
done_check_denied_focus:
|
||||
/* If the window is being denied focus and isn't a transient of the
|
||||
@ -909,17 +851,14 @@ meta_window_place (MetaWindow *window,
|
||||
*/
|
||||
if (window->denied_focus_and_not_transient)
|
||||
{
|
||||
gboolean found_fit;
|
||||
MetaWindow *focus_window;
|
||||
MetaRectangle overlap;
|
||||
gboolean found_fit;
|
||||
|
||||
focus_window = window->display->focus_window;
|
||||
g_assert (focus_window != NULL);
|
||||
|
||||
/* No need to do anything if the window doesn't overlap at all */
|
||||
found_fit = !meta_rectangle_intersect (&window->rect,
|
||||
&focus_window->rect,
|
||||
&overlap);
|
||||
found_fit = !window_overlaps_focus_window (window);
|
||||
|
||||
/* Try to do a first fit again, this time only taking into account the
|
||||
* focus window.
|
||||
@ -933,7 +872,7 @@ meta_window_place (MetaWindow *window,
|
||||
x = xi->rect.x;
|
||||
y = xi->rect.y;
|
||||
|
||||
found_fit = find_first_fit (window, borders, focus_window_list,
|
||||
found_fit = find_first_fit (window, focus_window_list,
|
||||
xi->number,
|
||||
x, y, &x, &y);
|
||||
g_list_free (focus_window_list);
|
||||
@ -943,7 +882,7 @@ meta_window_place (MetaWindow *window,
|
||||
* as possible.
|
||||
*/
|
||||
if (!found_fit)
|
||||
find_most_freespace (window, borders, focus_window, x, y, &x, &y);
|
||||
find_most_freespace (window, focus_window, x, y, &x, &y);
|
||||
}
|
||||
|
||||
done:
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "frame.h"
|
||||
|
||||
void meta_window_place (MetaWindow *window,
|
||||
MetaFrameBorders *borders,
|
||||
int x,
|
||||
int y,
|
||||
int *new_x,
|
||||
|
@ -476,6 +476,9 @@ create_guard_window (Display *xdisplay, MetaScreen *screen)
|
||||
CWEventMask|CWOverrideRedirect|CWBackPixel,
|
||||
&attributes);
|
||||
|
||||
/* https://bugzilla.gnome.org/show_bug.cgi?id=710346 */
|
||||
XStoreName (xdisplay, guard_window, "mutter guard window");
|
||||
|
||||
{
|
||||
unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
|
||||
XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };
|
||||
@ -856,9 +859,9 @@ meta_screen_free (MetaScreen *screen,
|
||||
screen->wm_sn_selection_window);
|
||||
|
||||
if (screen->work_area_later != 0)
|
||||
g_source_remove (screen->work_area_later);
|
||||
meta_later_remove (screen->work_area_later);
|
||||
if (screen->check_fullscreen_later != 0)
|
||||
g_source_remove (screen->check_fullscreen_later);
|
||||
meta_later_remove (screen->check_fullscreen_later);
|
||||
|
||||
if (screen->monitor_infos)
|
||||
g_free (screen->monitor_infos);
|
||||
@ -1525,7 +1528,7 @@ meta_screen_tab_popup_create (MetaScreen *screen,
|
||||
if (show_type == META_TAB_SHOW_INSTANTLY ||
|
||||
!entries[i].hidden ||
|
||||
!meta_window_get_icon_geometry (window, &r))
|
||||
meta_window_get_outer_rect (window, &r);
|
||||
meta_window_get_frame_rect (window, &r);
|
||||
|
||||
entries[i].rect = r;
|
||||
|
||||
@ -1908,7 +1911,7 @@ meta_screen_get_monitor_for_window (MetaScreen *screen,
|
||||
{
|
||||
MetaRectangle window_rect;
|
||||
|
||||
meta_window_get_outer_rect (window, &window_rect);
|
||||
meta_window_get_frame_rect (window, &window_rect);
|
||||
|
||||
return meta_screen_get_monitor_for_rect (screen, &window_rect);
|
||||
}
|
||||
|
@ -1465,7 +1465,7 @@ window_contains_point (MetaWindow *window,
|
||||
{
|
||||
MetaRectangle rect;
|
||||
|
||||
meta_window_get_outer_rect (window, &rect);
|
||||
meta_window_get_frame_rect (window, &rect);
|
||||
|
||||
return POINT_IN_RECT (root_x, root_y, rect);
|
||||
}
|
||||
@ -1484,14 +1484,12 @@ get_default_focus_window (MetaStack *stack,
|
||||
* or top window in same group as not_this_one.
|
||||
*/
|
||||
|
||||
MetaWindow *topmost_dock;
|
||||
MetaWindow *transient_parent;
|
||||
MetaWindow *topmost_in_group;
|
||||
MetaWindow *topmost_overall;
|
||||
MetaGroup *not_this_one_group;
|
||||
GList *link;
|
||||
|
||||
topmost_dock = NULL;
|
||||
transient_parent = NULL;
|
||||
topmost_in_group = NULL;
|
||||
topmost_overall = NULL;
|
||||
@ -1517,10 +1515,6 @@ get_default_focus_window (MetaStack *stack,
|
||||
(workspace == NULL ||
|
||||
meta_window_located_on_workspace (window, workspace)))
|
||||
{
|
||||
if (topmost_dock == NULL &&
|
||||
window->type == META_WINDOW_DOCK)
|
||||
topmost_dock = window;
|
||||
|
||||
if (not_this_one != NULL)
|
||||
{
|
||||
if (transient_parent == NULL &&
|
||||
@ -1538,10 +1532,6 @@ get_default_focus_window (MetaStack *stack,
|
||||
topmost_in_group = window;
|
||||
}
|
||||
|
||||
/* Note that DESKTOP windows can be topmost_overall so
|
||||
* we prefer focusing desktop or other windows over
|
||||
* focusing dock, even though docks are stacked higher.
|
||||
*/
|
||||
if (topmost_overall == NULL &&
|
||||
window->type != META_WINDOW_DOCK &&
|
||||
(!must_be_at_point ||
|
||||
@ -1563,7 +1553,7 @@ get_default_focus_window (MetaStack *stack,
|
||||
else if (topmost_overall)
|
||||
return topmost_overall;
|
||||
else
|
||||
return topmost_dock;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MetaWindow*
|
||||
|
@ -352,6 +352,12 @@ struct _MetaWindow
|
||||
/* if non-NULL, the opaque region _NET_WM_OPAQUE_REGION */
|
||||
cairo_region_t *opaque_region;
|
||||
|
||||
/* the input shape region for picking */
|
||||
cairo_region_t *input_region;
|
||||
|
||||
/* _NET_WM_WINDOW_OPACITY */
|
||||
guint opacity;
|
||||
|
||||
/* if TRUE, the we have the new form of sync request counter which
|
||||
* also handles application frames */
|
||||
guint extended_sync_request_counter : 1;
|
||||
@ -512,6 +518,7 @@ void meta_window_update_fullscreen_monitors (MetaWindow *window,
|
||||
unsigned long left,
|
||||
unsigned long right);
|
||||
|
||||
|
||||
/* args to move are window pos, not frame pos */
|
||||
void meta_window_move (MetaWindow *window,
|
||||
gboolean user_op,
|
||||
@ -655,6 +662,8 @@ void meta_window_recalc_features (MetaWindow *window);
|
||||
|
||||
void meta_window_recalc_window_type (MetaWindow *window);
|
||||
|
||||
void meta_window_frame_size_changed (MetaWindow *window);
|
||||
|
||||
void meta_window_stack_just_below (MetaWindow *window,
|
||||
MetaWindow *below_this_one);
|
||||
|
||||
@ -682,8 +691,16 @@ void meta_window_set_opaque_region (MetaWindow *window,
|
||||
cairo_region_t *region);
|
||||
void meta_window_update_opaque_region_x11 (MetaWindow *window);
|
||||
|
||||
void meta_window_set_input_region (MetaWindow *window,
|
||||
cairo_region_t *region);
|
||||
void meta_window_update_input_region_x11 (MetaWindow *window);
|
||||
|
||||
void meta_window_set_shape_region (MetaWindow *window,
|
||||
cairo_region_t *region);
|
||||
void meta_window_update_shape_region_x11 (MetaWindow *window);
|
||||
void meta_window_set_opacity (MetaWindow *window,
|
||||
guint opacity);
|
||||
|
||||
Window meta_window_get_toplevel_xwindow (MetaWindow *window);
|
||||
|
||||
#endif
|
||||
|
@ -316,6 +316,9 @@ reload_gtk_frame_extents (MetaWindow *window,
|
||||
{
|
||||
window->has_custom_frame_extents = FALSE;
|
||||
}
|
||||
|
||||
if (!initial)
|
||||
meta_window_queue(window, META_QUEUE_MOVE_RESIZE);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1706,6 +1709,20 @@ reload_bypass_compositor (MetaWindow *window,
|
||||
window->bypass_compositor = requested_value;
|
||||
}
|
||||
|
||||
static void
|
||||
reload_window_opacity (MetaWindow *window,
|
||||
MetaPropValue *value,
|
||||
gboolean initial)
|
||||
|
||||
{
|
||||
int requested_value = 0xFF;
|
||||
|
||||
if (value->type != META_PROP_VALUE_INVALID)
|
||||
requested_value = (int) value->v.cardinal;
|
||||
|
||||
meta_window_set_opacity (window, requested_value);
|
||||
}
|
||||
|
||||
#define RELOAD_STRING(var_name, propname) \
|
||||
static void \
|
||||
reload_ ## var_name (MetaWindow *window, \
|
||||
@ -1808,6 +1825,7 @@ meta_display_init_window_prop_hooks (MetaDisplay *display)
|
||||
{ display->atom__NET_WM_STRUT, META_PROP_VALUE_INVALID, reload_struts, FALSE, FALSE },
|
||||
{ display->atom__NET_WM_STRUT_PARTIAL, META_PROP_VALUE_INVALID, reload_struts, FALSE, FALSE },
|
||||
{ display->atom__NET_WM_BYPASS_COMPOSITOR, META_PROP_VALUE_CARDINAL, reload_bypass_compositor, FALSE, FALSE },
|
||||
{ display->atom__NET_WM_WINDOW_OPACITY, META_PROP_VALUE_CARDINAL, reload_window_opacity, TRUE, TRUE },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
|
@ -1194,12 +1194,15 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
||||
meta_display_register_x_window (display, &window->xwindow, window);
|
||||
|
||||
meta_window_update_shape_region_x11 (window);
|
||||
meta_window_update_input_region_x11 (window);
|
||||
|
||||
/* Assign this #MetaWindow a sequence number which can be used
|
||||
* for sorting.
|
||||
*/
|
||||
window->stable_sequence = ++display->window_sequence_counter;
|
||||
|
||||
window->opacity = 0xFF;
|
||||
|
||||
/* assign the window to its group, or create a new group if needed
|
||||
*/
|
||||
window->group = NULL;
|
||||
@ -1444,9 +1447,6 @@ meta_window_new_with_attrs (MetaDisplay *display,
|
||||
set_net_wm_state (window);
|
||||
}
|
||||
|
||||
if (screen->display->compositor)
|
||||
meta_compositor_add_window (screen->display->compositor, window);
|
||||
|
||||
/* Sync stack changes */
|
||||
meta_stack_thaw (window->screen->stack);
|
||||
|
||||
@ -1669,8 +1669,6 @@ meta_window_unmanage (MetaWindow *window,
|
||||
if (window->visible_to_compositor)
|
||||
meta_compositor_hide_window (window->display->compositor, window,
|
||||
META_COMP_EFFECT_DESTROY);
|
||||
|
||||
meta_compositor_remove_window (window->display->compositor, window);
|
||||
}
|
||||
|
||||
if (window->display->window_with_menu == window)
|
||||
@ -1869,6 +1867,8 @@ meta_window_unmanage (MetaWindow *window,
|
||||
meta_window_ungrab_keys (window);
|
||||
meta_display_ungrab_window_buttons (window->display, window->xwindow);
|
||||
meta_display_ungrab_focus_window_button (window->display, window);
|
||||
if (window->display->autoraise_window == window)
|
||||
meta_display_remove_autoraise_callback (window->display);
|
||||
|
||||
meta_display_unregister_x_window (window->display, window->xwindow);
|
||||
|
||||
@ -2791,8 +2791,8 @@ static gboolean
|
||||
windows_overlap (const MetaWindow *w1, const MetaWindow *w2)
|
||||
{
|
||||
MetaRectangle w1rect, w2rect;
|
||||
meta_window_get_outer_rect (w1, &w1rect);
|
||||
meta_window_get_outer_rect (w2, &w2rect);
|
||||
meta_window_get_frame_rect (w1, &w1rect);
|
||||
meta_window_get_frame_rect (w2, &w2rect);
|
||||
return meta_rectangle_overlap (&w1rect, &w2rect);
|
||||
}
|
||||
|
||||
@ -3138,7 +3138,7 @@ meta_window_show (MetaWindow *window)
|
||||
if (toplevel_now_mapped != toplevel_was_mapped)
|
||||
{
|
||||
if (window->display->compositor)
|
||||
meta_compositor_window_mapped (window->display->compositor, window);
|
||||
meta_compositor_add_window (window->display->compositor, window);
|
||||
}
|
||||
|
||||
if (!window->visible_to_compositor)
|
||||
@ -3287,13 +3287,7 @@ meta_window_hide (MetaWindow *window)
|
||||
if (toplevel_now_mapped != toplevel_was_mapped)
|
||||
{
|
||||
if (window->display->compositor)
|
||||
{
|
||||
/* As above, we may be *mapping* live hidden windows */
|
||||
if (toplevel_now_mapped)
|
||||
meta_compositor_window_mapped (window->display->compositor, window);
|
||||
else
|
||||
meta_compositor_window_unmapped (window->display->compositor, window);
|
||||
}
|
||||
meta_compositor_remove_window (window->display->compositor, window);
|
||||
}
|
||||
|
||||
set_net_wm_state (window);
|
||||
@ -3593,11 +3587,11 @@ meta_window_maximize (MetaWindow *window,
|
||||
MetaRectangle old_rect;
|
||||
MetaRectangle new_rect;
|
||||
|
||||
meta_window_get_outer_rect (window, &old_rect);
|
||||
meta_window_get_frame_rect (window, &old_rect);
|
||||
|
||||
meta_window_move_resize_now (window);
|
||||
|
||||
meta_window_get_outer_rect (window, &new_rect);
|
||||
meta_window_get_frame_rect (window, &new_rect);
|
||||
meta_compositor_maximize_window (window->display->compositor,
|
||||
window,
|
||||
&old_rect,
|
||||
@ -3656,7 +3650,7 @@ meta_window_get_all_monitors (MetaWindow *window, gsize *length)
|
||||
int i;
|
||||
|
||||
monitors = g_array_new (FALSE, FALSE, sizeof (int));
|
||||
meta_window_get_outer_rect (window, &window_rect);
|
||||
meta_window_get_frame_rect (window, &window_rect);
|
||||
|
||||
for (i = 0; i < window->screen->n_monitor_infos; i++)
|
||||
{
|
||||
@ -3689,7 +3683,7 @@ meta_window_is_screen_sized (MetaWindow *window)
|
||||
int screen_width, screen_height;
|
||||
|
||||
meta_screen_get_size (window->screen, &screen_width, &screen_height);
|
||||
meta_window_get_outer_rect (window, &window_rect);
|
||||
meta_window_get_frame_rect (window, &window_rect);
|
||||
|
||||
if (window_rect.x == 0 && window_rect.y == 0 &&
|
||||
window_rect.width == screen_width && window_rect.height == screen_height)
|
||||
@ -3718,7 +3712,7 @@ meta_window_is_monitor_sized (MetaWindow *window)
|
||||
{
|
||||
MetaRectangle window_rect, monitor_rect;
|
||||
|
||||
meta_window_get_outer_rect (window, &window_rect);
|
||||
meta_window_get_frame_rect (window, &window_rect);
|
||||
meta_screen_get_monitor_geometry (window->screen, window->monitor->number, &monitor_rect);
|
||||
|
||||
if (meta_rectangle_equal (&window_rect, &monitor_rect))
|
||||
@ -3786,11 +3780,11 @@ meta_window_tile (MetaWindow *window)
|
||||
MetaRectangle old_rect;
|
||||
MetaRectangle new_rect;
|
||||
|
||||
meta_window_get_outer_rect (window, &old_rect);
|
||||
meta_window_get_frame_rect (window, &old_rect);
|
||||
|
||||
meta_window_move_resize_now (window);
|
||||
|
||||
meta_window_get_outer_rect (window, &new_rect);
|
||||
meta_window_get_frame_rect (window, &new_rect);
|
||||
meta_compositor_maximize_window (window->display->compositor,
|
||||
window,
|
||||
&old_rect,
|
||||
@ -3819,7 +3813,7 @@ meta_window_can_tile_side_by_side (MetaWindow *window)
|
||||
{
|
||||
int monitor;
|
||||
MetaRectangle tile_area;
|
||||
MetaFrameBorders borders;
|
||||
MetaRectangle client_rect;
|
||||
|
||||
if (!meta_window_can_tile_maximized (window))
|
||||
return FALSE;
|
||||
@ -3833,13 +3827,10 @@ meta_window_can_tile_side_by_side (MetaWindow *window)
|
||||
|
||||
tile_area.width /= 2;
|
||||
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
meta_window_frame_rect_to_client_rect (window, &tile_area, &client_rect);
|
||||
|
||||
tile_area.width -= (borders.visible.left + borders.visible.right);
|
||||
tile_area.height -= (borders.visible.top + borders.visible.bottom);
|
||||
|
||||
return tile_area.width >= window->size_hints.min_width &&
|
||||
tile_area.height >= window->size_hints.min_height;
|
||||
return client_rect.width >= window->size_hints.min_width &&
|
||||
client_rect.height >= window->size_hints.min_height;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3900,8 +3891,10 @@ meta_window_unmaximize_internal (MetaWindow *window,
|
||||
{
|
||||
MetaRectangle target_rect;
|
||||
MetaRectangle work_area;
|
||||
MetaRectangle old_rect;
|
||||
|
||||
meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area);
|
||||
meta_window_get_frame_rect (window, &old_rect);
|
||||
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Unmaximizing %s%s\n",
|
||||
@ -3915,6 +3908,12 @@ meta_window_unmaximize_internal (MetaWindow *window,
|
||||
window->maximized_vertically =
|
||||
window->maximized_vertically && !unmaximize_vertically;
|
||||
|
||||
/* recalc_window_features() will eventually clear the cached frame
|
||||
* extents, but we need the correct frame extents in the code below,
|
||||
* so invalidate the old frame extents manually up front.
|
||||
*/
|
||||
meta_window_frame_size_changed (window);
|
||||
|
||||
/* Unmaximize to the saved_rect position in the direction(s)
|
||||
* being unmaximized.
|
||||
*/
|
||||
@ -3959,9 +3958,7 @@ meta_window_unmaximize_internal (MetaWindow *window,
|
||||
|
||||
if (window->display->compositor)
|
||||
{
|
||||
MetaRectangle old_rect, new_rect;
|
||||
|
||||
meta_window_get_outer_rect (window, &old_rect);
|
||||
MetaRectangle new_rect;
|
||||
|
||||
meta_window_move_resize_internal (window,
|
||||
META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION,
|
||||
@ -3971,7 +3968,7 @@ meta_window_unmaximize_internal (MetaWindow *window,
|
||||
target_rect.width,
|
||||
target_rect.height);
|
||||
|
||||
meta_window_get_outer_rect (window, &new_rect);
|
||||
meta_window_get_frame_rect (window, &new_rect);
|
||||
meta_compositor_unmaximize_window (window->display->compositor,
|
||||
window,
|
||||
&old_rect,
|
||||
@ -4076,6 +4073,7 @@ meta_window_set_above (MetaWindow *window,
|
||||
window->wm_state_above = new_value;
|
||||
meta_window_update_layer (window);
|
||||
set_net_wm_state (window);
|
||||
meta_window_frame_size_changed (window);
|
||||
g_object_notify (G_OBJECT (window), "above");
|
||||
}
|
||||
|
||||
@ -4215,6 +4213,7 @@ meta_window_shade (MetaWindow *window,
|
||||
window->shaded = TRUE;
|
||||
|
||||
meta_window_queue(window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING);
|
||||
meta_window_frame_size_changed (window);
|
||||
|
||||
/* After queuing the calc showing, since _focus flushes it,
|
||||
* and we need to focus the frame
|
||||
@ -4240,6 +4239,7 @@ meta_window_unshade (MetaWindow *window,
|
||||
{
|
||||
window->shaded = FALSE;
|
||||
meta_window_queue(window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING);
|
||||
meta_window_frame_size_changed (window);
|
||||
|
||||
/* focus the window */
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
@ -4967,7 +4967,6 @@ meta_window_move_resize_internal (MetaWindow *window,
|
||||
did_placement = !window->placed && window->calc_placement;
|
||||
|
||||
meta_window_constrain (window,
|
||||
window->frame ? &borders : NULL,
|
||||
flags,
|
||||
gravity,
|
||||
&old_rect,
|
||||
@ -5396,23 +5395,10 @@ meta_window_move_frame (MetaWindow *window,
|
||||
int root_x_nw,
|
||||
int root_y_nw)
|
||||
{
|
||||
int x = root_x_nw;
|
||||
int y = root_y_nw;
|
||||
MetaRectangle rect = { root_x_nw, root_y_nw, 0, 0 };
|
||||
|
||||
if (window->frame)
|
||||
{
|
||||
MetaFrameBorders borders;
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
|
||||
/* root_x_nw and root_y_nw correspond to where the top of
|
||||
* the visible frame should be. Offset by the distance between
|
||||
* the origin of the window and the origin of the enclosing
|
||||
* window decorations.
|
||||
*/
|
||||
x += window->frame->child_x - borders.invisible.left;
|
||||
y += window->frame->child_y - borders.invisible.top;
|
||||
}
|
||||
meta_window_move (window, user_op, x, y);
|
||||
meta_window_frame_rect_to_client_rect (window, &rect, &rect);
|
||||
meta_window_move (window, user_op, rect.x, rect.y);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -5460,18 +5446,10 @@ meta_window_move_resize_frame (MetaWindow *window,
|
||||
int w,
|
||||
int h)
|
||||
{
|
||||
MetaFrameBorders borders;
|
||||
MetaRectangle rect = { root_x_nw, root_y_nw, w, h };
|
||||
meta_window_frame_rect_to_client_rect (window, &rect, &rect);
|
||||
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
/* offset by the distance between the origin of the window
|
||||
* and the origin of the enclosing window decorations ( + border)
|
||||
*/
|
||||
root_x_nw += borders.visible.left;
|
||||
root_y_nw += borders.visible.top;
|
||||
w -= borders.visible.left + borders.visible.right;
|
||||
h -= borders.visible.top + borders.visible.bottom;
|
||||
|
||||
meta_window_move_resize (window, user_op, root_x_nw, root_y_nw, w, h);
|
||||
meta_window_move_resize (window, user_op, rect.x, rect.y, rect.width, rect.height);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -5784,16 +5762,110 @@ meta_window_get_input_rect (const MetaWindow *window,
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_get_outer_rect:
|
||||
* meta_window_client_rect_to_frame_rect:
|
||||
* @window: a #MetaWindow
|
||||
* @client_rect: client rectangle in root coordinates
|
||||
* @frame_rect: (out): location to store the computed corresponding frame bounds.
|
||||
*
|
||||
* Converts a desired bounds of the client window - what is passed to meta_window_move_resize() -
|
||||
* into the corresponding bounds of the window frame (excluding invisible borders
|
||||
* and client side shadows.)
|
||||
*/
|
||||
void
|
||||
meta_window_client_rect_to_frame_rect (MetaWindow *window,
|
||||
MetaRectangle *client_rect,
|
||||
MetaRectangle *frame_rect)
|
||||
{
|
||||
if (!frame_rect)
|
||||
return;
|
||||
|
||||
*frame_rect = *client_rect;
|
||||
|
||||
/* The support for G_MAXINT here to mean infinity is a convenience for
|
||||
* constraints.c:get_size_limits() and not something that we provide
|
||||
* in other locations or document.
|
||||
*/
|
||||
if (window->frame)
|
||||
{
|
||||
MetaFrameBorders borders;
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
|
||||
frame_rect->x -= borders.visible.left;
|
||||
frame_rect->y -= borders.visible.top;
|
||||
if (frame_rect->width != G_MAXINT)
|
||||
frame_rect->width += borders.visible.left + borders.visible.right;
|
||||
if (frame_rect->height != G_MAXINT)
|
||||
frame_rect->height += borders.visible.top + borders.visible.bottom;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (window->has_custom_frame_extents)
|
||||
{
|
||||
const GtkBorder *extents = &window->custom_frame_extents;
|
||||
frame_rect->x += extents->left;
|
||||
frame_rect->y += extents->top;
|
||||
if (frame_rect->width != G_MAXINT)
|
||||
frame_rect->width -= extents->left + extents->right;
|
||||
if (frame_rect->height != G_MAXINT)
|
||||
frame_rect->height -= extents->top + extents->bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_frame_rect_to_client_rect:
|
||||
* @window: a #MetaWindow
|
||||
* @frame_rect: desired frame bounds for the window
|
||||
* @client_rect: (out): location to store the computed corresponding client rectangle.
|
||||
*
|
||||
* Converts a desired frame bounds for a window into the bounds of the client
|
||||
* window - what is passed to meta_window_move_resize().
|
||||
*/
|
||||
void
|
||||
meta_window_frame_rect_to_client_rect (MetaWindow *window,
|
||||
MetaRectangle *frame_rect,
|
||||
MetaRectangle *client_rect)
|
||||
{
|
||||
if (!client_rect)
|
||||
return;
|
||||
|
||||
*client_rect = *frame_rect;
|
||||
|
||||
if (window->frame)
|
||||
{
|
||||
MetaFrameBorders borders;
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
|
||||
client_rect->x += borders.visible.left;
|
||||
client_rect->y += borders.visible.top;
|
||||
client_rect->width -= borders.visible.left + borders.visible.right;
|
||||
client_rect->height -= borders.visible.top + borders.visible.bottom;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (window->has_custom_frame_extents)
|
||||
{
|
||||
const GtkBorder *extents = &window->custom_frame_extents;
|
||||
client_rect->x -= extents->left;
|
||||
client_rect->y -= extents->top;
|
||||
client_rect->width += extents->left + extents->right;
|
||||
client_rect->height += extents->top + extents->bottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_get_frame_rect:
|
||||
* @window: a #MetaWindow
|
||||
* @rect: (out): pointer to an allocated #MetaRectangle
|
||||
*
|
||||
* Gets the rectangle that bounds @window that is responsive to mouse events.
|
||||
* This includes only what is visible; it doesn't include any extra reactive
|
||||
* area we add to the edges of windows.
|
||||
* Gets the rectangle that bounds @window that is what the user thinks of
|
||||
* as the edge of the window. This doesn't include any extra reactive
|
||||
* area that we or the client adds to the window, or any area that the
|
||||
* client adds to draw a client-side shadow.
|
||||
*/
|
||||
void
|
||||
meta_window_get_outer_rect (const MetaWindow *window,
|
||||
meta_window_get_frame_rect (const MetaWindow *window,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
if (window->frame)
|
||||
@ -5822,6 +5894,25 @@ meta_window_get_outer_rect (const MetaWindow *window,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* meta_window_get_outer_rect:
|
||||
* @window: a #MetaWindow
|
||||
* @rect: (out): pointer to an allocated #MetaRectangle
|
||||
*
|
||||
* Gets the rectangle that bounds @window that is what the user thinks of
|
||||
* as the edge of the window. This doesn't include any extra reactive
|
||||
* area that we or the client adds to the window, or any area that the
|
||||
* client adds to draw a client-side shadow.
|
||||
*
|
||||
* Deprecated: 3.12: Use meta_window_get_frame_rect() instead.
|
||||
*/
|
||||
void
|
||||
meta_window_get_outer_rect (const MetaWindow *window,
|
||||
MetaRectangle *rect)
|
||||
{
|
||||
meta_window_get_frame_rect (window, rect);
|
||||
}
|
||||
|
||||
const char*
|
||||
meta_window_get_startup_id (MetaWindow *window)
|
||||
{
|
||||
@ -6043,6 +6134,7 @@ window_stick_impl (MetaWindow *window)
|
||||
* toggled back off.
|
||||
*/
|
||||
window->on_all_workspaces_requested = TRUE;
|
||||
meta_window_frame_size_changed (window);
|
||||
meta_window_update_on_all_workspaces (window);
|
||||
|
||||
meta_window_queue(window, META_QUEUE_CALC_SHOWING);
|
||||
@ -6057,6 +6149,7 @@ window_unstick_impl (MetaWindow *window)
|
||||
/* Revert to window->workspaces */
|
||||
|
||||
window->on_all_workspaces_requested = FALSE;
|
||||
meta_window_frame_size_changed (window);
|
||||
meta_window_update_on_all_workspaces (window);
|
||||
|
||||
/* We change ourselves to the active workspace, since otherwise you'd get
|
||||
@ -6563,8 +6656,7 @@ meta_window_property_notify (MetaWindow *window,
|
||||
void
|
||||
meta_window_change_workspace_by_index (MetaWindow *window,
|
||||
gint space_index,
|
||||
gboolean append,
|
||||
guint32 timestamp)
|
||||
gboolean append)
|
||||
{
|
||||
MetaWorkspace *workspace;
|
||||
MetaScreen *screen;
|
||||
@ -6583,11 +6675,7 @@ meta_window_change_workspace_by_index (MetaWindow *window,
|
||||
meta_screen_get_workspace_by_index (screen, space_index);
|
||||
|
||||
if (!workspace && append)
|
||||
{
|
||||
if (timestamp == CurrentTime)
|
||||
timestamp = meta_display_get_current_time_roundtrip (window->display);
|
||||
workspace = meta_screen_append_new_workspace (screen, FALSE, timestamp);
|
||||
}
|
||||
workspace = meta_screen_append_new_workspace (screen, FALSE, CurrentTime);
|
||||
|
||||
if (workspace)
|
||||
{
|
||||
@ -7137,6 +7225,7 @@ static void
|
||||
meta_window_appears_focused_changed (MetaWindow *window)
|
||||
{
|
||||
set_net_wm_state (window);
|
||||
meta_window_frame_size_changed (window);
|
||||
|
||||
g_object_notify (G_OBJECT (window), "appears-focused");
|
||||
|
||||
@ -7717,6 +7806,91 @@ meta_window_set_shape_region (MetaWindow *window,
|
||||
meta_compositor_window_shape_changed (window->display->compositor, window);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_update_input_region_x11 (MetaWindow *window)
|
||||
{
|
||||
cairo_region_t *region = NULL;
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
if (META_DISPLAY_HAS_SHAPE (window->display))
|
||||
{
|
||||
/* Translate the set of XShape rectangles that we
|
||||
* get from the X server to a cairo_region. */
|
||||
XRectangle *rects = NULL;
|
||||
int n_rects, ordering;
|
||||
|
||||
int x_bounding, y_bounding, x_clip, y_clip;
|
||||
unsigned w_bounding, h_bounding, w_clip, h_clip;
|
||||
int bounding_shaped, clip_shaped;
|
||||
|
||||
meta_error_trap_push (window->display);
|
||||
XShapeQueryExtents (window->display->xdisplay, window->xwindow,
|
||||
&bounding_shaped, &x_bounding, &y_bounding,
|
||||
&w_bounding, &h_bounding,
|
||||
&clip_shaped, &x_clip, &y_clip,
|
||||
&w_clip, &h_clip);
|
||||
|
||||
rects = XShapeGetRectangles (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
ShapeInput,
|
||||
&n_rects,
|
||||
&ordering);
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
/* XXX: The x shape extension doesn't provide a way to only test if an
|
||||
* input shape has been specified, so we have to query and throw away the
|
||||
* rectangles. */
|
||||
if (rects)
|
||||
{
|
||||
if (n_rects > 1 ||
|
||||
(n_rects == 1 &&
|
||||
(rects[0].x != x_bounding ||
|
||||
rects[1].y != y_bounding ||
|
||||
rects[2].width != w_bounding ||
|
||||
rects[3].height != h_bounding)))
|
||||
region = region_create_from_x_rectangles (rects, n_rects);
|
||||
|
||||
XFree (rects);
|
||||
}
|
||||
}
|
||||
#endif /* HAVE_SHAPE */
|
||||
|
||||
if (region != NULL)
|
||||
{
|
||||
cairo_rectangle_int_t client_area;
|
||||
|
||||
client_area.x = 0;
|
||||
client_area.y = 0;
|
||||
client_area.width = window->rect.width;
|
||||
client_area.height = window->rect.height;
|
||||
|
||||
/* The shape we get back from the client may have coordinates
|
||||
* outside of the frame. The X SHAPE Extension requires that
|
||||
* the overall shape the client provides never exceeds the
|
||||
* "bounding rectangle" of the window -- the shape that the
|
||||
* window would have gotten if it was unshaped. In our case,
|
||||
* this is simply the client area.
|
||||
*/
|
||||
cairo_region_intersect_rectangle (region, &client_area);
|
||||
}
|
||||
|
||||
meta_window_set_input_region (window, region);
|
||||
cairo_region_destroy (region);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_set_input_region (MetaWindow *window,
|
||||
cairo_region_t *region)
|
||||
{
|
||||
g_clear_pointer (&window->input_region, cairo_region_destroy);
|
||||
|
||||
if (region != NULL)
|
||||
window->input_region = cairo_region_reference (region);
|
||||
|
||||
if (window->display->compositor)
|
||||
meta_compositor_window_shape_changed (window->display->compositor, window);
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_update_shape_region_x11 (MetaWindow *window)
|
||||
{
|
||||
@ -8224,6 +8398,13 @@ recalc_window_type (MetaWindow *window)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_frame_size_changed (MetaWindow *window)
|
||||
{
|
||||
if (window->frame)
|
||||
meta_frame_clear_cached_borders (window->frame);
|
||||
}
|
||||
|
||||
static void
|
||||
set_allowed_actions_hint (MetaWindow *window)
|
||||
{
|
||||
@ -8423,18 +8604,13 @@ recalc_window_features (MetaWindow *window)
|
||||
|
||||
if (window->has_maximize_func)
|
||||
{
|
||||
MetaRectangle work_area;
|
||||
MetaFrameBorders borders;
|
||||
int min_frame_width, min_frame_height;
|
||||
MetaRectangle work_area, client_rect;
|
||||
|
||||
meta_window_get_work_area_current_monitor (window, &work_area);
|
||||
meta_frame_calc_borders (window->frame, &borders);
|
||||
meta_window_frame_rect_to_client_rect (window, &work_area, &client_rect);
|
||||
|
||||
min_frame_width = window->size_hints.min_width + borders.visible.left + borders.visible.right;
|
||||
min_frame_height = window->size_hints.min_height + borders.visible.top + borders.visible.bottom;
|
||||
|
||||
if (min_frame_width >= work_area.width ||
|
||||
min_frame_height >= work_area.height)
|
||||
if (window->size_hints.min_width >= client_rect.width ||
|
||||
window->size_hints.min_height >= client_rect.height)
|
||||
window->has_maximize_func = FALSE;
|
||||
}
|
||||
|
||||
@ -8527,6 +8703,8 @@ recalc_window_features (MetaWindow *window)
|
||||
if (window->has_resize_func != old_has_resize_func)
|
||||
g_object_notify (G_OBJECT (window), "resizeable");
|
||||
|
||||
meta_window_frame_size_changed (window);
|
||||
|
||||
/* FIXME perhaps should ensure if we don't have a shade func,
|
||||
* we aren't shaded, etc.
|
||||
*/
|
||||
@ -8803,7 +8981,7 @@ meta_window_show_menu (MetaWindow *window,
|
||||
void
|
||||
meta_window_shove_titlebar_onscreen (MetaWindow *window)
|
||||
{
|
||||
MetaRectangle outer_rect;
|
||||
MetaRectangle frame_rect;
|
||||
GList *onscreen_region;
|
||||
int horiz_amount, vert_amount;
|
||||
int newx, newy;
|
||||
@ -8815,15 +8993,15 @@ meta_window_shove_titlebar_onscreen (MetaWindow *window)
|
||||
return;
|
||||
|
||||
/* Get the basic info we need */
|
||||
meta_window_get_outer_rect (window, &outer_rect);
|
||||
meta_window_get_frame_rect (window, &frame_rect);
|
||||
onscreen_region = window->screen->active_workspace->screen_region;
|
||||
|
||||
/* Extend the region (just in case the window is too big to fit on the
|
||||
* screen), then shove the window on screen, then return the region to
|
||||
* normal.
|
||||
*/
|
||||
horiz_amount = outer_rect.width;
|
||||
vert_amount = outer_rect.height;
|
||||
horiz_amount = frame_rect.width;
|
||||
vert_amount = frame_rect.height;
|
||||
meta_rectangle_expand_region (onscreen_region,
|
||||
horiz_amount,
|
||||
horiz_amount,
|
||||
@ -8831,15 +9009,15 @@ meta_window_shove_titlebar_onscreen (MetaWindow *window)
|
||||
vert_amount);
|
||||
meta_rectangle_shove_into_region(onscreen_region,
|
||||
FIXED_DIRECTION_X,
|
||||
&outer_rect);
|
||||
&frame_rect);
|
||||
meta_rectangle_expand_region (onscreen_region,
|
||||
-horiz_amount,
|
||||
-horiz_amount,
|
||||
0,
|
||||
-vert_amount);
|
||||
|
||||
newx = outer_rect.x + window->frame->child_x;
|
||||
newy = outer_rect.y + window->frame->child_y;
|
||||
newx = frame_rect.x + window->frame->child_x;
|
||||
newy = frame_rect.y + window->frame->child_y;
|
||||
meta_window_move_resize (window,
|
||||
FALSE,
|
||||
newx,
|
||||
@ -8864,7 +9042,7 @@ meta_window_titlebar_is_onscreen (MetaWindow *window)
|
||||
return FALSE;
|
||||
|
||||
/* Get the rectangle corresponding to the titlebar */
|
||||
meta_window_get_outer_rect (window, &titlebar_rect);
|
||||
meta_window_get_frame_rect (window, &titlebar_rect);
|
||||
titlebar_rect.height = window->frame->child_y;
|
||||
|
||||
/* Run through the spanning rectangles for the screen and see if one of
|
||||
@ -9711,47 +9889,51 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,
|
||||
switch (xev->evtype)
|
||||
{
|
||||
case XI_ButtonRelease:
|
||||
meta_display_check_threshold_reached (window->display,
|
||||
xev->root_x,
|
||||
xev->root_y);
|
||||
/* If the user was snap moving then ignore the button release
|
||||
* because they may have let go of shift before releasing the
|
||||
* mouse button and they almost certainly do not want a
|
||||
* non-snapped movement to occur from the button release.
|
||||
*/
|
||||
if (!window->display->grab_last_user_action_was_snap)
|
||||
if (xev->detail == 1 ||
|
||||
xev->detail == meta_prefs_get_mouse_button_resize ())
|
||||
{
|
||||
if (meta_grab_op_is_moving (window->display->grab_op))
|
||||
meta_display_check_threshold_reached (window->display,
|
||||
xev->root_x,
|
||||
xev->root_y);
|
||||
/* If the user was snap moving then ignore the button
|
||||
* release because they may have let go of shift before
|
||||
* releasing the mouse button and they almost certainly do
|
||||
* not want a non-snapped movement to occur from the button
|
||||
* release.
|
||||
*/
|
||||
if (!window->display->grab_last_user_action_was_snap)
|
||||
{
|
||||
if (window->tile_mode != META_TILE_NONE)
|
||||
meta_window_tile (window);
|
||||
else if (xev->root == window->screen->xroot)
|
||||
update_move (window,
|
||||
xev->mods.effective & ShiftMask,
|
||||
xev->root_x,
|
||||
xev->root_y);
|
||||
}
|
||||
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
||||
{
|
||||
if (xev->root == window->screen->xroot)
|
||||
update_resize (window,
|
||||
xev->mods.effective & ShiftMask,
|
||||
xev->root_x,
|
||||
xev->root_y,
|
||||
TRUE);
|
||||
if (meta_grab_op_is_moving (window->display->grab_op))
|
||||
{
|
||||
if (window->tile_mode != META_TILE_NONE)
|
||||
meta_window_tile (window);
|
||||
else if (xev->root == window->screen->xroot)
|
||||
update_move (window,
|
||||
xev->mods.effective & ShiftMask,
|
||||
xev->root_x,
|
||||
xev->root_y);
|
||||
}
|
||||
else if (meta_grab_op_is_resizing (window->display->grab_op))
|
||||
{
|
||||
if (xev->root == window->screen->xroot)
|
||||
update_resize (window,
|
||||
xev->mods.effective & ShiftMask,
|
||||
xev->root_x,
|
||||
xev->root_y,
|
||||
TRUE);
|
||||
|
||||
/* If a tiled window has been dragged free with a
|
||||
* mouse resize without snapping back to the tiled
|
||||
* state, it will end up with an inconsistent tile
|
||||
* mode on mouse release; cleaning the mode earlier
|
||||
* would break the ability to snap back to the tiled
|
||||
* state, so we wait until mouse release.
|
||||
*/
|
||||
update_tile_mode (window);
|
||||
/* If a tiled window has been dragged free with a
|
||||
* mouse resize without snapping back to the tiled
|
||||
* state, it will end up with an inconsistent tile
|
||||
* mode on mouse release; cleaning the mode earlier
|
||||
* would break the ability to snap back to the tiled
|
||||
* state, so we wait until mouse release.
|
||||
*/
|
||||
update_tile_mode (window);
|
||||
}
|
||||
}
|
||||
meta_display_end_grab_op (window->display, xev->time);
|
||||
}
|
||||
|
||||
meta_display_end_grab_op (window->display, xev->time);
|
||||
break;
|
||||
|
||||
case XI_Motion:
|
||||
@ -10162,7 +10344,7 @@ warp_grab_pointer (MetaWindow *window,
|
||||
/* We may not have done begin_grab_op yet, i.e. may not be in a grab
|
||||
*/
|
||||
|
||||
meta_window_get_outer_rect (window, &rect);
|
||||
meta_window_get_frame_rect (window, &rect);
|
||||
|
||||
switch (grab_op)
|
||||
{
|
||||
@ -10501,7 +10683,7 @@ meta_window_set_demands_attention (MetaWindow *window)
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_window_get_outer_rect (window, &candidate_rect);
|
||||
meta_window_get_frame_rect (window, &candidate_rect);
|
||||
|
||||
/* The stack is sorted with the top windows first. */
|
||||
|
||||
@ -10512,7 +10694,7 @@ meta_window_set_demands_attention (MetaWindow *window)
|
||||
|
||||
if (meta_window_located_on_workspace (other_window, window->workspace))
|
||||
{
|
||||
meta_window_get_outer_rect (other_window, &other_rect);
|
||||
meta_window_get_frame_rect (other_window, &other_rect);
|
||||
|
||||
if (meta_rectangle_overlap (&candidate_rect, &other_rect))
|
||||
{
|
||||
@ -11216,8 +11398,8 @@ meta_window_compute_tile_match (MetaWindow *window)
|
||||
bottommost = match;
|
||||
}
|
||||
|
||||
meta_window_get_outer_rect (bottommost, &bottommost_rect);
|
||||
meta_window_get_outer_rect (topmost, &topmost_rect);
|
||||
meta_window_get_frame_rect (bottommost, &bottommost_rect);
|
||||
meta_window_get_frame_rect (topmost, &topmost_rect);
|
||||
/*
|
||||
* If there's a window stacked in between which is partially visible
|
||||
* behind the topmost tile we don't consider the tiles to match.
|
||||
@ -11231,7 +11413,7 @@ meta_window_compute_tile_match (MetaWindow *window)
|
||||
meta_window_get_workspace (above) != meta_window_get_workspace (window))
|
||||
continue;
|
||||
|
||||
meta_window_get_outer_rect (above, &above_rect);
|
||||
meta_window_get_frame_rect (above, &above_rect);
|
||||
|
||||
if (meta_rectangle_overlap (&above_rect, &bottommost_rect) &&
|
||||
meta_rectangle_overlap (&above_rect, &topmost_rect))
|
||||
@ -11247,3 +11429,19 @@ meta_window_can_close (MetaWindow *window)
|
||||
{
|
||||
return window->has_close_func;
|
||||
}
|
||||
|
||||
Window
|
||||
meta_window_get_toplevel_xwindow (MetaWindow *window)
|
||||
{
|
||||
return window->frame ? window->frame->xwindow : window->xwindow;
|
||||
}
|
||||
|
||||
void
|
||||
meta_window_set_opacity (MetaWindow *window,
|
||||
guint opacity)
|
||||
{
|
||||
window->opacity = opacity;
|
||||
|
||||
if (window->display->compositor)
|
||||
meta_compositor_window_opacity_changed (window->display->compositor, window);
|
||||
}
|
||||
|
@ -81,6 +81,7 @@ item(TIMESTAMP)
|
||||
item(VERSION)
|
||||
item(ATOM_PAIR)
|
||||
item(BACKLIGHT)
|
||||
item(hotplug_mode_update)
|
||||
|
||||
/* Oddities: These are used, and we need atoms for them,
|
||||
* but when we need all _NET_WM hints (i.e. when we're making
|
||||
@ -178,6 +179,7 @@ item(_NET_WM_BYPASS_COMPOSITOR)
|
||||
item(_NET_WM_OPAQUE_REGION)
|
||||
item(_NET_WM_FRAME_DRAWN)
|
||||
item(_NET_WM_FRAME_TIMINGS)
|
||||
item(_NET_WM_WINDOW_OPACITY)
|
||||
|
||||
#if 0
|
||||
/* We apparently never use: */
|
||||
|
@ -66,6 +66,8 @@ void meta_compositor_unmanage_screen (MetaCompositor *compositor,
|
||||
|
||||
void meta_compositor_window_shape_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_window_opacity_changed (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
|
||||
gboolean meta_compositor_process_event (MetaCompositor *compositor,
|
||||
XEvent *event,
|
||||
@ -75,11 +77,10 @@ gboolean meta_compositor_filter_keybinding (MetaCompositor *compositor,
|
||||
MetaScreen *screen,
|
||||
MetaKeyBinding *binding);
|
||||
|
||||
void meta_compositor_add_window (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_remove_window (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
|
||||
void meta_compositor_add_window (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_remove_window (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_show_window (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
MetaCompEffect effect);
|
||||
@ -101,10 +102,6 @@ void meta_compositor_unmaximize_window (MetaCompositor *compositor,
|
||||
MetaRectangle *old_rect,
|
||||
MetaRectangle *new_rect);
|
||||
|
||||
void meta_compositor_window_mapped (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_window_unmapped (MetaCompositor *compositor,
|
||||
MetaWindow *window);
|
||||
void meta_compositor_sync_window_geometry (MetaCompositor *compositor,
|
||||
MetaWindow *window,
|
||||
gboolean did_placement);
|
||||
|
@ -35,13 +35,6 @@ gboolean meta_keybindings_set_custom_handler (const gchar *name,
|
||||
gpointer user_data,
|
||||
GDestroyNotify free_data);
|
||||
|
||||
void meta_keybindings_switch_window (MetaDisplay *display,
|
||||
MetaScreen *screen,
|
||||
MetaWindow *event_window,
|
||||
XIDeviceEvent *event,
|
||||
MetaKeyBinding *binding);
|
||||
|
||||
|
||||
void meta_screen_ungrab_all_keys (MetaScreen *screen, guint32 timestamp);
|
||||
gboolean meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp);
|
||||
#endif
|
||||
|
@ -83,6 +83,8 @@ CoglTexture * meta_shaped_texture_get_texture (MetaShapedTexture *stex);
|
||||
|
||||
void meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex,
|
||||
CoglTexture *mask_texture);
|
||||
void meta_shaped_texture_set_input_shape_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *shape_region);
|
||||
|
||||
void meta_shaped_texture_set_clip_region (MetaShapedTexture *stex,
|
||||
cairo_region_t *clip_region);
|
||||
|
@ -258,6 +258,7 @@ void meta_prefs_set_ignore_request_hide_titlebar (gboolean whether);
|
||||
* @META_KEYBINDING_ACTION_MOVE_TO_SIDE_W: FILLME
|
||||
* @META_KEYBINDING_ACTION_MOVE_TO_CENTER: FILLME
|
||||
* @META_KEYBINDING_ACTION_OVERLAY_KEY: FILLME
|
||||
* @META_KEYBINDING_ACTION_ALWAYS_ON_TOP: FILLME
|
||||
* @META_KEYBINDING_ACTION_LAST: FILLME
|
||||
*/
|
||||
/* XXX FIXME This should be x-macroed, but isn't yet because it would be
|
||||
@ -351,6 +352,7 @@ typedef enum _MetaKeyBindingAction
|
||||
META_KEYBINDING_ACTION_MOVE_TO_CENTER,
|
||||
META_KEYBINDING_ACTION_OVERLAY_KEY,
|
||||
META_KEYBINDING_ACTION_ISO_NEXT_GROUP,
|
||||
META_KEYBINDING_ACTION_ALWAYS_ON_TOP,
|
||||
|
||||
META_KEYBINDING_ACTION_LAST
|
||||
} MetaKeyBindingAction;
|
||||
@ -419,13 +421,13 @@ typedef struct
|
||||
*/
|
||||
GSList *bindings;
|
||||
|
||||
/** for keybindings that can have shift or not like Alt+Tab */
|
||||
/* for keybindings that can have shift or not like Alt+Tab */
|
||||
gboolean add_shift:1;
|
||||
|
||||
/** for keybindings that apply only to a window */
|
||||
/* for keybindings that apply only to a window */
|
||||
gboolean per_window:1;
|
||||
|
||||
/** for keybindings not added with meta_display_add_keybinding() */
|
||||
/* for keybindings not added with meta_display_add_keybinding() */
|
||||
gboolean builtin:1;
|
||||
} MetaKeyPref;
|
||||
|
||||
|
@ -100,7 +100,17 @@ gboolean meta_window_is_override_redirect (MetaWindow *window);
|
||||
gboolean meta_window_is_skip_taskbar (MetaWindow *window);
|
||||
MetaRectangle *meta_window_get_rect (MetaWindow *window);
|
||||
void meta_window_get_input_rect (const MetaWindow *window, MetaRectangle *rect);
|
||||
void meta_window_get_outer_rect (const MetaWindow *window, MetaRectangle *rect);
|
||||
|
||||
void meta_window_get_frame_rect (const MetaWindow *window, MetaRectangle *rect);
|
||||
void meta_window_get_outer_rect (const MetaWindow *window, MetaRectangle *rect) G_GNUC_DEPRECATED;
|
||||
|
||||
void meta_window_client_rect_to_frame_rect (MetaWindow *window,
|
||||
MetaRectangle *client_rect,
|
||||
MetaRectangle *frame_rect);
|
||||
void meta_window_frame_rect_to_client_rect (MetaWindow *window,
|
||||
MetaRectangle *frame_rect,
|
||||
MetaRectangle *client_rect);
|
||||
|
||||
MetaScreen *meta_window_get_screen (MetaWindow *window);
|
||||
MetaDisplay *meta_window_get_display (MetaWindow *window);
|
||||
Window meta_window_get_xwindow (MetaWindow *window);
|
||||
@ -140,8 +150,7 @@ void meta_window_unset_demands_attention (MetaWindow *window);
|
||||
const char* meta_window_get_startup_id (MetaWindow *window);
|
||||
void meta_window_change_workspace_by_index (MetaWindow *window,
|
||||
gint space_index,
|
||||
gboolean append,
|
||||
guint32 timestamp);
|
||||
gboolean append);
|
||||
void meta_window_change_workspace (MetaWindow *window,
|
||||
MetaWorkspace *workspace);
|
||||
GObject *meta_window_get_compositor_private (MetaWindow *window);
|
||||
|
Reference in New Issue
Block a user