From 5f87759af745b20e9969bffafb531a4265399a6d Mon Sep 17 00:00:00 2001 From: Maximiliano Curia Date: Thu, 5 May 2016 08:04:52 +0200 Subject: [PATCH] Imported Upstream version 3.0.0 --- configure.ac | 6 +- po/Makefile.in.in | 11 +- src/compositor/compositor.c | 29 +- src/compositor/meta-window-actor.c | 100 +--- src/core/bell.c | 337 +----------- src/core/bell.h | 23 +- src/core/constraints.c | 2 +- src/core/display-private.h | 1 + src/core/display.c | 83 ++- src/core/edge-resistance.c | 10 + src/core/frame.c | 8 +- src/core/frame.h | 1 - src/core/keybindings-private.h | 4 + src/core/keybindings.c | 134 ++++- src/core/muffin.c | 2 + src/core/prefs.c | 123 +---- src/core/screen-private.h | 3 + src/core/screen.c | 200 ++++++- src/core/stack-tracker.c | 2 +- src/core/stack.c | 6 + src/core/util.c | 3 + src/core/window-private.h | 1 - src/core/window.c | 694 ++++++++++++------------- src/core/workspace-private.h | 4 - src/core/workspace.c | 144 +++-- src/meta/common.h | 13 +- src/meta/compositor.h | 13 - src/meta/prefs.h | 7 +- src/meta/screen.h | 3 + src/meta/util.h | 6 + src/meta/window.h | 3 +- src/meta/workspace.h | 7 + src/org.cinnamon.muffin.gschema.xml.in | 16 +- src/ui/frames.c | 40 +- src/ui/theme.c | 2 +- src/ui/ui.c | 9 +- 36 files changed, 943 insertions(+), 1107 deletions(-) diff --git a/configure.ac b/configure.ac index a5cffd8..8318539 100644 --- a/configure.ac +++ b/configure.ac @@ -1,8 +1,8 @@ AC_PREREQ(2.50) -m4_define([muffin_major_version], [2]) -m4_define([muffin_minor_version], [8]) -m4_define([muffin_micro_version], [5]) +m4_define([muffin_major_version], [3]) +m4_define([muffin_minor_version], [0]) +m4_define([muffin_micro_version], [0]) m4_define([muffin_version], [muffin_major_version.muffin_minor_version.muffin_micro_version]) diff --git a/po/Makefile.in.in b/po/Makefile.in.in index 06a8cfe..fcd2c3b 100644 --- a/po/Makefile.in.in +++ b/po/Makefile.in.in @@ -33,8 +33,7 @@ exec_prefix = @exec_prefix@ datadir = @datadir@ datarootdir = @datarootdir@ libdir = @libdir@ -DATADIRNAME = @DATADIRNAME@ -itlocaledir = $(prefix)/$(DATADIRNAME)/locale +localedir = @localedir@ subdir = po install_sh = @install_sh@ # Automake >= 1.8 provides @mkdir_p@. @@ -80,7 +79,7 @@ INTLTOOL__v_MSGFMT_0 = @echo " MSGFMT" $@; .po.pox: $(MAKE) $(GETTEXT_PACKAGE).pot - $(MSGMERGE) $< $(GETTEXT_PACKAGE).pot -o $*.pox + $(MSGMERGE) $* $(GETTEXT_PACKAGE).pot -o $*.pox .po.mo: $(INTLTOOL_V_MSGFMT)$(MSGFMT) -o $@ $< @@ -108,7 +107,7 @@ install-data-no: all install-data-yes: all linguas="$(USE_LINGUAS)"; \ for lang in $$linguas; do \ - dir=$(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES; \ + dir=$(DESTDIR)$(localedir)/$$lang/LC_MESSAGES; \ $(mkdir_p) $$dir; \ if test -r $$lang.gmo; then \ $(INSTALL_DATA) $$lang.gmo $$dir/$(GETTEXT_PACKAGE).mo; \ @@ -142,8 +141,8 @@ install-exec installcheck: uninstall: linguas="$(USE_LINGUAS)"; \ for lang in $$linguas; do \ - rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \ - rm -f $(DESTDIR)$(itlocaledir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \ + rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo; \ + rm -f $(DESTDIR)$(localedir)/$$lang/LC_MESSAGES/$(GETTEXT_PACKAGE).mo.m; \ done check: all $(GETTEXT_PACKAGE).pot diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index 91455a7..a1c1681 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -669,6 +669,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor, clutter_container_add (CLUTTER_CONTAINER (info->stage), info->window_group, + info->top_window_group, info->overlay_group, info->hidden_group, NULL); @@ -1170,7 +1171,7 @@ meta_compositor_sync_stack (MetaCompositor *compositor, old_actor = old_stack->data; old_window = meta_window_actor_get_meta_window (old_actor); - if (old_window->hidden && + if ((old_window->hidden || old_window->unmanaging) && !meta_window_actor_effect_in_progress (old_actor)) { old_stack = g_list_delete_link (old_stack, old_stack); @@ -1204,7 +1205,7 @@ meta_compositor_sync_stack (MetaCompositor *compositor, * filtered out non-animating hidden windows above. */ if (old_actor && - (!stack_actor || old_window->hidden)) + (!stack_actor || old_window->hidden || old_window->unmanaging)) { actor = old_actor; window = old_window; @@ -1229,30 +1230,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, diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 55ffe9b..c5d4485 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -104,7 +104,6 @@ struct _MetaWindowActorPrivate GList *frames; guint visible : 1; - guint mapped : 1; guint argb32 : 1; guint disposed : 1; guint redecorating : 1; @@ -1018,7 +1017,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; meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor), @@ -1087,7 +1086,7 @@ meta_window_actor_queue_frame_drawn (MetaWindowActor *self, * send a _NET_WM_FRAME_DRAWN. We do a 1-pixel redraw to get * consistent timing with non-empty frames. */ - if (priv->mapped && !priv->needs_pixmap) + if (!priv->needs_pixmap) { const cairo_rectangle_int_t clip = { 0, 0, 1, 1 }; clutter_actor_queue_redraw_with_clip (priv->actor, &clip); @@ -1120,9 +1119,6 @@ meta_window_actor_queue_create_pixmap (MetaWindowActor *self) priv->needs_pixmap = TRUE; - if (!priv->mapped) - return; - if (is_frozen (self)) return; @@ -1220,9 +1216,6 @@ meta_window_actor_after_effects (MetaWindowActor *self) meta_window_actor_sync_visibility (self); meta_window_actor_sync_actor_geometry (self, FALSE); - if (!meta_window_is_mapped (priv->window)) - meta_window_actor_detach (self); - if (priv->needs_pixmap) clutter_actor_queue_redraw (priv->actor); } @@ -1403,7 +1396,6 @@ LOCAL_SYMBOL void meta_window_actor_destroy (MetaWindowActor *self) { MetaWindow *window; - MetaCompScreen *info; MetaWindowActorPrivate *priv; MetaWindowType window_type; @@ -1413,13 +1405,6 @@ meta_window_actor_destroy (MetaWindowActor *self) window_type = meta_window_get_window_type (window); meta_window_set_compositor_private (window, NULL); - /* - * We remove the window from internal lookup hashes and thus any other - * unmap events etc fail - */ - info = meta_screen_get_compositor_data (priv->screen); - info->windows = g_list_remove (info->windows, (gconstpointer) self); - if (window_type == META_WINDOW_DROPDOWN_MENU || window_type == META_WINDOW_POPUP_MENU || window_type == META_WINDOW_TOOLTIP || @@ -1672,8 +1657,7 @@ meta_window_actor_new (MetaWindow *window) MetaWindowActorPrivate *priv; MetaFrame *frame; Window top_window; - MetaRectangle rectWorkArea[1]; - MetaRectangle *rectWindow; + ClutterActor *window_group; frame = meta_window_get_frame (window); if (frame) @@ -1694,9 +1678,7 @@ 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_queue_create_pixmap (self); meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (priv->window)); @@ -1712,34 +1694,16 @@ meta_window_actor_new (MetaWindow *window) /* Hang our compositor window state off the MetaWindow for fast retrieval */ meta_window_set_compositor_private (window, G_OBJECT (self)); - if (window->type == META_WINDOW_DROPDOWN_MENU || - window->type == META_WINDOW_POPUP_MENU || - window->type == META_WINDOW_COMBO) { - clutter_container_add_actor (CLUTTER_CONTAINER (info->top_window_group), - CLUTTER_ACTOR (self)); - } - else if (window->type == META_WINDOW_TOOLTIP) { - meta_window_get_work_area_all_monitors(window, rectWorkArea); - rectWindow = meta_window_get_rect(window); - // move tooltip out of top panel if necessary - if (rectWindow->y < rectWorkArea->y) { - meta_window_move(window, FALSE, rectWindow->x, rectWorkArea->y); - } - rectWindow = meta_window_get_rect(window); - // move tooltip out of bottom panel if necessary - if ((rectWindow->y + rectWindow->height) > (rectWorkArea->y + rectWorkArea->height)) { - meta_window_move(window, FALSE, rectWindow->x, rectWorkArea->y + rectWorkArea->height - rectWindow->height); - } - clutter_container_add_actor (CLUTTER_CONTAINER (info->top_window_group), - CLUTTER_ACTOR (self)); - } - else if (window->type == META_WINDOW_DESKTOP) { - clutter_container_add_actor (CLUTTER_CONTAINER (info->bottom_window_group), - CLUTTER_ACTOR (self)); - }else{ - clutter_container_add_actor (CLUTTER_CONTAINER (info->window_group), - CLUTTER_ACTOR (self)); - } + if (window->layer == META_LAYER_OVERRIDE_REDIRECT) + window_group = info->top_window_group; + else if (window->type == META_WINDOW_DESKTOP) + window_group = info->bottom_window_group; + else + window_group = info->window_group; + + clutter_container_add_actor (CLUTTER_CONTAINER (window_group), + CLUTTER_ACTOR (self)); + clutter_actor_hide (CLUTTER_ACTOR (self)); /* Initial position in the stack is arbitrary; stacking will be synced @@ -1750,34 +1714,6 @@ meta_window_actor_new (MetaWindow *window) return self; } -LOCAL_SYMBOL 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); -} - -LOCAL_SYMBOL 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; -} - static void meta_window_actor_clear_shape_region (MetaWindowActor *self) { @@ -2020,9 +1956,6 @@ check_needs_pixmap (MetaWindowActor *self) 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; @@ -2106,9 +2039,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 @@ -2219,7 +2149,7 @@ meta_window_actor_process_damage (MetaWindowActor *self, return; } - if (!priv->mapped || priv->needs_pixmap) + if (priv->needs_pixmap) return; meta_shaped_texture_update_area (META_SHAPED_TEXTURE (priv->actor), diff --git a/src/core/bell.c b/src/core/bell.c index 25440f0..7d02cf0 100644 --- a/src/core/bell.c +++ b/src/core/bell.c @@ -51,312 +51,6 @@ #include #include "bell.h" -#include "screen-private.h" -#include -#ifdef HAVE_LIBCANBERRA -#include -#endif - -/* - * Flashes one entire screen. This is done by making a window the size of the - * whole screen (or reusing the old one, if it's still around), mapping it, - * painting it white and then black, and then unmapping it. We set saveunder so - * that all the windows behind it come back immediately. - * - * Unlike frame flashes, we don't do fullscreen flashes with a timeout; rather, - * we do them in one go, because we don't have to rely on the theme code - * redrawing the frame for us in order to do the flash. - * - * \param display The display which owns the screen (rather redundant) - * \param screen The screen to flash - * - * \bug The way I read it, this appears not to do the flash - * the first time we flash a particular display. Am I wrong? - * - * \bug This appears to destroy our current XSync status. - */ -static void -bell_flash_screen (MetaDisplay *display, - MetaScreen *screen) -{ - Window root = screen->xroot; - int width = screen->rect.width; - int height = screen->rect.height; - - if (screen->flash_window == None) - { - Visual *visual = (Visual *)CopyFromParent; - XSetWindowAttributes xswa; - int depth = CopyFromParent; - xswa.save_under = True; - xswa.override_redirect = True; - /* - * TODO: use XGetVisualInfo and determine which is an - * overlay, if one is present, and use the Overlay visual - * for this window (for performance reasons). - * Not sure how to tell this yet... - */ - screen->flash_window = XCreateWindow (display->xdisplay, root, - 0, 0, width, height, - 0, depth, - InputOutput, - visual, - /* note: XSun doesn't like SaveUnder here */ - CWSaveUnder | CWOverrideRedirect, - &xswa); - XSelectInput (display->xdisplay, screen->flash_window, ExposureMask); - XMapWindow (display->xdisplay, screen->flash_window); - XSync (display->xdisplay, False); - XFlush (display->xdisplay); - XUnmapWindow (display->xdisplay, screen->flash_window); - } - else - { - /* just draw something in the window */ - GC gc = XCreateGC (display->xdisplay, screen->flash_window, 0, NULL); - XMapWindow (display->xdisplay, screen->flash_window); - XSetForeground (display->xdisplay, gc, - WhitePixel (display->xdisplay, - XScreenNumberOfScreen (screen->xscreen))); - XFillRectangle (display->xdisplay, screen->flash_window, gc, - 0, 0, width, height); - XSetForeground (display->xdisplay, gc, - BlackPixel (display->xdisplay, - XScreenNumberOfScreen (screen->xscreen))); - XFillRectangle (display->xdisplay, screen->flash_window, gc, - 0, 0, width, height); - XFlush (display->xdisplay); - XSync (display->xdisplay, False); - XUnmapWindow (display->xdisplay, screen->flash_window); - XFreeGC (display->xdisplay, gc); - } - - if (meta_prefs_get_focus_mode () != C_DESKTOP_FOCUS_MODE_CLICK && - !display->mouse_mode) - meta_display_increment_focus_sentinel (display); - XFlush (display->xdisplay); -} - -/* - * Flashes one screen, or all screens, in response to a bell event. - * If the event is on a particular window, flash the screen that - * window is on. Otherwise, flash every screen on this display. - * - * If the configure script found we had no XKB, this does not exist. - * - * \param display The display the event came in on - * \param xkb_ev The bell event - */ -#ifdef HAVE_XKB -static void -bell_flash_fullscreen (MetaDisplay *display, - XkbAnyEvent *xkb_ev) -{ - XkbBellNotifyEvent *xkb_bell_ev = (XkbBellNotifyEvent *) xkb_ev; - MetaScreen *screen; - - g_assert (xkb_ev->xkb_type == XkbBellNotify); - if (xkb_bell_ev->window != None) - { - screen = meta_display_screen_for_xwindow (display, xkb_bell_ev->window); - if (screen) - { - if (display->compositor) - meta_compositor_flash_screen (display->compositor, screen); - else - bell_flash_screen (display, screen); - } - } - else - { - GSList *screen_list = display->screens; - while (screen_list) - { - screen = (MetaScreen *) screen_list->data; - if (display->compositor) - meta_compositor_flash_screen (display->compositor, screen); - else - bell_flash_screen (display, screen); - screen_list = screen_list->next; - } - } -} - -/* - * Makes a frame be not flashed; this is the timeout half of - * bell_flash_window_frame(). This is done simply by clearing the - * flash flag and queuing a redraw of the frame. - * - * If the configure script found we had no XKB, this does not exist. - * - * \param data The frame to unflash, cast to a gpointer so it can go into - * a callback function. - * \return Always FALSE, so we don't get called again. - * - * \bug This is the parallel to bell_flash_window_frame(), so it should - * really be called meta_bell_unflash_window_frame(). - */ -static gboolean -bell_unflash_frame (gpointer data) -{ - MetaFrame *frame = (MetaFrame *) data; - frame->is_flashing = 0; - meta_frame_queue_draw (frame); - return FALSE; -} - -/* - * Makes a frame flash and then return to normal shortly afterwards. - * This is done by setting a flag so that the theme - * code will temporarily draw the frame as focussed if it's unfocussed and - * vice versa, and then queueing a redraw. Lastly, we create a timeout so - * that the flag can be unset and the frame re-redrawn. - * - * If the configure script found we had no XKB, this does not exist. - * - * \param window The window to flash - */ -static void -bell_flash_window_frame (MetaWindow *window) -{ - g_assert (window->frame != NULL); - window->frame->is_flashing = 1; - meta_frame_queue_draw (window->frame); - /* Since this idle is added after the Clutter clock source, with - * the same priority, it will be executed after it as well, so - * we are guaranteed to get at least one frame drawn in the - * flashed state, no matter how loaded we are. - */ - g_timeout_add_full (META_PRIORITY_REDRAW, 100, - bell_unflash_frame, window->frame, NULL); -} - -/* - * Flashes the frame of the focussed window. If there is no focussed window, - * flashes the screen. - * - * \param display The display the bell event came in on - * \param xkb_ev The bell event we just received - */ -static void -bell_flash_frame (MetaDisplay *display, - XkbAnyEvent *xkb_ev) -{ - XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev; - MetaWindow *window; - - g_assert (xkb_ev->xkb_type == XkbBellNotify); - window = meta_display_lookup_x_window (display, xkb_bell_event->window); - if (!window && (display->focus_window)) - { - window = display->focus_window; - } - if (window && window->frame) - { - bell_flash_window_frame (window); - } - else /* revert to fullscreen flash if there's no focussed window */ - { - bell_flash_fullscreen (display, xkb_ev); - } -} - -/* - * Gives the user some kind of visual bell substitute, in response to a - * bell event. What this is depends on the "visual bell type" pref. - * - * If the configure script found we had no XKB, this does not exist. - * - * \param display The display the bell event came in on - * \param xkb_ev The bell event we just received - * - * \bug This should be merged with meta_bell_notify(). - */ -static void -bell_visual_notify (MetaDisplay *display, - XkbAnyEvent *xkb_ev) -{ - switch (meta_prefs_get_visual_bell_type ()) - { - case C_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH: - bell_flash_fullscreen (display, xkb_ev); - break; - case C_DESKTOP_VISUAL_BELL_FRAME_FLASH: - bell_flash_frame (display, xkb_ev); /* does nothing yet */ - break; - } -} - -LOCAL_SYMBOL void -meta_bell_notify (MetaDisplay *display, - XkbAnyEvent *xkb_ev) -{ - /* flash something */ - if (meta_prefs_get_visual_bell ()) - bell_visual_notify (display, xkb_ev); - -#ifdef HAVE_LIBCANBERRA - if (meta_prefs_bell_is_audible ()) - { - ca_proplist *p; - XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent*) xkb_ev; - MetaWindow *window; - int res; - - ca_proplist_create (&p); - ca_proplist_sets (p, CA_PROP_EVENT_ID, "bell-window-system"); - ca_proplist_sets (p, CA_PROP_EVENT_DESCRIPTION, _("Bell event")); - ca_proplist_sets (p, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent"); - - window = meta_display_lookup_x_window (display, xkb_bell_event->window); - if (!window && (display->focus_window) && (display->focus_window->frame)) - window = display->focus_window; - - if (window) - { - ca_proplist_sets (p, CA_PROP_WINDOW_NAME, window->title); - ca_proplist_setf (p, CA_PROP_WINDOW_X11_XID, "%lu", (unsigned long)window->xwindow); - ca_proplist_sets (p, CA_PROP_APPLICATION_NAME, window->res_name); - ca_proplist_setf (p, CA_PROP_APPLICATION_PROCESS_ID, "%d", window->net_wm_pid); - } - - /* First, we try to play a real sound ... */ - res = ca_context_play_full (ca_gtk_context_get (), 1, p, NULL, NULL); - - ca_proplist_destroy (p); - - if (res != CA_SUCCESS && res != CA_ERROR_DISABLED) - { - /* ...and in case that failed we use the classic X11 bell. */ - XkbForceDeviceBell (display->xdisplay, - xkb_bell_event->device, - xkb_bell_event->bell_class, - xkb_bell_event->bell_id, - xkb_bell_event->percent); - } - } -#endif /* HAVE_LIBCANBERRA */ -} -#endif /* HAVE_XKB */ - -LOCAL_SYMBOL void -meta_bell_set_audible (MetaDisplay *display, gboolean audible) -{ -#ifdef HAVE_XKB -#ifdef HAVE_LIBCANBERRA - /* When we are playing sounds using libcanberra support, we handle the - * bell whether its an audible bell or a visible bell */ - gboolean enable_system_bell = FALSE; -#else - gboolean enable_system_bell = audible; -#endif /* HAVE_LIBCANBERRA */ - - XkbChangeEnabledControls (display->xdisplay, - XkbUseCoreKbd, - XkbAudibleBellMask, - enable_system_bell ? XkbAudibleBellMask : 0); -#endif /* HAVE_XKB */ -} LOCAL_SYMBOL gboolean meta_bell_init (MetaDisplay *display) @@ -375,20 +69,10 @@ meta_bell_init (MetaDisplay *display) } else { - unsigned int mask = XkbBellNotifyMask; - gboolean visual_bell_auto_reset = FALSE; - /* TRUE if and when non-broken version is available */ XkbSelectEvents (display->xdisplay, XkbUseCoreKbd, XkbBellNotifyMask, XkbBellNotifyMask); - meta_bell_set_audible (display, meta_prefs_bell_is_audible ()); - if (visual_bell_auto_reset) { - XkbSetAutoResetControls (display->xdisplay, - XkbAudibleBellMask, - &mask, - &mask); - } return TRUE; } #endif @@ -407,17 +91,14 @@ meta_bell_shutdown (MetaDisplay *display) #endif } -/* - * Deals with a frame being destroyed. This is important because if we're - * using a visual bell, we might be flashing the edges of the frame, and - * so we'd have a timeout function waiting ready to un-flash them. If the - * frame's going away, we can tell the timeout not to bother. - * - * \param frame The frame which is being destroyed - */ LOCAL_SYMBOL void -meta_bell_notify_frame_destroy (MetaFrame *frame) +meta_bell_notify (MetaDisplay *display, + XkbAnyEvent *xkb_ev) { - if (frame->is_flashing) - g_source_remove_by_funcs_user_data (&g_timeout_funcs, frame); -} + XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev; + MetaWindow *bell_window = NULL; + + bell_window = meta_display_lookup_x_window (display, xkb_bell_event->window); + + g_signal_emit_by_name (display, "bell", bell_window); +} \ No newline at end of file diff --git a/src/core/bell.h b/src/core/bell.h index a98330e..c8c1b18 100644 --- a/src/core/bell.h +++ b/src/core/bell.h @@ -36,7 +36,7 @@ #include #endif #include "display-private.h" -#include "frame.h" +#include "window-private.h" #ifdef HAVE_XKB /** @@ -52,17 +52,6 @@ void meta_bell_notify (MetaDisplay *display, XkbAnyEvent *xkb_ev); #endif -/** - * Turns the bell to audible or visual. This tells X what to do, but - * not Muffin; you will need to set the "visual bell" pref for that. - * - * If the configure script found we had no XKB, this is a no-op. - * - * \param display The display we're configuring - * \param audible True for an audible bell, false for a visual bell - */ -void meta_bell_set_audible (MetaDisplay *display, gboolean audible); - /** * Initialises the bell subsystem. This involves intialising * XKB (which, despite being a keyboard extension, is the @@ -96,13 +85,3 @@ gboolean meta_bell_init (MetaDisplay *display); * we don't. */ void meta_bell_shutdown (MetaDisplay *display); - -/** - * Deals with a frame being destroyed. This is important because if we're - * using a visual bell, we might be flashing the edges of the frame, and - * so we'd have a timeout function waiting ready to un-flash them. If the - * frame's going away, we can tell the timeout not to bother. - * - * \param frame The frame which is being destroyed - */ -void meta_bell_notify_frame_destroy (MetaFrame *frame); diff --git a/src/core/constraints.c b/src/core/constraints.c index a8d38a0..06c795f 100644 --- a/src/core/constraints.c +++ b/src/core/constraints.c @@ -935,7 +935,7 @@ constrain_tiling (MetaWindow *window, return TRUE; /* Determine whether constraint applies; exit if it doesn't */ - if (!META_WINDOW_TILED_OR_SNAPPED (window)) + if (!META_WINDOW_TILED_OR_SNAPPED (window) || window->resizing_tile_type != META_WINDOW_TILE_TYPE_NONE) return TRUE; /* Calculate target_size - as the tile previews need this as well, we diff --git a/src/core/display-private.h b/src/core/display-private.h index fa73a0d..6c66295 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -417,6 +417,7 @@ gboolean meta_display_window_has_pending_pings (MetaDisplay *display, MetaWindow *window); int meta_resize_gravity_from_grab_op (MetaGrabOp op); +int meta_resize_gravity_from_tile_mode (MetaTileMode mode); gboolean meta_grab_op_is_moving (MetaGrabOp op); gboolean meta_grab_op_is_resizing (MetaGrabOp op); diff --git a/src/core/display.c b/src/core/display.c index b02f4f5..700959b 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -142,6 +142,7 @@ enum GRAB_OP_END, ZOOM_SCROLL_IN, ZOOM_SCROLL_OUT, + BELL, LAST_SIGNAL }; @@ -296,6 +297,14 @@ meta_display_class_init (MetaDisplayClass *klass) NULL, NULL, NULL, G_TYPE_NONE, 0); + display_signals[BELL] = + g_signal_new ("bell", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 1, META_TYPE_WINDOW); + g_object_class_install_property (object_class, PROP_FOCUS_WINDOW, g_param_spec_object ("focus-window", @@ -1769,9 +1778,8 @@ event_callback (XEvent *event, window->desc); } - if (display->compositor) - meta_compositor_window_shape_changed (display->compositor, - window); + meta_compositor_window_shape_changed (display->compositor, + window); } } else @@ -1868,8 +1876,10 @@ event_callback (XEvent *event, meta_stack_set_positions (screen->stack, display->grab_old_window_stacking); } - meta_display_end_grab_op (display, - event->xbutton.time); + + if (display->grab_window->tile_mode == META_TILE_NONE) + meta_display_end_grab_op (display, + event->xbutton.time); } else if (window && display->grab_op == META_GRAB_OP_NONE) { @@ -2298,7 +2308,7 @@ event_callback (XEvent *event, if (display->grab_op != META_GRAB_OP_NONE && display->grab_window == window && - ((window->frame == NULL) || !window->frame->mapped)) + window->frame == NULL) meta_display_end_grab_op (display, timestamp); if (!frame_was_receiver) @@ -2335,8 +2345,7 @@ event_callback (XEvent *event, /* NB: override redirect windows wont cause a map request so we * watch out for map notifies against any root windows too if a * compositor is enabled: */ - if (display->compositor && window == NULL - && meta_display_screen_for_root (display, event->xmap.event)) + if (window == NULL && meta_display_screen_for_root (display, event->xmap.event)) { window = meta_window_new (display, event->xmap.window, FALSE); @@ -2711,7 +2720,7 @@ event_callback (XEvent *event, break; } - if (display->compositor && !bypass_compositor) + if (!bypass_compositor) { if (meta_compositor_process_event (display->compositor, event, @@ -3852,7 +3861,16 @@ meta_display_end_grab_op (MetaDisplay *display, meta_screen_ungrab_all_keys (display->grab_screen, timestamp); } - + if (display->grab_window && + display->grab_window->resizing_tile_type != META_WINDOW_TILE_TYPE_NONE) { + display->grab_window->snap_queued = display->grab_window->resizing_tile_type == META_WINDOW_TILE_TYPE_SNAPPED; + display->grab_window->tile_mode = display->grab_window->resize_tile_mode; + display->grab_window->custom_snap_size = TRUE; + meta_window_real_tile (display->grab_window, TRUE); + } + + meta_screen_hide_hud_and_preview (display->grab_screen); + display->grab_window = NULL; display->grab_screen = NULL; display->grab_xwindow = None; @@ -4887,6 +4905,45 @@ meta_resize_gravity_from_grab_op (MetaGrabOp op) return gravity; } +LOCAL_SYMBOL int +meta_resize_gravity_from_tile_mode (MetaTileMode mode) +{ + int gravity; + + gravity = -1; + switch (mode) + { + case META_TILE_LEFT: + gravity = WestGravity; + break; + case META_TILE_RIGHT: + gravity = EastGravity; + break; + case META_TILE_TOP: + gravity = NorthGravity; + break; + case META_TILE_BOTTOM: + gravity = SouthGravity; + break; + case META_TILE_ULC: + gravity = NorthWestGravity; + break; + case META_TILE_LLC: + gravity = SouthWestGravity; + break; + case META_TILE_URC: + gravity = NorthEastGravity; + break; + case META_TILE_LRC: + gravity = SouthEastGravity; + break; + default: + break; + } + + return gravity; +} + static MetaScreen* find_screen_for_selection (MetaDisplay *display, Window owner, @@ -5258,8 +5315,6 @@ static void prefs_changed_callback (MetaPreference pref, void *data) { - MetaDisplay *display = data; - /* It may not be obvious why we regrab on focus mode * change; it's because we handle focus clicks a * bit differently for the different focus modes. @@ -5309,10 +5364,6 @@ prefs_changed_callback (MetaPreference pref, g_slist_free (windows); } - else if (pref == META_PREF_AUDIBLE_BELL) - { - meta_bell_set_audible (display, meta_prefs_bell_is_audible ()); - } } LOCAL_SYMBOL void diff --git a/src/core/edge-resistance.c b/src/core/edge-resistance.c index dd42601..3620b3e 100644 --- a/src/core/edge-resistance.c +++ b/src/core/edge-resistance.c @@ -377,6 +377,9 @@ apply_edge_resistance (MetaWindow *window, begin = CLAMP (begin, 0, last_edge); end = CLAMP (end, 0, last_edge); + /* Edge resistance between windows can be disabled in gettings. */ + gboolean window_edge_enabled = meta_prefs_get_edge_resistance_window (); + /* Loop over all these edges we're moving past/to. */ i = begin; while ((increasing && i <= end) || @@ -386,6 +389,13 @@ apply_edge_resistance (MetaWindow *window, MetaEdge *edge = g_array_index (edges, MetaEdge*, i); int compare = xdir ? edge->rect.x : edge->rect.y; + /* Pass window edge resistance if disabled. */ + if (edge->edge_type == META_EDGE_WINDOW && !window_edge_enabled) + { + i += increment; + continue; + } + /* Find out if this edge is relevant */ edges_align = meta_rectangle_edge_aligns (new_rect, edge) || meta_rectangle_edge_aligns (old_rect, edge); diff --git a/src/core/frame.c b/src/core/frame.c index 71cd6a9..261f225 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -25,7 +25,6 @@ #include #include "frame.h" -#include "bell.h" #include #include "keybindings-private.h" @@ -66,7 +65,6 @@ meta_window_ensure_frame (MetaWindow *window) frame->right_width = 0; frame->current_cursor = 0; - frame->mapped = FALSE; frame->is_flashing = FALSE; meta_verbose ("Framing window %s: visual %s default, depth %d default depth %d\n", @@ -166,6 +164,8 @@ meta_window_ensure_frame (MetaWindow *window) /* Move keybindings to frame instead of window */ meta_window_grab_keys (window); + meta_ui_map_frame (frame->window->screen->ui, frame->xwindow); + meta_display_ungrab (window->display); } @@ -183,9 +183,7 @@ meta_window_destroy_frame (MetaWindow *window) frame = window->frame; meta_frame_calc_borders (frame, &borders); - - meta_bell_notify_frame_destroy (frame); - + /* Unparent the client window; it may be destroyed, * thus the error trap. */ diff --git a/src/core/frame.h b/src/core/frame.h index d857eb5..7e3f107 100644 --- a/src/core/frame.h +++ b/src/core/frame.h @@ -48,7 +48,6 @@ struct _MetaFrame int right_width; int bottom_height; - guint mapped : 1; guint need_reapply_frame_shape : 1; guint is_flashing : 1; /* used by the visual bell flash */ }; diff --git a/src/core/keybindings-private.h b/src/core/keybindings-private.h index 5ac7825..d5df4bd 100644 --- a/src/core/keybindings-private.h +++ b/src/core/keybindings-private.h @@ -65,6 +65,10 @@ gboolean meta_window_grab_all_keys (MetaWindow *window, guint32 timestamp); void meta_window_ungrab_all_keys (MetaWindow *window, guint32 timestamp); + +gboolean meta_window_resize_or_move_allowed (MetaWindow *window, + MetaDirection dir); + gboolean meta_display_process_key_event (MetaDisplay *display, MetaWindow *window, XEvent *event); diff --git a/src/core/keybindings.c b/src/core/keybindings.c index 1c5e49d..1792509 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -1321,6 +1321,47 @@ meta_window_ungrab_all_keys (MetaWindow *window, guint32 timestamp) } } +LOCAL_SYMBOL gboolean +meta_window_resize_or_move_allowed (MetaWindow *window, + MetaDirection dir) +{ + if (!META_WINDOW_MAXIMIZED (window) && !META_WINDOW_TILED_OR_SNAPPED (window)) + return TRUE; + + switch (dir) + { + case META_DIRECTION_LEFT: + if (window->tile_mode == META_TILE_RIGHT || + window->tile_mode == META_TILE_URC || + window->tile_mode == META_TILE_LRC) + return TRUE; + break; + case META_DIRECTION_RIGHT: + if (window->tile_mode == META_TILE_LEFT || + window->tile_mode == META_TILE_ULC || + window->tile_mode == META_TILE_LLC) + return TRUE; + break; + case META_DIRECTION_UP: + if (window->tile_mode == META_TILE_BOTTOM || + window->tile_mode == META_TILE_LLC || + window->tile_mode == META_TILE_LRC) + return TRUE; + break; + case META_DIRECTION_DOWN: + if (window->tile_mode == META_TILE_TOP || + window->tile_mode == META_TILE_ULC || + window->tile_mode == META_TILE_URC) + return TRUE; + break; + default: + return FALSE; + } + + return FALSE; +} + + static gboolean is_modifier (MetaDisplay *display, unsigned int keycode) @@ -1843,17 +1884,26 @@ process_keyboard_move_grab (MetaDisplay *display, * remaximize it. In normal cases, we need to do a moveresize * now to get the position back to the original. */ - if (window->shaken_loose) - meta_window_maximize (window, - META_MAXIMIZE_HORIZONTAL | - META_MAXIMIZE_VERTICAL); + if (window->shaken_loose) + { + meta_window_maximize (window, + META_MAXIMIZE_HORIZONTAL | + META_MAXIMIZE_VERTICAL); + } + else if (window->tile_mode != META_TILE_NONE) + { + window->custom_snap_size = FALSE; + meta_window_real_tile (window, FALSE); + } else - meta_window_move_resize (display->grab_window, - TRUE, - display->grab_initial_window_pos.x, - display->grab_initial_window_pos.y, - display->grab_initial_window_pos.width, - display->grab_initial_window_pos.height); + { + meta_window_move_resize (display->grab_window, + TRUE, + display->grab_initial_window_pos.x, + display->grab_initial_window_pos.y, + display->grab_initial_window_pos.width, + display->grab_initial_window_pos.height); + } } /* When moving by increments, we still snap to edges if the move @@ -1904,6 +1954,8 @@ process_keyboard_move_grab (MetaDisplay *display, "Computed new window location %d,%d due to keypress\n", x, y); + meta_window_tile (window, META_TILE_NONE, FALSE); + meta_window_get_client_root_coords (window, &old_rect); meta_window_edge_resistance_for_move (window, @@ -1939,22 +1991,30 @@ process_keyboard_resize_grab_op_change (MetaDisplay *display, { case XK_Up: case XK_KP_Up: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_UP)) { + display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; + } handled = TRUE; break; case XK_Down: case XK_KP_Down: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_DOWN)) { + display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; + } handled = TRUE; break; case XK_Left: case XK_KP_Left: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_LEFT)) { + display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; + } handled = TRUE; break; case XK_Right: case XK_KP_Right: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_RIGHT)) { + display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; + } handled = TRUE; break; } @@ -1965,12 +2025,16 @@ process_keyboard_resize_grab_op_change (MetaDisplay *display, { case XK_Left: case XK_KP_Left: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_LEFT)) { + display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; + } handled = TRUE; break; case XK_Right: case XK_KP_Right: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_RIGHT)) { + display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; + } handled = TRUE; break; } @@ -1981,12 +2045,16 @@ process_keyboard_resize_grab_op_change (MetaDisplay *display, { case XK_Left: case XK_KP_Left: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_LEFT)) { + display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; + } handled = TRUE; break; case XK_Right: case XK_KP_Right: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_RIGHT)) { + display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; + } handled = TRUE; break; } @@ -1997,12 +2065,16 @@ process_keyboard_resize_grab_op_change (MetaDisplay *display, { case XK_Up: case XK_KP_Up: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_UP)) { + display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; + } handled = TRUE; break; case XK_Down: case XK_KP_Down: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_DOWN)) { + display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; + } handled = TRUE; break; } @@ -2013,12 +2085,16 @@ process_keyboard_resize_grab_op_change (MetaDisplay *display, { case XK_Up: case XK_KP_Up: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_UP)) { + display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; + } handled = TRUE; break; case XK_Down: case XK_KP_Down: - display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_DOWN)) { + display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; + } handled = TRUE; break; } @@ -2088,7 +2164,10 @@ process_keyboard_resize_grab (MetaDisplay *display, width = window->rect.width; height = window->rect.height; - gravity = meta_resize_gravity_from_grab_op (display->grab_op); + if (window->tile_mode != META_TILE_NONE) + gravity = meta_resize_gravity_from_tile_mode (window->tile_mode); + else + gravity = meta_resize_gravity_from_grab_op (display->grab_op); smart_snap = (event->xkey.state & ShiftMask) != 0; @@ -2615,9 +2694,6 @@ handle_tile_action (MetaDisplay *display, if (new_mode == window->tile_mode) return; - if (!meta_window_can_tile (window, new_mode)) - return; - meta_window_tile (window, new_mode, snap); } @@ -2732,6 +2808,12 @@ handle_begin_resize (MetaDisplay *display, { if (window->has_resize_func) { + if (window->tile_mode != META_TILE_NONE) + { + window->resize_tile_mode = window->tile_mode; + window->resizing_tile_type = window->tile_type; + } + meta_window_begin_grab_op (window, META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN, FALSE, diff --git a/src/core/muffin.c b/src/core/muffin.c index 1ad1476..f9d31be 100644 --- a/src/core/muffin.c +++ b/src/core/muffin.c @@ -69,6 +69,8 @@ main (int argc, char **argv) GOptionContext *ctx; GError *error = NULL; + g_setenv ("CLUTTER_BACKEND", "x11", TRUE); + g_type_init (); ctx = meta_get_option_context (); diff --git a/src/core/prefs.c b/src/core/prefs.c index 690f79f..45e62ca 100644 --- a/src/core/prefs.c +++ b/src/core/prefs.c @@ -54,14 +54,12 @@ #define KEY_WORKSPACE_CYCLE "workspace-cycle" /* Keys from "foreign" schemas */ -#define KEY_GNOME_ACCESSIBILITY "toolkit-accessibility" #define KEY_GNOME_ANIMATIONS "enable-animations" #define KEY_GNOME_CURSOR_THEME "cursor-theme" #define KEY_GNOME_CURSOR_SIZE "cursor-size" #define KEY_MIN_WINDOW_OPACITY "min-window-opacity" #define KEY_WS_NAMES_GNOME "workspace-names" -#define KEY_LIVE_HIDDEN_WINDOWS "live-hidden-windows" #define KEY_WORKSPACES_ONLY_ON_PRIMARY "workspaces-only-on-primary" #define KEY_MOUSEWHEEL_ZOOM_ENABLED "screen-magnifier-enabled" @@ -102,9 +100,6 @@ static gboolean application_based = FALSE; static gboolean disable_workarounds = FALSE; static gboolean auto_raise = FALSE; static gboolean auto_raise_delay = 500; -static gboolean bell_is_visible = FALSE; -static gboolean bell_is_audible = TRUE; -static gboolean gnome_accessibility = FALSE; static gboolean gnome_animations = TRUE; static char *cursor_theme = NULL; static int cursor_size = 24; @@ -115,16 +110,15 @@ static int ui_scale = 1; static int min_window_opacity = 0; static gboolean resize_with_right_button = FALSE; static gboolean edge_tiling = FALSE; +static gboolean edge_resistance_window = TRUE; static gboolean force_fullscreen = TRUE; static unsigned int snap_modifier[2]; -static CDesktopVisualBellType visual_bell_type = C_DESKTOP_VISUAL_BELL_FULLSCREEN_FLASH; static MetaButtonLayout button_layout; /* NULL-terminated array */ static char **workspace_names = NULL; -static gboolean live_hidden_windows = FALSE; static gboolean workspaces_only_on_primary = FALSE; static gboolean legacy_snap = FALSE; @@ -253,13 +247,6 @@ static MetaEnumPreference preferences_enum[] = }, &focus_mode, }, - { - { "visual-bell-type", - SCHEMA_GENERAL, - META_PREF_VISUAL_BELL_TYPE, - }, - &visual_bell_type, - }, { { "action-double-click-titlebar", SCHEMA_GENERAL, @@ -363,27 +350,6 @@ static MetaBoolPreference preferences_bool[] = }, &auto_raise, }, - { - { "visual-bell", - SCHEMA_GENERAL, - META_PREF_VISUAL_BELL, - }, - &bell_is_visible, /* FIXME: change the name: it's confusing */ - }, - { - { "audible-bell", - SCHEMA_GENERAL, - META_PREF_AUDIBLE_BELL, - }, - &bell_is_audible, /* FIXME: change the name: it's confusing */ - }, - { - { KEY_GNOME_ACCESSIBILITY, - SCHEMA_INTERFACE, - META_PREF_GNOME_ACCESSIBILITY, - }, - &gnome_accessibility, - }, { { KEY_MOUSEWHEEL_ZOOM_ENABLED, SCHEMA_A11Y_APPLICATIONS, @@ -413,11 +379,11 @@ static MetaBoolPreference preferences_bool[] = &edge_tiling, }, { - { KEY_LIVE_HIDDEN_WINDOWS, + { "edge-resistance-window", SCHEMA_MUFFIN, - META_PREF_LIVE_HIDDEN_WINDOWS, + META_PREF_EDGE_RESISTANCE_WINDOW, }, - &live_hidden_windows, + &edge_resistance_window, }, { { "workspaces-only-on-primary", @@ -944,8 +910,6 @@ meta_prefs_init (void) /* Individual keys we watch outside of our schemas */ settings = g_settings_new (SCHEMA_INTERFACE); - g_signal_connect (settings, "changed::" KEY_GNOME_ACCESSIBILITY, - G_CALLBACK (settings_changed), NULL); g_signal_connect (settings, "changed::" KEY_GNOME_ANIMATIONS, G_CALLBACK (settings_changed), NULL); g_signal_connect (settings, "changed::" KEY_GNOME_CURSOR_THEME, @@ -1835,18 +1799,6 @@ meta_preference_to_string (MetaPreference pref) case META_PREF_WORKSPACE_NAMES: return "WORKSPACE_NAMES"; - case META_PREF_VISUAL_BELL: - return "VISUAL_BELL"; - - case META_PREF_AUDIBLE_BELL: - return "AUDIBLE_BELL"; - - case META_PREF_VISUAL_BELL_TYPE: - return "VISUAL_BELL_TYPE"; - - case META_PREF_GNOME_ACCESSIBILITY: - return "GNOME_ACCESSIBILTY"; - case META_PREF_GNOME_ANIMATIONS: return "GNOME_ANIMATIONS"; @@ -1862,18 +1814,27 @@ meta_preference_to_string (MetaPreference pref) case META_PREF_EDGE_TILING: return "EDGE_TILING"; + case META_PREF_EDGE_RESISTANCE_WINDOW: + return "EDGE_RESISTANCE_WINDOW"; + case META_PREF_FORCE_FULLSCREEN: return "FORCE_FULLSCREEN"; - case META_PREF_LIVE_HIDDEN_WINDOWS: - return "LIVE_HIDDEN_WINDOWS"; - case META_PREF_WORKSPACES_ONLY_ON_PRIMARY: return "WORKSPACES_ONLY_ON_PRIMARY"; case META_PREF_WORKSPACE_CYCLE: return "WORKSPACE_CYCLE"; + case META_PREF_VISUAL_BELL: + return "VISUAL_BELL"; + + case META_PREF_AUDIBLE_BELL: + return "AUDIBLE_BELL"; + + case META_PREF_VISUAL_BELL_TYPE: + return "VISUAL_BELL_TYPE"; + case META_PREF_DRAGGABLE_BORDER_WIDTH: return "DRAGGABLE_BORDER_WIDTH"; @@ -1906,7 +1867,6 @@ meta_preference_to_string (MetaPreference pref) case META_PREF_MIN_WIN_OPACITY: return "MIN_WIN_OPACITY"; - } return "(unknown)"; @@ -2156,24 +2116,6 @@ meta_prefs_get_button_layout (MetaButtonLayout *button_layout_p) *button_layout_p = button_layout; } -gboolean -meta_prefs_get_visual_bell (void) -{ - return bell_is_visible; -} - -gboolean -meta_prefs_bell_is_audible (void) -{ - return bell_is_audible; -} - -CDesktopVisualBellType -meta_prefs_get_visual_bell_type (void) -{ - return visual_bell_type; -} - LOCAL_SYMBOL gboolean meta_prefs_add_keybinding (const char *name, const char *schema, @@ -2359,12 +2301,6 @@ meta_prefs_get_auto_raise_delay (void) return auto_raise_delay; } -gboolean -meta_prefs_get_gnome_accessibility () -{ - return gnome_accessibility; -} - gboolean meta_prefs_get_gnome_animations () { @@ -2377,6 +2313,12 @@ meta_prefs_get_edge_tiling () return edge_tiling; } +gboolean +meta_prefs_get_edge_resistance_window () +{ + return edge_resistance_window; +} + MetaKeyBindingAction meta_prefs_get_keybinding_action (const char *name) { @@ -2441,27 +2383,6 @@ meta_prefs_get_force_fullscreen (void) return force_fullscreen; } -gboolean -meta_prefs_get_live_hidden_windows (void) -{ -#if 0 - return live_hidden_windows; -#else - return TRUE; -#endif -} - -void -meta_prefs_set_live_hidden_windows (gboolean whether) -{ - MetaBasePreference *pref = NULL; - - find_pref (preferences_bool, sizeof(MetaBoolPreference), - KEY_LIVE_HIDDEN_WINDOWS, &pref); - g_settings_set_boolean (SETTINGS (pref->schema), KEY_LIVE_HIDDEN_WINDOWS, - whether); -} - gboolean meta_prefs_get_workspaces_only_on_primary (void) { diff --git a/src/core/screen-private.h b/src/core/screen-private.h index 2be25d8..e3703ce 100644 --- a/src/core/screen-private.h +++ b/src/core/screen-private.h @@ -46,6 +46,7 @@ struct _MetaMonitorInfo int number; MetaRectangle rect; gboolean is_primary; + gboolean in_fullscreen; XID output; /* The primary or first output for this crtc, None if no xrandr */ }; @@ -119,6 +120,7 @@ struct _MetaScreen guint32 wm_cm_timestamp; guint work_area_later; + guint check_fullscreen_later; int rows_of_workspaces; int columns_of_workspaces; @@ -197,6 +199,7 @@ void meta_screen_get_natural_monitor_list (MetaScreen *screen, void meta_screen_update_workspace_layout (MetaScreen *screen); void meta_screen_update_workspace_names (MetaScreen *screen); void meta_screen_queue_workarea_recalc (MetaScreen *screen); +void meta_screen_queue_check_fullscreen (MetaScreen *screen); Window meta_create_offscreen_window (Display *xdisplay, Window parent, diff --git a/src/core/screen.c b/src/core/screen.c index 3eb5005..e369038 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -109,6 +109,11 @@ enum SNAP_OSD_SHOW, SNAP_OSD_HIDE, WORKSPACE_OSD_SHOW, + WINDOW_ADDED, + WINDOW_REMOVED, + WINDOW_MONITOR_CHANGED, + WINDOW_WORKSPACE_CHANGED, + IN_FULLSCREEN_CHANGED, LAST_SIGNAL }; @@ -298,6 +303,53 @@ meta_screen_class_init (MetaScreenClass *klass) NULL, NULL, NULL, G_TYPE_NONE, 0); + screen_signals[WINDOW_ADDED] = + g_signal_new ("window-added", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 2, + META_TYPE_WINDOW, + G_TYPE_INT); + + screen_signals[WINDOW_REMOVED] = + g_signal_new ("window-removed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 1, + META_TYPE_WINDOW); + + screen_signals[WINDOW_MONITOR_CHANGED] = + g_signal_new ("window-monitor-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 2, + META_TYPE_WINDOW, + G_TYPE_INT); + + screen_signals[WINDOW_WORKSPACE_CHANGED] = + g_signal_new ("window-workspace-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 2, + META_TYPE_WINDOW, + META_TYPE_WORKSPACE); + + screen_signals[IN_FULLSCREEN_CHANGED] = + g_signal_new ("in-fullscreen-changed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 0); + g_object_class_install_property (object_class, PROP_N_WORKSPACES, pspec); @@ -527,11 +579,13 @@ reload_monitor_infos (MetaScreen *screen) screen->monitor_infos[0].number = 0; screen->monitor_infos[0].rect = screen->rect; screen->monitor_infos[0].rect.width = screen->rect.width / 2; + screen->monitor_infos[0].in_fullscreen = -1; screen->monitor_infos[1].number = 1; screen->monitor_infos[1].rect = screen->rect; screen->monitor_infos[1].rect.x = screen->rect.width / 2; screen->monitor_infos[1].rect.width = screen->rect.width / 2; + screen->monitor_infos[1].in_fullscreen = -1; } #ifdef HAVE_XFREE_XINERAMA @@ -562,6 +616,7 @@ reload_monitor_infos (MetaScreen *screen) screen->monitor_infos[i].rect.y = infos[i].y_org; screen->monitor_infos[i].rect.width = infos[i].width; screen->monitor_infos[i].rect.height = infos[i].height; + screen->monitor_infos[i].in_fullscreen = -1; meta_topic (META_DEBUG_XINERAMA, "Monitor %d is %d,%d %d x %d\n", @@ -685,6 +740,7 @@ reload_monitor_infos (MetaScreen *screen) screen->monitor_infos[0].number = 0; screen->monitor_infos[0].rect = screen->rect; + screen->monitor_infos[0].in_fullscreen = -1; } filter_mirrored_monitors (screen); @@ -904,6 +960,7 @@ meta_screen_new (MetaDisplay *display, xroot, NoEventMask); screen->work_area_later = 0; + screen->check_fullscreen_later = 0; screen->active_workspace = NULL; screen->workspaces = NULL; @@ -1021,12 +1078,9 @@ meta_screen_free (MetaScreen *screen, meta_display_grab (display); - if (screen->display->compositor) - { - meta_compositor_unmanage_screen (screen->display->compositor, - screen); - } - + meta_compositor_unmanage_screen (screen->display->compositor, + screen); + meta_display_unmanage_windows_for_screen (display, screen, timestamp); meta_prefs_remove_listener (prefs_changed_callback, screen); @@ -1072,6 +1126,9 @@ meta_screen_free (MetaScreen *screen, screen->work_area_later = 0; } + if (screen->check_fullscreen_later != 0) + g_source_remove (screen->check_fullscreen_later); + if (screen->monitor_infos) g_free (screen->monitor_infos); @@ -3029,9 +3086,8 @@ meta_screen_resize (MetaScreen *screen, reload_monitor_infos (screen); set_desktop_geometry_hint (screen); - if (screen->display->compositor) - meta_compositor_sync_screen_size (screen->display->compositor, - screen, width, height); + meta_compositor_sync_screen_size (screen->display->compositor, + screen, width, height); /* Queue a resize on all the windows */ meta_screen_foreach_window (screen, meta_screen_resize_func, 0); @@ -3050,6 +3106,8 @@ meta_screen_resize (MetaScreen *screen, g_free (old_monitor_infos); g_slist_free (windows); + meta_screen_queue_check_fullscreen (screen); + g_signal_emit (screen, screen_signals[MONITORS_CHANGED], 0); } @@ -3715,3 +3773,127 @@ meta_screen_update_snapped_windows (MetaScreen *screen) tmp = tmp->next; } } + +static gboolean +check_fullscreen_func (gpointer data) +{ + MetaScreen *screen = data; + MetaWindow *window; + GSList *fullscreen_monitors = NULL; + GSList *obscured_monitors = NULL; + gboolean in_fullscreen_changed = FALSE; + int i; + + screen->check_fullscreen_later = 0; + + /* We consider a monitor in fullscreen if it contains a fullscreen window; + * however we make an exception for maximized windows above the fullscreen + * one, as in that case window+chrome fully obscure the fullscreen window. + */ + for (window = meta_stack_get_top (screen->stack); + window; + window = meta_stack_get_below (screen->stack, window, FALSE)) + { + gboolean covers_monitors = FALSE; + + if (window->screen != screen || window->hidden) + continue; + + if (window->fullscreen) + { + covers_monitors = TRUE; + } + else if (window->override_redirect) + { + /* We want to handle the case where an application is creating an + * override-redirect window the size of the screen (monitor) and treat + * it similarly to a fullscreen window, though it doesn't have fullscreen + * window management behavior. (Being O-R, it's not managed at all.) + */ + if (meta_window_is_monitor_sized (window)) + covers_monitors = TRUE; + } + else if (window->maximized_horizontally && + window->maximized_vertically) + { + int monitor_index = meta_window_get_monitor (window); + /* + 1 to avoid NULL */ + gpointer monitor_p = GINT_TO_POINTER(monitor_index + 1); + if (!g_slist_find (obscured_monitors, monitor_p)) + obscured_monitors = g_slist_prepend (obscured_monitors, monitor_p); + } + + if (covers_monitors) + { + int *monitors; + gsize n_monitors; + gsize j; + + monitors = meta_window_get_all_monitors (window, &n_monitors); + for (j = 0; j < n_monitors; j++) + { + /* + 1 to avoid NULL */ + gpointer monitor_p = GINT_TO_POINTER(monitors[j] + 1); + if (!g_slist_find (fullscreen_monitors, monitor_p) && + !g_slist_find (obscured_monitors, monitor_p)) + fullscreen_monitors = g_slist_prepend (fullscreen_monitors, monitor_p); + } + + g_free (monitors); + } + } + + g_slist_free (obscured_monitors); + + for (i = 0; i < screen->n_monitor_infos; i++) + { + MetaMonitorInfo *info = &screen->monitor_infos[i]; + gboolean in_fullscreen = g_slist_find (fullscreen_monitors, GINT_TO_POINTER (i + 1)) != NULL; + if (in_fullscreen != info->in_fullscreen) + { + info->in_fullscreen = in_fullscreen; + in_fullscreen_changed = TRUE; + } + } + + g_slist_free (fullscreen_monitors); + + if (in_fullscreen_changed) + g_signal_emit (screen, screen_signals[IN_FULLSCREEN_CHANGED], 0, NULL); + + return FALSE; +} + +void +meta_screen_queue_check_fullscreen (MetaScreen *screen) +{ + if (!screen->check_fullscreen_later) + screen->check_fullscreen_later = meta_later_add (META_LATER_CHECK_FULLSCREEN, + check_fullscreen_func, + screen, NULL); +} + +/** + * meta_screen_get_monitor_in_fullscreen: + * @screen: a #MetaScreen + * @monitor: the monitor number + * + * Determines whether there is a fullscreen window obscuring the specified + * monitor. If there is a fullscreen window, the desktop environment will + * typically hide any controls that might obscure the fullscreen window. + * + * You can get notification when this changes by connecting to + * MetaScreen::in-fullscreen-changed. + * + * Returns: %TRUE if there is a fullscreen window covering the specified monitor. + */ +gboolean +meta_screen_get_monitor_in_fullscreen (MetaScreen *screen, + int monitor) +{ + g_return_val_if_fail (META_IS_SCREEN (screen), FALSE); + g_return_val_if_fail (monitor >= 0 && monitor < screen->n_monitor_infos, FALSE); + + /* We use -1 as a flag to mean "not known yet" for notification purposes */ + return screen->monitor_infos[monitor].in_fullscreen == TRUE; +} diff --git a/src/core/stack-tracker.c b/src/core/stack-tracker.c index 18d2101..19168d0 100644 --- a/src/core/stack-tracker.c +++ b/src/core/stack-tracker.c @@ -739,7 +739,7 @@ meta_stack_tracker_queue_sync_stack (MetaStackTracker *tracker) { if (tracker->sync_stack_later == 0) { - tracker->sync_stack_later = meta_later_add (META_LATER_BEFORE_REDRAW, + tracker->sync_stack_later = meta_later_add (META_LATER_SYNC_STACK, stack_tracker_sync_stack_later, tracker, NULL); } diff --git a/src/core/stack.c b/src/core/stack.c index a90ef80..6d57f87 100644 --- a/src/core/stack.c +++ b/src/core/stack.c @@ -395,6 +395,8 @@ get_maximum_layer_in_group (MetaWindow *window) static void compute_layer (MetaWindow *window) { + MetaStackLayer old_layer = window->layer; + window->layer = get_standalone_layer (window); /* We can only do promotion-due-to-group for dialogs and other @@ -430,6 +432,10 @@ compute_layer (MetaWindow *window) meta_topic (META_DEBUG_STACK, "Window %s on layer %u type = %u has_focus = %d\n", window->desc, window->layer, window->type, window->has_focus); + + if (window->layer != old_layer && + (old_layer == META_LAYER_FULLSCREEN || window->layer == META_LAYER_FULLSCREEN)) + meta_screen_queue_check_fullscreen (window->screen); } /* Front of the layer list is the topmost window, diff --git a/src/core/util.c b/src/core/util.c index 67bd4c5..d3483cc 100644 --- a/src/core/util.c +++ b/src/core/util.c @@ -897,6 +897,9 @@ meta_later_add (MetaLaterType when, later->source = g_idle_add_full (META_PRIORITY_RESIZE, call_idle_later, later, NULL); ensure_later_repaint_func (); break; + case META_LATER_CALC_SHOWING: + case META_LATER_CHECK_FULLSCREEN: + case META_LATER_SYNC_STACK: case META_LATER_BEFORE_REDRAW: ensure_later_repaint_func (); break; diff --git a/src/core/window-private.h b/src/core/window-private.h index 1b83bbe..d7959e8 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -558,7 +558,6 @@ MetaWindow* meta_window_new_with_attrs (MetaDisplay *display, XWindowAttributes *attrs); void meta_window_unmanage (MetaWindow *window, guint32 timestamp); -void meta_window_calc_showing (MetaWindow *window); void meta_window_queue (MetaWindow *window, guint queuebits); void meta_window_real_tile (MetaWindow *window, diff --git a/src/core/window.c b/src/core/window.c index 3873c88..b179ca3 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -122,8 +122,7 @@ static void update_resize (MetaWindow *window, gboolean snap, int x, int y, - gboolean force, - gboolean done); + gboolean force); static gboolean update_resize_timeout (gpointer data); static gboolean should_be_on_all_workspaces (MetaWindow *window); @@ -677,6 +676,37 @@ maybe_leave_show_desktop_mode (MetaWindow *window) } } +static gboolean +client_window_should_be_mapped (MetaWindow *window) +{ + return !window->shaded; +} + +static void +sync_client_window_mapped (MetaWindow *window) +{ + gboolean should_be_mapped = client_window_should_be_mapped (window); + + g_return_if_fail (!window->override_redirect); + + if (window->mapped == should_be_mapped) + return; + + window->mapped = should_be_mapped; + + meta_error_trap_push (window->display); + if (should_be_mapped) + { + XMapWindow (window->display->xdisplay, window->xwindow); + } + else + { + XUnmapWindow (window->display->xdisplay, window->xwindow); + window->unmaps_pending ++; + } + meta_error_trap_pop (window->display); +} + LOCAL_SYMBOL MetaWindow* meta_window_new (MetaDisplay *display, Window xwindow, @@ -885,10 +915,8 @@ meta_window_new_with_attrs (MetaDisplay *display, && attrs->width == 1 && attrs->height == 1) || xwindow == screen->wm_cm_selection_window || xwindow == screen->guard_window || - (display->compositor && - xwindow == XCompositeGetOverlayWindow (display->xdisplay, - screen->xroot) - ) + xwindow == XCompositeGetOverlayWindow (display->xdisplay, + screen->xroot) ) ) { meta_verbose ("Not managing our own windows\n"); @@ -1429,6 +1457,7 @@ meta_window_new_with_attrs (MetaDisplay *display, } g_signal_emit_by_name (window->screen, "window-entered-monitor", window->monitor->number, window); + g_signal_emit_by_name (window->screen, "window-added", window, window->monitor->number); /* Must add window to stack before doing move/resize, since the * window might have fullscreen size (i.e. should have been @@ -1480,8 +1509,7 @@ meta_window_new_with_attrs (MetaDisplay *display, set_net_wm_state (window); } - if (screen->display->compositor) - meta_compositor_add_window (screen->display->compositor, window); + meta_compositor_add_window (screen->display->compositor, window); /* Sync stack changes */ meta_stack_thaw (window->screen->stack); @@ -1700,14 +1728,11 @@ meta_window_unmanage (MetaWindow *window, meta_verbose ("Unmanaging 0x%lx\n", window->xwindow); - if (window->display->compositor) - { - if (window->visible_to_compositor || meta_window_is_attached_dialog (window)) - meta_compositor_hide_window (window->display->compositor, window, - META_COMP_EFFECT_DESTROY); + if (window->visible_to_compositor || meta_window_is_attached_dialog (window)) + meta_compositor_hide_window (window->display->compositor, window, + META_COMP_EFFECT_DESTROY); - meta_compositor_remove_window (window->display->compositor, window); - } + meta_compositor_remove_window (window->display->compositor, window); if (window->display->window_with_menu == window) { @@ -1823,12 +1848,6 @@ meta_window_unmanage (MetaWindow *window, window->tile_type != META_WINDOW_TILE_TYPE_NONE) unmaximize_window_before_freeing (window); - /* The XReparentWindow call in meta_window_destroy_frame() moves the - * window so we need to send a configure notify; see bug 399552. (We - * also do this just in case a window got unmaximized.) - */ - send_configure_notify (window); - meta_window_unqueue (window, META_QUEUE_CALC_SHOWING | META_QUEUE_MOVE_RESIZE | META_QUEUE_UPDATE_ICON); @@ -1865,7 +1884,15 @@ meta_window_unmanage (MetaWindow *window, meta_window_destroy_sync_request_alarm (window); if (window->frame) - meta_window_destroy_frame (window); + { + /* The XReparentWindow call in meta_window_destroy_frame() moves the + * window so we need to send a configure notify; see bug 399552. (We + * also do this just in case a window got unmaximized.) + */ + send_configure_notify (window); + + meta_window_destroy_frame (window); + } /* If an undecorated window is being withdrawn, that will change the * stack as presented to the compositing manager, without actually @@ -1966,7 +1993,10 @@ meta_window_unmanage (MetaWindow *window, meta_prefs_remove_listener (prefs_changed_callback, window); + meta_screen_queue_check_fullscreen (window->screen); + g_signal_emit (window, window_signals[UNMANAGED], 0); + g_signal_emit_by_name (window->screen, "window-removed", window); g_object_unref (window); } @@ -2180,6 +2210,12 @@ set_net_wm_state (MetaWindow *window) XA_CARDINAL, 32, PropModeReplace, (guchar*) data, 8); meta_error_trap_pop (window->display); + } else { + meta_error_trap_push (window->display); + XDeleteProperty (window->display->xdisplay, + window->xwindow, + window->display->atom__NET_WM_WINDOW_TILE_INFO); + meta_error_trap_pop (window->display); } } @@ -2315,7 +2351,7 @@ implement_showing (MetaWindow *window, * so we should place the window even if we're hiding it rather * than showing it. */ - if (!window->placed && meta_prefs_get_live_hidden_windows ()) + if (!window->placed) meta_window_force_placement (window); meta_window_hide (window); @@ -2323,10 +2359,13 @@ implement_showing (MetaWindow *window, else meta_window_show (window); + if (!window->override_redirect) + sync_client_window_mapped (window); + window->pending_compositor_effect = META_COMP_EFFECT_NONE; } -LOCAL_SYMBOL void +static void meta_window_calc_showing (MetaWindow *window) { implement_showing (window, meta_window_should_be_showing (window)); @@ -2570,7 +2609,7 @@ meta_window_queue (MetaWindow *window, guint queuebits) const MetaLaterType window_queue_later_when[NUMBER_OF_QUEUES] = { - META_LATER_BEFORE_REDRAW, /* CALC_SHOWING */ + META_LATER_CALC_SHOWING, /* CALC_SHOWING */ META_LATER_RESIZE, /* MOVE_RESIZE */ META_LATER_BEFORE_REDRAW /* UPDATE_ICON */ }; @@ -2902,108 +2941,6 @@ window_would_be_covered (const MetaWindow *newbie) return FALSE; /* none found */ } -static gboolean -map_frame (MetaWindow *window) -{ - if (window->frame && !window->frame->mapped) - { - meta_topic (META_DEBUG_WINDOW_STATE, - "Frame actually needs map\n"); - window->frame->mapped = TRUE; - meta_ui_map_frame (window->screen->ui, window->frame->xwindow); - return TRUE; - } - else - return FALSE; -} - -static gboolean -unmap_frame (MetaWindow *window) -{ - if (window->frame && window->frame->mapped) - { - meta_topic (META_DEBUG_WINDOW_STATE, "Frame actually needs unmap\n"); - window->frame->mapped = FALSE; - meta_ui_unmap_frame (window->screen->ui, window->frame->xwindow); - return TRUE; - } - else - return FALSE; -} - -static gboolean -map_client_window (MetaWindow *window) -{ - if (!window->mapped) - { - meta_topic (META_DEBUG_WINDOW_STATE, - "%s actually needs map\n", window->desc); - window->mapped = TRUE; - meta_error_trap_push (window->display); - XMapWindow (window->display->xdisplay, window->xwindow); - meta_error_trap_pop (window->display); - - return TRUE; - } - else - return FALSE; -} - -static gboolean -unmap_client_window (MetaWindow *window, - const char *reason) -{ - if (window->mapped) - { - meta_topic (META_DEBUG_WINDOW_STATE, - "%s actually needs unmap%s\n", - window->desc, reason); - meta_topic (META_DEBUG_WINDOW_STATE, - "Incrementing unmaps_pending on %s%s\n", - window->desc, reason); - window->mapped = FALSE; - window->unmaps_pending += 1; - meta_error_trap_push (window->display); - XUnmapWindow (window->display->xdisplay, window->xwindow); - meta_error_trap_pop (window->display); - - return TRUE; - } - else - return FALSE; -} - -/** - * meta_window_is_mapped: - * @window: a #MetaWindow - * - * Determines whether the X window for the MetaWindow is mapped. - */ -gboolean -meta_window_is_mapped (MetaWindow *window) -{ - return window->mapped; -} - -/** - * meta_window_toplevel_is_mapped: - * @window: a #MetaWindow - * - * Determines whether the toplevel X window for the MetaWindow is - * mapped. (The frame window is mapped even without the client window - * when a window is shaded.) - * - * Return Value: %TRUE if the toplevel is mapped. - */ -gboolean -meta_window_toplevel_is_mapped (MetaWindow *window) -{ - /* The frame is mapped but not the client window when the window - * is shaded. - */ - return window->mapped || (window->frame && window->frame->mapped); -} - static void meta_window_force_placement (MetaWindow *window) { @@ -3042,16 +2979,12 @@ meta_window_show (MetaWindow *window) gboolean place_on_top_on_map; gboolean needs_stacking_adjustment; MetaWindow *focus_window; - gboolean toplevel_was_mapped; - gboolean toplevel_now_mapped; gboolean notify_demands_attention = FALSE; meta_topic (META_DEBUG_WINDOW_STATE, "Showing window %s, shaded: %d iconic: %d placed: %d\n", window->desc, window->shaded, window->iconic, window->placed); - toplevel_was_mapped = meta_window_toplevel_is_mapped (window); - focus_window = window->display->focus_window; /* May be NULL! */ did_show = FALSE; window_state_on_map (window, &takes_focus_on_map, &place_on_top_on_map); @@ -3167,74 +3100,40 @@ meta_window_show (MetaWindow *window) } } - /* Shaded means the frame is mapped but the window is not */ - - if (map_frame (window)) - did_show = TRUE; - - if (window->shaded) + if (window->hidden) { - unmap_client_window (window, " (shading)"); - - if (!window->iconic) - { - window->iconic = TRUE; - set_wm_state (window, IconicState); - } - } - else - { - if (map_client_window (window)) - did_show = TRUE; - - if (meta_prefs_get_live_hidden_windows ()) - { - if (window->hidden) - { - meta_stack_freeze (window->screen->stack); - window->hidden = FALSE; - meta_stack_thaw (window->screen->stack); - did_show = TRUE; - } - } - - if (window->iconic) - { - window->iconic = FALSE; - set_wm_state (window, NormalState); - } + meta_stack_freeze (window->screen->stack); + window->hidden = FALSE; + meta_stack_thaw (window->screen->stack); + did_show = TRUE; } - toplevel_now_mapped = meta_window_toplevel_is_mapped (window); - if (toplevel_now_mapped != toplevel_was_mapped) + if (window->iconic) { - if (window->display->compositor) - meta_compositor_window_mapped (window->display->compositor, window); + window->iconic = FALSE; + set_wm_state (window, NormalState); } if (!window->visible_to_compositor) { window->visible_to_compositor = TRUE; - if (window->display->compositor) - { - MetaCompEffect effect = META_COMP_EFFECT_NONE; + MetaCompEffect effect = META_COMP_EFFECT_NONE; - switch (window->pending_compositor_effect) - { - case META_COMP_EFFECT_CREATE: - case META_COMP_EFFECT_UNMINIMIZE: - effect = window->pending_compositor_effect; - break; - case META_COMP_EFFECT_NONE: - case META_COMP_EFFECT_DESTROY: - case META_COMP_EFFECT_MINIMIZE: - break; - } - - meta_compositor_show_window (window->display->compositor, - window, effect); + switch (window->pending_compositor_effect) + { + case META_COMP_EFFECT_CREATE: + case META_COMP_EFFECT_UNMINIMIZE: + effect = window->pending_compositor_effect; + break; + case META_COMP_EFFECT_NONE: + case META_COMP_EFFECT_DESTROY: + case META_COMP_EFFECT_MINIMIZE: + break; } + + meta_compositor_show_window (window->display->compositor, + window, effect); } /* We don't want to worry about all cases from inside @@ -3282,6 +3181,9 @@ meta_window_show (MetaWindow *window) invalidate_work_areas (window); } + if (did_show) + meta_screen_queue_check_fullscreen (window->screen); + /* * Now that we have shown the window, we no longer want to consider the * initial timestamp in any subsequent deliberations whether to focus this @@ -3303,67 +3205,41 @@ static void meta_window_hide (MetaWindow *window) { gboolean did_hide; - gboolean toplevel_was_mapped; - gboolean toplevel_now_mapped; meta_topic (META_DEBUG_WINDOW_STATE, "Hiding window %s\n", window->desc); - toplevel_was_mapped = meta_window_toplevel_is_mapped (window); - if (window->visible_to_compositor) { window->visible_to_compositor = FALSE; - if (window->display->compositor) - { - MetaCompEffect effect = META_COMP_EFFECT_NONE; - - switch (window->pending_compositor_effect) - { - case META_COMP_EFFECT_CREATE: - case META_COMP_EFFECT_UNMINIMIZE: - case META_COMP_EFFECT_NONE: - break; - case META_COMP_EFFECT_DESTROY: - case META_COMP_EFFECT_MINIMIZE: - effect = window->pending_compositor_effect; - break; - } + MetaCompEffect effect = META_COMP_EFFECT_NONE; - meta_compositor_hide_window (window->display->compositor, - window, effect); + switch (window->pending_compositor_effect) + { + case META_COMP_EFFECT_CREATE: + case META_COMP_EFFECT_UNMINIMIZE: + case META_COMP_EFFECT_NONE: + break; + case META_COMP_EFFECT_DESTROY: + case META_COMP_EFFECT_MINIMIZE: + effect = window->pending_compositor_effect; + break; } + + meta_compositor_hide_window (window->display->compositor, + window, effect); } did_hide = FALSE; - if (meta_prefs_get_live_hidden_windows ()) + if (!window->hidden) { - /* If this is the first time that we've calculating the showing - * state of the window, the frame and client window might not - * yet be mapped, so we need to map them now */ - map_frame (window); - map_client_window (window); - - if (!window->hidden) - { - meta_stack_freeze (window->screen->stack); - window->hidden = TRUE; - meta_stack_thaw (window->screen->stack); + meta_stack_freeze (window->screen->stack); + window->hidden = TRUE; + meta_stack_thaw (window->screen->stack); - did_hide = TRUE; - } - } - else - { - /* Unmapping the frame is enough to make the window disappear, - * but we need to hide the window itself so the client knows - * it has been hidden */ - if (unmap_frame (window)) - did_hide = TRUE; - if (unmap_client_window (window, " (hiding)")) - did_hide = TRUE; + did_hide = TRUE; } if (!window->iconic) @@ -3372,19 +3248,6 @@ meta_window_hide (MetaWindow *window) set_wm_state (window, IconicState); } - toplevel_now_mapped = meta_window_toplevel_is_mapped (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); - } - } - set_net_wm_state (window); if (did_hide && window->struts) @@ -3424,6 +3287,9 @@ meta_window_hide (MetaWindow *window) not_this_one, timestamp); } + + if (did_hide) + meta_screen_queue_check_fullscreen (window->screen); } static gboolean @@ -3595,7 +3461,7 @@ meta_window_maximize_internal (MetaWindow *window, maximize_vertically = directions & META_MAXIMIZE_VERTICAL; g_assert (maximize_horizontally || maximize_vertically); -meta_topic (META_DEBUG_WINDOW_OPS, + meta_topic (META_DEBUG_WINDOW_OPS, "Maximizing %s%s\n", window->desc, maximize_horizontally && maximize_vertically ? "" : @@ -3625,6 +3491,9 @@ meta_topic (META_DEBUG_WINDOW_OPS, recalc_window_features (window); set_net_wm_state (window); + if (window->monitor->in_fullscreen) + meta_screen_queue_check_fullscreen (window->screen); + g_object_freeze_notify (G_OBJECT (window)); g_object_notify (G_OBJECT (window), "maximized-horizontally"); g_object_notify (G_OBJECT (window), "maximized-vertically"); @@ -3674,43 +3543,35 @@ meta_window_maximize (MetaWindow *window, return; } - if ((window->tile_mode != META_TILE_NONE || - window->last_tile_mode != META_TILE_NONE) && - window->tile_mode != META_TILE_MAXIMIZE) - { - saved_rect = &window->saved_rect; + if ((window->tile_mode != META_TILE_NONE || + window->last_tile_mode != META_TILE_NONE) && + window->tile_mode != META_TILE_MAXIMIZE) + { + saved_rect = &window->saved_rect; - window->maximized_vertically = FALSE; - } + window->maximized_vertically = FALSE; + } - meta_window_maximize_internal (window, - directions, - saved_rect); + meta_window_maximize_internal (window, + directions, + saved_rect); - if (window->display->compositor) - { - MetaRectangle old_rect; - MetaRectangle new_rect; + MetaRectangle old_rect; + MetaRectangle new_rect; - meta_window_get_outer_rect (window, &old_rect); + meta_window_get_outer_rect (window, &old_rect); - meta_window_move_resize_now (window); + meta_window_move_resize_now (window); - meta_window_get_outer_rect (window, &new_rect); - meta_compositor_maximize_window (window->display->compositor, - window, - &old_rect, - &new_rect); - } - else - { - /* move_resize with new maximization constraints - */ - meta_window_queue(window, META_QUEUE_MOVE_RESIZE); - } + meta_window_get_outer_rect (window, &new_rect); + meta_compositor_maximize_window (window->display->compositor, + window, + &old_rect, + &new_rect); } - meta_screen_tile_preview_hide (window->screen); - normalize_tile_state (window); + + meta_screen_tile_preview_hide (window->screen); + normalize_tile_state (window); } /** @@ -3739,6 +3600,42 @@ meta_window_is_fullscreen (MetaWindow *window) return window->fullscreen; } +/** + * meta_window_get_all_monitors: + * @window: The #MetaWindow + * @length: (out caller-allocates): gint holding the length, may be %NULL to + * ignore + * + * Returns: (array length=length) (element-type gint) (transfer container): + * List of the monitor indices the window is on. + */ +gint * +meta_window_get_all_monitors (MetaWindow *window, gsize *length) +{ + GArray *monitors; + MetaRectangle window_rect; + int i; + + monitors = g_array_new (FALSE, FALSE, sizeof (int)); + meta_window_get_outer_rect (window, &window_rect); + + for (i = 0; i < window->screen->n_monitor_infos; i++) + { + MetaRectangle *monitor_rect = &window->screen->monitor_infos[i].rect; + + if (meta_rectangle_overlap (&window_rect, monitor_rect)) + g_array_append_val (monitors, i); + } + + if (length) + *length = monitors->len; + + i = -1; + g_array_append_val (monitors, i); + + return (gint*) g_array_free (monitors, FALSE); +} + /** * meta_window_is_monitor_sized: * @@ -3836,8 +3733,8 @@ meta_window_real_tile (MetaWindow *window, gboolean force) meta_window_save_rect (window); } - window->maximized_horizontally = FALSE; - window->maximized_vertically = FALSE; + window->maximized_horizontally = FALSE || window->tile_mode == META_TILE_MAXIMIZE; + window->maximized_vertically = FALSE || window->tile_mode == META_TILE_MAXIMIZE; if (window->tile_mode != META_TILE_NONE) { if (window->snap_queued || window->resizing_tile_type == META_WINDOW_TILE_TYPE_SNAPPED) { @@ -3850,13 +3747,10 @@ meta_window_real_tile (MetaWindow *window, gboolean force) } recalc_window_features (window); - set_net_wm_state (window); - - normalize_tile_state (window); meta_screen_tile_preview_update (window->screen, FALSE); - if (window->display->compositor) + if (window->resize_tile_mode == META_TILE_NONE) { MetaRectangle old_rect; MetaRectangle new_rect; @@ -3881,6 +3775,10 @@ meta_window_real_tile (MetaWindow *window, gboolean force) meta_window_queue (window, META_QUEUE_MOVE_RESIZE); } + normalize_tile_state (window); + + set_net_wm_state (window); + meta_screen_tile_preview_hide (window->screen); meta_window_get_outer_rect (window, &window->snapped_rect); @@ -4019,12 +3917,17 @@ meta_window_unmaximize_internal (MetaWindow *window, */ if ((unmaximize_horizontally && window->maximized_horizontally) || (unmaximize_vertically && window->maximized_vertically) || - window->tile_type != META_WINDOW_TILE_TYPE_NONE || + window->tile_type == META_WINDOW_TILE_TYPE_NONE || window->tile_mode == META_TILE_NONE) { MetaRectangle target_rect; MetaRectangle work_area; + window->last_tile_mode = META_TILE_NONE; + window->tile_mode = META_TILE_NONE; + window->resizing_tile_type = META_WINDOW_TILE_TYPE_NONE; + window->tile_type = META_WINDOW_TILE_TYPE_NONE; + meta_window_get_work_area_for_monitor (window, window->monitor->number, &work_area); meta_topic (META_DEBUG_WINDOW_OPS, @@ -4060,11 +3963,11 @@ meta_window_unmaximize_internal (MetaWindow *window, */ ensure_size_hints_satisfied (&target_rect, &window->size_hints); - if (window->display->compositor && window->resizing_tile_type == META_WINDOW_TILE_TYPE_NONE) + if (window->resizing_tile_type == META_WINDOW_TILE_TYPE_NONE) { MetaRectangle old_rect, new_rect; - meta_window_get_outer_rect (window, &old_rect); + meta_window_get_outer_rect (window, &old_rect); meta_window_move_resize_internal (window, META_IS_MOVE_ACTION | META_IS_RESIZE_ACTION, @@ -4074,11 +3977,11 @@ meta_window_unmaximize_internal (MetaWindow *window, target_rect.width, target_rect.height); - meta_window_get_outer_rect (window, &new_rect); + meta_window_get_outer_rect (window, &new_rect); meta_compositor_unmaximize_window (window->display->compositor, - window, + window, &old_rect, - &new_rect); + &new_rect); } else { @@ -4119,6 +4022,8 @@ meta_window_unmaximize_internal (MetaWindow *window, recalc_window_features (window); set_net_wm_state (window); + if (!window->monitor->in_fullscreen) + meta_screen_queue_check_fullscreen (window->screen); } g_object_freeze_notify (G_OBJECT (window)); @@ -4232,6 +4137,9 @@ meta_window_make_fullscreen_internal (MetaWindow *window) recalc_window_features (window); set_net_wm_state (window); + /* For the auto-minimize feature, if we fail to get focus */ + meta_screen_queue_check_fullscreen (window->screen); + meta_stack_tracker_queue_sync_stack (window->screen->stack_tracker); g_object_notify (G_OBJECT (window), "fullscreen"); } @@ -4773,8 +4681,7 @@ sync_request_timeout (gpointer data) window->display->grab_last_user_action_was_snap, window->display->grab_latest_motion_x, window->display->grab_latest_motion_y, - TRUE, - FALSE); + TRUE); } return FALSE; @@ -4962,6 +4869,8 @@ meta_window_update_monitor (MetaWindow *window) g_signal_emit_by_name (window->screen, "window-left-monitor", old->number, window); g_signal_emit_by_name (window->screen, "window-entered-monitor", window->monitor->number, window); + g_signal_emit_by_name (window->screen, "window-monitor-changed", window, window->monitor->number); + /* If we're changing monitors, we need to update the has_maximize_func flag, * as the working area has changed. */ recalc_window_features (window); @@ -5037,9 +4946,7 @@ meta_window_move_resize_internal (MetaWindow *window, MetaRectangle new_rect; MetaRectangle old_rect; - if (!window->type == META_WINDOW_TOOLTIP) { - g_return_if_fail (!window->override_redirect); - } + g_return_if_fail (!window->override_redirect); is_configure_request = (flags & META_IS_CONFIGURE_REQUEST) != 0; do_gravity_adjust = (flags & META_DO_GRAVITY_ADJUST) != 0; @@ -5424,10 +5331,9 @@ meta_window_move_resize_internal (MetaWindow *window, newx, newy, window->rect.width, window->rect.height, window->user_rect.x, window->user_rect.y, window->user_rect.width, window->user_rect.height); - if (window->display->compositor) - meta_compositor_sync_window_geometry (window->display->compositor, - window, - did_placement); + meta_compositor_sync_window_geometry (window->display->compositor, + window, + did_placement); } else { @@ -5505,9 +5411,7 @@ meta_window_move (MetaWindow *window, { MetaMoveResizeFlags flags; - if (!window->type == META_WINDOW_TOOLTIP) { - g_return_if_fail (!window->override_redirect); - } + g_return_if_fail (!window->override_redirect); flags = (user_op ? META_IS_USER_ACTION : 0) | META_IS_MOVE_ACTION; @@ -5761,11 +5665,16 @@ meta_window_configure_notify (MetaWindow *window, window->rect.height = event->height; meta_window_update_monitor (window); + /* Whether an override-redirect window is considered fullscreen depends + * on its geometry. + */ + if (window->override_redirect) + meta_screen_queue_check_fullscreen (window->screen); + if (!event->override_redirect && !event->send_event) meta_warning ("Unhandled change of windows override redirect status\n"); - if (window->display->compositor) - meta_compositor_sync_window_geometry (window->display->compositor, window, FALSE); + meta_compositor_sync_window_geometry (window->display->compositor, window, FALSE); } LOCAL_SYMBOL void @@ -6195,6 +6104,7 @@ meta_window_change_workspace_without_transients (MetaWindow *window, meta_workspace_add_window (workspace, window); g_signal_emit (window, window_signals[WORKSPACE_CHANGED], 0, old_workspace); + g_signal_emit_by_name (window->screen, "window-workspace-changed", window, window->workspace); } } @@ -7907,7 +7817,7 @@ redraw_icon (MetaWindow *window) /* We could probably be smart and just redraw the icon here, * instead of the whole frame. */ - if (window->frame && (window->mapped || window->frame->mapped)) + if (window->frame) meta_ui_queue_frame_draw (window->screen->ui, window->frame->xwindow); } @@ -8778,6 +8688,12 @@ menu_callback (MetaWindowMenu *menu, break; case META_MENU_OP_RESIZE: + if (window->tile_mode != META_TILE_NONE) + { + window->resize_tile_mode = window->tile_mode; + window->resizing_tile_type = window->tile_type; + } + meta_window_begin_grab_op (window, META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN, TRUE, @@ -9234,8 +9150,6 @@ get_size_limits (const MetaWindow *window, } } - - static void update_move (MetaWindow *window, gboolean legacy_snap, @@ -9642,8 +9556,7 @@ update_resize_timeout (gpointer data) window->display->grab_last_user_action_was_snap, window->display->grab_latest_motion_x, window->display->grab_latest_motion_y, - TRUE, - FALSE); + TRUE); return FALSE; } @@ -9651,8 +9564,7 @@ static void update_resize (MetaWindow *window, gboolean snap, int x, int y, - gboolean force, - gboolean done) + gboolean force) { int dx, dy; int new_w, new_h; @@ -9689,44 +9601,80 @@ update_resize (MetaWindow *window, if (window->display->grab_op == META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN) { - if ((dx > 0) && (dy > 0)) - { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SE; - meta_window_update_keyboard_resize (window, TRUE); - } - else if ((dx < 0) && (dy > 0)) + if (window->tile_mode == META_TILE_NONE) { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SW; - meta_window_update_keyboard_resize (window, TRUE); - } - else if ((dx > 0) && (dy < 0)) - { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NE; - meta_window_update_keyboard_resize (window, TRUE); - } - else if ((dx < 0) && (dy < 0)) - { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NW; - meta_window_update_keyboard_resize (window, TRUE); - } - else if (dx < 0) - { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; - meta_window_update_keyboard_resize (window, TRUE); - } - else if (dx > 0) - { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; - meta_window_update_keyboard_resize (window, TRUE); - } - else if (dy > 0) - { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; - meta_window_update_keyboard_resize (window, TRUE); + if ((dx > 0) && (dy > 0)) + { + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SE; + meta_window_update_keyboard_resize (window, TRUE); + } + else if ((dx < 0) && (dy > 0)) + { + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SW; + meta_window_update_keyboard_resize (window, TRUE); + } + else if ((dx > 0) && (dy < 0)) + { + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NE; + meta_window_update_keyboard_resize (window, TRUE); + } + else if ((dx < 0) && (dy < 0)) + { + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NW; + meta_window_update_keyboard_resize (window, TRUE); + } + else if (dx < 0) + { + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; + meta_window_update_keyboard_resize (window, TRUE); + } + else if (dx > 0) + { + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; + meta_window_update_keyboard_resize (window, TRUE); + } + else if (dy > 0) + { + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; + meta_window_update_keyboard_resize (window, TRUE); + } + else if (dy < 0) + { + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; + meta_window_update_keyboard_resize (window, TRUE); + } } - else if (dy < 0) + else { - window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; + switch (window->tile_mode) + { + case META_TILE_LEFT: + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_E; + break; + case META_TILE_RIGHT: + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_W; + break; + case META_TILE_TOP: + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_S; + break; + case META_TILE_BOTTOM: + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_N; + break; + case META_TILE_ULC: + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SE; + break; + case META_TILE_LLC: + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NE; + break; + case META_TILE_URC: + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_SW; + break; + case META_TILE_LRC: + window->display->grab_op = META_GRAB_OP_KEYBOARD_RESIZING_NW; + break; + default: + break; + } meta_window_update_keyboard_resize (window, TRUE); } } @@ -9741,7 +9689,8 @@ update_resize (MetaWindow *window, case META_GRAB_OP_KEYBOARD_RESIZING_SE: case META_GRAB_OP_KEYBOARD_RESIZING_NE: case META_GRAB_OP_KEYBOARD_RESIZING_E: - new_w += dx; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_RIGHT)) + new_w += dx; break; case META_GRAB_OP_RESIZING_NW: @@ -9750,7 +9699,8 @@ update_resize (MetaWindow *window, case META_GRAB_OP_KEYBOARD_RESIZING_NW: case META_GRAB_OP_KEYBOARD_RESIZING_SW: case META_GRAB_OP_KEYBOARD_RESIZING_W: - new_w -= dx; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_LEFT)) + new_w -= dx; break; default: break; @@ -9764,7 +9714,8 @@ update_resize (MetaWindow *window, case META_GRAB_OP_KEYBOARD_RESIZING_SE: case META_GRAB_OP_KEYBOARD_RESIZING_S: case META_GRAB_OP_KEYBOARD_RESIZING_SW: - new_h += dy; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_DOWN)) + new_h += dy; break; case META_GRAB_OP_RESIZING_N: @@ -9773,7 +9724,8 @@ update_resize (MetaWindow *window, case META_GRAB_OP_KEYBOARD_RESIZING_N: case META_GRAB_OP_KEYBOARD_RESIZING_NE: case META_GRAB_OP_KEYBOARD_RESIZING_NW: - new_h -= dy; + if (meta_window_resize_or_move_allowed (window, META_DIRECTION_UP)) + new_h -= dy; break; default: break; @@ -9821,11 +9773,15 @@ update_resize (MetaWindow *window, { case META_GRAB_OP_RESIZING_S: case META_GRAB_OP_RESIZING_N: + case META_GRAB_OP_KEYBOARD_RESIZING_S: + case META_GRAB_OP_KEYBOARD_RESIZING_N: new_w = old.width; break; case META_GRAB_OP_RESIZING_E: case META_GRAB_OP_RESIZING_W: + case META_GRAB_OP_KEYBOARD_RESIZING_E: + case META_GRAB_OP_KEYBOARD_RESIZING_W: new_h = old.height; break; @@ -9834,7 +9790,11 @@ update_resize (MetaWindow *window, } /* compute gravity of client during operation */ - gravity = meta_resize_gravity_from_grab_op (window->display->grab_op); + if (window->tile_mode != META_TILE_NONE) + gravity = meta_resize_gravity_from_tile_mode (window->tile_mode); + else + gravity = meta_resize_gravity_from_grab_op (window->display->grab_op); + g_assert (gravity >= 0); /* Do any edge resistance/snapping */ @@ -9860,19 +9820,24 @@ update_resize (MetaWindow *window, } else { - if ((new_unmaximize & ~window->display->grab_resize_unmaximize) != 0 || window->tile_type != META_WINDOW_TILE_TYPE_NONE) + if ((new_unmaximize & ~window->display->grab_resize_unmaximize) != 0) { - if (window->resizing_tile_type == META_WINDOW_TILE_TYPE_NONE) - window->resizing_tile_type = window->tile_type; - if (window->tile_mode != META_TILE_NONE) { - window->resize_tile_mode = window->tile_mode; - } - meta_window_unmaximize_with_gravity (window, (new_unmaximize & ~window->display->grab_resize_unmaximize), new_w, new_h, gravity); } + if (window->tile_type != META_WINDOW_TILE_TYPE_NONE) + { + if (window->tile_mode != META_TILE_NONE) + { + window->resize_tile_mode = window->tile_mode; + window->resizing_tile_type = window->tile_type; + } + + meta_window_resize_with_gravity (window, TRUE, new_w, new_h, gravity); + } + if (window->resizing_tile_type == META_WINDOW_TILE_TYPE_NONE && (window->display->grab_resize_unmaximize & ~new_unmaximize)) { MetaRectangle saved_rect = window->saved_rect; @@ -9884,15 +9849,6 @@ update_resize (MetaWindow *window, window->display->grab_resize_unmaximize = new_unmaximize; /* Store the latest resize time, if we actually resized. */ - if (done) { - if (window->resizing_tile_type != META_WINDOW_TILE_TYPE_NONE) { - window->snap_queued = window->resizing_tile_type == META_WINDOW_TILE_TYPE_SNAPPED; - window->tile_mode = window->resize_tile_mode; - window->custom_snap_size = TRUE; - meta_window_real_tile (window, TRUE); - } - } - if (window->rect.width != old.width || window->rect.height != old.height) g_get_current_time (&window->display->grab_last_moveresize_time); @@ -10032,8 +9988,7 @@ meta_window_update_sync_request_counter (MetaWindow *window, window->display->grab_last_user_action_was_snap, window->display->grab_latest_motion_x, window->display->grab_latest_motion_y, - TRUE, - FALSE); + TRUE); } /* If sync was previously disabled, turn it back on and hope @@ -10091,8 +10046,7 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, window->display->grab_last_user_action_was_snap, window->display->grab_latest_motion_x, window->display->grab_latest_motion_y, - TRUE, - FALSE); + TRUE); break; default: @@ -10141,7 +10095,6 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, event->xbutton.state & ShiftMask, event->xbutton.x_root, event->xbutton.y_root, - TRUE, TRUE); /* If a tiled window has been dragged free with a @@ -10186,7 +10139,6 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, event->xmotion.state & ShiftMask, event->xmotion.x_root, event->xmotion.y_root, - FALSE, FALSE); } } diff --git a/src/core/workspace-private.h b/src/core/workspace-private.h index 2cc3918..5ac70d6 100644 --- a/src/core/workspace-private.h +++ b/src/core/workspace-private.h @@ -98,10 +98,6 @@ GList* meta_workspace_get_onscreen_region (MetaWorkspace *workspace); GList* meta_workspace_get_onmonitor_region (MetaWorkspace *workspace, int which_monitor); -void meta_workspace_focus_default_window (MetaWorkspace *workspace, - MetaWindow *not_this_one, - guint32 timestamp); - MetaWorkspace* meta_workspace_get_neighbor (MetaWorkspace *workspace, MetaMotionDirection direction); diff --git a/src/core/workspace.c b/src/core/workspace.c index 4d37d90..0e81bef 100644 --- a/src/core/workspace.c +++ b/src/core/workspace.c @@ -517,29 +517,64 @@ workspace_switch_sound(MetaWorkspace *from, #endif /* HAVE_LIBCANBERRA */ } -/** - * meta_workspace_activate_with_focus: - * @workspace: a #MetaWorkspace - * @focus_this: the #MetaWindow to be focused, or %NULL - * @timestamp: timestamp for @focus_this - * - * Switches to @workspace and possibly activates the window @focus_this. - * - * The window @focus_this is activated by calling meta_window_activate() - * which will unminimize it and transient parents, raise it and give it - * the focus. - * - * If a window is currently being moved by the user, it will be - * moved to @workspace. - * - * The advantage of calling this function instead of meta_workspace_activate() - * followed by meta_window_activate() is that it happens as a unit, so - * no other window gets focused first before @focus_this. - */ -void -meta_workspace_activate_with_focus (MetaWorkspace *workspace, - MetaWindow *focus_this, - guint32 timestamp) +static MetaMotionDirection +get_wrapped_horizontal_direction (gint from, + gint to, + MetaMotionDirection suggested_dir, + gint num_workspaces) +{ + MetaMotionDirection ret = 0; + gboolean wrap = meta_prefs_get_workspace_cycle(); + + if (suggested_dir != 0 && wrap) + { + if (meta_ui_get_direction () == META_UI_DIRECTION_RTL) + { + if (suggested_dir == META_MOTION_LEFT) + suggested_dir = META_MOTION_RIGHT; + else + if (suggested_dir == META_MOTION_RIGHT) + suggested_dir = META_MOTION_LEFT; + } + + return suggested_dir; + } + + if (meta_ui_get_direction() == META_UI_DIRECTION_RTL) + { + if (from < to) + if (wrap) + ret = (to - from) <= ((num_workspaces - to) + from) ? META_MOTION_LEFT : META_MOTION_RIGHT; + else + ret = META_MOTION_LEFT; + else + if (wrap) + ret = (from - to) <= ((num_workspaces - from) + to) ? META_MOTION_RIGHT : META_MOTION_LEFT; + else + ret = META_MOTION_RIGHT; + } + else + { + if (from < to) + if (wrap) + ret = (to - from) <= ((num_workspaces - to) + from) ? META_MOTION_RIGHT : META_MOTION_LEFT; + else + ret = META_MOTION_RIGHT; + else + if (wrap) + ret = (from - to) <= ((num_workspaces - from) + to) ? META_MOTION_LEFT : META_MOTION_RIGHT; + else + ret = META_MOTION_LEFT; + } + + return ret; +} + +static void +meta_workspace_activate_internal (MetaWorkspace *workspace, + MetaWindow *focus_this, + MetaMotionDirection suggested_dir, + guint32 timestamp) { MetaWorkspace *old; MetaWindow *move_window; @@ -629,20 +664,7 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace, meta_screen_calc_workspace_layout (workspace->screen, num_workspaces, new_space, &layout2); - if (meta_ui_get_direction() == META_UI_DIRECTION_RTL) - { - if (layout1.current_col > layout2.current_col) - direction = META_MOTION_RIGHT; - else if (layout1.current_col < layout2.current_col) - direction = META_MOTION_LEFT; - } - else - { - if (layout1.current_col < layout2.current_col) - direction = META_MOTION_RIGHT; - else if (layout1.current_col > layout2.current_col) - direction = META_MOTION_LEFT; - } + direction = get_wrapped_horizontal_direction (layout1.current_col, layout2.current_col, suggested_dir, num_workspaces); if (layout1.current_row < layout2.current_row) { @@ -692,11 +714,55 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace, meta_screen_workspace_switched (screen, current_space, new_space, direction); } +/** + * meta_workspace_activate_with_focus: + * @workspace: a #MetaWorkspace + * @focus_this: the #MetaWindow to be focused, or %NULL + * @timestamp: timestamp for @focus_this + * + * Switches to @workspace and possibly activates the window @focus_this. + * + * The window @focus_this is activated by calling meta_window_activate() + * which will unminimize it and transient parents, raise it and give it + * the focus. + * + * If a window is currently being moved by the user, it will be + * moved to @workspace. + * + * The advantage of calling this function instead of meta_workspace_activate() + * followed by meta_window_activate() is that it happens as a unit, so + * no other window gets focused first before @focus_this. + */ +void +meta_workspace_activate_with_focus (MetaWorkspace *workspace, + MetaWindow *focus_this, + guint32 timestamp) +{ + meta_workspace_activate_internal (workspace, focus_this, 0, timestamp); +} + void meta_workspace_activate (MetaWorkspace *workspace, guint32 timestamp) { - meta_workspace_activate_with_focus (workspace, NULL, timestamp); + meta_workspace_activate_internal (workspace, NULL, 0, timestamp); +} + +/** + * meta_workspace_activate_with_direction_hint: + * @workspace: a #MetaWorkspace + * @direction: the suggested #MetaMotionDirection + * @timestamp: timestamp for @focus_this + * + * Switches to @workspace in the specified @direction (if possible) + */ + +void +meta_workspace_activate_with_direction_hint (MetaWorkspace *workspace, + MetaMotionDirection direction, + guint32 timestamp) +{ + meta_workspace_activate_internal (workspace, NULL, direction, timestamp); } int @@ -1279,7 +1345,7 @@ meta_workspace_get_name (MetaWorkspace *workspace) return meta_prefs_get_workspace_name (meta_workspace_index (workspace)); } -LOCAL_SYMBOL void +void meta_workspace_focus_default_window (MetaWorkspace *workspace, MetaWindow *not_this_one, guint32 timestamp) diff --git a/src/meta/common.h b/src/meta/common.h index e9812ce..14e7efd 100644 --- a/src/meta/common.h +++ b/src/meta/common.h @@ -62,10 +62,8 @@ typedef enum META_FRAME_ABOVE = 1 << 16, META_FRAME_TILED_LEFT = 1 << 17, META_FRAME_TILED_RIGHT = 1 << 18, - META_FRAME_ALLOWS_VERTICAL_RESIZE = (META_FRAME_ALLOWS_TOP_RESIZE | - META_FRAME_ALLOWS_BOTTOM_RESIZE), - META_FRAME_ALLOWS_HORIZONTAL_RESIZE = (META_FRAME_ALLOWS_LEFT_RESIZE | - META_FRAME_ALLOWS_RIGHT_RESIZE) + META_FRAME_ALLOWS_VERTICAL_RESIZE = (META_FRAME_ALLOWS_TOP_RESIZE | META_FRAME_ALLOWS_BOTTOM_RESIZE), + META_FRAME_ALLOWS_HORIZONTAL_RESIZE = (META_FRAME_ALLOWS_LEFT_RESIZE | META_FRAME_ALLOWS_RIGHT_RESIZE) } MetaFrameFlags; typedef enum @@ -299,6 +297,13 @@ typedef enum { META_WINDOW_TILE_TYPE_SNAPPED } MetaWindowTileType; +typedef enum { + META_BELL_TYPE_NONE, + META_BELL_TYPE_STICKY_KEYS, + META_BELL_TYPE_SLOW_KEYS, + META_BELL_TYPE_BOUNCE_KEYS +} MetaBellType; + #define MAX_BUTTONS_PER_CORNER META_BUTTON_FUNCTION_LAST typedef struct _MetaButtonLayout MetaButtonLayout; diff --git a/src/meta/compositor.h b/src/meta/compositor.h index e0c635f..2c995da 100644 --- a/src/meta/compositor.h +++ b/src/meta/compositor.h @@ -106,15 +106,6 @@ gboolean meta_compositor_process_event (MetaCompositor *compositor, * the visible state. The window is resized *before* the call, so * it may be necessary to readjust the display based on the old_rect * to start the animation. - * - * window_mapped() and 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 show_window() - * is called and will not be unmapped until after hide_window() is - * called. If the live_hidden_windows preference is set, windows will - * never be unmapped. */ void meta_compositor_add_window (MetaCompositor *compositor, @@ -143,10 +134,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); diff --git a/src/meta/prefs.h b/src/meta/prefs.h index cadd39a..b1f6845 100644 --- a/src/meta/prefs.h +++ b/src/meta/prefs.h @@ -60,14 +60,13 @@ typedef enum META_PREF_VISUAL_BELL, META_PREF_AUDIBLE_BELL, META_PREF_VISUAL_BELL_TYPE, - META_PREF_GNOME_ACCESSIBILITY, META_PREF_GNOME_ANIMATIONS, META_PREF_CURSOR_THEME, META_PREF_CURSOR_SIZE, META_PREF_RESIZE_WITH_RIGHT_BUTTON, META_PREF_EDGE_TILING, META_PREF_FORCE_FULLSCREEN, - META_PREF_LIVE_HIDDEN_WINDOWS, + META_PREF_EDGE_RESISTANCE_WINDOW, META_PREF_WORKSPACES_ONLY_ON_PRIMARY, META_PREF_DRAGGABLE_BORDER_WIDTH, META_PREF_TILE_HUD_THRESHOLD, @@ -120,6 +119,7 @@ int meta_prefs_get_auto_raise_delay (void); gboolean meta_prefs_get_gnome_accessibility (void); gboolean meta_prefs_get_gnome_animations (void); gboolean meta_prefs_get_edge_tiling (void); +gboolean meta_prefs_get_edge_resistance_window (void); const char* meta_prefs_get_screenshot_command (void); @@ -155,9 +155,6 @@ void meta_prefs_set_compositing_manager (gboolean whether); void meta_prefs_set_force_fullscreen (gboolean whether); -gboolean meta_prefs_get_live_hidden_windows (void); -void meta_prefs_set_live_hidden_windows (gboolean whether); - gboolean meta_prefs_get_workspaces_only_on_primary (void); int meta_prefs_get_draggable_border_width (void); diff --git a/src/meta/screen.h b/src/meta/screen.h index a1547ec..7e536ce 100644 --- a/src/meta/screen.h +++ b/src/meta/screen.h @@ -90,6 +90,9 @@ void meta_screen_get_monitor_geometry (MetaScreen *screen, int monitor, MetaRectangle *geometry); +gboolean meta_screen_get_monitor_in_fullscreen (MetaScreen *screen, + int monitor); + int meta_screen_get_monitor_index_for_rect (MetaScreen *screen, MetaRectangle *rect); diff --git a/src/meta/util.h b/src/meta/util.h index a2c3b9a..66a3ab3 100644 --- a/src/meta/util.h +++ b/src/meta/util.h @@ -140,12 +140,18 @@ GPid meta_show_dialog (const char *type, * MetaLaterType: * @META_LATER_RESIZE: call in a resize processing phase that is done * before GTK+ repainting (including window borders) is done. + * @META_LATER_CALC_SHOWING: used by Muffin to compute which windows should be mapped + * @META_LATER_CHECK_FULLSCREEN: used by Muffin to see if there's a fullscreen window + * @META_LATER_SYNC_STACK: used by Muffin to send it's idea of the stacking order to the server * @META_LATER_BEFORE_REDRAW: call before the stage is redrawn * @META_LATER_IDLE: call at a very low priority (can be blocked * by running animations or redrawing applications) **/ typedef enum { META_LATER_RESIZE, + META_LATER_CALC_SHOWING, + META_LATER_CHECK_FULLSCREEN, + META_LATER_SYNC_STACK, META_LATER_BEFORE_REDRAW, META_LATER_IDLE } MetaLaterType; diff --git a/src/meta/window.h b/src/meta/window.h index bef05d3..724feb9 100644 --- a/src/meta/window.h +++ b/src/meta/window.h @@ -143,6 +143,7 @@ MetaMaximizeFlags meta_window_get_maximized (MetaWindow *window); gboolean meta_window_is_fullscreen (MetaWindow *window); gboolean meta_window_is_monitor_sized (MetaWindow *window); gboolean meta_window_is_on_primary_monitor (MetaWindow *window); +gint *meta_window_get_all_monitors (MetaWindow *window, gsize *length); gboolean meta_window_is_demanding_attention (MetaWindow *window); gboolean meta_window_is_urgent (MetaWindow *window); @@ -150,8 +151,6 @@ gboolean meta_window_is_urgent (MetaWindow *window); gboolean meta_window_requested_bypass_compositor (MetaWindow *window); gboolean meta_window_requested_dont_bypass_compositor (MetaWindow *window); -gboolean meta_window_is_mapped (MetaWindow *window); -gboolean meta_window_toplevel_is_mapped (MetaWindow *window); gboolean meta_window_get_icon_geometry (MetaWindow *window, MetaRectangle *rect); void meta_window_set_icon_geometry (MetaWindow *window, diff --git a/src/meta/workspace.h b/src/meta/workspace.h index 1cbd86f..58fa122 100644 --- a/src/meta/workspace.h +++ b/src/meta/workspace.h @@ -57,6 +57,9 @@ void meta_workspace_activate (MetaWorkspace *workspace, guint32 timestamp); void meta_workspace_activate_with_focus (MetaWorkspace *workspace, MetaWindow *focus_this, guint32 timestamp); +void meta_workspace_activate_with_direction_hint (MetaWorkspace *workspace, + MetaMotionDirection direction, + guint32 timestamp); void meta_workspace_update_window_hints (MetaWorkspace *workspace); void meta_workspace_set_builtin_struts (MetaWorkspace *workspace, @@ -64,4 +67,8 @@ void meta_workspace_set_builtin_struts (MetaWorkspace *workspace, MetaWorkspace *meta_workspace_get_neighbor (MetaWorkspace *workspace, MetaMotionDirection direction); +void meta_workspace_focus_default_window (MetaWorkspace *workspace, + MetaWindow *not_this_one, + guint32 timestamp); + #endif diff --git a/src/org.cinnamon.muffin.gschema.xml.in b/src/org.cinnamon.muffin.gschema.xml.in index d9aa5ad..d1d0a5d 100644 --- a/src/org.cinnamon.muffin.gschema.xml.in +++ b/src/org.cinnamon.muffin.gschema.xml.in @@ -19,16 +19,6 @@ - - false - <_summary>Live Hidden Windows - <_description> - Determines whether hidden windows (i.e., minimized windows and - windows on other workspaces than the current one) should be kept - alive. - - - true <_summary>Enable edge tiling and snapping @@ -38,6 +28,12 @@ + + true + Enable windows edge resitance + Determine whether the window edges can snap to each other. + + false <_summary>Workspaces are managed dynamically diff --git a/src/ui/frames.c b/src/ui/frames.c index 7f12eb6..9afbde5 100644 --- a/src/ui/frames.c +++ b/src/ui/frames.c @@ -47,8 +47,6 @@ static void meta_frames_destroy (GtkWidget *object); static void meta_frames_finalize (GObject *object); static void meta_frames_style_updated (GtkWidget *widget); -static void meta_frames_map (GtkWidget *widget); -static void meta_frames_unmap (GtkWidget *widget); static void meta_frames_update_prelit_control (MetaFrames *frames, MetaUIFrame *frame, @@ -138,9 +136,6 @@ meta_frames_class_init (MetaFramesClass *class) widget_class->style_updated = meta_frames_style_updated; - widget_class->map = meta_frames_map; - widget_class->unmap = meta_frames_unmap; - widget_class->draw = meta_frames_draw; widget_class->destroy_event = meta_frames_destroy_event; widget_class->button_press_event = meta_frames_button_press_event; @@ -642,13 +637,26 @@ LOCAL_SYMBOL MetaFrames* meta_frames_new (int screen_number) { GdkScreen *screen; + MetaFrames *frames; screen = gdk_display_get_screen (gdk_display_get_default (), screen_number); - return g_object_new (META_TYPE_FRAMES, - "screen", screen, - NULL); + frames = g_object_new (META_TYPE_FRAMES, + "screen", screen, + "type", GTK_WINDOW_POPUP, + NULL); + + /* Put the window at an arbitrary offscreen location; the one place + * it can't be is at -100x-100, since the meta_window_new() will + * mistake it for a window created via meta_create_offscreen_window() + * and ignore it, and we need this window to get frame-synchronization + * messages so that GTK+'s style change handling works. + */ + gtk_window_move (GTK_WINDOW (frames), -200, -200); + gtk_window_resize (GTK_WINDOW (frames), 1, 1); + + return frames; } /* In order to use a style with a window it has to be attached to that @@ -761,22 +769,6 @@ meta_frames_unmanage_window (MetaFrames *frames, meta_warning ("Frame 0x%lx not managed, can't unmanage\n", xwindow); } -static void -meta_frames_map (GtkWidget *widget) -{ - /* We override the parent map function to a no-op because we don't - * want to actually show the GDK window. But GTK needs to think that - * the widget is mapped or it won't deliver the events we care about. - */ - gtk_widget_set_mapped (widget, TRUE); -} - -static void -meta_frames_unmap (GtkWidget *widget) -{ - gtk_widget_set_mapped (widget, FALSE); -} - static MetaUIFrame* meta_frames_lookup_window (MetaFrames *frames, Window xwindow) diff --git a/src/ui/theme.c b/src/ui/theme.c index 620815b..b38f25a 100644 --- a/src/ui/theme.c +++ b/src/ui/theme.c @@ -5964,7 +5964,7 @@ meta_gtk_widget_get_font_desc (GtkWidget *widget, g_return_val_if_fail (gtk_widget_get_realized (widget), NULL); style = gtk_widget_get_style_context (widget); - gtk_style_context_get (style, GTK_STATE_FLAG_NORMAL, + gtk_style_context_get (style, gtk_style_context_get_state (style), GTK_STYLE_PROPERTY_FONT, &font_desc, NULL); diff --git a/src/ui/ui.c b/src/ui/ui.c index e05e11d..a242706 100644 --- a/src/ui/ui.c +++ b/src/ui/ui.c @@ -288,9 +288,12 @@ meta_ui_new (Display *xdisplay, g_assert (gdisplay == gdk_display_get_default ()); ui->frames = meta_frames_new (XScreenNumberOfScreen (screen)); - /* This does not actually show any widget. MetaFrames has been hacked so - * that showing it doesn't actually do anything. But we need the flags - * set for GTK to deliver events properly. */ + /* GTK+ needs the frame-sync protocol to work in order to properly + * handle style changes. This means that the dummy widget we create + * to get the style for title bars actually needs to be mapped + * and fully tracked as a MetaWindow. Horrible, but mostly harmless - + * the window is a 1x1 overide redirect window positioned offscreen. + */ gtk_widget_show (GTK_WIDGET (ui->frames)); g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui);