diff --git a/xfwm4-4.10.0/defaults/.defaults.swp b/xfwm4-4.10.0/defaults/.defaults.swp
deleted file mode 100644
index b04c262..0000000
Binary files a/xfwm4-4.10.0/defaults/.defaults.swp and /dev/null differ
diff --git a/xfwm4-4.10.0/defaults/defaults b/xfwm4-4.10.0/defaults/defaults
index 6db210a..17dc3d7 100644
--- a/xfwm4-4.10.0/defaults/defaults
+++ b/xfwm4-4.10.0/defaults/defaults
@@ -49,6 +49,7 @@ snap_resist=false
snap_to_border=true
snap_to_windows=false
snap_width=10
+sync_to_vblank=false
theme=Default
tile_on_move=true
title_alignment=center
diff --git a/xfwm4-4.10.0/settings-dialogs/tweaks-settings.c b/xfwm4-4.10.0/settings-dialogs/tweaks-settings.c
index f60b606..0c7cd4e 100644
--- a/xfwm4-4.10.0/settings-dialogs/tweaks-settings.c
+++ b/xfwm4-4.10.0/settings-dialogs/tweaks-settings.c
@@ -205,6 +205,7 @@ wm_tweaks_dialog_configure_widgets (GtkBuilder *builder)
GtkWidget *show_frame_shadow_check = GTK_WIDGET (gtk_builder_get_object (builder, "show_frame_shadow_check"));
GtkWidget *show_popup_shadow_check = GTK_WIDGET (gtk_builder_get_object (builder, "show_popup_shadow_check"));
GtkWidget *show_dock_shadow_check = GTK_WIDGET (gtk_builder_get_object (builder, "show_dock_shadow_check"));
+ GtkWidget *sync_to_vblank_check = GTK_WIDGET (gtk_builder_get_object (builder, "sync_to_vblank_check"));
GtkWidget *frame_opacity_scale = GTK_WIDGET (gtk_builder_get_object (builder, "frame_opacity_scale"));
GtkWidget *inactive_opacity_scale = GTK_WIDGET (gtk_builder_get_object (builder, "inactive_opacity_scale"));
@@ -405,6 +406,10 @@ wm_tweaks_dialog_configure_widgets (GtkBuilder *builder)
"/general/show_dock_shadow",
G_TYPE_BOOLEAN,
(GObject *)show_dock_shadow_check, "active");
+ xfconf_g_property_bind (xfwm4_channel,
+ "/general/sync_to_vblank",
+ G_TYPE_BOOLEAN,
+ (GObject *)sync_to_vblank_check, "active");
xfconf_g_property_bind (xfwm4_channel,
"/general/frame_opacity",
diff --git a/xfwm4-4.10.0/settings-dialogs/xfwm4-tweaks-dialog.glade b/xfwm4-4.10.0/settings-dialogs/xfwm4-tweaks-dialog.glade
index bd2a86f..10b0a72 100644
--- a/xfwm4-4.10.0/settings-dialogs/xfwm4-tweaks-dialog.glade
+++ b/xfwm4-4.10.0/settings-dialogs/xfwm4-tweaks-dialog.glade
@@ -773,6 +773,20 @@ when switching via keyboard shortcuts
+
+ Synchronize drawing to the _vertical blank
+ True
+ True
+ False
+ True
+ True
+
+
+ False
+ 4
+
+
+
True
0
@@ -782,7 +796,7 @@ when switching via keyboard shortcuts
False
- 4
+ 5
@@ -836,7 +850,7 @@ when switching via keyboard shortcuts
False
False
- 5
+ 6
@@ -850,7 +864,7 @@ when switching via keyboard shortcuts
False
False
- 6
+ 7
@@ -904,7 +918,7 @@ when switching via keyboard shortcuts
False
False
- 7
+ 8
@@ -918,7 +932,7 @@ when switching via keyboard shortcuts
False
False
- 8
+ 9
@@ -972,7 +986,7 @@ when switching via keyboard shortcuts
False
False
- 9
+ 10
@@ -986,7 +1000,7 @@ when switching via keyboard shortcuts
False
False
- 10
+ 11
@@ -1040,7 +1054,7 @@ when switching via keyboard shortcuts
False
False
- 11
+ 12
@@ -1054,7 +1068,7 @@ when switching via keyboard shortcuts
False
False
- 12
+ 13
@@ -1108,7 +1122,7 @@ when switching via keyboard shortcuts
False
False
- 13
+ 14
diff --git a/xfwm4-4.10.0/settings-dialogs/xfwm4-tweaks-dialog_ui.h b/xfwm4-4.10.0/settings-dialogs/xfwm4-tweaks-dialog_ui.h
index a6121dd..9418ca9 100644
--- a/xfwm4-4.10.0/settings-dialogs/xfwm4-tweaks-dialog_ui.h
+++ b/xfwm4-4.10.0/settings-dialogs/xfwm4-tweaks-dialog_ui.h
@@ -386,187 +386,194 @@ static const char tweaks_dialog_ui[] =
"eceives_default\">FalseTrue"
" True
False 3 True 0 Op"
- "aci_ty of window decorations: True frame_opacity_scale<"
- "/property> False <"
- "property name=\"position\">4Tr"
- "ue 2 12 True True <i>Transparent</i>"
- ";True False F"
- "alse 0 TrueTrue
discontinuous adjustment2False False1 True <i>Opaque</i> True FalseFalse 2 False
False"
- "property>5 True 0 Opacity of _inactive windows: True
inactive_opacity_scale False False 6 "
- "True 2 12 True True <i>Transparent</i&g"
- "t;True False "
- "False 0 TrueTru"
- "e discontinuous adjustment3False Fals"
- "e
1 <"
- "/packing>True<i>Opaque</i> True False"
- " False 2 False Fal"
- "se 7 "
- "True 0 Opacity of windows during _move:True move_opacity_scale 3 Synchronize drawing to the _vertical blank True True FalseTrue True
False 4 True 0 Opaci_ty of window decorations: True fra"
+ "me_opacity_scale "
+ "False 5 True 212 True "
+ "Tr"
+ "ue <i>Tra"
+ "nsparent</i> True False False 0 True True discontinuous"
+ " adjustment2 FalseFalse "
+ "1 True <i>Opaque</i> True False False 2 False False 6 True 0 "
+ "Opacity of _inactive wind"
+ "ows: True inactive_opacity_scale False False 7
True 212 True T"
+ "rue <i>Tr"
+ "ansparent</i> True False False0 True True discontin"
+ "uous adjustment3 FalseFalse 1 True <i>Opaque</i> True False False 2 False False 8 <"
+ "/packing>True0Opacity of windows du"
+ "ring _move: True <"
+ "property name=\"mnemonic_widget\">move_opacity_scale False False 9 "
+ "True212 True True <i&g"
+ "t;Transparent</i> True False False 0 True True discontin"
+ "uous adjustment4 FalseFalse 1 True <i>Opaque</i> True False False 2 False False 10 "
+ "True0Opacity of windows d"
+ "uring resi_ze: Trueresize_opacity_scale False False 11 <"
+ "property name=\"visible\">True2 12 TrueTrue &"
+ "lt;i>Transparent</i> T"
+ "rue FalseFalse "
+ "0 True True d"
+ "iscontinuous adjustment5False False 1 True <i>Opaque</i> True FalseFalse8 True 2 12 True True <i>Transparent<"
- "/i> True "
- "False False 0 <"
- "/child>TrueTru"
- "e discontinuous adjustment4False Fals"
- "e
1 <"
- "/packing>True<i>Opaque</i> True False"
- " False 2 False Fal"
- "se 9 "
- "True 0 Opacity of windows during resi_ze:True resize_opacity_scale FalseFalse10 True 2 12True True<i>Transparent"
- "</i> True 2 "
+ " False False12 True "
+ "0 Opacity of po"
+ "pup window_s: True popup_opacity_scale False False 0 True True discontinuousadjustment5 False "
- "False 1 <"
- "property name=\"visible\">True<i>Opaque</i> True F"
- "alse False 2 False13 True2<"
+ "/property>12 True True <"
+ "i>Transparent</i> True"
+ " False "
+ "False 0"
+ "property> True True disco"
+ "ntinuous adjustment6 "
+ "False False 1 True <i>Opaque</i> True
False False 2 False False14 1 <"
+ "/child>5 True C_ompositor True 5False 1 <"
+ "child internal-child=\"action_area\">True endgtk-help TrueTrue"
+ "property>True True True False False0True g"
+ "tk-close True True T"
+ "rue True False "
- "False 11 True 0 Opacity of popup window_s:True popup_opacity_scale FalseFalse12 True 2 12 True True <i>Transparent<"
- "/i> True "
- "False False 0 <"
- "/child>1 "
- "True<i>Opaque</i> True Fals"
- "e False 2 False Fa"
- "lse 13 "
- "1 5 True C"
- "_ompositor True "
- "object>5 False 1 True end gtk-help True True True "
- "True True False False 0 True gtk-close True True True True False False 1
False end 0 bu"
- "tton2 button1 "
+ "False1 False end0 button2 bu"
+ "tton1 "
};
-static const unsigned tweaks_dialog_ui_length = 37803u;
+static const unsigned tweaks_dialog_ui_length = 38296u;
diff --git a/xfwm4-4.10.0/src/compositor.c b/xfwm4-4.10.0/src/compositor.c
index c0ce4ea..d9502e6 100644
--- a/xfwm4-4.10.0/src/compositor.c
+++ b/xfwm4-4.10.0/src/compositor.c
@@ -36,6 +36,11 @@
#include
#include
+#include
+#include
+#include
+#include
+
#include "display.h"
#include "screen.h"
#include "client.h"
@@ -87,6 +92,9 @@
/* Set TIMEOUT_REPAINT to 0 to disable timeout repaint */
#define TIMEOUT_REPAINT 10 /* msec.) */
+#define TIMEOUT_REPAINT_MIN 1
+#define TIMEOUT_REPAINT_MAX 20
+#define TIMEOUT_DRI 10 /* seconds */
typedef struct _CWindow CWindow;
struct _CWindow
@@ -1243,6 +1251,102 @@ paint_win (CWindow *cw, XserverRegion region, gboolean solid_part)
}
}
+#if TIMEOUT_REPAINT
+
+static void
+open_dri (ScreenInfo *screen_info)
+{
+ const char* dev = "/dev/dri/card0";
+ screen_info->dri_fd = open(dev, O_RDWR);
+ if (screen_info->dri_fd == -1)
+ g_warning ("Error opening %s: %s", dev, strerror(errno));
+}
+
+static void
+close_dri (ScreenInfo *screen_info)
+{
+ close(screen_info->dri_fd);
+ screen_info->dri_fd = -1;
+}
+
+static gboolean
+dri_enabled (ScreenInfo *screen_info)
+{
+ return (screen_info->dri_fd != -1 && screen_info->params->sync_to_vblank);
+}
+
+static void
+wait_vblank (ScreenInfo *screen_info)
+{
+ int retval;
+ drm_wait_vblank_t vblank;
+
+ if (screen_info->dri_time > g_get_monotonic_time())
+ return;
+
+ vblank.request.sequence = 1;
+ vblank.request.type = _DRM_VBLANK_RELATIVE;
+ if (screen_info->dri_secondary)
+ vblank.request.type |= _DRM_VBLANK_SECONDARY;
+
+ do
+ {
+ retval = ioctl(screen_info->dri_fd, DRM_IOCTL_WAIT_VBLANK, &vblank);
+ vblank.request.type &= ~_DRM_VBLANK_RELATIVE;
+ }
+ while (retval == -1 && errno == EINTR);
+
+ screen_info->vblank_time = g_get_monotonic_time();
+
+ if (retval == -1)
+ {
+ if (screen_info->dri_success)
+ {
+ screen_info->dri_success = FALSE;
+ g_warning ("Error waiting on vblank with DRI: %s", strerror(errno));
+ }
+
+ /* if getting the vblank fails, try to get it from the other output */
+ screen_info->dri_secondary = !screen_info->dri_secondary;
+
+ /* the output that we tried to get the vblank from might be disabled,
+ if that's the case, the device needs to be reopened, or it will continue to fail */
+ close_dri(screen_info);
+ open_dri(screen_info);
+
+ /* retry in 10 seconds */
+ screen_info->dri_time = g_get_monotonic_time() + TIMEOUT_DRI * 1000000;
+ }
+ else if (!screen_info->dri_success)
+ {
+ g_message ("Using vertical blank of %s DRI output",
+ screen_info->dri_secondary ? "secondary" : "primary");
+
+ screen_info->dri_success = TRUE;
+ }
+}
+
+#ifdef HAVE_RANDR
+static void
+get_refresh_rate (ScreenInfo* screen_info)
+{
+ gint refresh_rate;
+ XRRScreenConfiguration* randr_info;
+
+ randr_info = XRRGetScreenInfo(screen_info->display_info->dpy, screen_info->xroot);
+ refresh_rate = XRRConfigCurrentRate(randr_info);
+ XRRFreeScreenConfigInfo(randr_info);
+
+ if (refresh_rate != screen_info->refresh_rate)
+ {
+ g_message ("Detected refreshrate:%i hertz", refresh_rate);
+ screen_info->refresh_rate = refresh_rate;
+ }
+}
+#endif
+
+#endif
+
static void
paint_all (ScreenInfo *screen_info, XserverRegion region)
{
@@ -1254,6 +1358,10 @@ paint_all (ScreenInfo *screen_info, XserverRegion region)
gint screen_height;
CWindow *cw;
+#if TIMEOUT_REPAINT
+ gboolean use_dri;
+#endif
+
TRACE ("entering paint_all");
g_return_if_fail (screen_info);
@@ -1402,8 +1510,24 @@ paint_all (ScreenInfo *screen_info, XserverRegion region)
TRACE ("Copying data back to screen");
/* Set clipping back to the given region */
XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer, 0, 0, region);
+
+#if TIMEOUT_REPAINT
+ use_dri = dri_enabled(screen_info);
+ /*sync all previous rendering commands, tell xlib to render the pixmap onto the root window,
+ wait for the vblank, then flush, this minimizes tearing*/
+ if (use_dri)
+ XFlush(dpy);
+#endif
XRenderComposite (dpy, PictOpSrc, screen_info->rootBuffer, None, screen_info->rootPicture,
0, 0, 0, 0, 0, 0, screen_width, screen_height);
+#if TIMEOUT_REPAINT
+ if (use_dri)
+ {
+ wait_vblank(screen_info);
+ XFlush(dpy);
+ }
+#endif
+
XFixesDestroyRegion (dpy, paint_region);
}
@@ -1463,12 +1587,42 @@ static void
add_repair (ScreenInfo *screen_info)
{
#if TIMEOUT_REPAINT
+ gint64 interval;
+
if (screen_info->compositor_timeout_id != 0)
{
return;
}
+
+ if (dri_enabled(screen_info))
+ {
+ /* schedule the next render to be half a refresh period after the last vertical blank,
+ but at least 1 ms in the future so that all queued events can be processed,
+ and to reduce latency if we didn't render for a while */
+#ifdef HAVE_RANDR
+ if (screen_info->refresh_rate > 0)
+ {
+ interval = (screen_info->vblank_time + 500000 / screen_info->refresh_rate -
+ g_get_monotonic_time()) / 1000;
+ }
+ else
+#endif
+ {
+ interval = TIMEOUT_REPAINT - ((g_get_monotonic_time() - screen_info->vblank_time) / 1000);
+ }
+
+ if (interval > TIMEOUT_REPAINT_MAX)
+ interval = TIMEOUT_REPAINT_MAX;
+ else if (interval < TIMEOUT_REPAINT_MIN)
+ interval = TIMEOUT_REPAINT_MIN;
+ }
+ else
+ {
+ interval = TIMEOUT_REPAINT;
+ }
+
screen_info->compositor_timeout_id =
- g_timeout_add (TIMEOUT_REPAINT,
+ g_timeout_add (interval,
compositor_timeout_cb, screen_info);
#endif /* TIMEOUT_REPAINT */
}
@@ -2539,6 +2693,24 @@ compositorHandleShapeNotify (DisplayInfo *display_info, XShapeEvent *ev)
}
}
+#ifdef HAVE_RANDR
+static void
+compositorHandleRandrNotify (DisplayInfo *display_info, XRRScreenChangeNotifyEvent *ev)
+{
+ ScreenInfo *screen_info;
+
+ g_return_if_fail (display_info != NULL);
+ g_return_if_fail (ev != NULL);
+ TRACE ("entering compositorHandleRandrNotify for 0x%lx", ev->window);
+
+ screen_info = myDisplayGetScreenFromRoot (display_info, ev->window);
+ if (screen_info)
+ get_refresh_rate(screen_info);
+
+ XRRUpdateConfiguration ((XEvent *) ev);
+}
+#endif
+
static void
compositorSetCMSelection (ScreenInfo *screen_info, Window w)
{
@@ -2749,6 +2921,13 @@ compositorHandleEvent (DisplayInfo *display_info, XEvent *ev)
{
compositorHandleShapeNotify (display_info, (XShapeEvent *) ev);
}
+#ifdef HAVE_RANDR
+ else if (ev->type == (display_info->xrandr_event_base + RRScreenChangeNotify))
+ {
+ compositorHandleRandrNotify (display_info, (XRRScreenChangeNotifyEvent *) ev);
+ }
+#endif
+
#if TIMEOUT_REPAINT == 0
repair_display (display_info);
#endif /* TIMEOUT_REPAINT */
@@ -2967,6 +3146,20 @@ compositorManageScreen (ScreenInfo *screen_info)
compositorSetCMSelection (screen_info, screen_info->xfwm4_win);
TRACE ("Manual compositing enabled");
+ open_dri(screen_info);
+ screen_info->dri_success = TRUE;
+ screen_info->dri_secondary = FALSE;
+ screen_info->dri_time = 0;
+ screen_info->vblank_time = 0;
+
+#ifdef HAVE_RANDR
+ if (display_info->have_xrandr)
+ {
+ get_refresh_rate(screen_info);
+ XRRSelectInput(display_info->dpy, screen_info->xroot, RRScreenChangeNotifyMask);
+ }
+#endif
+
return TRUE;
#else
return FALSE;
@@ -3059,6 +3252,14 @@ compositorUnmanageScreen (ScreenInfo *screen_info)
display_info->composite_mode);
compositorSetCMSelection (screen_info, None);
+
+ close_dri(screen_info);
+
+#ifdef HAVE_RANDR
+ if (display_info->have_xrandr)
+ XRRSelectInput(display_info->dpy, screen_info->xroot, 0);
+#endif
+
#endif /* HAVE_COMPOSITOR */
}
diff --git a/xfwm4-4.10.0/src/screen.h b/xfwm4-4.10.0/src/screen.h
index 88e4845..8d8ccb3 100644
--- a/xfwm4-4.10.0/src/screen.h
+++ b/xfwm4-4.10.0/src/screen.h
@@ -181,6 +181,17 @@ struct _ScreenInfo
gboolean damages_pending;
guint compositor_timeout_id;
+
+ gint dri_fd;
+ gboolean dri_secondary;
+ gboolean dri_success;
+ gint64 dri_time;
+ gint64 vblank_time;
+
+#ifdef HAVE_RANDR
+ gint refresh_rate;
+#endif
+
#endif /* HAVE_COMPOSITOR */
};
diff --git a/xfwm4-4.10.0/src/settings.c b/xfwm4-4.10.0/src/settings.c
index 607bb7b..a8a9e06 100644
--- a/xfwm4-4.10.0/src/settings.c
+++ b/xfwm4-4.10.0/src/settings.c
@@ -720,6 +720,7 @@ loadSettings (ScreenInfo *screen_info)
{"snap_to_border", NULL, G_TYPE_BOOLEAN, TRUE},
{"snap_to_windows", NULL, G_TYPE_BOOLEAN, TRUE},
{"snap_width", NULL, G_TYPE_INT, TRUE},
+ {"sync_to_vblank", NULL, G_TYPE_BOOLEAN, TRUE},
{"theme", NULL, G_TYPE_STRING, TRUE},
{"tile_on_move", NULL, G_TYPE_BOOLEAN, TRUE},
{"title_alignment", NULL, G_TYPE_STRING, TRUE},
@@ -823,6 +824,8 @@ loadSettings (ScreenInfo *screen_info)
getBoolValue ("snap_resist", rc);
screen_info->params->snap_width =
getIntValue ("snap_width", rc);
+ screen_info->params->sync_to_vblank =
+ getBoolValue ("sync_to_vblank", rc);
screen_info->params->tile_on_move =
getBoolValue ("tile_on_move", rc);
screen_info->params->toggle_workspaces =
@@ -1329,6 +1332,10 @@ cb_xfwm4_channel_property_changed(XfconfChannel *channel, const gchar *property_
{
screen_info->params->tile_on_move = g_value_get_boolean (value);
}
+ else if (!strcmp (name, "sync_to_vblank"))
+ {
+ screen_info->params->sync_to_vblank = g_value_get_boolean (value);
+ }
else if (!strcmp (name, "toggle_workspaces"))
{
screen_info->params->toggle_workspaces = g_value_get_boolean (value);
diff --git a/xfwm4-4.10.0/src/settings.h b/xfwm4-4.10.0/src/settings.h
index be01b6b..d595ddc 100644
--- a/xfwm4-4.10.0/src/settings.h
+++ b/xfwm4-4.10.0/src/settings.h
@@ -223,6 +223,7 @@ struct _XfwmParams
gboolean snap_resist;
gboolean snap_to_border;
gboolean snap_to_windows;
+ gboolean sync_to_vblank;
gboolean tile_on_move;
gboolean title_vertical_offset_active;
gboolean title_vertical_offset_inactive;