summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt3
-rw-r--r--gtk/window-decorator/decorator.c221
-rw-r--r--include/core/core.h4
-rw-r--r--include/core/screen.h3
-rw-r--r--include/core/timer.h35
-rw-r--r--plugins/composite/src/screen.cpp22
-rw-r--r--src/privateregion.h3
-rw-r--r--src/privatescreen.h78
-rw-r--r--src/region.cpp102
-rw-r--r--src/screen.cpp391
-rw-r--r--src/timer.cpp41
-rw-r--r--src/window.cpp14
12 files changed, 628 insertions, 289 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 75e7109..2c08c5b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -62,6 +62,9 @@ set (COMPIZ_REQUIRES
sm
libxml-2.0
libxslt
+ glib-2.0
+ gio-2.0
+ glibmm-2.4
"libstartup-notification-1.0 >= 0.7"
)
diff --git a/gtk/window-decorator/decorator.c b/gtk/window-decorator/decorator.c
index 68eb22f..703abee 100644
--- a/gtk/window-decorator/decorator.c
+++ b/gtk/window-decorator/decorator.c
@@ -1,5 +1,11 @@
#include "gtk-window-decorator.h"
+/*
+ * get_titlebar_font
+ *
+ * Returns: PangoFontDescription * or NULL if using system font
+ * Description: Helper function to get the font for the titlebar
+ */
static const PangoFontDescription *
get_titlebar_font (void)
{
@@ -11,6 +17,13 @@ get_titlebar_font (void)
return titlebar_font;
}
+/*
+ * update_titlebar_font
+ *
+ * Returns: void
+ * Description: updates the titlebar font from the pango context, should
+ * be called whenever the gtk style or font has changed
+ */
void
update_titlebar_font (void)
{
@@ -38,6 +51,56 @@ update_titlebar_font (void)
pango_font_metrics_unref (metrics);
}
+/*
+ * update_event_windows
+ *
+ * Returns: void
+ * Description: creates small "event windows" for the buttons specified to be
+ * on the titlebar by wnck. Note here that for the pixmap mode we create actual
+ * X windows but in the reparenting mode this is not possible so we create event
+ * capture boxes on the window instead. The geometry of the decoration is retrieved
+ * with wnck_window_get_client_window_geometry and adjusted for shade. Also we
+ * need to query the theme for what window positions are appropriate here.
+ *
+ * This function works on the buttons and also the small event regions that we need
+ * in order to toggle certain actions on the window decoration (eg resize, move)
+ *
+ * So your window decoration might look something like this (not to scale):
+ *
+ * -----------------------------------------------------------
+ * | rtl | rt | rtr |
+ * | --- |---------------------------------------------| --- |
+ * | | [i][s][m] mv [_][M][X] | |
+ * | |---------------------------------------------| |
+ * | | | |
+ * | rl | window contents | rr |
+ * | | | |
+ * | | | |
+ * | --- |---------------------------------------------| --- |
+ * | rbl | rb | rbr |
+ * -----------------------------------------------------------
+ *
+ * Where:
+ * - rtl = resize top left
+ * - rtr = resize top right
+ * - rbl = resize bottom left
+ * - rbr = resize bottom right
+ * - rt = resize top
+ * - rb = resize bottom
+ * - rl = resize left
+ * - rr = resize right
+ * - mv = "grab move" area (eg titlebar)
+ * - i = icon
+ * - s = shade
+ * - m = menu
+ * - _ = minimize
+ * - M = maximize
+ * - X = close
+ *
+ * For the reparenting mode we use button_windows[i].pos and for the pixmap mode
+ * we use buttons_windows[i].window
+ *
+ */
void
update_event_windows (WnckWindow *win)
{
@@ -49,8 +112,10 @@ update_event_windows (WnckWindow *win)
xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ /* Get the geometry of the client */
wnck_window_get_client_window_geometry (win, &x0, &y0, &width, &height);
+ /* Shaded windows have no height - also skip some event windows */
if (d->state & WNCK_WINDOW_STATE_SHADED)
{
height = 0;
@@ -64,6 +129,7 @@ update_event_windows (WnckWindow *win)
gdk_error_trap_push ();
+ /* [rtl, ru, rtr], [rl, mv, rr], [rbl, rb, rbr] */
for (i = 0; i < 3; i++)
{
static guint event_window_actions[3][3] = {
@@ -91,6 +157,7 @@ update_event_windows (WnckWindow *win)
(*theme_get_event_window_position) (d, i, j, width, height,
&x, &y, &w, &h);
+ /* Reparenting mode - create boxes which we monitor motionnotify on */
if (d->frame_window)
{
BoxPtr box = &d->event_windows[i][j].pos;
@@ -99,12 +166,14 @@ update_event_windows (WnckWindow *win)
box->y1 = y;
box->y2 = y + h;
}
+ /* Pixmap mode with window geometry - create small event windows */
else if (!d->frame_window && w != 0 && h != 0)
{
XMapWindow (xdisplay, d->event_windows[i][j].window);
XMoveResizeWindow (xdisplay, d->event_windows[i][j].window,
x, y, w, h);
}
+ /* No parent and no geometry - unmap all event windows */
else if (!d->frame_window)
{
XUnmapWindow (xdisplay, d->event_windows[i][j].window);
@@ -116,6 +185,7 @@ update_event_windows (WnckWindow *win)
if (width < ICON_SPACE + d->button_width)
actions = 0;
+ /* Above, stick, unshade and unstick are only available in wnck => 2.18.1 */
for (i = 0; i < BUTTON_NUM; i++)
{
static guint button_actions[BUTTON_NUM] = {
@@ -141,11 +211,13 @@ update_event_windows (WnckWindow *win)
};
+ /* Reparenting mode - if a box was set and we no longer need it reset its geometry */
if (d->frame_window &&
button_actions[i] && !(actions & button_actions[i]))
{
memset (&d->button_windows[i].pos, 0, sizeof (Box));
}
+ /* Pixmap mode - if a box was set and we no longer need it unmap its window */
else if (!d->frame_window &&
button_actions[i] && !(actions & button_actions[i]))
{
@@ -153,6 +225,8 @@ update_event_windows (WnckWindow *win)
continue;
}
+ /* Reparenting mode - if there is a button position for this
+ * button then set the geometry */
if (d->frame_window &&
(*theme_get_button_position) (d, i, width, height, &x, &y, &w, &h))
{
@@ -162,6 +236,8 @@ update_event_windows (WnckWindow *win)
box->x2 = x + w;
box->y2 = y + h;
}
+ /* Pixmap mode - if there is a button position for this button then map the window
+ * and resize it to this position */
else if (!d->frame_window &&
(*theme_get_button_position) (d, i, width, height,
&x, &y, &w, &h))
@@ -180,6 +256,14 @@ update_event_windows (WnckWindow *win)
gdk_error_trap_pop ();
}
+/*
+ * wnck_window_get_real_name
+ *
+ * Returns: const char * or NULL
+ * Description: Wrapper function to either get the name of the window or
+ * return NULL
+ */
+
#ifdef HAVE_WNCK_WINDOW_HAS_NAME
static const char *
wnck_window_get_real_name (WnckWindow *win)
@@ -189,6 +273,14 @@ wnck_window_get_real_name (WnckWindow *win)
#define wnck_window_get_name wnck_window_get_real_name
#endif
+/*
+ * max_window_name_width
+ *
+ * Returns: gint
+ * Description: Calculate the width of the decoration required to display
+ * the window name using pango (with 6px padding)
+ * Returns zero if window has no name.
+ */
gint
max_window_name_width (WnckWindow *win)
{
@@ -196,6 +288,7 @@ max_window_name_width (WnckWindow *win)
const gchar *name;
gint w;
+ /* Ensure that a layout is created */
if (!d->layout)
{
d->layout = pango_layout_new (pango_context);
@@ -205,10 +298,12 @@ max_window_name_width (WnckWindow *win)
pango_layout_set_wrap (d->layout, PANGO_WRAP_CHAR);
}
+ /* Return zero if window has no name */
name = wnck_window_get_name (win);
if (!name)
return 0;
+ /* Reset the width, set hte text and get the size required */
pango_layout_set_auto_dir (d->layout, FALSE);
pango_layout_set_width (d->layout, -1);
pango_layout_set_text (d->layout, name, strlen (name));
@@ -220,6 +315,14 @@ max_window_name_width (WnckWindow *win)
return w + 6;
}
+/*
+ * update_window_decoration_name
+ *
+ * Returns: void
+ * Description: frees the last window name and gets the new one from
+ * wnck. Also checks to see if the name has a length (slight optimization)
+ * and re-creates the pango context to re-render the name
+ */
void
update_window_decoration_name (WnckWindow *win)
{
@@ -234,15 +337,18 @@ update_window_decoration_name (WnckWindow *win)
d->name = NULL;
}
+ /* Only operate if the window name has a length */
name = wnck_window_get_name (win);
if (name && (name_length = strlen (name)))
{
gint w;
+ /* Cairo mode: w = SHRT_MAX */
if (theme_draw_window_decoration != draw_window_decoration)
{
w = SHRT_MAX;
}
+ /* Need to get a minimum width for the name */
else
{
gint width;
@@ -255,6 +361,9 @@ update_window_decoration_name (WnckWindow *win)
w = 1;
}
+ /* Set the maximum width for the layout (in case
+ * decoration size < text width) since we
+ * still need to show the buttons and the window name */
pango_layout_set_auto_dir (d->layout, FALSE);
pango_layout_set_width (d->layout, w * PANGO_SCALE);
pango_layout_set_text (d->layout, name, name_length);
@@ -276,15 +385,23 @@ update_window_decoration_name (WnckWindow *win)
else
d->name = g_strndup (name, name_length);
+ /* Truncate the text */
pango_layout_set_text (d->layout, d->name, name_length);
}
}
+/*
+ * update_window_decoration_icon
+ *
+ * Updates the window icon (destroys the existing cairo pattern
+ * and creates a new one for the pixmap)
+ */
void
update_window_decoration_icon (WnckWindow *win)
{
decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ /* Destroy old stuff */
if (d->icon)
{
cairo_pattern_destroy (d->icon);
@@ -300,6 +417,7 @@ update_window_decoration_icon (WnckWindow *win)
if (d->icon_pixbuf)
g_object_unref (G_OBJECT (d->icon_pixbuf));
+ /* Get the mini icon pixbuf from libwnck */
d->icon_pixbuf = wnck_window_get_mini_icon (win);
if (d->icon_pixbuf)
{
@@ -307,6 +425,7 @@ update_window_decoration_icon (WnckWindow *win)
g_object_ref (G_OBJECT (d->icon_pixbuf));
+ /* 32 bit pixmap on pixmap mode, 24 for reparenting */
if (d->frame_window)
d->icon_pixmap = pixmap_new_from_pixbuf (d->icon_pixbuf,
24);
@@ -320,7 +439,16 @@ update_window_decoration_icon (WnckWindow *win)
}
-
+/*
+ * update_window_decoration_size
+ * Returns: FALSE for failure, TRUE for success
+ * Description: Calculates the minimum size of the decoration that we need
+ * to render. This is mostly done by the theme but there is some work that
+ * we need to do here first, such as getting the client geometry, setting
+ * drawable depths, creating pixmaps, creating XRenderPictures and
+ * updating the window decoration name
+ */
+
gboolean
update_window_decoration_size (WnckWindow *win)
{
@@ -335,10 +463,14 @@ update_window_decoration_size (WnckWindow *win)
xdisplay = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
+ /* Get the geometry of the window, we'll need it later */
wnck_window_get_client_window_geometry (win, &x, &y, &w, &h);
+ /* Get the width of the name */
name_width = max_window_name_width (win);
+ /* Ask the theme to tell us how much space it needs. If this is not successful
+ * update the decoration name and return false */
if (!(*theme_calc_decoration_size) (d, w, h, name_width, &width, &height))
{
update_window_decoration_name (win);
@@ -347,15 +479,19 @@ update_window_decoration_size (WnckWindow *win)
gdk_error_trap_push ();
+ /* Get the correct depth for the frame window in reparenting mode, otherwise
+ * enforce 32 */
if (d->frame_window)
depth = gdk_drawable_get_depth (GDK_DRAWABLE (d->frame_window));
else
depth = 32;
+ /* Create pixmap of decoration size */
pixmap = create_pixmap (width, height, depth);
gdk_flush ();
+ /* Handle failure */
if (!pixmap || gdk_error_trap_pop ())
{
memset (pixmap, 0, sizeof (pixmap));
@@ -364,10 +500,12 @@ update_window_decoration_size (WnckWindow *win)
gdk_error_trap_push ();
+ /* Create backbuffer pixmap */
buffer_pixmap = create_pixmap (width, height, depth);
gdk_flush ();
+ /* Handle failure */
if (!buffer_pixmap || gdk_error_trap_pop ())
{
memset (buffer_pixmap, 0, sizeof (buffer_pixmap));
@@ -375,10 +513,12 @@ update_window_decoration_size (WnckWindow *win)
return FALSE;
}
+ /* Create XRender context */
format = get_format_for_drawable (d, GDK_DRAWABLE (buffer_pixmap));
picture = XRenderCreatePicture (xdisplay, GDK_PIXMAP_XID (buffer_pixmap),
format, 0, NULL);
+ /* Destroy the old pixmaps and pictures */
if (d->pixmap)
g_object_unref (G_OBJECT (d->pixmap));
@@ -391,6 +531,7 @@ update_window_decoration_size (WnckWindow *win)
if (d->cr)
cairo_destroy (d->cr);
+ /* Assign new pixmaps and pictures */
d->pixmap = pixmap;
d->buffer_pixmap = buffer_pixmap;
d->cr = gdk_cairo_create (pixmap);
@@ -404,6 +545,7 @@ update_window_decoration_size (WnckWindow *win)
update_window_decoration_name (win);
+ /* Redraw decoration on idle */
queue_decor_draw (d);
return TRUE;
@@ -412,6 +554,11 @@ update_window_decoration_size (WnckWindow *win)
/* to save some memory, value is specific to current decorations */
#define TRANSLUCENT_CORNER_SIZE 3
+/*
+ * draw_border_shape
+ * Returns: void
+ * Description: Draws a slight border around the decoration
+ */
static void
draw_border_shape (Display *xdisplay,
Pixmap pixmap,
@@ -465,6 +612,22 @@ draw_border_shape (Display *xdisplay,
g_object_unref (G_OBJECT (d.pixmap));
}
+/*
+ * update_shadow
+ * Returns: 1 for success, 0 for failure
+ * Description: creates a libdecoration shadow context and updates
+ * the decoration context for the shadow for the properties that we
+ * have already read from the root window.
+ *
+ * For the pixmap mode we have opt_shadow which is passed to
+ * decor_shadow_create (which contains the shadow settings from
+ * the root window)
+ *
+ * For the reparenting mode we always enforce a zero-shadow in
+ * the opt_no_shadow passed to decor_shadow_create.
+ *
+ * We do something similar for the maximimzed mode as well
+ */
int
update_shadow (void)
{
@@ -474,6 +637,7 @@ update_shadow (void)
GdkDisplay *display = gdk_display_get_default ();
GdkScreen *screen = gdk_display_get_default_screen (display);
+ /* Pixmap mode non maximized window shadow */
opt_shadow.shadow_radius = shadow_radius;
opt_shadow.shadow_opacity = shadow_opacity;
@@ -482,12 +646,14 @@ update_shadow (void)
opt_shadow.shadow_offset_x = shadow_offset_x;
opt_shadow.shadow_offset_y = shadow_offset_y;
+ /* Reparenting mode non maximized window shadow */
opt_no_shadow.shadow_radius = 0;
opt_no_shadow.shadow_opacity = 0;
opt_no_shadow.shadow_offset_x = 0;
opt_no_shadow.shadow_offset_y = 0;
+ /* Create a special no_border_shadow for the pixmap mode in case we need it */
if (no_border_shadow)
{
decor_shadow_destroy (xdisplay, no_border_shadow);
@@ -507,6 +673,7 @@ update_shadow (void)
decor_draw_simple,
0);
+ /* Normal window shadow pixmap mode */
if (border_shadow)
{
decor_shadow_destroy (xdisplay, border_shadow);
@@ -533,6 +700,7 @@ update_shadow (void)
draw_border_shape,
0);
+ /* Enforced zero-shadow for reparenting mode for normal windows */
if (border_no_shadow)
{
decor_shadow_destroy (xdisplay, border_no_shadow);
@@ -561,7 +729,7 @@ update_shadow (void)
decor_context_t *context = &window_context_no_shadow;
-
+ /* Maximized border shadow pixmap mode */
if (max_border_shadow)
{
decor_shadow_destroy (xdisplay, max_border_shadow);
@@ -586,6 +754,7 @@ update_shadow (void)
draw_border_shape,
(void *) 1);
+ /* Enforced maximize zero shadow reparenting mode */
if (max_border_no_shadow)
{
decor_shadow_destroy (xdisplay, max_border_shadow);
@@ -610,6 +779,7 @@ update_shadow (void)
draw_border_shape,
(void *) 1);
+ /* Special shadow for the switcher window */
if (switcher_shadow)
{
decor_shadow_destroy (xdisplay, switcher_shadow);
@@ -639,11 +809,19 @@ update_shadow (void)
return 1;
}
+/*
+ * update_window_decoration
+ *
+ * Returns: void
+ * Description: The master function to update the window decoration
+ * if the pixmap needs to be redrawn
+ */
void
update_window_decoration (WnckWindow *win)
{
decor_t *d = g_object_get_data (G_OBJECT (win), "decor");
+ /* Handle normally decorated windows */
if (d->decorated)
{
/* force size update */
@@ -653,6 +831,7 @@ update_window_decoration (WnckWindow *win)
update_window_decoration_size (win);
update_event_windows (win);
}
+ /* Handle switcher windows */
else
{
Window xid = wnck_window_get_xid (win);
@@ -670,6 +849,12 @@ update_window_decoration (WnckWindow *win)
}
}
+/*
+ * update_window_decoration_state
+ *
+ * Returns: void
+ * Description: helper function to update the state of the decor_t
+ */
void
update_window_decoration_state (WnckWindow *win)
{
@@ -678,6 +863,12 @@ update_window_decoration_state (WnckWindow *win)
d->state = wnck_window_get_state (win);
}
+/*
+ * update_window_decoration_actions
+ *
+ * Returns: void
+ * Description: helper function to update the actions of the decor_t
+ */
void
update_window_decoration_actions (WnckWindow *win)
{
@@ -686,6 +877,14 @@ update_window_decoration_actions (WnckWindow *win)
d->actions = wnck_window_get_actions (win);
}
+
+/*
+ * draw_decor_list
+ *
+ * Returns: bool
+ * Description: function to be called on g_idle_add to draw window
+ * decorations when we are not doing anything
+ */
static gboolean
draw_decor_list (void *data)
{
@@ -706,6 +905,14 @@ draw_decor_list (void *data)
return FALSE;
}
+/*
+ * queue_decor_draw
+ *
+ * Description :queue a redraw request for this decoration. Since this function
+ * only gets called on idle, don't redraw window decorations multiple
+ * times if they are already waiting to be drawn (since the drawn copy
+ * will always be the most updated one)
+ */
void
queue_decor_draw (decor_t *d)
{
@@ -718,6 +925,11 @@ queue_decor_draw (decor_t *d)
draw_idle_id = g_idle_add (draw_decor_list, NULL);
}
+/*
+ * update_default_decorations
+ *
+ * Description: update the default decorations
+ */
void
update_default_decorations (GdkScreen *screen)
{
@@ -860,6 +1072,11 @@ update_default_decorations (GdkScreen *screen)
g_object_unref (G_OBJECT (d.layout));
}
+/*
+ * copy_to_front_buffer
+ *
+ * Description: Helper function to copy the buffer pixmap to a front buffer
+ */
void
copy_to_front_buffer (decor_t *d)
{
diff --git a/include/core/core.h b/include/core/core.h
index 40f2eec..8ba7169 100644
--- a/include/core/core.h
+++ b/include/core/core.h
@@ -26,7 +26,7 @@
#ifndef _COMPIZ_CORE_H
#define _COMPIZ_CORE_H
-#define CORE_ABIVERSION 20080618
+#define CORE_ABIVERSION 20101111
#include <stdio.h>
#include <assert.h>
@@ -51,6 +51,8 @@ typedef XBool Bool;
#include <boost/foreach.hpp>
#define foreach BOOST_FOREACH
+#include <glib.h>
+
/*
* WORDS_BIGENDIAN should be defined before including this file for
* IMAGE_BYTE_ORDER and BITMAP_BIT_ORDER to be set correctly.
diff --git a/include/core/screen.h b/include/core/screen.h
index c5bfc4c..aa6ab5a 100644
--- a/include/core/screen.h
+++ b/include/core/screen.h
@@ -157,6 +157,7 @@ class CompScreen :
bool init (const char *name);
void eventLoop ();
+ void processEvents ();
CompFileWatchHandle addFileWatch (const char *path,
int mask,
@@ -400,7 +401,9 @@ class CompScreen :
friend class CompWindow;
friend class PrivateWindow;
friend class ModifierHandler;
+ friend class CompEventSource;
friend class CompManager;
+ friend class CompWatchFd;
private:
PrivateScreen *priv;
diff --git a/include/core/timer.h b/include/core/timer.h
index 93c47e0..3119178 100644
--- a/include/core/timer.h
+++ b/include/core/timer.h
@@ -27,6 +27,10 @@
#define _TIMER_H
#include <boost/function.hpp>
+#include <sys/time.h>
+#include <core/core.h>
+
+#include <glibmm/main.h>
/**
* A simple timer for use with invoking a CallBack during a timed duration.
@@ -36,18 +40,18 @@ class CompTimer {
public:
typedef boost::function<bool ()> CallBack;
-
+
/**
* Empty constructor setting everything to zero and NULL.
*/
CompTimer ();
-
+
/**
* Frees the private data for this timer and any information about it's
* context.
*/
~CompTimer ();
-
+
/**
* Checks if this timer is active and will have it's CallBack invoked.
*/
@@ -56,43 +60,47 @@ class CompTimer {
unsigned int maxTime ();
unsigned int minLeft ();
unsigned int maxLeft ();
-
+
/**
* Sets the timing durations of this timer.
*/
void setTimes (unsigned int min, unsigned int max = 0);
-
+
/**
* Sets the callback function to invoke for this timer. This defaults
* to NULL.
*/
void setCallback (CallBack callback);
-
+
/**
* Starts this timer without modifying any of it's parameters. The timer is
* stop()'d before this occurs.
*/
void start ();
-
+
/**
* Starts this timer setting the paramters with setTimes(). The timer is stop()'d
* before this occurs.
*/
void start (unsigned int min, unsigned int max = 0);
-
+
/**
* Starts this timer setting the parameters with setTimes() and setCallback(). The timer is
* stop()'d before this occurs.
*/
void start (CallBack callback,
unsigned int min, unsigned int max = 0);
-
+
/**
* Stops this timer. After this the timer should not be active() and it's CallBack shouldn't
* be invoked.
*/
void stop ();
+ void tick ();
+
+ const struct timeval & tickInfo () const;
+
friend class CompScreen;
friend class PrivateScreen;
@@ -102,7 +110,16 @@ class CompTimer {
unsigned int mMaxTime;
int mMinLeft;
int mMaxLeft;
+
+ private:
CallBack mCallBack;
+ bool mForceFail;
+ bool mExecuting;
+ struct timeval tickStart;
+
+ bool internalCallback (unsigned int);
+ Glib::RefPtr <Glib::TimeoutSource> mSource;
+
};
#endif
diff --git a/plugins/composite/src/screen.cpp b/plugins/composite/src/screen.cpp
index 76fe562..7cdf1c3 100644
--- a/plugins/composite/src/screen.cpp
+++ b/plugins/composite/src/screen.cpp
@@ -45,7 +45,6 @@
CompWindow *lastDamagedWindow = 0;
-
void
PrivateCompositeScreen::handleEvent (XEvent *event)
{
@@ -420,7 +419,7 @@ CompositeScreen::registerPaintHandler (PaintHandler *pHnd)
priv->paintTimer.start
(boost::bind (&CompositeScreen::handlePaintTimeout, this),
- priv->optimalRedrawTime, MAXSHORT);
+ priv->optimalRedrawTime);
return true;
}
@@ -459,9 +458,6 @@ CompositeScreen::compositingActive ()
void
CompositeScreen::damageScreen ()
{
- if (priv->damageMask == 0)
- priv->paintTimer.setTimes (priv->paintTimer.minLeft ());
-
priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_ALL_MASK;
priv->damageMask &= ~COMPOSITE_SCREEN_DAMAGE_REGION_MASK;
}
@@ -472,11 +468,7 @@ CompositeScreen::damageRegion (const CompRegion &region)
if (priv->damageMask & COMPOSITE_SCREEN_DAMAGE_ALL_MASK)
return;
- if (priv->damageMask == 0)
- priv->paintTimer.setTimes (priv->paintTimer.minLeft ());
-
priv->damage += region;
-
priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_REGION_MASK;
/* if the number of damage rectangles grows two much between repaints,
@@ -491,9 +483,6 @@ CompositeScreen::damageRegion (const CompRegion &region)
void
CompositeScreen::damagePending ()
{
- if (priv->damageMask == 0)
- priv->paintTimer.setTimes (priv->paintTimer.minLeft ());
-
priv->damageMask |= COMPOSITE_SCREEN_DAMAGE_PENDING_MASK;
}
@@ -694,7 +683,7 @@ PrivateCompositeScreen::getTimeToNextRedraw (struct timeval *tv)
/* handle clock rollback */
if (diff < 0)
diff = 0;
-
+
bool hasVSyncBehavior =
(FPSLimiterMode == CompositeFPSLimiterModeVSyncLike ||
(pHnd && pHnd->hasVSync ()));
@@ -747,6 +736,7 @@ PrivateCompositeScreen::getTimeToNextRedraw (struct timeval *tv)
}
}
}
+
if (diff >= redrawTime)
return 1;
@@ -855,7 +845,6 @@ CompositeScreen::handlePaintTimeout ()
paint (outputs, mask);
- priv->lastRedraw = tv;
donePaint ();
@@ -875,6 +864,7 @@ CompositeScreen::handlePaintTimeout ()
priv->idle = true;
}
+ priv->lastRedraw = tv;
gettimeofday (&tv, 0);
if (priv->FPSLimiterMode == CompositeFPSLimiterModeDisabled)
@@ -893,10 +883,6 @@ CompositeScreen::handlePaintTimeout ()
else
timeToNextRedraw = priv->getTimeToNextRedraw (&tv);
- if (priv->idle)
- priv->paintTimer.setTimes (timeToNextRedraw, MAXSHORT);
- else
- priv->paintTimer.setTimes (timeToNextRedraw);
return true;
}
diff --git a/src/privateregion.h b/src/privateregion.h
index d91e9c1..13314f5 100644
--- a/src/privateregion.h
+++ b/src/privateregion.h
@@ -34,11 +34,8 @@ class PrivateRegion {
PrivateRegion ();
~PrivateRegion ();
- void makeReal ();
-
public:
Region region;
- REGION box;
};
#endif
diff --git a/src/privatescreen.h b/src/privatescreen.h
index 961daf2..f6b9bb9 100644
--- a/src/privatescreen.h
+++ b/src/privatescreen.h
@@ -35,6 +35,8 @@
#include <core/timer.h>
#include <core/plugin.h>
+#include <glibmm/main.h>
+
#include "core_options.h"
CompPlugin::VTable * getCoreVTable ();
@@ -42,11 +44,31 @@ CompPlugin::VTable * getCoreVTable ();
extern bool shutDown;
extern bool restartSignal;
-typedef struct _CompWatchFd {
- int fd;
- FdWatchCallBack callBack;
- CompWatchFdHandle handle;
-} CompWatchFd;
+class CompWatchFd :
+ public Glib::IOSource
+{
+ public:
+
+ static
+ Glib::RefPtr <CompWatchFd> create (int,
+ Glib::IOCondition,
+ FdWatchCallBack);
+
+ protected:
+
+ explicit CompWatchFd (int, Glib::IOCondition, FdWatchCallBack);
+ bool internalCallback (Glib::IOCondition);
+
+ private:
+
+ int mFd;
+ FdWatchCallBack mCallBack;
+ CompWatchFdHandle mHandle;
+ bool mForceFail;
+ bool mExecuting;
+
+ friend class CompScreen;
+};
extern CompWindow *lastFoundWindow;
extern bool useDesktopHints;
@@ -81,6 +103,13 @@ typedef struct _CompDelayedEdgeSettings
#define SCREEN_EDGE_BOTTOMRIGHT 7
#define SCREEN_EDGE_NUM 8
+#define TIMEVALDIFF(tv1, tv2) \
+ ((tv1)->tv_sec == (tv2)->tv_sec || (tv1)->tv_usec >= (tv2)->tv_usec) ? \
+ ((((tv1)->tv_sec - (tv2)->tv_sec) * 1000000) + \
+ ((tv1)->tv_usec - (tv2)->tv_usec)) / 1000 : \
+ ((((tv1)->tv_sec - 1 - (tv2)->tv_sec) * 1000000) + \
+ (1000000 + (tv1)->tv_usec - (tv2)->tv_usec)) / 1000
+
struct CompScreenEdge {
Window id;
unsigned int count;
@@ -97,6 +126,33 @@ struct CompStartupSequence {
unsigned int viewportY;
};
+class CompEventSource:
+ public Glib::Source
+{
+ public:
+
+ static
+ Glib::RefPtr <CompEventSource> create ();
+
+ sigc::connection connect (const sigc::slot <bool> &slot);
+
+ protected:
+
+ bool prepare (int &timeout);
+ bool check ();
+ bool dispatch (sigc::slot_base *slot);
+ bool callback ();
+
+ explicit CompEventSource ();
+ virtual ~CompEventSource ();
+
+ private:
+
+ Display *mDpy;
+ Glib::PollFD mPollFD;
+ int mConnectionFD;
+};
+
class PrivateScreen : public CoreOptions {
public:
@@ -135,8 +191,6 @@ class PrivateScreen : public CoreOptions {
void updatePassiveGrabs ();
- int doPoll (int timeout);
-
void handleTimers (struct timeval *tv);
void addTimer (CompTimer *timer);
@@ -300,16 +354,18 @@ class PrivateScreen : public CoreOptions {
PrivateScreen *priv;
+ Glib::RefPtr <Glib::MainLoop> mainloop;
+ Glib::RefPtr <CompEventSource> source;
+ Glib::RefPtr <Glib::MainContext> ctx;
+
CompFileWatchList fileWatch;
CompFileWatchHandle lastFileWatchHandle;
- std::list<CompTimer *> timers;
+ std::list <int> removedTimers;
struct timeval lastTimeout;
- std::list<CompWatchFd *> watchFds;
+ std::list<Glib::RefPtr <CompWatchFd> > watchFds;
CompWatchFdHandle lastWatchFdHandle;
- struct pollfd *watchPollFds;
- int nWatchFds;
std::map<CompString, CompPrivate> valueMap;
diff --git a/src/region.cpp b/src/region.cpp
index 725ed53..6649524 100644
--- a/src/region.cpp
+++ b/src/region.cpp
@@ -45,30 +45,39 @@ CompRegion::CompRegion ()
CompRegion::CompRegion (const CompRegion &c)
{
priv = new PrivateRegion ();
- priv->box = c.priv->box;
- if (priv->box.rects)
- priv->box.rects = &priv->box.extents;
- if (c.priv->region)
- {
- priv->region = XCreateRegion ();
- XUnionRegion (CompRegion ().handle (), c.priv->region, priv->region);
- }
+ XUnionRegion (CompRegion ().handle (), c.priv->region, priv->region);
}
CompRegion::CompRegion ( int x, int y, int w, int h)
{
priv = new PrivateRegion ();
- priv->box.extents = CompRect (x, y, w, h).region ()->extents;
- priv->box.numRects = 1;
- priv->box.rects = &priv->box.extents;
+
+ XRectangle rect;
+
+ rect.x = x;
+ rect.y = y;
+ rect.width = w;
+ rect.height = h;
+
+ Region tmp = XCreateRegion ();
+ XUnionRectWithRegion (&rect, tmp, priv->region);
+ XDestroyRegion (tmp);
}
CompRegion::CompRegion (const CompRect &r)
{
priv = new PrivateRegion ();
- priv->box.extents = r.region ()->extents;
- priv->box.numRects = 1;
- priv->box.rects = &priv->box.extents;
+
+ XRectangle rect;
+
+ rect.x = r.x ();
+ rect.y = r.y ();
+ rect.width = r.width ();
+ rect.height = r.height ();
+
+ Region tmp = XCreateRegion ();
+ XUnionRectWithRegion (&rect, tmp, priv->region);
+ XDestroyRegion (tmp);
}
CompRegion::CompRegion (const CompPoint::vector &points)
@@ -85,10 +94,9 @@ CompRegion::CompRegion (const CompPoint::vector &points)
}
priv = new PrivateRegion ();
+
+ XDestroyRegion (priv->region);
priv->region = XPolygonRegion (pts, points.size (), WindingRule);
- priv->box.extents = priv->region->extents;
- priv->box.numRects = priv->region->numRects;
- priv->box.rects = &priv->box.extents;
}
CompRegion::~CompRegion ()
@@ -99,29 +107,13 @@ CompRegion::~CompRegion ()
const Region
CompRegion::handle () const
{
- return (priv->region)? priv->region : &priv->box;
+ return priv->region;
}
CompRegion &
CompRegion::operator= (const CompRegion &c)
{
- priv->box = c.priv->box;
- if (priv->box.rects)
- priv->box.rects = &priv->box.extents;
- if (c.priv->region)
- {
- if (!priv->region)
- priv->region = XCreateRegion ();
- XUnionRegion (CompRegion ().handle (), c.priv->region, priv->region);
- }
- else
- {
- if (priv->region)
- {
- XDestroyRegion (priv->region);
- priv->region = NULL;
- }
- }
+ XUnionRegion (CompRegion ().handle (), c.priv->region, priv->region);
return *this;
}
@@ -174,7 +166,6 @@ CompRegion
CompRegion::intersected (const CompRegion &r) const
{
CompRegion reg (r);
- reg.priv->makeReal ();
XIntersectRegion (reg.handle (), handle (), reg.handle ());
return reg;
}
@@ -183,7 +174,6 @@ CompRegion
CompRegion::intersected (const CompRect &r) const
{
CompRegion reg (r);
- reg.priv->makeReal ();
XIntersectRegion (reg.handle (), handle (), reg.handle ());
return reg;
}
@@ -221,14 +211,6 @@ CompRegion::rects () const
CompRect::vector rv;
if (!numRects ())
return rv;
- if (!priv->region)
- {
- rv.push_back (CompRect (priv->box.extents.x1,
- priv->box.extents.y1,
- priv->box.extents.x2 - priv->box.extents.x1,
- priv->box.extents.y2 - priv->box.extents.y1));
- return rv;
- }
BOX b;
for (int i = 0; i < priv->region->numRects; i++)
@@ -243,7 +225,6 @@ CompRegion
CompRegion::subtracted (const CompRegion &r) const
{
CompRegion rv;
- rv.priv->makeReal ();
XSubtractRegion (handle (), r.handle (), rv.handle ());
return rv;
}
@@ -252,7 +233,6 @@ CompRegion
CompRegion::subtracted (const CompRect &r) const
{
CompRegion rv;
- rv.priv->makeReal ();
XSubtractRegion (handle (), r.region (), rv.handle ());
return rv;
}
@@ -260,7 +240,6 @@ CompRegion::subtracted (const CompRect &r) const
void
CompRegion::translate (int dx, int dy)
{
- priv->makeReal ();
XOffsetRegion (handle (), dx, dy);
}
@@ -289,7 +268,6 @@ CompRegion::translated (const CompPoint &p) const
void
CompRegion::shrink (int dx, int dy)
{
- priv->makeReal ();
XShrinkRegion (handle (), dx, dy);
}
@@ -319,7 +297,6 @@ CompRegion
CompRegion::united (const CompRegion &r) const
{
CompRegion rv;
- rv.priv->makeReal ();
XUnionRegion (handle (), r.handle (), rv.handle ());
return rv;
}
@@ -328,7 +305,6 @@ CompRegion
CompRegion::united (const CompRect &r) const
{
CompRegion rv;
- rv.priv->makeReal ();
XUnionRegion (handle (), r.region (), rv.handle ());
return rv;
}
@@ -337,7 +313,6 @@ CompRegion
CompRegion::xored (const CompRegion &r) const
{
CompRegion rv;
- rv.priv->makeReal ();
XXorRegion (handle (), r.handle (), rv.handle ());
return rv;
}
@@ -441,29 +416,10 @@ CompRegion::operator|= (const CompRegion &r)
PrivateRegion::PrivateRegion ()
{
- region = NULL;
- box.numRects = 0;
- box.extents.x1 = 0;
- box.extents.y1 = 0;
- box.extents.x2 = 0;
- box.extents.y2 = 0;
- box.rects = NULL;
- box.size = 0;
+ region = XCreateRegion ();
}
PrivateRegion::~PrivateRegion ()
{
- if (region)
- XDestroyRegion (region);
-}
-
-void
-PrivateRegion::makeReal ()
-{
- if (region)
- return;
- region = XCreateRegion ();
- if (box.numRects)
- XUnionRegion (CompRegion ().handle (), &box, region);
+ XDestroyRegion (region);
}
-
diff --git a/src/screen.cpp b/src/screen.cpp
index 80cf93b..e296b03 100644
--- a/src/screen.cpp
+++ b/src/screen.cpp
@@ -52,7 +52,6 @@
#include <X11/extensions/shape.h>
#include <X11/cursorfont.h>
-
#include <core/core.h>
#include <core/screen.h>
@@ -111,67 +110,85 @@ CompScreen::freePluginClassIndex (unsigned int index)
screen->pluginClasses.resize (screenPluginClassIndices.size ());
}
-#define TIMEVALDIFF(tv1, tv2) \
- ((tv1)->tv_sec == (tv2)->tv_sec || (tv1)->tv_usec >= (tv2)->tv_usec) ? \
- ((((tv1)->tv_sec - (tv2)->tv_sec) * 1000000) + \
- ((tv1)->tv_usec - (tv2)->tv_usec)) / 1000 : \
- ((((tv1)->tv_sec - 1 - (tv2)->tv_sec) * 1000000) + \
- (1000000 + (tv1)->tv_usec - (tv2)->tv_usec)) / 1000
+Glib::RefPtr <CompEventSource>
+CompEventSource::create ()
+{
+ return Glib::RefPtr <CompEventSource> (new CompEventSource ());
+}
-void
-CompScreen::eventLoop ()
+sigc::connection
+CompEventSource::connect (const sigc::slot <bool> &slot)
{
- struct timeval tv;
- CompTimer *t;
- int time;
- CompWatchFdHandle watchFdHandle;
+ return connect_generic (slot);
+}
+
+CompEventSource::CompEventSource () :
+ Glib::Source (),
+ mDpy (screen->dpy ()),
+ mConnectionFD (ConnectionNumber (screen->dpy ()))
+{
+ mPollFD.set_fd (mConnectionFD);
+ mPollFD.set_events (Glib::IO_IN);
- watchFdHandle = addWatchFd (ConnectionNumber (priv->dpy), POLLIN, NULL);
+ set_priority (G_PRIORITY_DEFAULT);
+ add_poll (mPollFD);
+ set_can_recurse (true);
+
+ connect (sigc::mem_fun <bool, CompEventSource> (this, &CompEventSource::callback));
+}
- for (;;)
+CompEventSource::~CompEventSource ()
+{
+}
+
+bool
+CompEventSource::callback ()
+{
+ if (restartSignal || shutDown)
{
- if (restartSignal || shutDown)
- break;
+ screen->priv->mainloop->quit ();
+ return false;
+ }
+ else
+ screen->priv->processEvents ();
+ return true;
+}
- priv->processEvents ();
+bool
+CompEventSource::prepare (int &timeout)
+{
+ timeout = -1;
+ return XPending (mDpy);
+}
- if (!priv->timers.empty ())
- {
- gettimeofday (&tv, 0);
- priv->handleTimers (&tv);
+bool
+CompEventSource::check ()
+{
+ if (mPollFD.get_revents () & Glib::IO_IN)
+ return XPending (mDpy);
- if (priv->timers.front ()->mMinLeft > 0)
- {
- std::list<CompTimer *>::iterator it = priv->timers.begin ();
+ return false;
+}
- t = (*it);
- time = t->mMaxLeft;
- while (it != priv->timers.end ())
- {
- t = (*it);
- if (t->mMinLeft >= time)
- break;
- if (t->mMaxLeft < time)
- time = t->mMaxLeft;
- it++;
- }
+bool
+CompEventSource::dispatch (sigc::slot_base *slot)
+{
+ return (*static_cast <sigc::slot <bool> *> (slot)) ();
+}
- if (time < 5)
- usleep (time * 1000);
- else
- priv->doPoll (time);
+void
+CompScreen::eventLoop ()
+{
+ priv->ctx = Glib::MainContext::get_default ();
+ priv->mainloop = Glib::MainLoop::create (priv->ctx, false);
+ priv->source = CompEventSource::create ();
- gettimeofday (&tv, 0);
- priv->handleTimers (&tv);
- }
- }
- else
- {
- priv->doPoll (-1);
- }
- }
+ priv->source->attach (priv->ctx);
+
+ /* Kick the event loop */
+ priv->ctx->iteration (false);
- removeWatchFd (watchFdHandle);
+ priv->mainloop->run ();
}
CompFileWatchHandle
@@ -225,39 +242,108 @@ CompScreen::getFileWatches () const
return priv->fileWatch;
}
-void
-PrivateScreen::addTimer (CompTimer *timer)
+/* TODO: move this code to timer.cpp */
+
+bool
+CompTimer::internalCallback (unsigned int id)
{
- std::list<CompTimer *>::iterator it;
+ bool result;
+
+ /* Detect when the timer is still going and the internal
+ * object has been freed */
+ if (!screen->priv->removedTimers.empty ())
+ {
+ if (std::find (screen->priv->removedTimers.begin (),
+ screen->priv->removedTimers.end (),
+ id) != screen->priv->removedTimers.end ())
+ {
+ screen->priv->removedTimers.remove (id);
+ return false;
+ }
+ }
- it = std::find (timers.begin (), timers.end (), timer);
+ if (!mActive)
+ return false;
- if (it != timers.end ())
- return;
+ mForceFail = false;
+ mExecuting = true;
+
+ result = mCallBack ();
+
+ mExecuting = false;
- for (it = timers.begin (); it != timers.end (); it++)
+ if (mForceFail)
+ return false;
+
+ if (result)
{
- if ((int) timer->mMinTime < (*it)->mMinLeft)
- break;
+ tick ();
+ return true;
}
+ else
+ {
+ if (mSource)
+ mSource.reset ();
+ return false;
+ }
+}
+
+void
+PrivateScreen::addTimer (CompTimer *timer)
+{
+ unsigned int time = timer->mMinTime;
+ unsigned int id;
- timer->mMinLeft = timer->mMinTime;
- timer->mMaxLeft = timer->mMaxTime;
+ if (timer->mSource)
+ return;
- timers.insert (it, timer);
+ timer->mSource = Glib::TimeoutSource::create (time);
+
+ if (timer->mSource)
+ {
+ timer->mSource->attach (priv->ctx);
+ id = g_source_get_id (timer->mSource->gobj ());
+ removedTimers.remove (id);
+ timer->mSource->connect (sigc::bind <unsigned int>(sigc::mem_fun (timer, &CompTimer::internalCallback), id));
+ timer->tick ();
+ }
+ else
+ timer->mActive = false;
}
void
PrivateScreen::removeTimer (CompTimer *timer)
{
- std::list<CompTimer *>::iterator it;
+ if (!timer->mSource)
+ return;
- it = std::find (timers.begin (), timers.end (), timer);
+ if (timer->mExecuting)
+ timer->mForceFail = true;
- if (it == timers.end ())
- return;
+ removedTimers.push_back (g_source_get_id (timer->mSource->gobj ()));
+
+ timer->mSource.reset (); /* This will NULL the pointer */
+}
+
+CompWatchFd::CompWatchFd (int fd,
+ Glib::IOCondition events,
+ FdWatchCallBack callback) :
+ Glib::IOSource (fd, events),
+ mFd (fd),
+ mCallBack (callback),
+ mForceFail (false),
+ mExecuting (false)
+{
+ connect (sigc::mem_fun <Glib::IOCondition, bool>
+ (this, &CompWatchFd::internalCallback));
+}
- timers.erase (it);
+Glib::RefPtr <CompWatchFd>
+CompWatchFd::create (int fd,
+ Glib::IOCondition events,
+ FdWatchCallBack callback)
+{
+ return Glib::RefPtr <CompWatchFd> (new CompWatchFd (fd, events, callback));
}
CompWatchFdHandle
@@ -265,42 +351,47 @@ CompScreen::addWatchFd (int fd,
short int events,
FdWatchCallBack callBack)
{
- CompWatchFd *watchFd = new CompWatchFd ();
+ Glib::IOCondition gEvents;
+
+ memset (&gEvents, 0, sizeof (Glib::IOCondition));
+
+ if (events & POLLIN)
+ gEvents |= Glib::IO_IN;
+ if (events & POLLOUT)
+ gEvents |= Glib::IO_OUT;
+ if (events & POLLPRI)
+ gEvents |= Glib::IO_PRI;
+ if (events & POLLERR)
+ gEvents |= Glib::IO_ERR;
+ if (events & POLLHUP)
+ gEvents |= Glib::IO_HUP;
+
+ Glib::RefPtr <CompWatchFd> watchFd = CompWatchFd::create (fd, gEvents, callBack);
+
+ watchFd->attach (priv->ctx);
if (!watchFd)
return 0;
-
- watchFd->fd = fd;
- watchFd->callBack = callBack;
- watchFd->handle = priv->lastWatchFdHandle++;
+ watchFd->mHandle = priv->lastWatchFdHandle++;
if (priv->lastWatchFdHandle == MAXSHORT)
priv->lastWatchFdHandle = 1;
priv->watchFds.push_front (watchFd);
- priv->nWatchFds++;
-
- priv->watchPollFds = (struct pollfd *) realloc (priv->watchPollFds,
- priv->nWatchFds * sizeof (struct pollfd));
-
- priv->watchPollFds[priv->nWatchFds - 1].fd = fd;
- priv->watchPollFds[priv->nWatchFds - 1].events = events;
-
- return watchFd->handle;
+ return watchFd->mHandle;
}
void
CompScreen::removeWatchFd (CompWatchFdHandle handle)
{
- std::list<CompWatchFd *>::iterator it;
- CompWatchFd *w;
- int i;
+ std::list<Glib::RefPtr <CompWatchFd> >::iterator it;
+ Glib::RefPtr <CompWatchFd> w;
- for (it = priv->watchFds.begin(), i = priv->nWatchFds - 1;
- it != priv->watchFds.end (); it++, i--)
+ for (it = priv->watchFds.begin();
+ it != priv->watchFds.end (); it++)
{
- if ((*it)->handle == handle)
+ if ((*it)->mHandle == handle)
break;
}
@@ -308,15 +399,15 @@ CompScreen::removeWatchFd (CompWatchFdHandle handle)
return;
w = (*it);
- priv->watchFds.erase (it);
-
- priv->nWatchFds--;
- if (i < priv->nWatchFds)
- memmove (&priv->watchPollFds[i], &priv->watchPollFds[i + 1],
- (priv->nWatchFds - i) * sizeof (struct pollfd));
+ if (w->mExecuting)
+ {
+ w->mForceFail = true;
+ return;
+ }
- delete w;
+ w.reset ();
+ priv->watchFds.erase (it);
}
void
@@ -361,78 +452,54 @@ CompScreen::getValue (CompString key)
}
}
-void
-CompScreen::eraseValue (CompString key)
-{
- std::map<CompString,CompPrivate>::iterator it;
- it = priv->valueMap.find (key);
-
- if (it != priv->valueMap.end ())
- {
- priv->valueMap.erase (key);
- }
-}
+bool
+CompWatchFd::internalCallback (Glib::IOCondition events)
+{
+ short int revents = 0;
+
+ if (events & Glib::IO_IN)
+ revents |= POLLIN;
+ if (events & Glib::IO_OUT)
+ revents |= POLLOUT;
+ if (events & Glib::IO_PRI)
+ revents |= POLLPRI;
+ if (events & Glib::IO_ERR)
+ revents |= POLLERR;
+ if (events & Glib::IO_HUP)
+ revents |= POLLHUP;
+ if (events & Glib::IO_NVAL)
+ return false;
-int
-PrivateScreen::doPoll (int timeout)
-{
- int rv;
+ mExecuting = true;
+ mCallBack (revents);
+ mExecuting = false;
- rv = poll (watchPollFds, nWatchFds, timeout);
- if (rv)
+ if (mForceFail)
{
- std::list<CompWatchFd *>::iterator it;
- int i;
-
- for (it = watchFds.begin (), i = nWatchFds - 1; it != watchFds.end ();
- it++, i--)
- {
- if (watchPollFds[i].revents != 0 && (*it)->callBack)
- (*it)->callBack (watchPollFds[i].revents);
- }
+ /* FIXME: Need to find a way to properly remove the watchFd
+ * from the internal list in core */
+ //screen->priv->watchFds.remove (this);
+ return false;
}
-
- return rv;
+
+ return true;
}
+
+
+
void
-PrivateScreen::handleTimers (struct timeval *tv)
+CompScreen::eraseValue (CompString key)
{
- CompTimer *t;
- int timeDiff;
- std::list<CompTimer *>::iterator it;
-
- timeDiff = TIMEVALDIFF (tv, &lastTimeout);
-
- /* handle clock rollback */
- if (timeDiff < 0)
- timeDiff = 0;
-
- for (it = timers.begin (); it != timers.end (); it++)
- {
- t = (*it);
- t->mMinLeft -= timeDiff;
- t->mMaxLeft -= timeDiff;
- }
+ std::map<CompString,CompPrivate>::iterator it;
+ it = priv->valueMap.find (key);
- while (timers.begin () != timers.end () &&
- timers.front ()->mMinLeft <= 0)
+ if (it != priv->valueMap.end ())
{
- t = timers.front ();
- timers.pop_front ();
-
- t->mActive = false;
- if (t->mCallBack ())
- {
- addTimer (t);
- t->mActive = true;
- }
+ priv->valueMap.erase (key);
}
-
- lastTimeout = *tv;
}
-
void
CompScreen::fileWatchAdded (CompFileWatch *watch)
WRAPABLE_HND_FUNC (0, fileWatchAdded, watch)
@@ -735,7 +802,7 @@ PrivateScreen::setOption (const CompString &name,
void
PrivateScreen::processEvents ()
{
- XEvent event;
+ XEvent event, peekEvent;
/* remove destroyed windows */
removeDestroyed ();
@@ -759,6 +826,16 @@ PrivateScreen::processEvents ()
pointerY = event.xkey.y_root;
break;
case MotionNotify:
+ while (XPending (dpy))
+ {
+ XPeekEvent (dpy, &peekEvent);
+
+ if (peekEvent.type != MotionNotify)
+ break;
+
+ XNextEvent (dpy, &event);
+ }
+
pointerX = event.xmotion.x_root;
pointerY = event.xmotion.y_root;
break;
@@ -4616,9 +4693,6 @@ CompScreen::~CompScreen ()
if (priv->snDisplay)
sn_display_unref (priv->snDisplay);
- if (priv->watchPollFds)
- free (priv->watchPollFds);
-
XSync (priv->dpy, False);
XCloseDisplay (priv->dpy);
@@ -4631,11 +4705,8 @@ PrivateScreen::PrivateScreen (CompScreen *screen) :
priv (this),
fileWatch (0),
lastFileWatchHandle (1),
- timers (0),
watchFds (0),
lastWatchFdHandle (1),
- watchPollFds (0),
- nWatchFds (0),
valueMap (),
screenInfo (0),
activeWindow (0),
diff --git a/src/timer.cpp b/src/timer.cpp
index c9bfdee..793dad4 100644
--- a/src/timer.cpp
+++ b/src/timer.cpp
@@ -33,7 +33,10 @@ CompTimer::CompTimer () :
mMaxTime (0),
mMinLeft (0),
mMaxLeft (0),
- mCallBack (NULL)
+ mCallBack (NULL),
+ mForceFail (false),
+ mExecuting (false),
+ mSource (NULL)
{
}
@@ -80,8 +83,10 @@ CompTimer::start ()
return;
}
+ if (!mActive)
+ screen->priv->addTimer (this);
+
mActive = true;
- screen->priv->addTimer (this);
}
void
@@ -105,8 +110,10 @@ CompTimer::start (CompTimer::CallBack callback,
void
CompTimer::stop ()
{
+ if (mActive)
+ screen->priv->removeTimer (this);
+
mActive = false;
- screen->priv->removeTimer (this);
}
unsigned int
@@ -124,13 +131,25 @@ CompTimer::maxTime ()
unsigned int
CompTimer::minLeft ()
{
- return (mMinLeft < 0)? 0 : mMinLeft;
+ struct timeval current;
+ int left;
+
+ gettimeofday (&current, 0);
+ left = mMinTime - TIMEVALDIFF (&current, &tickStart);
+
+ return (left < 0)? 0 : (unsigned int) left;
}
unsigned int
CompTimer::maxLeft ()
{
- return (mMaxLeft < 0)? 0 : mMaxLeft;
+ struct timeval current;
+ int left;
+
+ gettimeofday (&current, 0);
+ left = mMaxTime - TIMEVALDIFF (&current, &tickStart);
+
+ return (left < 0)? 0 : (unsigned int) left;
}
bool
@@ -138,3 +157,15 @@ CompTimer::active ()
{
return mActive;
}
+
+void
+CompTimer::tick ()
+{
+ gettimeofday (&tickStart, 0);
+}
+
+const struct timeval &
+CompTimer::tickInfo () const
+{
+ return tickStart;
+}
diff --git a/src/window.cpp b/src/window.cpp
index 32dc8b1..93b5c2c 100644
--- a/src/window.cpp
+++ b/src/window.cpp
@@ -3514,7 +3514,7 @@ CompWindow::constrainNewWindowSize (int width,
#define FLOOR(value, base) (((int) ((value) / (base))) * (base))
#define FLOOR64(value, base) (((uint64_t) ((value) / (base))) * (base))
-#define CLAMP(v, min, max) ((v) <= (min) ? (min) : (v) >= (max) ? (max) : (v))
+#define CLAMPW(v, min, max) ((v) <= (min) ? (min) : (v) >= (max) ? (max) : (v))
if ((flags & PBaseSize) && (flags & PMinSize))
{
@@ -3551,8 +3551,8 @@ CompWindow::constrainNewWindowSize (int width,
yinc = MAX (yinc, hints->height_inc);
/* clamp width and height to min and max values */
- width = CLAMP (width, min_width, max_width);
- height = CLAMP (height, min_height, max_height);
+ width = CLAMPW (width, min_width, max_width);
+ height = CLAMPW (height, min_height, max_height);
/* shrink to base + N * inc */
width = base_width + FLOOR (width - base_width, xinc);
@@ -3605,7 +3605,7 @@ CompWindow::constrainNewWindowSize (int width,
}
}
-#undef CLAMP
+#undef CLAMPW
#undef FLOOR64
#undef FLOOR
@@ -5047,9 +5047,9 @@ CompWindow::CompWindow (Window id,
priv->clientLeader = None;
XSelectInput (screen->dpy (), id,
- PropertyChangeMask |
- EnterWindowMask |
- FocusChangeMask);
+ EnterWindowMask |
+ PropertyChangeMask |
+ FocusChangeMask);
priv->id = id;