mirror of
https://github.com/brl/mutter.git
synced 2025-06-13 16:59:30 +00:00
Synced with Metacity 2.23.89 (r3800)
Merge commit '51de9ef8605f7a195ef360afb3a504488125611f' into clutter
This commit is contained in:
@ -23,7 +23,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file core/bell.c Ring the bell or flash the screen
|
||||
* \file bell.c Ring the bell or flash the screen
|
||||
*
|
||||
* Sometimes, X programs "ring the bell", whatever that means. Metacity lets
|
||||
* the user configure the bell to be audible or visible (aka visual), and
|
||||
@ -31,13 +31,13 @@
|
||||
* We never get told about audible bells; X handles them just fine by itself.
|
||||
*
|
||||
* Visual bells come in at meta_bell_notify(), which checks we are actually
|
||||
* in visual mode and calls through to meta_bell_visual_notify(). That
|
||||
* in visual mode and calls through to bell_visual_notify(). That
|
||||
* function then checks what kind of visual flash you like, and calls either
|
||||
* meta_bell_flash_fullscreen()-- which calls meta_bell_flash_screen() to do
|
||||
* its work-- or meta_bell_flash_frame(), which flashes the focussed window
|
||||
* using meta_bell_flash_window_frame(), unless there is no such window, in
|
||||
* which case it flashes the screen instead. meta_bell_flash_window_frame()
|
||||
* flashes the frame and calls meta_bell_unflash_frame() as a timeout to
|
||||
* bell_flash_fullscreen()-- which calls bell_flash_screen() to do
|
||||
* its work-- or bell_flash_frame(), which flashes the focussed window
|
||||
* using bell_flash_window_frame(), unless there is no such window, in
|
||||
* which case it flashes the screen instead. bell_flash_window_frame()
|
||||
* flashes the frame and calls bell_unflash_frame() as a timeout to
|
||||
* remove the flash.
|
||||
*
|
||||
* The visual bell was the result of a discussion in Bugzilla here:
|
||||
@ -46,8 +46,6 @@
|
||||
* Several of the functions in this file are ifdeffed out entirely if we are
|
||||
* found not to have the XKB extension, which is required to do these clever
|
||||
* things with bells; some others are entirely no-ops in that case.
|
||||
*
|
||||
* \bug Static functions should not be called meta_*.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
@ -74,7 +72,7 @@
|
||||
* \bug This appears to destroy our current XSync status.
|
||||
*/
|
||||
static void
|
||||
meta_bell_flash_screen (MetaDisplay *display,
|
||||
bell_flash_screen (MetaDisplay *display,
|
||||
MetaScreen *screen)
|
||||
{
|
||||
Window root = screen->xroot;
|
||||
@ -147,7 +145,7 @@ meta_bell_flash_screen (MetaDisplay *display,
|
||||
*/
|
||||
#ifdef HAVE_XKB
|
||||
static void
|
||||
meta_bell_flash_fullscreen (MetaDisplay *display,
|
||||
bell_flash_fullscreen (MetaDisplay *display,
|
||||
XkbAnyEvent *xkb_ev)
|
||||
{
|
||||
XkbBellNotifyEvent *xkb_bell_ev = (XkbBellNotifyEvent *) xkb_ev;
|
||||
@ -158,7 +156,7 @@ meta_bell_flash_fullscreen (MetaDisplay *display,
|
||||
{
|
||||
screen = meta_display_screen_for_xwindow (display, xkb_bell_ev->window);
|
||||
if (screen)
|
||||
meta_bell_flash_screen (display, screen);
|
||||
bell_flash_screen (display, screen);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -166,7 +164,7 @@ meta_bell_flash_fullscreen (MetaDisplay *display,
|
||||
while (screen_list)
|
||||
{
|
||||
screen = (MetaScreen *) screen_list->data;
|
||||
meta_bell_flash_screen (display, screen);
|
||||
bell_flash_screen (display, screen);
|
||||
screen_list = screen_list->next;
|
||||
}
|
||||
}
|
||||
@ -174,7 +172,7 @@ meta_bell_flash_fullscreen (MetaDisplay *display,
|
||||
|
||||
/**
|
||||
* Makes a frame be not flashed; this is the timeout half of
|
||||
* meta_bell_flash_window_frame(). This is done simply by clearing the
|
||||
* 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.
|
||||
@ -183,11 +181,11 @@ meta_bell_flash_fullscreen (MetaDisplay *display,
|
||||
* a callback function.
|
||||
* \return Always FALSE, so we don't get called again.
|
||||
*
|
||||
* \bug This is the parallel to meta_bell_flash_window_frame(), so it should
|
||||
* \bug This is the parallel to bell_flash_window_frame(), so it should
|
||||
* really be called meta_bell_unflash_window_frame().
|
||||
*/
|
||||
static gboolean
|
||||
meta_bell_unflash_frame (gpointer data)
|
||||
bell_unflash_frame (gpointer data)
|
||||
{
|
||||
MetaFrame *frame = (MetaFrame *) data;
|
||||
frame->is_flashing = 0;
|
||||
@ -207,13 +205,13 @@ meta_bell_unflash_frame (gpointer data)
|
||||
* \param window The window to flash
|
||||
*/
|
||||
static void
|
||||
meta_bell_flash_window_frame (MetaWindow *window)
|
||||
bell_flash_window_frame (MetaWindow *window)
|
||||
{
|
||||
g_assert (window->frame != NULL);
|
||||
window->frame->is_flashing = 1;
|
||||
meta_frame_queue_draw (window->frame);
|
||||
g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 100,
|
||||
meta_bell_unflash_frame, window->frame, NULL);
|
||||
bell_unflash_frame, window->frame, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -224,7 +222,7 @@ meta_bell_flash_window_frame (MetaWindow *window)
|
||||
* \param xkb_ev The bell event we just received
|
||||
*/
|
||||
static void
|
||||
meta_bell_flash_frame (MetaDisplay *display,
|
||||
bell_flash_frame (MetaDisplay *display,
|
||||
XkbAnyEvent *xkb_ev)
|
||||
{
|
||||
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev;
|
||||
@ -238,11 +236,11 @@ meta_bell_flash_frame (MetaDisplay *display,
|
||||
}
|
||||
if (window)
|
||||
{
|
||||
meta_bell_flash_window_frame (window);
|
||||
bell_flash_window_frame (window);
|
||||
}
|
||||
else /* revert to fullscreen flash if there's no focussed window */
|
||||
{
|
||||
meta_bell_flash_fullscreen (display, xkb_ev);
|
||||
bell_flash_fullscreen (display, xkb_ev);
|
||||
}
|
||||
}
|
||||
|
||||
@ -258,16 +256,16 @@ meta_bell_flash_frame (MetaDisplay *display,
|
||||
* \bug This should be merged with meta_bell_notify().
|
||||
*/
|
||||
static void
|
||||
meta_bell_visual_notify (MetaDisplay *display,
|
||||
bell_visual_notify (MetaDisplay *display,
|
||||
XkbAnyEvent *xkb_ev)
|
||||
{
|
||||
switch (meta_prefs_get_visual_bell_type ())
|
||||
{
|
||||
case META_VISUAL_BELL_FULLSCREEN_FLASH:
|
||||
meta_bell_flash_fullscreen (display, xkb_ev);
|
||||
bell_flash_fullscreen (display, xkb_ev);
|
||||
break;
|
||||
case META_VISUAL_BELL_FRAME_FLASH:
|
||||
meta_bell_flash_frame (display, xkb_ev); /* does nothing yet */
|
||||
bell_flash_frame (display, xkb_ev); /* does nothing yet */
|
||||
break;
|
||||
case META_VISUAL_BELL_INVALID:
|
||||
/* do nothing */
|
||||
@ -275,35 +273,16 @@ meta_bell_visual_notify (MetaDisplay *display,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gives the user some kind of visual bell; in fact, this is our response
|
||||
* to any kind of bell request, but we set it up so that we only get
|
||||
* notified about visual bells, and X deals with audible ones.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
void
|
||||
meta_bell_notify (MetaDisplay *display,
|
||||
XkbAnyEvent *xkb_ev)
|
||||
{
|
||||
/* flash something */
|
||||
if (meta_prefs_get_visual_bell ())
|
||||
meta_bell_visual_notify (display, xkb_ev);
|
||||
bell_visual_notify (display, xkb_ev);
|
||||
}
|
||||
#endif /* HAVE_XKB */
|
||||
|
||||
/**
|
||||
* Turns the bell to audible or visual. This tells X what to do, but
|
||||
* not Metacity; 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)
|
||||
{
|
||||
@ -315,27 +294,6 @@ meta_bell_set_audible (MetaDisplay *display, gboolean audible)
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises the bell subsystem. This involves intialising
|
||||
* XKB (which, despite being a keyboard extension, is the
|
||||
* place to look for bell notifications), then asking it
|
||||
* to send us bell notifications, and then also switching
|
||||
* off the audible bell if we're using a visual one ourselves.
|
||||
*
|
||||
* Unlike most X extensions we use, we only initialise XKB here
|
||||
* (rather than in main()). It's possible that XKB is not
|
||||
* installed at all, but if that was known at build time
|
||||
* we will have HAVE_XKB undefined, which will cause this
|
||||
* function to be a no-op.
|
||||
*
|
||||
* \param display The display which is opening
|
||||
*
|
||||
* \bug There is a line of code that's never run that tells
|
||||
* XKB to reset the bell status after we quit. Bill H said
|
||||
* (<http://bugzilla.gnome.org/show_bug.cgi?id=99886#c12>)
|
||||
* that XFree86's implementation is broken so we shouldn't
|
||||
* call it, but that was in 2002. Is it working now?
|
||||
*/
|
||||
gboolean
|
||||
meta_bell_init (MetaDisplay *display)
|
||||
{
|
||||
@ -377,15 +335,6 @@ meta_bell_init (MetaDisplay *display)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down the bell subsystem.
|
||||
*
|
||||
* \param display The display which is closing
|
||||
*
|
||||
* \bug This is never called! If we had XkbSetAutoResetControls
|
||||
* enabled in meta_bell_init(), this wouldn't be a problem, but
|
||||
* we don't.
|
||||
*/
|
||||
void
|
||||
meta_bell_shutdown (MetaDisplay *display)
|
||||
{
|
||||
|
@ -1,6 +1,17 @@
|
||||
/* Metacity visual bell */
|
||||
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/**
|
||||
* \file bell.h Ring the bell or flash the screen
|
||||
*
|
||||
* Sometimes, X programs "ring the bell", whatever that means. Metacity lets
|
||||
* the user configure the bell to be audible or visible (aka visual), and
|
||||
* if it's visual it can be configured to be frame-flash or fullscreen-flash.
|
||||
* We never get told about audible bells; X handles them just fine by itself.
|
||||
*
|
||||
* The visual bell was the result of a discussion in Bugzilla here:
|
||||
* <http://bugzilla.gnome.org/show_bug.cgi?id=99886>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2002 Sun Microsystems Inc.
|
||||
*
|
||||
@ -28,9 +39,70 @@
|
||||
#include "frame-private.h"
|
||||
|
||||
#ifdef HAVE_XKB
|
||||
/**
|
||||
* Gives the user some kind of visual bell; in fact, this is our response
|
||||
* to any kind of bell request, but we set it up so that we only get
|
||||
* notified about visual bells, and X deals with audible ones.
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
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 Metacity; 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
|
||||
* place to look for bell notifications), then asking it
|
||||
* to send us bell notifications, and then also switching
|
||||
* off the audible bell if we're using a visual one ourselves.
|
||||
*
|
||||
* Unlike most X extensions we use, we only initialise XKB here
|
||||
* (rather than in main()). It's possible that XKB is not
|
||||
* installed at all, but if that was known at build time
|
||||
* we will have HAVE_XKB undefined, which will cause this
|
||||
* function to be a no-op.
|
||||
*
|
||||
* \param display The display which is opening
|
||||
*
|
||||
* \bug There is a line of code that's never run that tells
|
||||
* XKB to reset the bell status after we quit. Bill H said
|
||||
* (<http://bugzilla.gnome.org/show_bug.cgi?id=99886#c12>)
|
||||
* that XFree86's implementation is broken so we shouldn't
|
||||
* call it, but that was in 2002. Is it working now?
|
||||
*/
|
||||
gboolean meta_bell_init (MetaDisplay *display);
|
||||
|
||||
/**
|
||||
* Shuts down the bell subsystem.
|
||||
*
|
||||
* \param display The display which is closing
|
||||
*
|
||||
* \bug This is never called! If we had XkbSetAutoResetControls
|
||||
* enabled in meta_bell_init(), this wouldn't be a problem, but
|
||||
* 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);
|
||||
|
@ -1070,13 +1070,16 @@ do_screen_and_xinerama_relative_constraints (
|
||||
MetaRectangle how_far_it_can_be_smushed, min_size, max_size;
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
/* First, log some debugging information */
|
||||
char spanning_region[1 + 28 * g_list_length (region_spanning_rectangles)];
|
||||
if (meta_is_verbose ())
|
||||
{
|
||||
/* First, log some debugging information */
|
||||
char spanning_region[1 + 28 * g_list_length (region_spanning_rectangles)];
|
||||
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"screen/xinerama constraint; region_spanning_rectangles: %s\n",
|
||||
meta_rectangle_region_to_string (region_spanning_rectangles, ", ",
|
||||
spanning_region));
|
||||
meta_topic (META_DEBUG_GEOMETRY,
|
||||
"screen/xinerama constraint; region_spanning_rectangles: %s\n",
|
||||
meta_rectangle_region_to_string (region_spanning_rectangles, ", ",
|
||||
spanning_region));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Determine whether constraint applies; exit if it doesn't */
|
||||
|
@ -1910,11 +1910,13 @@ event_callback (XEvent *event,
|
||||
meta_event_mode_to_string (event->xfocus.mode),
|
||||
meta_event_detail_to_string (event->xfocus.detail));
|
||||
}
|
||||
else if (meta_display_screen_for_root (display,
|
||||
event->xany.window) != NULL)
|
||||
else
|
||||
{
|
||||
MetaScreen * screen;
|
||||
screen = meta_display_screen_for_root (display, event->xany.window);
|
||||
MetaScreen *screen =
|
||||
meta_display_screen_for_root(display,
|
||||
event->xany.window);
|
||||
if (screen == NULL)
|
||||
break;
|
||||
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focus %s event received on root window 0x%lx "
|
||||
@ -1930,17 +1932,24 @@ event_callback (XEvent *event,
|
||||
event->xfocus.detail == NotifyDetailNone)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focus got set to None, probably due to brain-damage in the X protocol (see bug 125492). Setting the default focus window.\n");
|
||||
|
||||
meta_workspace_focus_default_window (screen->active_workspace, NULL, meta_display_get_current_time_roundtrip (display));
|
||||
"Focus got set to None, probably due to "
|
||||
"brain-damage in the X protocol (see bug "
|
||||
"125492). Setting the default focus window.\n");
|
||||
meta_workspace_focus_default_window (screen->active_workspace,
|
||||
NULL,
|
||||
meta_display_get_current_time_roundtrip (display));
|
||||
}
|
||||
else if (event->type == FocusIn &&
|
||||
event->xfocus.mode == NotifyNormal &&
|
||||
event->xfocus.detail == NotifyInferior)
|
||||
{
|
||||
meta_topic (META_DEBUG_FOCUS,
|
||||
"Focus got set to root window, probably due to gnome-session logout dialog usage (see bug 153220). Setting the default focus window.\n");
|
||||
meta_workspace_focus_default_window (screen->active_workspace, NULL, meta_display_get_current_time_roundtrip (display));
|
||||
"Focus got set to root window, probably due to "
|
||||
"gnome-session logout dialog usage (see bug "
|
||||
"153220). Setting the default focus window.\n");
|
||||
meta_workspace_focus_default_window (screen->active_workspace,
|
||||
NULL,
|
||||
meta_display_get_current_time_roundtrip (display));
|
||||
}
|
||||
|
||||
}
|
||||
@ -5166,9 +5175,11 @@ meta_display_get_damage_event_base (MetaDisplay *display)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_COMPOSITE_EXTENSIONS
|
||||
#ifdef HAVE_SHAPE
|
||||
int
|
||||
meta_display_get_shape_event_base (MetaDisplay *display)
|
||||
{
|
||||
return display->shape_event_base;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,6 +1,40 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Metacity animation effects */
|
||||
/**
|
||||
* \file effects.c "Special effects" other than compositor effects.
|
||||
*
|
||||
* Before we had a serious compositor, we supported swooping
|
||||
* rectangles for minimising and so on. These are still supported
|
||||
* today, even when the compositor is enabled. The file contains two
|
||||
* parts:
|
||||
*
|
||||
* 1) A set of functions, each of which implements a special effect.
|
||||
* (Only the minimize function does anything interesting; we should
|
||||
* probably get rid of the rest.)
|
||||
*
|
||||
* 2) A set of functions for moving a highlighted wireframe box around
|
||||
* the screen, optionally with height and width shown in the middle.
|
||||
* This is used for moving and resizing when reduced_resources is set.
|
||||
*
|
||||
* There was formerly a system which allowed callers to drop in their
|
||||
* own handlers for various things; it was never used (people who want
|
||||
* their own handlers can just modify this file, after all) and it added
|
||||
* a good deal of extra complexity, so it has been removed. If you want it,
|
||||
* it can be found in svn r3769.
|
||||
*
|
||||
* Once upon a time there were three different ways of drawing the box
|
||||
* animation: window wireframe, window opaque, and root. People who had
|
||||
* the shape extension theoretically had the choice of all three, and
|
||||
* people who didn't weren't given the choice of the wireframe option.
|
||||
* In practice, though, the opaque animation was never perfect, so it came
|
||||
* down to the wireframe option for those who had the extension and
|
||||
* the root option for those who didn't; there was actually no way of choosing
|
||||
* any other option anyway. Work on the opaque animation stopped in 2002;
|
||||
* anyone who wants something like that these days will be using the
|
||||
* compositor anyway.
|
||||
*
|
||||
* In svn r3769 this was made explicit.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Anders Carlsson, Havoc Pennington
|
||||
@ -21,35 +55,24 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \file effects.c "Special effects" other than compositor effects.
|
||||
*
|
||||
* Before we had a serious compositor, we supported swooping
|
||||
* rectangles for minimising and so on. These are still supported
|
||||
* today, even when the compositor is enabled.
|
||||
*/
|
||||
|
||||
|
||||
#include <config.h>
|
||||
#include "effects.h"
|
||||
#include "display-private.h"
|
||||
#include "ui.h"
|
||||
#include "window-private.h"
|
||||
#include "prefs.h"
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
#include <X11/extensions/shape.h>
|
||||
#endif
|
||||
|
||||
#define META_MINIMIZE_ANIMATION_LENGTH 0.25
|
||||
#define META_SHADE_ANIMATION_LENGTH 0.2
|
||||
|
||||
#include <string.h>
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_ANIMATION_DRAW_ROOT,
|
||||
META_ANIMATION_WINDOW_WIREFRAME,
|
||||
META_ANIMATION_WINDOW_OPAQUE
|
||||
|
||||
} MetaAnimationStyle;
|
||||
typedef struct MetaEffect MetaEffect;
|
||||
typedef struct MetaEffectPriv MetaEffectPriv;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -58,65 +81,85 @@ typedef struct
|
||||
double millisecs_duration;
|
||||
GTimeVal start_time;
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
/** For wireframe window */
|
||||
Window wireframe_xwindow;
|
||||
#else
|
||||
/** Rectangle to erase */
|
||||
MetaRectangle last_rect;
|
||||
|
||||
/** First time we've plotted anything in this animation? */
|
||||
gboolean first_time;
|
||||
|
||||
/** For wireframe drawn on root window */
|
||||
GC gc;
|
||||
#endif
|
||||
|
||||
MetaRectangle start_rect;
|
||||
MetaRectangle end_rect;
|
||||
|
||||
/* rect to erase */
|
||||
MetaRectangle last_rect;
|
||||
|
||||
/* used instead of the global flag, since
|
||||
* we don't want to change midstream.
|
||||
*/
|
||||
MetaAnimationStyle style;
|
||||
|
||||
/* For wireframe drawn on root window */
|
||||
GC gc;
|
||||
|
||||
/* For wireframe window */
|
||||
Window wireframe_xwindow;
|
||||
|
||||
/* For opaque */
|
||||
MetaImageWindow *image_window;
|
||||
GdkPixbuf *orig_pixbuf;
|
||||
|
||||
MetaBoxAnimType anim_type;
|
||||
|
||||
} BoxAnimationContext;
|
||||
|
||||
/**
|
||||
* Information we need to know during a maximise or minimise effect.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/** This is the normal-size window. */
|
||||
MetaRectangle window_rect;
|
||||
/** This is the size of the window when it's an icon. */
|
||||
MetaRectangle icon_rect;
|
||||
} MetaMinimizeEffect, MetaUnminimizeEffect;
|
||||
|
||||
struct MetaEffectPriv
|
||||
{
|
||||
MetaEffectFinished finished;
|
||||
gpointer finished_data;
|
||||
gpointer finished_data;
|
||||
};
|
||||
|
||||
struct MetaEffect
|
||||
{
|
||||
/** The window the effect is applied to. */
|
||||
MetaWindow *window;
|
||||
/** Which effect is happening here. */
|
||||
MetaEffectType type;
|
||||
/** The effect handler can hang data here. */
|
||||
gpointer info;
|
||||
|
||||
union
|
||||
{
|
||||
MetaMinimizeEffect minimize;
|
||||
/* ... and theoretically anything else */
|
||||
} u;
|
||||
|
||||
MetaEffectPriv *priv;
|
||||
};
|
||||
|
||||
static void run_default_effect_handler (MetaEffect *effect);
|
||||
static void run_handler (MetaEffect *effect);
|
||||
|
||||
static MetaEffectHandler effect_handler;
|
||||
static gpointer effect_handler_data;
|
||||
|
||||
void
|
||||
meta_push_effect_handler (MetaEffectHandler handler,
|
||||
gpointer data)
|
||||
{
|
||||
effect_handler = handler;
|
||||
effect_handler_data = data;
|
||||
}
|
||||
|
||||
void
|
||||
meta_pop_effect_handler (void)
|
||||
{
|
||||
/* FIXME: not implemented yet */
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
static void effect_free (MetaEffect *effect);
|
||||
|
||||
static MetaEffect *
|
||||
create_effect (MetaEffectType type,
|
||||
MetaWindow *window,
|
||||
MetaEffectFinished finished,
|
||||
gpointer finished_data)
|
||||
MetaWindow *window,
|
||||
MetaEffectFinished finished,
|
||||
gpointer finished_data);
|
||||
|
||||
static void
|
||||
draw_box_animation (MetaScreen *screen,
|
||||
MetaRectangle *initial_rect,
|
||||
MetaRectangle *destination_rect,
|
||||
double seconds_duration);
|
||||
|
||||
/**
|
||||
* Creates an effect.
|
||||
*
|
||||
*/
|
||||
static MetaEffect*
|
||||
create_effect (MetaEffectType type,
|
||||
MetaWindow *window,
|
||||
MetaEffectFinished finished,
|
||||
gpointer finished_data)
|
||||
{
|
||||
MetaEffect *effect = g_new (MetaEffect, 1);
|
||||
|
||||
@ -129,14 +172,20 @@ create_effect (MetaEffectType type,
|
||||
return effect;
|
||||
}
|
||||
|
||||
void
|
||||
meta_effect_end (MetaEffect *effect)
|
||||
/**
|
||||
* Destroys an effect. If the effect has a "finished" hook, it will be
|
||||
* called before cleanup.
|
||||
*
|
||||
* \param effect The effect.
|
||||
*/
|
||||
static void
|
||||
effect_free (MetaEffect *effect)
|
||||
{
|
||||
if (effect->priv->finished)
|
||||
effect->priv->finished (effect, effect->priv->finished_data);
|
||||
if (effect->priv->finished)
|
||||
effect->priv->finished (effect->priv->finished_data);
|
||||
|
||||
g_free (effect->priv);
|
||||
g_free (effect);
|
||||
g_free (effect->priv);
|
||||
g_free (effect);
|
||||
}
|
||||
|
||||
void
|
||||
@ -155,10 +204,10 @@ meta_effect_run_focus (MetaWindow *window,
|
||||
|
||||
void
|
||||
meta_effect_run_minimize (MetaWindow *window,
|
||||
MetaRectangle *window_rect,
|
||||
MetaRectangle *icon_rect,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data)
|
||||
MetaRectangle *window_rect,
|
||||
MetaRectangle *icon_rect,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data)
|
||||
{
|
||||
MetaEffect *effect;
|
||||
|
||||
@ -175,10 +224,10 @@ meta_effect_run_minimize (MetaWindow *window,
|
||||
|
||||
void
|
||||
meta_effect_run_unminimize (MetaWindow *window,
|
||||
MetaRectangle *window_rect,
|
||||
MetaRectangle *icon_rect,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data)
|
||||
MetaRectangle *window_rect,
|
||||
MetaRectangle *icon_rect,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data)
|
||||
{
|
||||
MetaEffect *effect;
|
||||
|
||||
@ -203,7 +252,7 @@ meta_effect_run_close (MetaWindow *window,
|
||||
g_return_if_fail (window != NULL);
|
||||
|
||||
effect = create_effect (META_EFFECT_CLOSE, window,
|
||||
finished, data);
|
||||
finished, data);
|
||||
|
||||
run_handler (effect);
|
||||
}
|
||||
@ -211,6 +260,7 @@ meta_effect_run_close (MetaWindow *window,
|
||||
|
||||
/* old ugly minimization effect */
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
static void
|
||||
update_wireframe_window (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
@ -221,8 +271,6 @@ update_wireframe_window (MetaDisplay *display,
|
||||
rect->x, rect->y,
|
||||
rect->width, rect->height);
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
|
||||
#define OUTLINE_WIDTH 3
|
||||
|
||||
if (rect->width > OUTLINE_WIDTH * 2 &&
|
||||
@ -263,8 +311,8 @@ update_wireframe_window (MetaDisplay *display,
|
||||
XShapeCombineMask (display->xdisplay, xwindow,
|
||||
ShapeBounding, 0, 0, None, ShapeSet);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A hack to force the X server to synchronize with the
|
||||
@ -276,9 +324,9 @@ graphics_sync (BoxAnimationContext *context)
|
||||
XImage *image;
|
||||
|
||||
image = XGetImage (context->screen->display->xdisplay,
|
||||
context->screen->xroot,
|
||||
0, 0, 1, 1,
|
||||
AllPlanes, ZPixmap);
|
||||
context->screen->xroot,
|
||||
0, 0, 1, 1,
|
||||
AllPlanes, ZPixmap);
|
||||
|
||||
XDestroyImage (image);
|
||||
}
|
||||
@ -291,20 +339,20 @@ effects_draw_box_animation_timeout (BoxAnimationContext *context)
|
||||
MetaRectangle draw_rect;
|
||||
double fraction;
|
||||
|
||||
#ifndef HAVE_SHAPE
|
||||
if (!context->first_time)
|
||||
{
|
||||
if (context->style == META_ANIMATION_DRAW_ROOT)
|
||||
{
|
||||
/* Restore the previously drawn background */
|
||||
XDrawRectangle (context->screen->display->xdisplay,
|
||||
context->screen->xroot,
|
||||
context->gc,
|
||||
context->last_rect.x, context->last_rect.y,
|
||||
context->last_rect.width, context->last_rect.height);
|
||||
}
|
||||
/* Restore the previously drawn background */
|
||||
XDrawRectangle (context->screen->display->xdisplay,
|
||||
context->screen->xroot,
|
||||
context->gc,
|
||||
context->last_rect.x, context->last_rect.y,
|
||||
context->last_rect.width, context->last_rect.height);
|
||||
}
|
||||
else
|
||||
context->first_time = FALSE;
|
||||
|
||||
context->first_time = FALSE;
|
||||
#endif /* !HAVE_SHAPE */
|
||||
|
||||
g_get_current_time (¤t_time);
|
||||
|
||||
@ -323,23 +371,15 @@ effects_draw_box_animation_timeout (BoxAnimationContext *context)
|
||||
if (elapsed > context->millisecs_duration)
|
||||
{
|
||||
/* All done */
|
||||
if (context->style == META_ANIMATION_WINDOW_OPAQUE)
|
||||
{
|
||||
g_object_unref (G_OBJECT (context->orig_pixbuf));
|
||||
meta_image_window_free (context->image_window);
|
||||
}
|
||||
else if (context->style == META_ANIMATION_DRAW_ROOT)
|
||||
{
|
||||
meta_display_ungrab (context->screen->display);
|
||||
meta_ui_pop_delay_exposes (context->screen->ui);
|
||||
XFreeGC (context->screen->display->xdisplay,
|
||||
context->gc);
|
||||
}
|
||||
else if (context->style == META_ANIMATION_WINDOW_WIREFRAME)
|
||||
{
|
||||
XDestroyWindow (context->screen->display->xdisplay,
|
||||
#ifdef HAVE_SHAPE
|
||||
XDestroyWindow (context->screen->display->xdisplay,
|
||||
context->wireframe_xwindow);
|
||||
}
|
||||
#else
|
||||
meta_display_ungrab (context->screen->display);
|
||||
meta_ui_pop_delay_exposes (context->screen->ui);
|
||||
XFreeGC (context->screen->display->xdisplay,
|
||||
context->gc);
|
||||
#endif /* !HAVE_SHAPE */
|
||||
|
||||
graphics_sync (context);
|
||||
|
||||
@ -363,195 +403,99 @@ effects_draw_box_animation_timeout (BoxAnimationContext *context)
|
||||
draw_rect.width = 1;
|
||||
if (draw_rect.height < 1)
|
||||
draw_rect.height = 1;
|
||||
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
update_wireframe_window (context->screen->display,
|
||||
context->wireframe_xwindow,
|
||||
&draw_rect);
|
||||
#else
|
||||
context->last_rect = draw_rect;
|
||||
|
||||
if (context->style == META_ANIMATION_WINDOW_OPAQUE)
|
||||
{
|
||||
GdkPixbuf *scaled;
|
||||
|
||||
scaled = NULL;
|
||||
switch (context->anim_type)
|
||||
{
|
||||
case META_BOX_ANIM_SCALE:
|
||||
scaled = gdk_pixbuf_scale_simple (context->orig_pixbuf,
|
||||
draw_rect.width,
|
||||
draw_rect.height,
|
||||
GDK_INTERP_BILINEAR);
|
||||
break;
|
||||
case META_BOX_ANIM_SLIDE_UP:
|
||||
{
|
||||
int x, y;
|
||||
|
||||
x = context->start_rect.width - draw_rect.width;
|
||||
y = context->start_rect.height - draw_rect.height;
|
||||
|
||||
/* paranoia */
|
||||
if (x < 0)
|
||||
x = 0;
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
|
||||
scaled = gdk_pixbuf_new_subpixbuf (context->orig_pixbuf,
|
||||
x, y,
|
||||
draw_rect.width,
|
||||
draw_rect.height);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* handle out-of-memory */
|
||||
if (scaled != NULL)
|
||||
{
|
||||
meta_image_window_set (context->image_window,
|
||||
scaled,
|
||||
draw_rect.x, draw_rect.y);
|
||||
|
||||
g_object_unref (G_OBJECT (scaled));
|
||||
}
|
||||
}
|
||||
else if (context->style == META_ANIMATION_DRAW_ROOT)
|
||||
{
|
||||
/* Draw the rectangle */
|
||||
XDrawRectangle (context->screen->display->xdisplay,
|
||||
context->screen->xroot,
|
||||
context->gc,
|
||||
draw_rect.x, draw_rect.y,
|
||||
draw_rect.width, draw_rect.height);
|
||||
}
|
||||
else if (context->style == META_ANIMATION_WINDOW_WIREFRAME)
|
||||
{
|
||||
update_wireframe_window (context->screen->display,
|
||||
context->wireframe_xwindow,
|
||||
&draw_rect);
|
||||
}
|
||||
/* Draw the rectangle */
|
||||
XDrawRectangle (context->screen->display->xdisplay,
|
||||
context->screen->xroot,
|
||||
context->gc,
|
||||
draw_rect.x, draw_rect.y,
|
||||
draw_rect.width, draw_rect.height);
|
||||
|
||||
#endif /* !HAVE_SHAPE */
|
||||
|
||||
/* kick changes onto the server */
|
||||
graphics_sync (context);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* I really don't want this to be a configuration option, but I think
|
||||
* the wireframe is sucky from a UI standpoint (more confusing than
|
||||
* opaque), but the opaque is definitely still too slow on some
|
||||
* systems, and also doesn't look quite right due to the mapping
|
||||
* and unmapping of windows that's going on.
|
||||
*/
|
||||
|
||||
static MetaAnimationStyle animation_style = META_ANIMATION_WINDOW_WIREFRAME;
|
||||
|
||||
void
|
||||
meta_effects_draw_box_animation (MetaScreen *screen,
|
||||
MetaRectangle *initial_rect,
|
||||
MetaRectangle *destination_rect,
|
||||
double seconds_duration,
|
||||
MetaBoxAnimType anim_type)
|
||||
draw_box_animation (MetaScreen *screen,
|
||||
MetaRectangle *initial_rect,
|
||||
MetaRectangle *destination_rect,
|
||||
double seconds_duration)
|
||||
{
|
||||
BoxAnimationContext *context;
|
||||
|
||||
#ifdef HAVE_SHAPE
|
||||
XSetWindowAttributes attrs;
|
||||
#else
|
||||
XGCValues gc_values;
|
||||
#endif
|
||||
|
||||
g_return_if_fail (seconds_duration > 0.0);
|
||||
|
||||
if (g_getenv ("METACITY_DEBUG_EFFECTS"))
|
||||
seconds_duration *= 10; /* slow things down */
|
||||
|
||||
/* Create the animation context */
|
||||
context = g_new0 (BoxAnimationContext, 1);
|
||||
context = g_new0 (BoxAnimationContext, 1);
|
||||
|
||||
context->screen = screen;
|
||||
|
||||
context->millisecs_duration = seconds_duration * 1000.0;
|
||||
context->first_time = TRUE;
|
||||
|
||||
context->start_rect = *initial_rect;
|
||||
context->end_rect = *destination_rect;
|
||||
context->anim_type = anim_type;
|
||||
|
||||
context->style = animation_style;
|
||||
#ifdef HAVE_SHAPE
|
||||
|
||||
#ifndef HAVE_SHAPE
|
||||
if (context->style == META_ANIMATION_WINDOW_WIREFRAME)
|
||||
context->style = META_ANIMATION_DRAW_ROOT;
|
||||
attrs.override_redirect = True;
|
||||
attrs.background_pixel = BlackPixel (screen->display->xdisplay,
|
||||
screen->number);
|
||||
|
||||
context->wireframe_xwindow = XCreateWindow (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
initial_rect->x,
|
||||
initial_rect->y,
|
||||
initial_rect->width,
|
||||
initial_rect->height,
|
||||
0,
|
||||
CopyFromParent,
|
||||
CopyFromParent,
|
||||
(Visual *)CopyFromParent,
|
||||
CWOverrideRedirect | CWBackPixel,
|
||||
&attrs);
|
||||
|
||||
update_wireframe_window (screen->display,
|
||||
context->wireframe_xwindow,
|
||||
initial_rect);
|
||||
|
||||
XMapWindow (screen->display->xdisplay,
|
||||
context->wireframe_xwindow);
|
||||
|
||||
#else /* !HAVE_SHAPE */
|
||||
|
||||
context->first_time = TRUE;
|
||||
gc_values.subwindow_mode = IncludeInferiors;
|
||||
gc_values.function = GXinvert;
|
||||
|
||||
context->gc = XCreateGC (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
GCSubwindowMode | GCFunction,
|
||||
&gc_values);
|
||||
|
||||
/* Grab the X server to avoid screen dirt */
|
||||
meta_display_grab (context->screen->display);
|
||||
meta_ui_push_delay_exposes (context->screen->ui);
|
||||
#endif
|
||||
|
||||
if (context->style == META_ANIMATION_WINDOW_OPAQUE)
|
||||
{
|
||||
GdkPixbuf *pix;
|
||||
|
||||
pix = meta_gdk_pixbuf_get_from_window (NULL,
|
||||
screen->xroot,
|
||||
initial_rect->x,
|
||||
initial_rect->y,
|
||||
0, 0,
|
||||
initial_rect->width,
|
||||
initial_rect->height);
|
||||
|
||||
if (pix == NULL)
|
||||
{
|
||||
/* Fall back to wireframe */
|
||||
context->style = META_ANIMATION_WINDOW_WIREFRAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->image_window = meta_image_window_new (screen->display->xdisplay,
|
||||
screen->number,
|
||||
initial_rect->width,
|
||||
initial_rect->height);
|
||||
context->orig_pixbuf = pix;
|
||||
meta_image_window_set (context->image_window,
|
||||
context->orig_pixbuf,
|
||||
initial_rect->x,
|
||||
initial_rect->y);
|
||||
meta_image_window_set_showing (context->image_window, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Not an else, so that fallback works */
|
||||
if (context->style == META_ANIMATION_WINDOW_WIREFRAME)
|
||||
{
|
||||
XSetWindowAttributes attrs;
|
||||
|
||||
attrs.override_redirect = True;
|
||||
attrs.background_pixel = BlackPixel (screen->display->xdisplay,
|
||||
screen->number);
|
||||
|
||||
context->wireframe_xwindow = XCreateWindow (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
initial_rect->x,
|
||||
initial_rect->y,
|
||||
initial_rect->width,
|
||||
initial_rect->height,
|
||||
0,
|
||||
CopyFromParent,
|
||||
CopyFromParent,
|
||||
(Visual *)CopyFromParent,
|
||||
CWOverrideRedirect | CWBackPixel,
|
||||
&attrs);
|
||||
|
||||
update_wireframe_window (screen->display,
|
||||
context->wireframe_xwindow,
|
||||
initial_rect);
|
||||
|
||||
XMapWindow (screen->display->xdisplay,
|
||||
context->wireframe_xwindow);
|
||||
}
|
||||
|
||||
if (context->style == META_ANIMATION_DRAW_ROOT)
|
||||
{
|
||||
XGCValues gc_values;
|
||||
|
||||
gc_values.subwindow_mode = IncludeInferiors;
|
||||
gc_values.function = GXinvert;
|
||||
|
||||
context->gc = XCreateGC (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
GCSubwindowMode | GCFunction,
|
||||
&gc_values);
|
||||
|
||||
/* Grab the X server to avoid screen dirt */
|
||||
meta_display_grab (context->screen->display);
|
||||
meta_ui_push_delay_exposes (context->screen->ui);
|
||||
}
|
||||
|
||||
/* Do this only after we get the pixbuf from the server,
|
||||
* so that the animation doesn't get truncated.
|
||||
@ -770,28 +714,22 @@ run_default_effect_handler (MetaEffect *effect)
|
||||
switch (effect->type)
|
||||
{
|
||||
case META_EFFECT_MINIMIZE:
|
||||
meta_effects_draw_box_animation (effect->window->screen,
|
||||
&(effect->u.minimize.window_rect),
|
||||
&(effect->u.minimize.icon_rect),
|
||||
META_MINIMIZE_ANIMATION_LENGTH,
|
||||
META_BOX_ANIM_SCALE);
|
||||
break;
|
||||
draw_box_animation (effect->window->screen,
|
||||
&(effect->u.minimize.window_rect),
|
||||
&(effect->u.minimize.icon_rect),
|
||||
META_MINIMIZE_ANIMATION_LENGTH);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
run_handler (MetaEffect *effect)
|
||||
{
|
||||
if (effect_handler)
|
||||
{
|
||||
effect_handler (effect, effect_handler_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
run_default_effect_handler (effect);
|
||||
meta_effect_end (effect);
|
||||
}
|
||||
if (meta_prefs_get_gnome_animations ())
|
||||
run_default_effect_handler (effect);
|
||||
|
||||
effect_free (effect);
|
||||
}
|
||||
|
@ -1,6 +1,27 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Metacity animation effects */
|
||||
/**
|
||||
* \file effects.h "Special effects" other than compositor effects.
|
||||
*
|
||||
* Before we had a serious compositor, we supported swooping
|
||||
* rectangles for minimising and so on. These are still supported
|
||||
* today, even when the compositor is enabled. The file contains two
|
||||
* parts:
|
||||
*
|
||||
* 1) A set of functions, each of which implements a special effect.
|
||||
* (Only the minimize function does anything interesting; we should
|
||||
* probably get rid of the rest.)
|
||||
*
|
||||
* 2) A set of functions for moving a highlighted wireframe box around
|
||||
* the screen, optionally with height and width shown in the middle.
|
||||
* This is used for moving and resizing when reduced_resources is set.
|
||||
*
|
||||
* There was formerly a system which allowed callers to drop in their
|
||||
* own handlers for various things; it was never used (people who want
|
||||
* their own handlers can just modify this file, after all) and it added
|
||||
* a good deal of extra complexity, so it has been removed. If you want it,
|
||||
* it can be found in svn r3769.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Anders Carlsson, Havoc Pennington
|
||||
@ -27,116 +48,104 @@
|
||||
#include "util.h"
|
||||
#include "screen-private.h"
|
||||
|
||||
typedef struct MetaEffect MetaEffect;
|
||||
typedef struct MetaEffectPriv MetaEffectPriv;
|
||||
|
||||
#define META_MINIMIZE_ANIMATION_LENGTH 0.25
|
||||
#define META_SHADE_ANIMATION_LENGTH 0.2
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_BOX_ANIM_SCALE,
|
||||
META_BOX_ANIM_SLIDE_UP
|
||||
|
||||
} MetaBoxAnimType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
META_EFFECT_MINIMIZE,
|
||||
META_EFFECT_UNMINIMIZE,
|
||||
META_EFFECT_MENU_MAP,
|
||||
META_EFFECT_MENU_UNMAP,
|
||||
META_EFFECT_DIALOG_MAP,
|
||||
META_EFFECT_DIALOG_UNMAP,
|
||||
META_EFFECT_TOPLEVEL_MAP,
|
||||
META_EFFECT_TOPLEVEL_UNMAP,
|
||||
META_EFFECT_WIREFRAME_BEGIN,
|
||||
META_EFFECT_WIREFRAME_UPDATE,
|
||||
META_EFFECT_WIREFRAME_END,
|
||||
META_EFFECT_FOCUS,
|
||||
META_EFFECT_CLOSE,
|
||||
META_NUM_EFFECTS
|
||||
} MetaEffectType;
|
||||
|
||||
typedef void (* MetaEffectHandler) (MetaEffect *effect,
|
||||
gpointer data);
|
||||
typedef void (* MetaEffectFinished) (const MetaEffect *effect,
|
||||
gpointer data);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaRectangle window_rect;
|
||||
MetaRectangle icon_rect;
|
||||
} MetaMinimizeEffect, MetaUnminimizeEffect;
|
||||
|
||||
#if 0
|
||||
/* Solaris abhors an empty struct. #397296. */
|
||||
typedef struct
|
||||
{
|
||||
|
||||
} MetaCloseEffect;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
} MetaFocusEffect;
|
||||
#endif
|
||||
|
||||
struct MetaEffect
|
||||
{
|
||||
MetaWindow *window;
|
||||
MetaEffectType type;
|
||||
gpointer info; /* effect handler can hang data here */
|
||||
|
||||
union
|
||||
{
|
||||
MetaMinimizeEffect minimize;
|
||||
MetaUnminimizeEffect unminimize;
|
||||
#if 0
|
||||
/* These don't currently exist, so we aren't using them. #397296. */
|
||||
MetaCloseEffect close;
|
||||
MetaFocusEffect focus;
|
||||
#endif
|
||||
} u;
|
||||
|
||||
MetaEffectPriv *priv;
|
||||
};
|
||||
|
||||
void meta_push_effect_handler (MetaEffectHandler handler,
|
||||
gpointer data);
|
||||
void meta_pop_effect_handler (void);
|
||||
/**
|
||||
* A callback which will be called when the effect has finished.
|
||||
*/
|
||||
typedef void (* MetaEffectFinished) (gpointer data);
|
||||
|
||||
/**
|
||||
* Performs the minimize effect.
|
||||
*
|
||||
* \param window The window we're moving
|
||||
* \param window_rect Its current state
|
||||
* \param target Where it should end up
|
||||
* \param finished Callback for when it's finished
|
||||
* \param data Data for callback
|
||||
*/
|
||||
void meta_effect_run_minimize (MetaWindow *window,
|
||||
MetaRectangle *window_rect,
|
||||
MetaRectangle *target,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data);
|
||||
MetaRectangle *window_rect,
|
||||
MetaRectangle *target,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* Performs the unminimize effect. There is no such effect.
|
||||
* FIXME: delete this.
|
||||
*
|
||||
* \param window The window we're moving
|
||||
* \param icon_rect Its current state
|
||||
* \param window_rect Where it should end up
|
||||
* \param finished Callback for when it's finished
|
||||
* \param data Data for callback
|
||||
*/
|
||||
void meta_effect_run_unminimize (MetaWindow *window,
|
||||
MetaRectangle *window_rect,
|
||||
MetaRectangle *icon_rect,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data);
|
||||
MetaRectangle *window_rect,
|
||||
MetaRectangle *icon_rect,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* Performs the close effect. There is no such effect.
|
||||
* FIXME: delete this.
|
||||
*
|
||||
* \param window The window we're moving
|
||||
* \param finished Callback for when it's finished
|
||||
* \param data Data for callback
|
||||
*/
|
||||
void meta_effect_run_close (MetaWindow *window,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data);
|
||||
MetaEffectFinished finished,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* Performs the focus effect. There is no such effect.
|
||||
* FIXME: delete this.
|
||||
*
|
||||
* \param window The window we're moving
|
||||
* \param finished Callback for when it's finished
|
||||
* \param data Data for callback
|
||||
*/
|
||||
void meta_effect_run_focus (MetaWindow *window,
|
||||
MetaEffectFinished finished,
|
||||
gpointer data);
|
||||
void meta_effect_end (MetaEffect *effect);
|
||||
|
||||
|
||||
|
||||
/* Stuff that should become static functions */
|
||||
|
||||
void meta_effects_draw_box_animation (MetaScreen *screen,
|
||||
MetaRectangle *initial_rect,
|
||||
MetaRectangle *destination_rect,
|
||||
double seconds_duration,
|
||||
MetaBoxAnimType anim_type);
|
||||
MetaEffectFinished finished,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* Grabs the server and paints a wireframe rectangle on the screen.
|
||||
* Since this involves starting a grab, please be considerate of other
|
||||
* users and don't keep the grab for long. You may move the wireframe
|
||||
* around using meta_effects_update_wireframe() and remove it, and undo
|
||||
* the grab, using meta_effects_end_wireframe().
|
||||
*
|
||||
* \param screen The screen to draw the rectangle on.
|
||||
* \param rect The size of the rectangle to draw.
|
||||
* \param width The width to display in the middle (or 0 not to)
|
||||
* \param height The width to display in the middle (or 0 not to)
|
||||
*/
|
||||
void meta_effects_begin_wireframe (MetaScreen *screen,
|
||||
const MetaRectangle *rect,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
/**
|
||||
* Moves a wireframe rectangle around after its creation by
|
||||
* meta_effects_begin_wireframe(). (Perhaps we ought to remember the old
|
||||
* positions and not require people to pass them in?)
|
||||
*
|
||||
* \param old_rect Where the rectangle is now
|
||||
* \param old_width The width that was displayed on it (or 0 if there wasn't)
|
||||
* \param old_height The height that was displayed on it (or 0 if there wasn't)
|
||||
* \param new_rect Where the rectangle is going
|
||||
* \param new_width The width that will be displayed on it (or 0 not to)
|
||||
* \param new_height The height that will be displayed on it (or 0 not to)
|
||||
*/
|
||||
void meta_effects_update_wireframe (MetaScreen *screen,
|
||||
const MetaRectangle *old_rect,
|
||||
int old_width,
|
||||
@ -144,6 +153,15 @@ void meta_effects_update_wireframe (MetaScreen *screen,
|
||||
const MetaRectangle *new_rect,
|
||||
int new_width,
|
||||
int new_height);
|
||||
|
||||
/**
|
||||
* Removes a wireframe rectangle from the screen and ends the grab started by
|
||||
* meta_effects_begin_wireframe().
|
||||
*
|
||||
* \param old_rect Where the rectangle is now
|
||||
* \param old_width The width that was displayed on it (or 0 if there wasn't)
|
||||
* \param old_height The height that was displayed on it (or 0 if there wasn't)
|
||||
*/
|
||||
void meta_effects_end_wireframe (MetaScreen *screen,
|
||||
const MetaRectangle *old_rect,
|
||||
int width,
|
||||
|
@ -109,8 +109,6 @@ meta_window_get_group (MetaWindow *window)
|
||||
if (window->unmanaging)
|
||||
return NULL;
|
||||
|
||||
g_assert (window->group != NULL);
|
||||
|
||||
return window->group;
|
||||
}
|
||||
|
||||
|
@ -2549,6 +2549,13 @@ process_tab_grab (MetaDisplay *display,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* !! TO HERE !!
|
||||
* alt-f6 during alt-{Tab,Escape} does not end the grab
|
||||
* but does change the grab op (and redraws the window,
|
||||
* of course).
|
||||
* See _{SWITCH,CYCLE}_GROUP.@@@
|
||||
*/
|
||||
|
||||
popup_not_showing = FALSE;
|
||||
key_used = FALSE;
|
||||
|
386
src/core/prefs.c
386
src/core/prefs.c
@ -5,6 +5,7 @@
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington, Copyright (C) 2002 Red Hat Inc.
|
||||
* Copyright (C) 2006 Elijah Newren
|
||||
* Copyright (C) 2008 Thomas Thurman
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
@ -46,7 +47,6 @@
|
||||
* not given a name here, because the purpose of the unified handlers
|
||||
* is that keys should be referred to exactly once.
|
||||
*/
|
||||
#define KEY_AUTO_RAISE_DELAY "/apps/metacity/general/auto_raise_delay"
|
||||
#define KEY_TITLEBAR_FONT "/apps/metacity/general/titlebar_font"
|
||||
#define KEY_NUM_WORKSPACES "/apps/metacity/general/num_workspaces"
|
||||
#define KEY_GNOME_ACCESSIBILITY "/desktop/gnome/interface/accessibility"
|
||||
@ -62,7 +62,6 @@
|
||||
|
||||
#define KEY_WORKSPACE_NAME_PREFIX "/apps/metacity/workspace_names/name_"
|
||||
|
||||
#define KEY_CURSOR_SIZE "/desktop/gnome/peripherals/mouse/cursor_size"
|
||||
|
||||
#ifdef HAVE_GCONF
|
||||
static GConfClient *default_client = NULL;
|
||||
@ -90,6 +89,7 @@ static gboolean provide_visual_bell = FALSE;
|
||||
static gboolean bell_is_audible = TRUE;
|
||||
static gboolean reduced_resources = FALSE;
|
||||
static gboolean gnome_accessibility = FALSE;
|
||||
static gboolean gnome_animations = TRUE;
|
||||
static char *cursor_theme = NULL;
|
||||
static int cursor_size = 24;
|
||||
static gboolean compositing_manager = FALSE;
|
||||
@ -107,8 +107,6 @@ static char *workspace_names[MAX_REASONABLE_WORKSPACES] = { NULL, };
|
||||
#ifdef HAVE_GCONF
|
||||
static gboolean handle_preference_update_enum (const gchar *key, GConfValue *value);
|
||||
|
||||
static gboolean update_num_workspaces (int value);
|
||||
static gboolean update_auto_raise_delay (int value);
|
||||
static gboolean update_window_binding (const char *name,
|
||||
const char *value);
|
||||
static gboolean update_screen_binding (const char *name,
|
||||
@ -124,7 +122,6 @@ static gboolean update_command (const char *name,
|
||||
const char *value);
|
||||
static gboolean update_workspace_name (const char *name,
|
||||
const char *value);
|
||||
static gboolean update_cursor_size (int size);
|
||||
|
||||
static void change_notify (GConfClient *client,
|
||||
guint cnxn_id,
|
||||
@ -246,16 +243,16 @@ static GConfEnumStringPair symtab_titlebar_action[] =
|
||||
typedef struct
|
||||
{
|
||||
gchar *key;
|
||||
MetaPreference pref;
|
||||
GConfEnumStringPair *symtab;
|
||||
gpointer target;
|
||||
MetaPreference pref;
|
||||
} MetaEnumPreference;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *key;
|
||||
gboolean *target;
|
||||
MetaPreference pref;
|
||||
gboolean *target;
|
||||
gboolean becomes_true_on_destruction;
|
||||
} MetaBoolPreference;
|
||||
|
||||
@ -285,101 +282,131 @@ typedef struct
|
||||
/**
|
||||
* Where to write the incoming string.
|
||||
*
|
||||
* This must be NULL if the handler is non-NULL.
|
||||
* If the incoming string is NULL, no change will be made.
|
||||
* This is ignored if the handler is non-NULL.
|
||||
*/
|
||||
gchar **target;
|
||||
|
||||
} MetaStringPreference;
|
||||
|
||||
#define METAINTPREFERENCE_NO_CHANGE_ON_DESTROY G_MININT
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar *key;
|
||||
MetaPreference pref;
|
||||
gint *target;
|
||||
/**
|
||||
* Minimum and maximum values of the integer.
|
||||
* If the new value is out of bounds, it will be discarded with a warning.
|
||||
*/
|
||||
gint minimum, maximum;
|
||||
/**
|
||||
* Value to use if the key is destroyed.
|
||||
* If this is METAINTPREFERENCE_NO_CHANGE_ON_DESTROY, it will
|
||||
* not be changed when the key is destroyed.
|
||||
*/
|
||||
gint value_if_destroyed;
|
||||
} MetaIntPreference;
|
||||
|
||||
/* FIXMEs: */
|
||||
/* @@@ Don't use NULL lines at the end; glib can tell you how big it is */
|
||||
/* @@@ /apps/metacity/general should be assumed if first char is not / */
|
||||
/* @@@ Will it ever be possible to merge init and update? If not, why not? */
|
||||
|
||||
static MetaEnumPreference preferences_enum[] =
|
||||
{
|
||||
{ "/apps/metacity/general/focus_new_windows",
|
||||
META_PREF_FOCUS_NEW_WINDOWS,
|
||||
symtab_focus_new_windows,
|
||||
&focus_new_windows,
|
||||
META_PREF_FOCUS_NEW_WINDOWS,
|
||||
},
|
||||
{ "/apps/metacity/general/focus_mode",
|
||||
META_PREF_FOCUS_MODE,
|
||||
symtab_focus_mode,
|
||||
&focus_mode,
|
||||
META_PREF_FOCUS_MODE,
|
||||
},
|
||||
{ "/apps/metacity/general/visual_bell_type",
|
||||
META_PREF_VISUAL_BELL_TYPE,
|
||||
symtab_visual_bell_type,
|
||||
&visual_bell_type,
|
||||
META_PREF_VISUAL_BELL_TYPE,
|
||||
},
|
||||
{ "/apps/metacity/general/action_double_click_titlebar",
|
||||
META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR,
|
||||
symtab_titlebar_action,
|
||||
&action_double_click_titlebar,
|
||||
META_PREF_ACTION_DOUBLE_CLICK_TITLEBAR,
|
||||
},
|
||||
{ "/apps/metacity/general/action_middle_click_titlebar",
|
||||
META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR,
|
||||
symtab_titlebar_action,
|
||||
&action_middle_click_titlebar,
|
||||
META_PREF_ACTION_MIDDLE_CLICK_TITLEBAR,
|
||||
},
|
||||
{ "/apps/metacity/general/action_right_click_titlebar",
|
||||
META_PREF_ACTION_RIGHT_CLICK_TITLEBAR,
|
||||
symtab_titlebar_action,
|
||||
&action_right_click_titlebar,
|
||||
META_PREF_ACTION_RIGHT_CLICK_TITLEBAR,
|
||||
},
|
||||
{ NULL, NULL, NULL, 0 },
|
||||
{ NULL, 0, NULL, NULL },
|
||||
};
|
||||
|
||||
static MetaBoolPreference preferences_bool[] =
|
||||
{
|
||||
{ "/apps/metacity/general/raise_on_click",
|
||||
&raise_on_click,
|
||||
META_PREF_RAISE_ON_CLICK,
|
||||
&raise_on_click,
|
||||
TRUE,
|
||||
},
|
||||
{ "/apps/metacity/general/titlebar_uses_system_font",
|
||||
&use_system_font,
|
||||
META_PREF_TITLEBAR_FONT, /* note! shares a pref */
|
||||
&use_system_font,
|
||||
TRUE,
|
||||
},
|
||||
{ "/apps/metacity/general/application_based",
|
||||
NULL, /* feature is known but disabled */
|
||||
META_PREF_APPLICATION_BASED,
|
||||
NULL, /* feature is known but disabled */
|
||||
FALSE,
|
||||
},
|
||||
{ "/apps/metacity/general/disable_workarounds",
|
||||
&disable_workarounds,
|
||||
META_PREF_DISABLE_WORKAROUNDS,
|
||||
&disable_workarounds,
|
||||
FALSE,
|
||||
},
|
||||
{ "/apps/metacity/general/auto_raise",
|
||||
&auto_raise,
|
||||
META_PREF_AUTO_RAISE,
|
||||
&auto_raise,
|
||||
FALSE,
|
||||
},
|
||||
{ "/apps/metacity/general/visual_bell",
|
||||
&provide_visual_bell, /* FIXME: change the name: it's confusing */
|
||||
META_PREF_VISUAL_BELL,
|
||||
&provide_visual_bell, /* FIXME: change the name: it's confusing */
|
||||
FALSE,
|
||||
},
|
||||
{ "/apps/metacity/general/audible_bell",
|
||||
&bell_is_audible, /* FIXME: change the name: it's confusing */
|
||||
META_PREF_AUDIBLE_BELL,
|
||||
&bell_is_audible, /* FIXME: change the name: it's confusing */
|
||||
FALSE,
|
||||
},
|
||||
{ "/apps/metacity/general/reduced_resources",
|
||||
&reduced_resources,
|
||||
META_PREF_REDUCED_RESOURCES,
|
||||
&reduced_resources,
|
||||
FALSE,
|
||||
},
|
||||
{ "/desktop/gnome/interface/accessibility",
|
||||
&gnome_accessibility,
|
||||
META_PREF_GNOME_ACCESSIBILITY,
|
||||
&gnome_accessibility,
|
||||
FALSE,
|
||||
},
|
||||
{ "/desktop/gnome/interface/enable_animations",
|
||||
META_PREF_GNOME_ANIMATIONS,
|
||||
&gnome_animations,
|
||||
TRUE,
|
||||
},
|
||||
{ "/apps/metacity/general/compositing_manager",
|
||||
&compositing_manager,
|
||||
META_PREF_COMPOSITING_MANAGER,
|
||||
&compositing_manager,
|
||||
FALSE,
|
||||
},
|
||||
{ NULL, NULL, 0, FALSE },
|
||||
{ NULL, 0, NULL, FALSE },
|
||||
};
|
||||
|
||||
static MetaStringPreference preferences_string[] =
|
||||
@ -417,6 +444,31 @@ static MetaStringPreference preferences_string[] =
|
||||
{ NULL, 0, NULL, NULL },
|
||||
};
|
||||
|
||||
static MetaIntPreference preferences_int[] =
|
||||
{
|
||||
{ "/apps/metacity/general/num_workspaces",
|
||||
META_PREF_NUM_WORKSPACES,
|
||||
&num_workspaces,
|
||||
/* I would actually recommend we change the destroy value to 4
|
||||
* and get rid of METAINTPREFERENCE_NO_CHANGE_ON_DESTROY entirely.
|
||||
* -- tthurman
|
||||
*/
|
||||
1, MAX_REASONABLE_WORKSPACES, METAINTPREFERENCE_NO_CHANGE_ON_DESTROY,
|
||||
},
|
||||
{ "/apps/metacity/general/auto_raise_delay",
|
||||
META_PREF_AUTO_RAISE_DELAY,
|
||||
&auto_raise_delay,
|
||||
0, 10000, 0,
|
||||
/* @@@ Get rid of MAX_REASONABLE_AUTO_RAISE_DELAY */
|
||||
},
|
||||
{ "/desktop/gnome/peripherals/mouse/cursor_size",
|
||||
META_PREF_CURSOR_SIZE,
|
||||
&cursor_size,
|
||||
1, 128, 24,
|
||||
},
|
||||
{ NULL, 0, NULL, 0, 0, 0, },
|
||||
};
|
||||
|
||||
static void
|
||||
handle_preference_init_enum (void)
|
||||
{
|
||||
@ -510,6 +562,44 @@ handle_preference_init_string (void)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
handle_preference_init_int (void)
|
||||
{
|
||||
MetaIntPreference *cursor = preferences_int;
|
||||
|
||||
|
||||
while (cursor->key!=NULL)
|
||||
{
|
||||
gint value;
|
||||
GError *error = NULL;
|
||||
|
||||
value = gconf_client_get_int (default_client,
|
||||
cursor->key,
|
||||
&error);
|
||||
cleanup_error (&error);
|
||||
|
||||
if (value < cursor->minimum || value > cursor->maximum)
|
||||
{
|
||||
meta_warning (_("%d stored in GConf key %s is out of range %d to %d\n"),
|
||||
value, cursor->key, cursor->minimum, cursor->maximum);
|
||||
/* Former behaviour for out-of-range values was:
|
||||
* - number of workspaces was clamped;
|
||||
* - auto raise delay was always reset to zero even if too high!;
|
||||
* - cursor size was ignored.
|
||||
*
|
||||
* These seem to be meaningless variations. If they did
|
||||
* have meaning we could have put them into MetaIntPreference.
|
||||
* The last of these is the closest to how we behave for
|
||||
* other types, so I think we should standardise on that.
|
||||
*/
|
||||
}
|
||||
else if (cursor->target)
|
||||
*cursor->target = value;
|
||||
|
||||
++cursor;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_preference_update_enum (const gchar *key, GConfValue *value)
|
||||
{
|
||||
@ -689,6 +779,70 @@ handle_preference_update_string (const gchar *key, GConfValue *value)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
handle_preference_update_int (const gchar *key, GConfValue *value)
|
||||
{
|
||||
MetaIntPreference *cursor = preferences_int;
|
||||
gint new_value;
|
||||
|
||||
while (cursor->key!=NULL && strcmp (key, cursor->key)!=0)
|
||||
++cursor;
|
||||
|
||||
if (cursor->key==NULL)
|
||||
/* Didn't recognise that key. */
|
||||
return FALSE;
|
||||
|
||||
if (cursor->target==NULL)
|
||||
/* No work for us to do. */
|
||||
return TRUE;
|
||||
|
||||
if (value==NULL)
|
||||
{
|
||||
/* Value was destroyed. */
|
||||
|
||||
if (cursor->value_if_destroyed != METAINTPREFERENCE_NO_CHANGE_ON_DESTROY)
|
||||
*((gint *)cursor->target) = cursor->value_if_destroyed;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Check the type. */
|
||||
|
||||
if (value->type != GCONF_VALUE_INT)
|
||||
{
|
||||
meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
|
||||
key);
|
||||
/* But we did recognise it. */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
new_value = gconf_value_get_int (value);
|
||||
|
||||
if (new_value < cursor->minimum || new_value > cursor->maximum)
|
||||
{
|
||||
meta_warning (_("%d stored in GConf key %s is out of range %d to %d\n"),
|
||||
new_value, cursor->key,
|
||||
cursor->minimum, cursor->maximum);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Did it change? If so, tell the listeners about it. */
|
||||
|
||||
if (*cursor->target != new_value)
|
||||
{
|
||||
*cursor->target = new_value;
|
||||
queue_changed (cursor->pref);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Listeners. */
|
||||
/****************************************************************************/
|
||||
|
||||
void
|
||||
meta_prefs_add_listener (MetaPrefsChangedFunc func,
|
||||
gpointer data)
|
||||
@ -817,12 +971,18 @@ meta_prefs_remove_listener (MetaPrefsChangedFunc func,
|
||||
|
||||
#endif /* HAVE_GCONF */
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Initialisation. */
|
||||
/****************************************************************************/
|
||||
|
||||
/* @@@ again, use glib's ability to tell you the size of the array */
|
||||
static gchar *gconf_dirs_we_are_interested_in[] = {
|
||||
"/apps/metacity",
|
||||
KEY_TERMINAL_DIR,
|
||||
KEY_GNOME_ACCESSIBILITY,
|
||||
"/desktop/gnome/peripherals/mouse",
|
||||
"/desktop/gnome/interface",
|
||||
NULL,
|
||||
};
|
||||
|
||||
@ -831,8 +991,6 @@ meta_prefs_init (void)
|
||||
{
|
||||
#ifdef HAVE_GCONF
|
||||
GError *err = NULL;
|
||||
int int_val;
|
||||
GConfValue *gconf_val;
|
||||
gchar **gconf_dir_cursor;
|
||||
|
||||
if (default_client != NULL)
|
||||
@ -857,40 +1015,9 @@ meta_prefs_init (void)
|
||||
handle_preference_init_enum ();
|
||||
handle_preference_init_bool ();
|
||||
handle_preference_init_string ();
|
||||
handle_preference_init_int ();
|
||||
|
||||
/* To follow: initialisation with ordinary ints. */
|
||||
|
||||
/* Pick up initial values using the legacy system. */
|
||||
|
||||
gconf_val = gconf_client_get (default_client, KEY_AUTO_RAISE_DELAY,
|
||||
&err);
|
||||
cleanup_error (&err);
|
||||
if (gconf_val)
|
||||
{
|
||||
if (gconf_val->type == GCONF_VALUE_INT)
|
||||
update_auto_raise_delay (gconf_value_get_int (gconf_val));
|
||||
else
|
||||
meta_warning(_("Type of %s was not integer"), KEY_AUTO_RAISE_DELAY);
|
||||
|
||||
gconf_value_free (gconf_val);
|
||||
}
|
||||
|
||||
|
||||
/* If the keys aren't set in the database, we use essentially
|
||||
* bogus values instead of any kind of default. This is
|
||||
* just lazy. But they keys ought to be set, anyhow.
|
||||
*/
|
||||
|
||||
int_val = gconf_client_get_int (default_client, KEY_NUM_WORKSPACES,
|
||||
&err);
|
||||
cleanup_error (&err);
|
||||
update_num_workspaces (int_val);
|
||||
|
||||
int_val = gconf_client_get_int (default_client, KEY_CURSOR_SIZE,
|
||||
&err);
|
||||
cleanup_error (&err);
|
||||
update_cursor_size (int_val);
|
||||
|
||||
/* @@@ Is there any reason we don't do the add_dir here? */
|
||||
for (gconf_dir_cursor=gconf_dirs_we_are_interested_in;
|
||||
*gconf_dir_cursor!=NULL;
|
||||
gconf_dir_cursor++)
|
||||
@ -917,23 +1044,23 @@ meta_prefs_init (void)
|
||||
init_button_layout();
|
||||
#endif /* HAVE_GCONF */
|
||||
|
||||
/* Load keybindings prefs */
|
||||
init_bindings ();
|
||||
|
||||
/* commands */
|
||||
init_commands ();
|
||||
|
||||
/* workspace names */
|
||||
init_workspace_names ();
|
||||
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Updates. */
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef HAVE_GCONF
|
||||
|
||||
gboolean (*preference_update_handler[]) (const gchar*, GConfValue*) = {
|
||||
handle_preference_update_enum,
|
||||
handle_preference_update_bool,
|
||||
handle_preference_update_string,
|
||||
handle_preference_update_int,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -967,25 +1094,10 @@ change_notify (GConfClient *client,
|
||||
|
||||
/* Otherwise, use the enormous if statement. We'll move entries
|
||||
* out of here as it becomes possible to deal with them in a
|
||||
* more general way. */
|
||||
* more general way.
|
||||
*/
|
||||
|
||||
if (strcmp (key, KEY_NUM_WORKSPACES) == 0)
|
||||
{
|
||||
int d;
|
||||
|
||||
if (value && value->type != GCONF_VALUE_INT)
|
||||
{
|
||||
meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
|
||||
KEY_NUM_WORKSPACES);
|
||||
goto out;
|
||||
}
|
||||
|
||||
d = value ? gconf_value_get_int (value) : num_workspaces;
|
||||
|
||||
if (update_num_workspaces (d))
|
||||
queue_changed (META_PREF_NUM_WORKSPACES);
|
||||
}
|
||||
else if (g_str_has_prefix (key, KEY_WINDOW_BINDINGS_PREFIX))
|
||||
if (g_str_has_prefix (key, KEY_WINDOW_BINDINGS_PREFIX))
|
||||
{
|
||||
if (g_str_has_suffix (key, KEY_LIST_BINDINGS_SUFFIX))
|
||||
{
|
||||
@ -1055,23 +1167,6 @@ change_notify (GConfClient *client,
|
||||
queue_changed (META_PREF_SCREEN_KEYBINDINGS);
|
||||
}
|
||||
}
|
||||
else if (strcmp (key, KEY_AUTO_RAISE_DELAY) == 0)
|
||||
{
|
||||
int d;
|
||||
|
||||
if (value && value->type != GCONF_VALUE_INT)
|
||||
{
|
||||
meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
|
||||
KEY_AUTO_RAISE_DELAY);
|
||||
goto out;
|
||||
}
|
||||
|
||||
d = value ? gconf_value_get_int (value) : 0;
|
||||
|
||||
if (update_auto_raise_delay (d))
|
||||
queue_changed (META_PREF_AUTO_RAISE_DELAY);
|
||||
|
||||
}
|
||||
else if (g_str_has_prefix (key, KEY_COMMAND_PREFIX))
|
||||
{
|
||||
const char *str;
|
||||
@ -1104,22 +1199,6 @@ change_notify (GConfClient *client,
|
||||
if (update_workspace_name (key, str))
|
||||
queue_changed (META_PREF_WORKSPACE_NAMES);
|
||||
}
|
||||
else if (strcmp (key, KEY_CURSOR_SIZE) == 0)
|
||||
{
|
||||
int d;
|
||||
|
||||
if (value && value->type != GCONF_VALUE_INT)
|
||||
{
|
||||
meta_warning (_("GConf key \"%s\" is set to an invalid type\n"),
|
||||
KEY_CURSOR_SIZE);
|
||||
goto out;
|
||||
}
|
||||
|
||||
d = value ? gconf_value_get_int (value) : 24;
|
||||
|
||||
if (update_cursor_size (d))
|
||||
queue_changed (META_PREF_CURSOR_SIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_topic (META_DEBUG_PREFS, "Key %s doesn't mean anything to Metacity\n",
|
||||
@ -1144,6 +1223,7 @@ cleanup_error (GError **error)
|
||||
}
|
||||
|
||||
/* get_bool returns TRUE if *val is filled in, FALSE otherwise */
|
||||
/* @@@ probably worth moving this inline; only used once */
|
||||
static gboolean
|
||||
get_bool (const char *key, gboolean *val)
|
||||
{
|
||||
@ -1225,28 +1305,17 @@ meta_prefs_get_cursor_theme (void)
|
||||
return cursor_theme;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GCONF
|
||||
static gboolean
|
||||
update_cursor_size (int value)
|
||||
{
|
||||
int old = cursor_size;
|
||||
|
||||
if (value >= 1 && value <= 128)
|
||||
cursor_size = value;
|
||||
else
|
||||
meta_warning (_("%d stored in GConf key %s is not a reasonable cursor_size; must be in the range 1..128\n"),
|
||||
value, KEY_CURSOR_SIZE);
|
||||
|
||||
return old != value;
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
meta_prefs_get_cursor_size (void)
|
||||
{
|
||||
return cursor_size;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
||||
/* Handlers for string preferences. */
|
||||
/****************************************************************************/
|
||||
|
||||
#ifdef HAVE_GCONF
|
||||
|
||||
static void
|
||||
@ -1591,28 +1660,6 @@ meta_prefs_get_titlebar_font (void)
|
||||
return titlebar_font;
|
||||
}
|
||||
|
||||
#ifdef HAVE_GCONF
|
||||
static gboolean
|
||||
update_num_workspaces (int value)
|
||||
{
|
||||
int old = num_workspaces;
|
||||
|
||||
if (value < 1 || value > MAX_REASONABLE_WORKSPACES)
|
||||
{
|
||||
meta_warning (_("%d stored in GConf key %s is not a reasonable number of workspaces, current maximum is %d\n"),
|
||||
value, KEY_NUM_WORKSPACES, MAX_REASONABLE_WORKSPACES);
|
||||
if (value < 1)
|
||||
value = 1;
|
||||
else if (value > MAX_REASONABLE_WORKSPACES)
|
||||
value = MAX_REASONABLE_WORKSPACES;
|
||||
}
|
||||
|
||||
num_workspaces = value;
|
||||
|
||||
return old != num_workspaces;
|
||||
}
|
||||
#endif /* HAVE_GCONF */
|
||||
|
||||
int
|
||||
meta_prefs_get_num_workspaces (void)
|
||||
{
|
||||
@ -1636,24 +1683,6 @@ meta_prefs_get_disable_workarounds (void)
|
||||
#ifdef HAVE_GCONF
|
||||
#define MAX_REASONABLE_AUTO_RAISE_DELAY 10000
|
||||
|
||||
static gboolean
|
||||
update_auto_raise_delay (int value)
|
||||
{
|
||||
int old = auto_raise_delay;
|
||||
|
||||
if (value < 0 || value > MAX_REASONABLE_AUTO_RAISE_DELAY)
|
||||
{
|
||||
meta_warning (_("%d stored in GConf key %s is out of range 0 to %d\n"),
|
||||
value, KEY_AUTO_RAISE_DELAY,
|
||||
MAX_REASONABLE_AUTO_RAISE_DELAY);
|
||||
value = 0;
|
||||
}
|
||||
|
||||
auto_raise_delay = value;
|
||||
|
||||
return old != auto_raise_delay;
|
||||
}
|
||||
|
||||
#endif /* HAVE_GCONF */
|
||||
|
||||
#ifdef WITH_VERBOSE_MODE
|
||||
@ -1738,6 +1767,9 @@ meta_preference_to_string (MetaPreference pref)
|
||||
case META_PREF_GNOME_ACCESSIBILITY:
|
||||
return "GNOME_ACCESSIBILTY";
|
||||
|
||||
case META_PREF_GNOME_ANIMATIONS:
|
||||
return "GNOME_ANIMATIONS";
|
||||
|
||||
case META_PREF_CURSOR_THEME:
|
||||
return "CURSOR_THEME";
|
||||
|
||||
@ -2840,6 +2872,12 @@ meta_prefs_get_gnome_accessibility ()
|
||||
return gnome_accessibility;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_prefs_get_gnome_animations ()
|
||||
{
|
||||
return gnome_animations;
|
||||
}
|
||||
|
||||
MetaKeyBindingAction
|
||||
meta_prefs_get_keybinding_action (const char *name)
|
||||
{
|
||||
|
322
src/core/stack.c
322
src/core/stack.c
@ -1,6 +1,8 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Metacity Window Stack */
|
||||
/**
|
||||
* \file stack.c Which windows cover which other windows
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
@ -49,9 +51,16 @@
|
||||
|
||||
#define WINDOW_IN_STACK(w) (w->stack_position >= 0)
|
||||
|
||||
static void meta_stack_sync_to_server (MetaStack *stack);
|
||||
static void stack_sync_to_server (MetaStack *stack);
|
||||
static void meta_window_set_stack_position_no_sync (MetaWindow *window,
|
||||
int position);
|
||||
static void stack_do_window_deletions (MetaStack *stack);
|
||||
static void stack_do_window_additions (MetaStack *stack);
|
||||
static void stack_do_relayer (MetaStack *stack);
|
||||
static void stack_do_constrain (MetaStack *stack);
|
||||
static void stack_do_resort (MetaStack *stack);
|
||||
|
||||
static void stack_ensure_sorted (MetaStack *stack);
|
||||
|
||||
MetaStack*
|
||||
meta_stack_new (MetaScreen *screen)
|
||||
@ -111,7 +120,7 @@ meta_stack_add (MetaStack *stack,
|
||||
"Window %s has stack_position initialized to %d\n",
|
||||
window->desc, window->stack_position);
|
||||
|
||||
meta_stack_sync_to_server (stack);
|
||||
stack_sync_to_server (stack);
|
||||
}
|
||||
|
||||
void
|
||||
@ -136,12 +145,17 @@ meta_stack_remove (MetaStack *stack,
|
||||
stack->added = g_list_remove (stack->added, window);
|
||||
stack->sorted = g_list_remove (stack->sorted, window);
|
||||
|
||||
/* Remember the window ID to remove it from the stack array */
|
||||
stack->removed = g_list_prepend (stack->removed, (void*) window->xwindow);
|
||||
/* Remember the window ID to remove it from the stack array.
|
||||
* The macro is safe to use: Window is guaranteed to be 32 bits, and
|
||||
* GUINT_TO_POINTER says it only works on 32 bits.
|
||||
*/
|
||||
stack->removed = g_list_prepend (stack->removed,
|
||||
GUINT_TO_POINTER (window->xwindow));
|
||||
if (window->frame)
|
||||
stack->removed = g_list_prepend (stack->removed, (void*) window->frame->xwindow);
|
||||
stack->removed = g_list_prepend (stack->removed,
|
||||
GUINT_TO_POINTER (window->frame->xwindow));
|
||||
|
||||
meta_stack_sync_to_server (stack);
|
||||
stack_sync_to_server (stack);
|
||||
}
|
||||
|
||||
void
|
||||
@ -150,7 +164,7 @@ meta_stack_update_layer (MetaStack *stack,
|
||||
{
|
||||
stack->need_relayer = TRUE;
|
||||
|
||||
meta_stack_sync_to_server (stack);
|
||||
stack_sync_to_server (stack);
|
||||
}
|
||||
|
||||
void
|
||||
@ -159,7 +173,7 @@ meta_stack_update_transient (MetaStack *stack,
|
||||
{
|
||||
stack->need_constrain = TRUE;
|
||||
|
||||
meta_stack_sync_to_server (stack);
|
||||
stack_sync_to_server (stack);
|
||||
}
|
||||
|
||||
/* raise/lower within a layer */
|
||||
@ -170,7 +184,7 @@ meta_stack_raise (MetaStack *stack,
|
||||
meta_window_set_stack_position_no_sync (window,
|
||||
stack->n_positions - 1);
|
||||
|
||||
meta_stack_sync_to_server (stack);
|
||||
stack_sync_to_server (stack);
|
||||
}
|
||||
|
||||
void
|
||||
@ -179,10 +193,9 @@ meta_stack_lower (MetaStack *stack,
|
||||
{
|
||||
meta_window_set_stack_position_no_sync (window, 0);
|
||||
|
||||
meta_stack_sync_to_server (stack);
|
||||
stack_sync_to_server (stack);
|
||||
}
|
||||
|
||||
/* Prevent syncing to server until thaw */
|
||||
void
|
||||
meta_stack_freeze (MetaStack *stack)
|
||||
{
|
||||
@ -195,7 +208,7 @@ meta_stack_thaw (MetaStack *stack)
|
||||
g_return_if_fail (stack->freeze_count > 0);
|
||||
|
||||
stack->freeze_count -= 1;
|
||||
meta_stack_sync_to_server (stack);
|
||||
stack_sync_to_server (stack);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@ -710,54 +723,24 @@ apply_constraints (Constraint **constraints,
|
||||
g_slist_free (heads);
|
||||
}
|
||||
|
||||
/**
|
||||
* Go through "deleted" and take the matching windows
|
||||
* out of "windows".
|
||||
*/
|
||||
static void
|
||||
constrain_stacking (MetaStack *stack)
|
||||
stack_do_window_deletions (MetaStack *stack)
|
||||
{
|
||||
Constraint **constraints;
|
||||
|
||||
/* It'd be nice if this were all faster, probably */
|
||||
|
||||
if (!stack->need_constrain)
|
||||
return;
|
||||
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Reapplying constraints\n");
|
||||
|
||||
constraints = g_new0 (Constraint*,
|
||||
stack->n_positions);
|
||||
|
||||
create_constraints (constraints, stack->sorted);
|
||||
|
||||
graph_constraints (constraints, stack->n_positions);
|
||||
|
||||
apply_constraints (constraints, stack->n_positions);
|
||||
|
||||
free_constraints (constraints, stack->n_positions);
|
||||
g_free (constraints);
|
||||
|
||||
stack->need_constrain = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_stack_ensure_sorted (MetaStack *stack)
|
||||
{
|
||||
GList *tmp;
|
||||
int i;
|
||||
int n_added;
|
||||
|
||||
/* Note that the additions, relayers, reconstrains
|
||||
* may all set need_resort to TRUE
|
||||
*/
|
||||
|
||||
/* Do removals before adds, with paranoid idea that we might re-add
|
||||
* the same window IDs.
|
||||
*/
|
||||
GList *tmp;
|
||||
int i;
|
||||
|
||||
tmp = stack->removed;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
Window xwindow;
|
||||
|
||||
xwindow = (unsigned long) tmp->data;
|
||||
xwindow = GPOINTER_TO_UINT (tmp->data);
|
||||
|
||||
/* We go from the end figuring removals are more
|
||||
* likely to be recent.
|
||||
@ -785,8 +768,15 @@ meta_stack_ensure_sorted (MetaStack *stack)
|
||||
}
|
||||
|
||||
g_list_free (stack->removed);
|
||||
stack->removed = NULL;
|
||||
|
||||
stack->removed = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
stack_do_window_additions (MetaStack *stack)
|
||||
{
|
||||
GList *tmp;
|
||||
gint i, n_added;
|
||||
|
||||
n_added = g_list_length (stack->added);
|
||||
if (n_added > 0)
|
||||
{
|
||||
@ -831,77 +821,138 @@ meta_stack_ensure_sorted (MetaStack *stack)
|
||||
|
||||
g_list_free (stack->added);
|
||||
stack->added = NULL;
|
||||
|
||||
/* Update the layers that windows are in */
|
||||
if (stack->need_relayer)
|
||||
{
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Recomputing layers\n");
|
||||
|
||||
tmp = stack->sorted;
|
||||
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *w;
|
||||
MetaStackLayer old_layer;
|
||||
|
||||
w = tmp->data;
|
||||
old_layer = w->layer;
|
||||
|
||||
compute_layer (w);
|
||||
|
||||
if (w->layer != old_layer)
|
||||
{
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Window %s moved from layer %u to %u\n",
|
||||
w->desc, old_layer, w->layer);
|
||||
|
||||
stack->need_resort = TRUE;
|
||||
stack->need_constrain = TRUE;
|
||||
/* don't need to constrain as constraining
|
||||
* purely operates in terms of stack_position
|
||||
* not layer
|
||||
*/
|
||||
}
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
stack->need_relayer = FALSE;
|
||||
}
|
||||
|
||||
/* Update stack_position and layer to reflect transiency
|
||||
constraints */
|
||||
constrain_stacking (stack);
|
||||
|
||||
/* Sort stack->sorted with layers having priority over stack_position
|
||||
*/
|
||||
|
||||
if (stack->need_resort)
|
||||
{
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Sorting stack list\n");
|
||||
|
||||
stack->sorted = g_list_sort (stack->sorted, (GCompareFunc) compare_window_position);
|
||||
|
||||
stack->need_resort = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the layers that windows are in
|
||||
*/
|
||||
static void
|
||||
stack_do_relayer (MetaStack *stack)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
if (!stack->need_relayer)
|
||||
return;
|
||||
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Recomputing layers\n");
|
||||
|
||||
tmp = stack->sorted;
|
||||
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaWindow *w;
|
||||
MetaStackLayer old_layer;
|
||||
|
||||
w = tmp->data;
|
||||
old_layer = w->layer;
|
||||
|
||||
compute_layer (w);
|
||||
|
||||
if (w->layer != old_layer)
|
||||
{
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Window %s moved from layer %u to %u\n",
|
||||
w->desc, old_layer, w->layer);
|
||||
|
||||
stack->need_resort = TRUE;
|
||||
stack->need_constrain = TRUE;
|
||||
/* don't need to constrain as constraining
|
||||
* purely operates in terms of stack_position
|
||||
* not layer
|
||||
*/
|
||||
}
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
stack->need_relayer = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update stack_position and layer to reflect transiency
|
||||
* constraints
|
||||
*/
|
||||
static void
|
||||
stack_do_constrain (MetaStack *stack)
|
||||
{
|
||||
Constraint **constraints;
|
||||
|
||||
/* It'd be nice if this were all faster, probably */
|
||||
|
||||
if (!stack->need_constrain)
|
||||
return;
|
||||
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Reapplying constraints\n");
|
||||
|
||||
constraints = g_new0 (Constraint*,
|
||||
stack->n_positions);
|
||||
|
||||
create_constraints (constraints, stack->sorted);
|
||||
|
||||
graph_constraints (constraints, stack->n_positions);
|
||||
|
||||
apply_constraints (constraints, stack->n_positions);
|
||||
|
||||
free_constraints (constraints, stack->n_positions);
|
||||
g_free (constraints);
|
||||
|
||||
stack->need_constrain = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort stack->sorted with layers having priority over stack_position.
|
||||
*/
|
||||
static void
|
||||
stack_do_resort (MetaStack *stack)
|
||||
{
|
||||
if (!stack->need_resort)
|
||||
return;
|
||||
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Sorting stack list\n");
|
||||
|
||||
stack->sorted = g_list_sort (stack->sorted,
|
||||
(GCompareFunc) compare_window_position);
|
||||
|
||||
stack->need_resort = FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts the stack into canonical form.
|
||||
*
|
||||
* Honour the removed and added lists of the stack, and then recalculate
|
||||
* all the layers (if the flag is set), re-run all the constraint calculations
|
||||
* (if the flag is set), and finally re-sort the stack (if the flag is set,
|
||||
* and if it wasn't already it might have become so during all the previous
|
||||
* activity).
|
||||
*/
|
||||
static void
|
||||
stack_ensure_sorted (MetaStack *stack)
|
||||
{
|
||||
stack_do_window_deletions (stack);
|
||||
stack_do_window_additions (stack);
|
||||
stack_do_relayer (stack);
|
||||
stack_do_constrain (stack);
|
||||
stack_do_resort (stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is used to avoid raising a window above popup
|
||||
* menus and other such things.
|
||||
*
|
||||
* FIXME This is sort of an expensive function, should probably
|
||||
* do something to avoid it. One approach would be to reverse
|
||||
* the stacking algorithm to work by placing each window above
|
||||
* the others, and start by lowering a window to the bottom
|
||||
* (instead of the current way, which works by placing each
|
||||
* window below another and starting with a raise)
|
||||
*/
|
||||
static void
|
||||
raise_window_relative_to_managed_windows (MetaScreen *screen,
|
||||
Window xwindow)
|
||||
{
|
||||
/* This function is used to avoid raising a window above popup
|
||||
* menus and other such things.
|
||||
*
|
||||
* FIXME This is sort of an expensive function, should probably
|
||||
* do something to avoid it. One approach would be to reverse
|
||||
* the stacking algorithm to work by placing each window above
|
||||
* the others, and start by lowering a window to the bottom
|
||||
* (instead of the current way, which works by placing each
|
||||
* window below another and starting with a raise)
|
||||
*/
|
||||
|
||||
Window ignored1, ignored2;
|
||||
Window *children;
|
||||
@ -987,8 +1038,15 @@ raise_window_relative_to_managed_windows (MetaScreen *screen,
|
||||
XFree (children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Order the windows on the X server to be the same as in our structure.
|
||||
* We do this using XRestackWindows if we don't know the previous order,
|
||||
* or XConfigureWindow on a few particular windows if we do and can figure
|
||||
* out the minimum set of changes. After that, we set __NET_CLIENT_LIST
|
||||
* and __NET_CLIENT_LIST_STACKING.
|
||||
*/
|
||||
static void
|
||||
meta_stack_sync_to_server (MetaStack *stack)
|
||||
stack_sync_to_server (MetaStack *stack)
|
||||
{
|
||||
GArray *stacked;
|
||||
GArray *root_children_stacked;
|
||||
@ -1000,7 +1058,7 @@ meta_stack_sync_to_server (MetaStack *stack)
|
||||
|
||||
meta_topic (META_DEBUG_STACK, "Syncing window stack to server\n");
|
||||
|
||||
meta_stack_ensure_sorted (stack);
|
||||
stack_ensure_sorted (stack);
|
||||
|
||||
/* Create stacked xwindow arrays.
|
||||
* Painfully, "stacked" is in bottom-to-top order for the
|
||||
@ -1184,7 +1242,7 @@ meta_stack_sync_to_server (MetaStack *stack)
|
||||
MetaWindow*
|
||||
meta_stack_get_top (MetaStack *stack)
|
||||
{
|
||||
meta_stack_ensure_sorted (stack);
|
||||
stack_ensure_sorted (stack);
|
||||
|
||||
if (stack->sorted)
|
||||
return stack->sorted->data;
|
||||
@ -1197,7 +1255,7 @@ meta_stack_get_bottom (MetaStack *stack)
|
||||
{
|
||||
GList *link;
|
||||
|
||||
meta_stack_ensure_sorted (stack);
|
||||
stack_ensure_sorted (stack);
|
||||
|
||||
link = g_list_last (stack->sorted);
|
||||
if (link != NULL)
|
||||
@ -1214,7 +1272,7 @@ meta_stack_get_above (MetaStack *stack,
|
||||
GList *link;
|
||||
MetaWindow *above;
|
||||
|
||||
meta_stack_ensure_sorted (stack);
|
||||
stack_ensure_sorted (stack);
|
||||
|
||||
link = g_list_find (stack->sorted, window);
|
||||
if (link == NULL)
|
||||
@ -1239,7 +1297,7 @@ meta_stack_get_below (MetaStack *stack,
|
||||
GList *link;
|
||||
MetaWindow *below;
|
||||
|
||||
meta_stack_ensure_sorted (stack);
|
||||
stack_ensure_sorted (stack);
|
||||
|
||||
link = g_list_find (stack->sorted, window);
|
||||
|
||||
@ -1299,7 +1357,7 @@ get_default_focus_window (MetaStack *stack,
|
||||
else
|
||||
not_this_one_group = NULL;
|
||||
|
||||
meta_stack_ensure_sorted (stack);
|
||||
stack_ensure_sorted (stack);
|
||||
|
||||
/* top of this layer is at the front of the list */
|
||||
link = stack->sorted;
|
||||
@ -1392,7 +1450,7 @@ meta_stack_list_windows (MetaStack *stack,
|
||||
GList *workspace_windows = NULL;
|
||||
GList *link;
|
||||
|
||||
meta_stack_ensure_sorted (stack); /* do adds/removes */
|
||||
stack_ensure_sorted (stack); /* do adds/removes */
|
||||
|
||||
link = stack->sorted;
|
||||
|
||||
@ -1422,7 +1480,7 @@ meta_stack_windows_cmp (MetaStack *stack,
|
||||
|
||||
/* -1 means a below b */
|
||||
|
||||
meta_stack_ensure_sorted (stack); /* update constraints, layers */
|
||||
stack_ensure_sorted (stack); /* update constraints, layers */
|
||||
|
||||
if (window_a->layer < window_b->layer)
|
||||
return -1;
|
||||
@ -1457,7 +1515,7 @@ meta_stack_get_positions (MetaStack *stack)
|
||||
GList *tmp;
|
||||
|
||||
/* Make sure to handle any adds or removes */
|
||||
meta_stack_ensure_sorted (stack);
|
||||
stack_ensure_sorted (stack);
|
||||
|
||||
tmp = g_list_copy (stack->sorted);
|
||||
tmp = g_list_sort (tmp, (GCompareFunc) compare_just_window_stack_position);
|
||||
@ -1510,7 +1568,7 @@ meta_stack_set_positions (MetaStack *stack,
|
||||
GList *tmp;
|
||||
|
||||
/* Make sure any adds or removes aren't in limbo -- is this needed? */
|
||||
meta_stack_ensure_sorted (stack);
|
||||
stack_ensure_sorted (stack);
|
||||
|
||||
if (!lists_contain_same_windows (windows, stack->sorted))
|
||||
{
|
||||
@ -1537,7 +1595,7 @@ meta_stack_set_positions (MetaStack *stack,
|
||||
meta_topic (META_DEBUG_STACK,
|
||||
"Reset the stack positions of (nearly) all windows\n");
|
||||
|
||||
meta_stack_sync_to_server (stack);
|
||||
stack_sync_to_server (stack);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1599,5 +1657,5 @@ meta_window_set_stack_position (MetaWindow *window,
|
||||
int position)
|
||||
{
|
||||
meta_window_set_stack_position_no_sync (window, position);
|
||||
meta_stack_sync_to_server (window->screen->stack);
|
||||
stack_sync_to_server (window->screen->stack);
|
||||
}
|
||||
|
323
src/core/stack.h
323
src/core/stack.h
@ -1,6 +1,22 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* Metacity Window Stack */
|
||||
/**
|
||||
* \file stack.h Which windows cover which other windows
|
||||
*
|
||||
* There are two factors that determine window position.
|
||||
*
|
||||
* One is window->stack_position, which is a unique integer
|
||||
* indicating how windows are ordered with respect to one
|
||||
* another. The ordering here transcends layers; it isn't changed
|
||||
* as the window is moved among layers. This allows us to move several
|
||||
* windows from one layer to another, while preserving the relative
|
||||
* order of the moved windows. Also, it allows us to restore
|
||||
* the stacking order from a saved session.
|
||||
*
|
||||
* However when actually stacking windows on the screen, the
|
||||
* layer overrides the stack_position; windows are first sorted
|
||||
* by layer, then by stack_position within each layer.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
@ -27,26 +43,10 @@
|
||||
|
||||
#include "screen-private.h"
|
||||
|
||||
/* Layers vs. stack positions
|
||||
* ==========================
|
||||
*
|
||||
* There are two factors that determine window position.
|
||||
*
|
||||
* One is window->stack_position, which is a unique integer
|
||||
* indicating how windows are ordered with respect to one
|
||||
* another. The ordering here transcends layers; it isn't changed
|
||||
* as the window is moved among layers. This allows us to move several
|
||||
* windows from one layer to another, while preserving the relative
|
||||
* order of the moved windows. Also, it allows us to restore
|
||||
* the stacking order from a saved session.
|
||||
*
|
||||
* However when actually stacking windows on the screen, the
|
||||
* layer overrides the stack_position; windows are first sorted
|
||||
* by layer, then by stack_position within each layer.
|
||||
*
|
||||
/**
|
||||
* Layers a window can be in.
|
||||
* These MUST be in the order of stacking.
|
||||
*/
|
||||
|
||||
/* These MUST be in the order of stacking */
|
||||
typedef enum
|
||||
{
|
||||
META_LAYER_DESKTOP = 0,
|
||||
@ -59,90 +59,343 @@ typedef enum
|
||||
META_LAYER_LAST = 7
|
||||
} MetaStackLayer;
|
||||
|
||||
/**
|
||||
* A sorted list of windows bearing some level of resemblance to the stack of
|
||||
* windows on the X server.
|
||||
*
|
||||
* (This is only used as a field within a MetaScreen; we treat it as a separate
|
||||
* class for simplicity.)
|
||||
*/
|
||||
struct _MetaStack
|
||||
{
|
||||
/** The MetaScreen containing this stack. */
|
||||
MetaScreen *screen;
|
||||
|
||||
/* All X windows that we manage, in mapping order,
|
||||
* for _NET_CLIENT_LIST
|
||||
/**
|
||||
* A sequence of all the Windows (X handles, not MetaWindows) of the windows
|
||||
* we manage, sorted in order. Suitable to be passed into _NET_CLIENT_LIST.
|
||||
*/
|
||||
GArray *windows;
|
||||
|
||||
/* Currently-stacked MetaWindow */
|
||||
/** The MetaWindows of the windows we manage, sorted in order. */
|
||||
GList *sorted;
|
||||
/* MetaWindow to be added to the sorted list */
|
||||
|
||||
/**
|
||||
* MetaWindows waiting to be added to the "sorted" and "windows" list, after
|
||||
* being added by meta_stack_add() and before being assimilated by
|
||||
* stack_ensure_sorted().
|
||||
*
|
||||
* The order of the elements in this list is not important; what is important
|
||||
* is the stack_position element of each window.
|
||||
*/
|
||||
GList *added;
|
||||
/* Window IDs to be removed from the stack */
|
||||
|
||||
/**
|
||||
* Windows (X handles, not MetaWindows) waiting to be removed from the
|
||||
* "windows" list, after being removed by meta_stack_remove() and before
|
||||
* being assimilated by stack_ensure_sorted(). (We already removed them
|
||||
* from the "sorted" list.)
|
||||
*
|
||||
* The order of the elements in this list is not important.
|
||||
*/
|
||||
GList *removed;
|
||||
|
||||
/**
|
||||
* If this is zero, the local stack oughtn't to be brought up to date with
|
||||
* the X server's stack, because it is in the middle of being updated.
|
||||
* If it is positive, the local stack is said to be "frozen", and will need
|
||||
* to be thawed that many times before the stack can be brought up to date
|
||||
* again. You may freeze the stack with meta_stack_freeze() and thaw it
|
||||
* with meta_stack_thaw().
|
||||
*/
|
||||
int freeze_count;
|
||||
|
||||
/* The last-known stack */
|
||||
/**
|
||||
* The last-known stack of all windows, bottom to top. We cache it here
|
||||
* so that subsequent times we'll be able to do incremental moves.
|
||||
*/
|
||||
GArray *last_root_children_stacked;
|
||||
|
||||
/* number of stack positions */
|
||||
int n_positions;
|
||||
/**
|
||||
* Number of stack positions; same as the length of added, but
|
||||
* kept for quick reference.
|
||||
*/
|
||||
gint n_positions;
|
||||
|
||||
/* What needs doing */
|
||||
/** Is the stack in need of re-sorting? */
|
||||
unsigned int need_resort : 1;
|
||||
|
||||
/**
|
||||
* Are the windows in the stack in need of having their
|
||||
* layers recalculated?
|
||||
*/
|
||||
unsigned int need_relayer : 1;
|
||||
|
||||
/**
|
||||
* Are the windows in the stack in need of having their positions
|
||||
* recalculated with respect to transiency (parent and child windows)?
|
||||
*/
|
||||
unsigned int need_constrain : 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates and initialises a MetaStack.
|
||||
*
|
||||
* \param screen The MetaScreen which will be the parent of this stack.
|
||||
* \return The new screen.
|
||||
*/
|
||||
MetaStack *meta_stack_new (MetaScreen *screen);
|
||||
|
||||
/**
|
||||
* Destroys and frees a MetaStack.
|
||||
*
|
||||
* \param stack The stack to destroy.
|
||||
*/
|
||||
void meta_stack_free (MetaStack *stack);
|
||||
|
||||
/**
|
||||
* Adds a window to the local stack. It is a fatal error to call this
|
||||
* function on a window which already exists on the stack of any screen.
|
||||
*
|
||||
* \param window The window to add
|
||||
* \param stack The stack to add it to
|
||||
*/
|
||||
void meta_stack_add (MetaStack *stack,
|
||||
MetaWindow *window);
|
||||
|
||||
/**
|
||||
* Removes a window from the local stack. It is a fatal error to call this
|
||||
* function on a window which exists on the stack of any screen.
|
||||
*
|
||||
* \param window The window to remove
|
||||
* \param stack The stack to remove it from
|
||||
*/
|
||||
void meta_stack_remove (MetaStack *stack,
|
||||
MetaWindow *window);
|
||||
/* re-read layer-related hints */
|
||||
/**
|
||||
* Recalculates the correct layer for all windows in the stack,
|
||||
* and moves them about accordingly.
|
||||
*
|
||||
* \param window Dummy parameter
|
||||
* \param stack The stack to recalculate
|
||||
* \bug What's with the dummy parameter?
|
||||
*/
|
||||
void meta_stack_update_layer (MetaStack *stack,
|
||||
MetaWindow *window);
|
||||
/* reconsider transient_for */
|
||||
|
||||
/**
|
||||
* Recalculates the correct stacking order for all windows in the stack
|
||||
* according to their transience, and moves them about accordingly.
|
||||
*
|
||||
* \param window Dummy parameter
|
||||
* \param stack The stack to recalculate
|
||||
* \bug What's with the dummy parameter?
|
||||
*/
|
||||
void meta_stack_update_transient (MetaStack *stack,
|
||||
MetaWindow *window);
|
||||
|
||||
/* raise/lower within a layer */
|
||||
/**
|
||||
* Move a window to the top of its layer.
|
||||
*
|
||||
* \param stack The stack to modify.
|
||||
* \param window The window that's making an ascension.
|
||||
* (Amulet of Yendor not required.)
|
||||
*/
|
||||
void meta_stack_raise (MetaStack *stack,
|
||||
MetaWindow *window);
|
||||
/**
|
||||
* Move a window to the bottom of its layer.
|
||||
*
|
||||
* \param stack The stack to modify.
|
||||
* \param window The window that's on the way downwards.
|
||||
*/
|
||||
void meta_stack_lower (MetaStack *stack,
|
||||
MetaWindow *window);
|
||||
|
||||
/* On thaw, process pending and sync to server */
|
||||
/**
|
||||
* Prevent syncing to server until the next call of meta_stack_thaw(),
|
||||
* so that we can carry out multiple operations in one go without having
|
||||
* everything halfway reflected on the X server.
|
||||
*
|
||||
* (Calls to meta_stack_freeze() nest, so that multiple calls to
|
||||
* meta_stack_freeze will require multiple calls to meta_stack_thaw().)
|
||||
*
|
||||
* \param stack The stack to freeze.
|
||||
*/
|
||||
void meta_stack_freeze (MetaStack *stack);
|
||||
|
||||
/**
|
||||
* Undoes a meta_stack_freeze(), and processes anything which has become
|
||||
* necessary during the freeze. It is an error to call this function if
|
||||
* the stack has not been frozen.
|
||||
*
|
||||
* \param stack The stack to thaw.
|
||||
*/
|
||||
void meta_stack_thaw (MetaStack *stack);
|
||||
|
||||
/**
|
||||
* Finds the top window on the stack.
|
||||
*
|
||||
* \param stack The stack to examine.
|
||||
* \return The top window on the stack, or NULL in the vanishingly unlikely
|
||||
* event that you have no windows on your screen whatsoever.
|
||||
*/
|
||||
MetaWindow* meta_stack_get_top (MetaStack *stack);
|
||||
|
||||
/**
|
||||
* Finds the window at the bottom of the stack. Since that's pretty much
|
||||
* always the desktop, this isn't the most useful of functions, and nobody
|
||||
* actually calls it. We should probably get rid of it.
|
||||
*
|
||||
* \param stack The stack to search
|
||||
*/
|
||||
MetaWindow* meta_stack_get_bottom (MetaStack *stack);
|
||||
|
||||
/**
|
||||
* Finds the window above a given window in the stack.
|
||||
* It is not an error to pass in a window which does not exist in
|
||||
* the stack; the function will merely return NULL.
|
||||
*
|
||||
* \param stack The stack to search.
|
||||
* \param window The window to look above.
|
||||
* \param only_within_layer If true, will return NULL if "window" is the
|
||||
* top window in its layer.
|
||||
* \return NULL if there is no such window;
|
||||
* the window above "window" otherwise.
|
||||
*/
|
||||
MetaWindow* meta_stack_get_above (MetaStack *stack,
|
||||
MetaWindow *window,
|
||||
gboolean only_within_layer);
|
||||
|
||||
/**
|
||||
* Finds the window below a given window in the stack.
|
||||
* It is not an error to pass in a window which does not exist in
|
||||
* the stack; the function will merely return NULL.
|
||||
*
|
||||
* \param stack The stack to search.
|
||||
* \param window The window to look below.
|
||||
* \param only_within_layer If true, will return NULL if "window" is the
|
||||
* bottom window in its layer.
|
||||
* \return NULL if there is no such window;
|
||||
* the window below "window" otherwise.
|
||||
*/
|
||||
MetaWindow* meta_stack_get_below (MetaStack *stack,
|
||||
MetaWindow *window,
|
||||
gboolean only_within_layer);
|
||||
|
||||
/**
|
||||
* Find the topmost, focusable, mapped, window in a stack. If you supply
|
||||
* a window as "not_this_one", we won't return that one (presumably
|
||||
* because it's going to be going away). But if you do supply "not_this_one"
|
||||
* and we find its parent, we'll return that; and if "not_this_one" is in
|
||||
* a group, we'll return the top window of that group.
|
||||
*
|
||||
* Also, we are prejudiced against dock windows. Every kind of window, even
|
||||
* the desktop, will be returned in preference to a dock window.
|
||||
*
|
||||
* \param stack The stack to search.
|
||||
* \param workspace NULL to search all workspaces; otherwise only windows
|
||||
* from that workspace will be returned.
|
||||
* \param not_this_one Window to ignore because it's being unfocussed or
|
||||
* going away.
|
||||
* \return The window matching all these constraints or NULL if none does.
|
||||
*
|
||||
* \bug Never called!
|
||||
*/
|
||||
MetaWindow* meta_stack_get_default_focus_window (MetaStack *stack,
|
||||
MetaWorkspace *workspace,
|
||||
MetaWindow *not_this_one);
|
||||
|
||||
/**
|
||||
* Find the topmost, focusable, mapped, window in a stack. If you supply
|
||||
* a window as "not_this_one", we won't return that one (presumably
|
||||
* because it's going to be going away). But if you do supply "not_this_one"
|
||||
* and we find its parent, we'll return that; and if "not_this_one" is in
|
||||
* a group, we'll return the top window of that group.
|
||||
*
|
||||
* Also, we are prejudiced against dock windows. Every kind of window, even
|
||||
* the desktop, will be returned in preference to a dock window.
|
||||
*
|
||||
* \param stack The stack to search.
|
||||
* \param workspace NULL to search all workspaces; otherwise only windows
|
||||
* from that workspace will be returned.
|
||||
* \param not_this_one Window to ignore because it's being unfocussed or
|
||||
* going away.
|
||||
* \param root_x The returned window must contain this point,
|
||||
* unless it's a dock.
|
||||
* \param root_y See root_x.
|
||||
* \return The window matching all these constraints or NULL if none does.
|
||||
*/
|
||||
MetaWindow* meta_stack_get_default_focus_window_at_point (MetaStack *stack,
|
||||
MetaWorkspace *workspace,
|
||||
MetaWindow *not_this_one,
|
||||
int root_x,
|
||||
int root_y);
|
||||
|
||||
/**
|
||||
* Finds all the windows in the stack, in order.
|
||||
*
|
||||
* \param stack The stack to examine.
|
||||
* \param workspace If non-NULL, only windows on this workspace will be
|
||||
* returned; otherwise all windows in the stack will be
|
||||
* returned.
|
||||
* \return A list of windows, in stacking order, honouring layers.
|
||||
*/
|
||||
GList* meta_stack_list_windows (MetaStack *stack,
|
||||
MetaWorkspace *workspace);
|
||||
|
||||
|
||||
/* -1 if a < b, etc. */
|
||||
/**
|
||||
* Comparison function for windows within a stack. This is not directly
|
||||
* suitable for use within a standard comparison routine, because it takes
|
||||
* an extra parameter; you will need to wrap it.
|
||||
*
|
||||
* (FIXME: We could remove the stack parameter and use the stack of
|
||||
* the screen of window A, and complain if the stack of the screen of
|
||||
* window B differed; then this would be a usable general comparison function.)
|
||||
*
|
||||
* (FIXME: Apparently identical to compare_window_position(). Merge them.)
|
||||
*
|
||||
* \param stack A stack containing both window_a and window_b
|
||||
* \param window_a A window
|
||||
* \param window_b Another window
|
||||
* \return -1 if window_a is below window_b, honouring layers; 1 if it's
|
||||
* above it; 0 if you passed in the same window twice!
|
||||
*/
|
||||
int meta_stack_windows_cmp (MetaStack *stack,
|
||||
MetaWindow *window_a,
|
||||
MetaWindow *window_b);
|
||||
|
||||
/**
|
||||
* Sets the position of a window within the stack. This will only move it
|
||||
* up or down within its layer. It is an error to attempt to move this
|
||||
* below position zero or above the last position in the stack (however, since
|
||||
* we don't provide a simple way to tell the number of windows in the stack,
|
||||
* this requirement may not be easy to fulfil).
|
||||
*
|
||||
* \param window The window which is moving.
|
||||
* \param position Where it should move to (0 is the bottom).
|
||||
*/
|
||||
void meta_window_set_stack_position (MetaWindow *window,
|
||||
int position);
|
||||
|
||||
/**
|
||||
* Returns the current stack state, allowing rudimentary transactions.
|
||||
*
|
||||
* \param stack The stack to examine.
|
||||
* \return An opaque GList representing the current stack sort order;
|
||||
* it is the caller's responsibility to free it.
|
||||
* Pass this to meta_stack_set_positions() later if you want to restore
|
||||
* the state to where it was when you called this function.
|
||||
*/
|
||||
GList* meta_stack_get_positions (MetaStack *stack);
|
||||
|
||||
/**
|
||||
* Rolls back a transaction, given the list returned from
|
||||
* meta_stack_get_positions().
|
||||
*
|
||||
* \param stack The stack to roll back.
|
||||
* \param windows The list returned from meta_stack_get_positions().
|
||||
*/
|
||||
void meta_stack_set_positions (MetaStack *stack,
|
||||
GList *windows);
|
||||
|
||||
|
@ -1,6 +1,17 @@
|
||||
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
||||
|
||||
/* MetaWindow property handling */
|
||||
/**
|
||||
* \file window-props.c MetaWindow property handling
|
||||
*
|
||||
* A system which can inspect sets of properties of given windows
|
||||
* and take appropriate action given their values.
|
||||
*
|
||||
* Note that all the meta_window_reload_propert* functions require a
|
||||
* round trip to the server.
|
||||
*
|
||||
* \bug Not all the properties have moved over from their original
|
||||
* handler in window.c yet.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001, 2002, 2003 Red Hat, Inc.
|
||||
|
@ -1412,8 +1412,7 @@ meta_window_should_be_showing (MetaWindow *window)
|
||||
}
|
||||
|
||||
static void
|
||||
finish_minimize (const MetaEffect *effect,
|
||||
gpointer data)
|
||||
finish_minimize (gpointer data)
|
||||
{
|
||||
MetaWindow *window = data;
|
||||
/* FIXME: It really sucks to put timestamp pinging here; it'd
|
||||
@ -1440,11 +1439,11 @@ implement_showing (MetaWindow *window,
|
||||
/* Actually show/hide the window */
|
||||
meta_verbose ("Implement showing = %d for window %s\n",
|
||||
showing, window->desc);
|
||||
|
||||
|
||||
if (!showing)
|
||||
{
|
||||
gboolean on_workspace;
|
||||
|
||||
|
||||
on_workspace = meta_window_located_on_workspace (window,
|
||||
window->screen->active_workspace);
|
||||
|
||||
@ -1484,7 +1483,7 @@ implement_showing (MetaWindow *window,
|
||||
}
|
||||
else
|
||||
{
|
||||
finish_minimize (NULL, window);
|
||||
finish_minimize (window);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -2776,31 +2775,7 @@ meta_window_shade (MetaWindow *window,
|
||||
meta_topic (META_DEBUG_WINDOW_OPS,
|
||||
"Shading %s\n", window->desc);
|
||||
if (!window->shaded)
|
||||
{
|
||||
#if 0
|
||||
if (window->mapped)
|
||||
{
|
||||
/* Animation */
|
||||
MetaRectangle starting_size;
|
||||
MetaRectangle titlebar_size;
|
||||
|
||||
meta_window_get_outer_rect (window, &starting_size);
|
||||
if (window->frame)
|
||||
{
|
||||
starting_size.y += window->frame->child_y;
|
||||
starting_size.height -= window->frame->child_y;
|
||||
}
|
||||
titlebar_size = starting_size;
|
||||
titlebar_size.height = 0;
|
||||
|
||||
meta_effects_draw_box_animation (window->screen,
|
||||
&starting_size,
|
||||
&titlebar_size,
|
||||
META_SHADE_ANIMATION_LENGTH,
|
||||
META_BOX_ANIM_SLIDE_UP);
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
window->shaded = TRUE;
|
||||
|
||||
meta_window_queue(window, META_QUEUE_MOVE_RESIZE | META_QUEUE_CALC_SHOWING);
|
||||
@ -3874,7 +3849,6 @@ meta_window_get_wireframe_geometry (MetaWindow *window,
|
||||
int *width,
|
||||
int *height)
|
||||
{
|
||||
|
||||
if (!window->display->grab_wireframe_active)
|
||||
return;
|
||||
|
||||
@ -7582,9 +7556,13 @@ gboolean
|
||||
meta_window_same_application (MetaWindow *window,
|
||||
MetaWindow *other_window)
|
||||
{
|
||||
MetaGroup *group = meta_window_get_group (window);
|
||||
MetaGroup *other_group = meta_window_get_group (other_window);
|
||||
|
||||
return
|
||||
meta_window_get_group (window) ==
|
||||
meta_window_get_group (other_window);
|
||||
group!=NULL &&
|
||||
other_group!=NULL &&
|
||||
group==other_group;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -116,15 +116,25 @@ meta_workspace_free (MetaWorkspace *workspace)
|
||||
g_free (workspace->work_area_xinerama);
|
||||
|
||||
g_list_free (workspace->mru_list);
|
||||
g_slist_free (workspace->all_struts);
|
||||
g_list_free (workspace->list_containing_self);
|
||||
|
||||
for (i = 0; i < screen->n_xinerama_infos; i++)
|
||||
meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]);
|
||||
g_free (workspace->xinerama_region);
|
||||
meta_rectangle_free_list_and_elements (workspace->screen_region);
|
||||
meta_rectangle_free_list_and_elements (workspace->screen_edges);
|
||||
meta_rectangle_free_list_and_elements (workspace->xinerama_edges);
|
||||
/* screen.c:update_num_workspaces(), which calls us, removes windows from
|
||||
* workspaces first, which can cause the workareas on the workspace to be
|
||||
* invalidated (and hence for struts/regions/edges to be freed).
|
||||
* So, no point trying to double free it; that causes a crash
|
||||
* anyway. #361804.
|
||||
*/
|
||||
|
||||
if (!workspace->work_areas_invalid)
|
||||
{
|
||||
g_slist_free (workspace->all_struts);
|
||||
for (i = 0; i < screen->n_xinerama_infos; i++)
|
||||
meta_rectangle_free_list_and_elements (workspace->xinerama_region[i]);
|
||||
g_free (workspace->xinerama_region);
|
||||
meta_rectangle_free_list_and_elements (workspace->screen_region);
|
||||
meta_rectangle_free_list_and_elements (workspace->screen_edges);
|
||||
meta_rectangle_free_list_and_elements (workspace->xinerama_edges);
|
||||
}
|
||||
|
||||
g_free (workspace);
|
||||
|
||||
|
@ -1051,7 +1051,7 @@ meta_prop_get_values (MetaDisplay *display,
|
||||
&results.type, &results.format,
|
||||
&results.n_items,
|
||||
&results.bytes_after,
|
||||
(gchar **)&results.prop) != Success ||
|
||||
(unsigned char **)(&results.prop)) != Success ||
|
||||
results.type == None)
|
||||
{
|
||||
values[i].type = META_PROP_VALUE_INVALID;
|
||||
|
Reference in New Issue
Block a user