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" "TrueFalse3True0Op" - "aci_ty of window decorations:Trueframe_opacity_scale<" - "/property>False<" - "property name=\"position\">4Tr" - "ue212TrueTrue<i>Transparent</i>" - ";TrueFalseF" - "alse0TrueTruediscontinuousadjustment2FalseFalse1True<i>Opaque</i>TrueFalseFalse2FalseFalse5True0Opacity of _inactive windows:Trueinactive_opacity_scaleFalseFalse6" - "True212TrueTrue<i>Transparent</i&g" - "t;TrueFalse" - "False0TrueTru" - "ediscontinuousadjustment3FalseFals" - "e1<" - "/packing>True<i>Opaque</i>TrueFalse" - "False2FalseFal" - "se7" - "True0Opacity of windows during _move:Truemove_opacity_scale3Synchronize drawing to the _vertical blankTrueTrueFalseTrueTrueFalse4True0Opaci_ty of window decorations:Truefra" + "me_opacity_scale" + "False5True212True" + "Tr" + "ue<i>Tra" + "nsparent</i>TrueFalseFalse0TrueTruediscontinuous" + "adjustment2FalseFalse" + "1True<i>Opaque</i>TrueFalseFalse2FalseFalse6True0" + "Opacity of _inactive wind" + "ows:Trueinactive_opacity_scaleFalseFalse7True212TrueT" + "rue<i>Tr" + "ansparent</i>TrueFalseFalse0TrueTruediscontin" + "uousadjustment3FalseFalse1True<i>Opaque</i>TrueFalseFalse2FalseFalse8<" + "/packing>True0Opacity of windows du" + "ring _move:True<" + "property name=\"mnemonic_widget\">move_opacity_scaleFalseFalse9" + "True212TrueTrue<i&g" + "t;Transparent</i>TrueFalseFalse0TrueTruediscontin" + "uousadjustment4FalseFalse1True<i>Opaque</i>TrueFalseFalse2FalseFalse10" + "True0Opacity of windows d" + "uring resi_ze:Trueresize_opacity_scaleFalseFalse11<" + "property name=\"visible\">True212TrueTrue&" + "lt;i>Transparent</i>T" + "rueFalseFalse" + "0TrueTrued" + "iscontinuousadjustment5FalseFalse1True<i>Opaque</i>TrueFalseFalse8True212TrueTrue<i>Transparent<" - "/i>True" - "FalseFalse0<" - "/child>TrueTru" - "ediscontinuousadjustment4FalseFals" - "e1<" - "/packing>True<i>Opaque</i>TrueFalse" - "False2FalseFal" - "se9" - "True0Opacity of windows during resi_ze:Trueresize_opacity_scaleFalseFalse10True212TrueTrue<i>Transparent" - "</i>True2" + "FalseFalse12True" + "0Opacity of po" + "pup window_s:Truepopup_opacity_scaleFalseFalse0TrueTruediscontinuousadjustment5False" - "False1<" - "property name=\"visible\">True<i>Opaque</i>TrueF" - "alseFalse2False13True2<" + "/property>12TrueTrue<" + "i>Transparent</i>True" + "False" + "False0TrueTruedisco" + "ntinuousadjustment6" + "FalseFalse1True<i>Opaque</i>TrueFalseFalse2FalseFalse141<" + "/child>5TrueC_ompositorTrue5False1<" + "child internal-child=\"action_area\">Trueendgtk-helpTrueTrueTrueTrueTrueFalseFalse0Trueg" + "tk-closeTrueTrueT" + "rueTrueFalse" - "False11True0Opacity of popup window_s:Truepopup_opacity_scaleFalseFalse12True212TrueTrue<i>Transparent<" - "/i>True" - "FalseFalse0<" - "/child>TrueTr" - "uediscontinuous<" - "property name=\"adjustment\">adjustment6FalseFal" - "se1" - "True<i>Opaque</i>TrueFals" - "eFalse2FalseFa" - "lse13" - "15TrueC" - "_ompositorTrue5False1Trueendgtk-helpTrueTrueTrue" - "TrueTrueFalseFalse0Truegtk-closeTrueTrueTrueTrueFalseFalse1Falseend0bu" - "tton2button1" + "False1Falseend0button2bu" + "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;