changed timing functions to use a monotonic increasing clock
gettimeofday() is subject to be changed on daylight-saving or to ntp-related
(think leap-seconds). even worse, it is subject to be changed BACK in time. this
is hard to fix correctly (see commit 45726d3016
and bug #3560509). it is
irrelevant for timers to know the nano-seconds since the epoch anyways.
This commit is contained in:
parent
60a53113e0
commit
541c8c407b
19 changed files with 365 additions and 286 deletions
68
configure.in
68
configure.in
|
@ -35,7 +35,7 @@ AC_HEADER_STDC
|
||||||
AC_HEADER_STDBOOL
|
AC_HEADER_STDBOOL
|
||||||
AC_CHECK_HEADERS(errno.h ctype.h dirent.h fcntl.h libgen.h \
|
AC_CHECK_HEADERS(errno.h ctype.h dirent.h fcntl.h libgen.h \
|
||||||
locale.h math.h nl_types.h process.h signal.h stdarg.h \
|
locale.h math.h nl_types.h process.h signal.h stdarg.h \
|
||||||
stdio.h time.h unistd.h \
|
stdint.h stdio.h time.h unistd.h \
|
||||||
sys/param.h sys/select.h sys/signal.h sys/stat.h \
|
sys/param.h sys/select.h sys/signal.h sys/stat.h \
|
||||||
sys/time.h sys/types.h sys/wait.h \
|
sys/time.h sys/types.h sys/wait.h \
|
||||||
langinfo.h iconv.h)
|
langinfo.h iconv.h)
|
||||||
|
@ -48,7 +48,7 @@ AC_CHECK_HEADERS(sstream, ,
|
||||||
)]
|
)]
|
||||||
)
|
)
|
||||||
|
|
||||||
AC_CHECK_HEADERS(cassert cctype cerrno cmath cstdarg cstdio cstdlib cstring ctime)
|
AC_CHECK_HEADERS(cassert cctype cerrno cmath cstdarg cstdint cstdio cstdlib cstring ctime)
|
||||||
|
|
||||||
|
|
||||||
dnl Check for existance of basename(), setlocale() and strftime()
|
dnl Check for existance of basename(), setlocale() and strftime()
|
||||||
|
@ -61,10 +61,11 @@ AC_FUNC_SELECT_ARGTYPES
|
||||||
AC_FUNC_STAT
|
AC_FUNC_STAT
|
||||||
|
|
||||||
AC_CHECK_FUNCS(basename, , AC_CHECK_LIB(gen, basename, LIBS="-lgen $LIBS"))
|
AC_CHECK_FUNCS(basename, , AC_CHECK_LIB(gen, basename, LIBS="-lgen $LIBS"))
|
||||||
AC_CHECK_FUNCS(catclose catgets catopen getpid gettimeofday memset mkdir \
|
AC_CHECK_FUNCS(catclose catgets catopen getpid memset mkdir \
|
||||||
nl_langinfo putenv regcomp select setenv setlocale sigaction snprintf \
|
nl_langinfo putenv regcomp select setenv setlocale sigaction snprintf \
|
||||||
sqrt strcasecmp strcasestr strchr strstr strtol strtoul sync vsnprintf)
|
sqrt strcasecmp strcasestr strchr strstr strtol strtoul sync vsnprintf)
|
||||||
|
|
||||||
|
|
||||||
dnl Windows requires the mingw-catgets library for the catgets function.
|
dnl Windows requires the mingw-catgets library for the catgets function.
|
||||||
AC_SEARCH_LIBS([catgets], [catgets], [], [])
|
AC_SEARCH_LIBS([catgets], [catgets], [], [])
|
||||||
|
|
||||||
|
@ -92,6 +93,48 @@ size_t x = strftime(s, 5, "%a", localtime(&t));
|
||||||
[AC_MSG_RESULT(no)])
|
[AC_MSG_RESULT(no)])
|
||||||
|
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(for clock_gettime)
|
||||||
|
AC_COMPILE_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM(
|
||||||
|
[#include <time.h>],
|
||||||
|
[[
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, 0);
|
||||||
|
return 0;
|
||||||
|
]]
|
||||||
|
)],
|
||||||
|
[
|
||||||
|
AC_DEFINE(HAVE_CLOCK_GETTIME, 1, [Define to 1 if you have the 'clock_gettime' function.])
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
# *bsd has clock_gettime() in libc
|
||||||
|
AC_CHECK_LIB(rt, clock_gettime, LIBS="-lrt $LIBS")
|
||||||
|
],
|
||||||
|
[
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
AC_MSG_CHECKING(for mach_absolute_time)
|
||||||
|
AC_COMPILE_IFELSE(
|
||||||
|
[AC_LANG_PROGRAM(
|
||||||
|
[#include <mach/mach_time.h>],
|
||||||
|
[[
|
||||||
|
mach_absolute_time();
|
||||||
|
return 0;
|
||||||
|
]]
|
||||||
|
)],
|
||||||
|
[
|
||||||
|
AC_DEFINE(HAVE_MACH_ABSOLUTE_TIME, 1, [Define to 1 if you have the 'mach_absolute_time' function.])
|
||||||
|
AC_MSG_RESULT(yes)
|
||||||
|
#AC_CHECK_LIB(, clock_gettime, LIBS="-lrt $LIBS")
|
||||||
|
],
|
||||||
|
[
|
||||||
|
AC_MSG_RESULT(no)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AC_STRUCT_TM
|
AC_STRUCT_TM
|
||||||
|
|
||||||
dnl ---------------
|
dnl ---------------
|
||||||
|
@ -130,18 +173,8 @@ if test "x$ac_cv_header_iconv_h" = "xyes"; then
|
||||||
|
|
||||||
if test "x$ac_found_iconv" = xyes; then
|
if test "x$ac_found_iconv" = xyes; then
|
||||||
AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
|
AC_DEFINE(HAVE_ICONV, 1, [Define if you have the iconv() function.])
|
||||||
AC_CHECK_LIB([iconv],
|
AC_CHECK_LIB(iconv, iconv_open, LIBS="-liconv $LIBS")
|
||||||
[iconv_open],
|
AC_CHECK_LIB(iconv, libiconv_open, LIBS="-liconv $LIBS")
|
||||||
[
|
|
||||||
LIBS="-liconv $LIBS"
|
|
||||||
],
|
|
||||||
[])
|
|
||||||
AC_CHECK_LIB([iconv],
|
|
||||||
[libiconv_open],
|
|
||||||
[
|
|
||||||
LIBS="-liconv $LIBS"
|
|
||||||
],
|
|
||||||
[])
|
|
||||||
|
|
||||||
dnl Check if iconv uses const in prototype declaration
|
dnl Check if iconv uses const in prototype declaration
|
||||||
AC_CACHE_CHECK(for iconv declaration,
|
AC_CACHE_CHECK(for iconv declaration,
|
||||||
|
@ -185,10 +218,7 @@ LDFLAGS="$LDFLAGS $LIBS $X_PRE_LIBS"
|
||||||
|
|
||||||
|
|
||||||
dnl Check for required functions in -lX11
|
dnl Check for required functions in -lX11
|
||||||
AC_CHECK_LIB(X11, XOpenDisplay,
|
AC_CHECK_LIB(X11, XOpenDisplay, LIBS="-lX11 $LIBS", AC_MSG_ERROR([Could not find XOpenDisplay in -lX11.]))
|
||||||
LIBS="-lX11 $LIBS",
|
|
||||||
AC_MSG_ERROR([Could not find XOpenDisplay in -lX11.])
|
|
||||||
)
|
|
||||||
LIBS="$X_EXTRA_LIBS $LIBS"
|
LIBS="$X_EXTRA_LIBS $LIBS"
|
||||||
|
|
||||||
AC_CHECK_LIB(xpg4, setlocale, LIBS="-lxpg4 $LIBS")
|
AC_CHECK_LIB(xpg4, setlocale, LIBS="-lxpg4 $LIBS")
|
||||||
|
|
|
@ -81,7 +81,7 @@ void AttentionNoticeHandler::addAttention(Focusable &client) {
|
||||||
RefCount<Command<void> > cmd(new ToggleFrameFocusCmd(client));
|
RefCount<Command<void> > cmd(new ToggleFrameFocusCmd(client));
|
||||||
Timer *timer = new Timer();
|
Timer *timer = new Timer();
|
||||||
timer->setCommand(cmd);
|
timer->setCommand(cmd);
|
||||||
timer->setTimeout(**timeout_res);
|
timer->setTimeout(**timeout_res * FbTk::FbTime::IN_MILLISECONDS);
|
||||||
timer->fireOnce(false); // will repeat until window has focus
|
timer->fireOnce(false); // will repeat until window has focus
|
||||||
timer->start();
|
timer->start();
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "FbTk/Menu.hh"
|
#include "FbTk/Menu.hh"
|
||||||
#include "FbTk/MenuItem.hh"
|
#include "FbTk/MenuItem.hh"
|
||||||
#include "FbTk/I18n.hh"
|
#include "FbTk/I18n.hh"
|
||||||
|
#include "FbTk/FbTime.hh"
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -45,16 +46,15 @@
|
||||||
#else
|
#else
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#endif
|
#endif
|
||||||
#include <sys/time.h>
|
|
||||||
#include <typeinfo>
|
#include <typeinfo>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
static const char SWITCHES_SECONDS[] = "crsSTX+";
|
const char SWITCHES_SECONDS[] = "crsSTX+";
|
||||||
static const char SWITCHES_12_24H[] = "lIrkHT";
|
const char SWITCHES_12_24H[] = "lIrkHT";
|
||||||
static const char SWITCHES_24_12H[] = "kHTlIr";
|
const char SWITCHES_24_12H[] = "kHTlIr";
|
||||||
static const char SWITCH_AM_PM[] = "pP";
|
const char SWITCH_AM_PM[] = "pP";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return true if clock shows seconds. If clock doesn't show seconds then
|
* return true if clock shows seconds. If clock doesn't show seconds then
|
||||||
|
@ -68,23 +68,13 @@ int showSeconds(const std::string& fmt_string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
timeval calcNextTimeout(const std::string& fmt_string) {
|
uint64_t calcNextTimeout(const std::string& fmt_string) {
|
||||||
timeval now;
|
|
||||||
timeval next;
|
|
||||||
gettimeofday(&now, 0);
|
|
||||||
next.tv_sec = 60 - (now.tv_sec % 60) - 1;
|
|
||||||
next.tv_usec = 1000000 - now.tv_usec;
|
|
||||||
if (next.tv_usec >= 1000000) {
|
|
||||||
next.tv_sec++;
|
|
||||||
next.tv_usec -= 1000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
// wake up at next second-change
|
if (showSeconds(fmt_string)) { // microseconds till next full second
|
||||||
if (showSeconds(fmt_string)) {
|
return FbTk::FbTime::remainingNext(FbTk::FbTime::IN_SECONDS);
|
||||||
next.tv_sec = 0;
|
} else { // microseconds until next full minute
|
||||||
|
return FbTk::FbTime::remainingNext(60L * FbTk::FbTime::IN_SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return next;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -278,13 +268,10 @@ unsigned int ClockTool::height() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClockTool::updateTime() {
|
void ClockTool::updateTime() {
|
||||||
// update clock
|
|
||||||
timeval now;
|
|
||||||
gettimeofday(&now, 0);
|
|
||||||
time_t the_time = now.tv_sec;
|
|
||||||
|
|
||||||
m_timer.setTimeout(calcNextTimeout(*m_timeformat));
|
m_timer.setTimeout(calcNextTimeout(*m_timeformat));
|
||||||
|
|
||||||
|
time_t the_time = time(NULL);
|
||||||
if (the_time != -1) {
|
if (the_time != -1) {
|
||||||
char time_string[255];
|
char time_string[255];
|
||||||
int time_string_len;
|
int time_string_len;
|
||||||
|
|
97
src/FbTk/FbTime.cc
Normal file
97
src/FbTk/FbTime.cc
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
// FbTime.cc for FbTk - Fluxbox Toolkit
|
||||||
|
// Copyright (c) 2012 Mathias Gumz (akira at fluxbox dot org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#include "FbTime.hh"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_CLOCK_GETTIME // linux|*bsd|solaris
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
uint64_t _now() {
|
||||||
|
|
||||||
|
uint64_t n = 0L;
|
||||||
|
timespec ts;
|
||||||
|
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
|
||||||
|
n = (ts.tv_sec * FbTk::FbTime::IN_SECONDS) + (ts.tv_nsec / 1000L);
|
||||||
|
}
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HAVE_CLOCK_GETTIME
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_MACH_ABSOLUTE_TIME // macosx
|
||||||
|
|
||||||
|
// http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x
|
||||||
|
// https://github.com/ThomasHabets/monotonic_clock/blob/master/src/monotonic_mach.c
|
||||||
|
// http://shiftedbits.org/2008/10/01/mach_absolute_time-on-the-iphone/
|
||||||
|
|
||||||
|
|
||||||
|
#include <mach/mach_time.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
uint64_t _now() {
|
||||||
|
|
||||||
|
// mach_absolute_time() * info.numer / info.denom yields
|
||||||
|
// nanoseconds.
|
||||||
|
|
||||||
|
static double micro_scale = 0.001; // 1000ms == 1ns
|
||||||
|
static bool initial = true;
|
||||||
|
|
||||||
|
if (initial) {
|
||||||
|
initial = false;
|
||||||
|
mach_timebase_info_data_t info;
|
||||||
|
if (mach_timebase_info(&info) == 0) {
|
||||||
|
micro_scale *= static_cast<double>info.numer / static_cast<double>(info.denom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<uint64_t>(mach_absolute_time() * micro_scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // HAVE_MACH_ABSOLUTE_TIME
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t FbTk::FbTime::now() {
|
||||||
|
return ::_now();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t FbTk::FbTime::remainingNext(uint64_t unit) {
|
||||||
|
return (unit - (::_now() % unit) - 1);
|
||||||
|
}
|
||||||
|
|
58
src/FbTk/FbTime.hh
Normal file
58
src/FbTk/FbTime.hh
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
// FbTime.hh for FbTk - Fluxbox Toolkit
|
||||||
|
// Copyright (c) 2012 Mathias Gumz (akira at fluxbox dot org)
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
// copy of this software and associated documentation files (the "Software"),
|
||||||
|
// to deal in the Software without restriction, including without limitation
|
||||||
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
// and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
// Software is furnished to do so, subject to the following conditions:
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||||
|
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
// DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
#ifndef FBTK_FBTIME_HH
|
||||||
|
#define FBTK_FBTIME_HH
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif // HAVE_CONFIG_H
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_INTTYPES_H
|
||||||
|
#include <inttypes.h>
|
||||||
|
#endif // HAVE_INTTYPES_H
|
||||||
|
|
||||||
|
namespace FbTk {
|
||||||
|
|
||||||
|
// time in micro-seconds, monotonic increasing
|
||||||
|
//
|
||||||
|
// interesting links:
|
||||||
|
//
|
||||||
|
// http://www.python.org/dev/peps/pep-0418/#operating-system-time-functions
|
||||||
|
// http://en.cppreference.com/w/cpp/chrono
|
||||||
|
|
||||||
|
namespace FbTime {
|
||||||
|
|
||||||
|
const uint64_t IN_MILLISECONDS = 1000L;
|
||||||
|
const uint64_t IN_SECONDS = 1000L * 1000L;
|
||||||
|
|
||||||
|
uint64_t now();
|
||||||
|
|
||||||
|
// calculates the remaining microseconds up to the next full 'unit'
|
||||||
|
uint64_t remainingNext(uint64_t unit);
|
||||||
|
|
||||||
|
} // namespace FbTime
|
||||||
|
|
||||||
|
} // namespace FbTk
|
||||||
|
|
||||||
|
#endif // FBTK_TIME_HH
|
|
@ -188,7 +188,7 @@ ImageControl::ImageControl(int screen_num,
|
||||||
cache_max = cmax;
|
cache_max = cmax;
|
||||||
|
|
||||||
if (cache_timeout && s_timed_cache) {
|
if (cache_timeout && s_timed_cache) {
|
||||||
m_timer.setTimeout(cache_timeout);
|
m_timer.setTimeout(cache_timeout * FbTk::FbTime::IN_MILLISECONDS);
|
||||||
RefCount<Command<void> > clean_cache(new SimpleCommand<ImageControl>(*this, &ImageControl::cleanCache));
|
RefCount<Command<void> > clean_cache(new SimpleCommand<ImageControl>(*this, &ImageControl::cleanCache));
|
||||||
m_timer.setCommand(clean_cache);
|
m_timer.setCommand(clean_cache);
|
||||||
m_timer.start();
|
m_timer.start();
|
||||||
|
|
|
@ -36,6 +36,7 @@ libFbTk_a_SOURCES = App.hh App.cc Color.cc Color.hh Command.hh \
|
||||||
Texture.cc Texture.hh TextureRender.hh TextureRender.cc \
|
Texture.cc Texture.hh TextureRender.hh TextureRender.cc \
|
||||||
Shape.hh Shape.cc \
|
Shape.hh Shape.cc \
|
||||||
Theme.hh Theme.cc ThemeItems.cc Timer.hh Timer.cc \
|
Theme.hh Theme.cc ThemeItems.cc Timer.hh Timer.cc \
|
||||||
|
FbTime.cc FbTime.hh \
|
||||||
XFontImp.cc XFontImp.hh \
|
XFontImp.cc XFontImp.hh \
|
||||||
Button.hh Button.cc \
|
Button.hh Button.cc \
|
||||||
TextButton.hh TextButton.cc \
|
TextButton.hh TextButton.cc \
|
||||||
|
|
|
@ -1006,7 +1006,7 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itmp->submenu()) { // start submenu open delay
|
if (itmp->submenu()) { // start submenu open delay
|
||||||
m_submenu_timer.setTimeout(theme()->getDelay());
|
m_submenu_timer.setTimeout(theme()->getDelay() * FbTk::FbTime::IN_MILLISECONDS);
|
||||||
m_submenu_timer.start();
|
m_submenu_timer.start();
|
||||||
} else if (isItemSelectable(w)){
|
} else if (isItemSelectable(w)){
|
||||||
// else normal menu item
|
// else normal menu item
|
||||||
|
@ -1225,7 +1225,7 @@ void Menu::closeMenu() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Menu::startHide() {
|
void Menu::startHide() {
|
||||||
m_hide_timer.setTimeout(theme()->getDelay());
|
m_hide_timer.setTimeout(theme()->getDelay() * FbTk::FbTime::IN_MILLISECONDS);
|
||||||
m_hide_timer.start();
|
m_hide_timer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
// Timer.cc for FbTk - Fluxbox Toolkit
|
// Timer.cc for FbTk - Fluxbox Toolkit
|
||||||
// Copyright (c) 2003 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org)
|
// Copyright (c) 2003 - 2012 Henrik Kinnunen (fluxgen at fluxbox dot org)
|
||||||
//
|
//
|
||||||
// Timer.cc for Blackbox - An X11 Window Manager
|
// Timer.cc for Blackbox - An X11 Window Manager
|
||||||
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
|
// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
|
||||||
|
@ -32,10 +32,6 @@
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#endif // _GNU_SOURCE
|
#endif // _GNU_SOURCE
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
|
||||||
#include "config.h"
|
|
||||||
#endif // HAVE_CONFIG_H
|
|
||||||
|
|
||||||
#ifdef HAVE_CASSERT
|
#ifdef HAVE_CASSERT
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#else
|
#else
|
||||||
|
@ -55,9 +51,48 @@
|
||||||
# include <winsock.h>
|
# include <winsock.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace FbTk {
|
#include <cstdio>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
Timer::TimerList Timer::m_timerlist;
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct TimerCompare {
|
||||||
|
bool operator() (const FbTk::Timer* a, const FbTk::Timer* b) {
|
||||||
|
return a->getEndTime() < b->getEndTime();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
typedef std::set<FbTk::Timer*, TimerCompare> TimerList;
|
||||||
|
|
||||||
|
TimerList s_timerlist;
|
||||||
|
|
||||||
|
|
||||||
|
/// add a timer to the static list
|
||||||
|
void addTimer(FbTk::Timer *timer) {
|
||||||
|
|
||||||
|
assert(timer);
|
||||||
|
int interval = timer->getInterval();
|
||||||
|
|
||||||
|
// interval timers have their timeout change every time they are started!
|
||||||
|
if (interval != 0) {
|
||||||
|
timer->setTimeout(interval * FbTk::FbTime::IN_SECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
s_timerlist.insert(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// remove a timer from the static list
|
||||||
|
void removeTimer(FbTk::Timer *timer) {
|
||||||
|
|
||||||
|
assert(timer);
|
||||||
|
s_timerlist.erase(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace FbTk {
|
||||||
|
|
||||||
Timer::Timer():m_timing(false), m_once(false), m_interval(0) {
|
Timer::Timer():m_timing(false), m_once(false), m_interval(0) {
|
||||||
|
|
||||||
|
@ -76,22 +111,8 @@ Timer::~Timer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Timer::setTimeout(time_t t) {
|
void Timer::setTimeout(uint64_t timeout) {
|
||||||
m_timeout.tv_sec = t / 1000;
|
m_timeout = timeout;
|
||||||
m_timeout.tv_usec = t;
|
|
||||||
m_timeout.tv_usec -= (m_timeout.tv_sec * 1000);
|
|
||||||
m_timeout.tv_usec *= 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Timer::setTimeout(const timeval &t) {
|
|
||||||
m_timeout.tv_sec = t.tv_sec;
|
|
||||||
m_timeout.tv_usec = t.tv_usec;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Timer::setTimeout(unsigned int secs, unsigned int usecs) {
|
|
||||||
m_timeout.tv_sec = secs;
|
|
||||||
m_timeout.tv_usec = usecs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timer::setCommand(const RefCount<Slot<void> > &cmd) {
|
void Timer::setCommand(const RefCount<Slot<void> > &cmd) {
|
||||||
|
@ -99,28 +120,24 @@ void Timer::setCommand(const RefCount<Slot<void> > &cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timer::start() {
|
void Timer::start() {
|
||||||
gettimeofday(&m_start, 0);
|
|
||||||
|
m_start = FbTk::FbTime::now();
|
||||||
|
|
||||||
// only add Timers that actually DO something
|
// only add Timers that actually DO something
|
||||||
if ((! m_timing || m_interval != 0) && m_handler) {
|
if ((! m_timing || m_interval != 0) && m_handler) {
|
||||||
m_timing = true;
|
m_timing = true;
|
||||||
addTimer(this); //add us to the list
|
::addTimer(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Timer::stop() {
|
void Timer::stop() {
|
||||||
m_timing = false;
|
m_timing = false;
|
||||||
removeTimer(this); //remove us from the list
|
::removeTimer(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timer::makeEndTime(timeval &tm) const {
|
uint64_t Timer::getEndTime() const {
|
||||||
tm.tv_sec = m_start.tv_sec + m_timeout.tv_sec;
|
return m_start + m_timeout;
|
||||||
tm.tv_usec = m_start.tv_usec + m_timeout.tv_usec;
|
|
||||||
if (tm.tv_usec >= 1000000) {
|
|
||||||
tm.tv_usec -= 1000000;
|
|
||||||
tm.tv_sec++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -129,42 +146,34 @@ void Timer::fireTimeout() {
|
||||||
(*m_handler)();
|
(*m_handler)();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Timer::updateTimers(int fd) {
|
void Timer::updateTimers(int fd) {
|
||||||
|
|
||||||
fd_set rfds;
|
fd_set rfds;
|
||||||
timeval now, tm, *timeout = 0;
|
timeval tm;
|
||||||
|
timeval* timeout = 0;
|
||||||
|
TimerList::iterator it;
|
||||||
|
|
||||||
FD_ZERO(&rfds);
|
FD_ZERO(&rfds);
|
||||||
FD_SET(fd, &rfds);
|
FD_SET(fd, &rfds);
|
||||||
|
|
||||||
bool overdue = false;
|
bool overdue = false;
|
||||||
|
uint64_t now = FbTime::now();
|
||||||
|
uint64_t end_time;
|
||||||
|
|
||||||
// see, if the first timer in the
|
// see, if the first timer in the
|
||||||
// list is overdue
|
// list is overdue
|
||||||
if (!m_timerlist.empty()) {
|
if (!s_timerlist.empty()) {
|
||||||
gettimeofday(&now, 0);
|
|
||||||
|
|
||||||
Timer *timer = m_timerlist.front();
|
Timer* timer = *s_timerlist.begin();
|
||||||
|
end_time = timer->getEndTime();
|
||||||
|
|
||||||
timer->makeEndTime(tm);
|
if (end_time < now) {
|
||||||
|
|
||||||
tm.tv_sec -= now.tv_sec;
|
|
||||||
tm.tv_usec -= now.tv_usec;
|
|
||||||
|
|
||||||
while (tm.tv_usec < 0) {
|
|
||||||
if (tm.tv_sec > 0) {
|
|
||||||
tm.tv_sec--;
|
|
||||||
tm.tv_usec += 1000000;
|
|
||||||
} else {
|
|
||||||
overdue = true;
|
|
||||||
tm.tv_usec = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tm.tv_sec < 0) { // usec zero-ed above if negative
|
|
||||||
tm.tv_sec = 0;
|
|
||||||
tm.tv_usec = 0;
|
|
||||||
overdue = true;
|
overdue = true;
|
||||||
|
} else {
|
||||||
|
uint64_t diff = (end_time - now);
|
||||||
|
tm.tv_sec = diff / FbTime::IN_SECONDS;
|
||||||
|
tm.tv_usec = diff % FbTime::IN_SECONDS;
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout = &tm;
|
timeout = &tm;
|
||||||
|
@ -173,99 +182,40 @@ void Timer::updateTimers(int fd) {
|
||||||
// if not overdue, wait for the next xevent via the blocking
|
// if not overdue, wait for the next xevent via the blocking
|
||||||
// select(), so OS sends fluxbox to sleep. the select() will
|
// select(), so OS sends fluxbox to sleep. the select() will
|
||||||
// time out when the next timer has to be handled
|
// time out when the next timer has to be handled
|
||||||
if (!overdue && select(fd + 1, &rfds, 0, 0, timeout) != 0)
|
if (!overdue && select(fd + 1, &rfds, 0, 0, timeout) != 0) {
|
||||||
// didn't time out! x events are pending
|
// didn't time out! x events are pending
|
||||||
return;
|
return;
|
||||||
|
|
||||||
TimerList::iterator it;
|
|
||||||
|
|
||||||
// check for timer timeout
|
|
||||||
gettimeofday(&now, 0);
|
|
||||||
|
|
||||||
// someone set the date of the machine BACK
|
|
||||||
// so we have to adjust the start_time
|
|
||||||
static time_t last_time = 0;
|
|
||||||
if (now.tv_sec < last_time) {
|
|
||||||
|
|
||||||
time_t delta = last_time - now.tv_sec;
|
|
||||||
|
|
||||||
for (it = m_timerlist.begin(); it != m_timerlist.end(); ++it) {
|
|
||||||
(*it)->m_start.tv_sec -= delta;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
last_time = now.tv_sec;
|
|
||||||
|
|
||||||
|
now = FbTime::now();
|
||||||
|
for (it = s_timerlist.begin(); it != s_timerlist.end(); ) {
|
||||||
|
|
||||||
//must check end ...the timer might remove
|
// t->fireTimeout() might add timers to the list
|
||||||
//it self from the list (should be fixed in the future)
|
// this invalidates 'it'. thus we store the current
|
||||||
for(it = m_timerlist.begin(); it != m_timerlist.end(); ) {
|
// item here
|
||||||
//This is to make sure we don't get an invalid iterator
|
Timer* t = *it;
|
||||||
//when we do fireTimeout
|
if (now < t->getEndTime()) {
|
||||||
Timer &t = *(*it);
|
|
||||||
|
|
||||||
t.makeEndTime(tm);
|
|
||||||
|
|
||||||
if (((now.tv_sec < tm.tv_sec) ||
|
|
||||||
(now.tv_sec == tm.tv_sec && now.tv_usec < tm.tv_usec)))
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
t.fireTimeout();
|
t->fireTimeout();
|
||||||
// restart the current timer so that the start time is updated
|
|
||||||
if (! t.doOnce()) {
|
// find the iterator to the timer again
|
||||||
// must erase so that it's put into the right place in the list
|
// and continue working on the list
|
||||||
it = m_timerlist.erase(it);
|
it = s_timerlist.find(t);
|
||||||
t.m_timing = false;
|
it++;
|
||||||
t.start();
|
s_timerlist.erase(t);
|
||||||
|
|
||||||
|
if (! t->doOnce()) { // restart the current timer
|
||||||
|
t->m_timing = false;
|
||||||
|
t->start();
|
||||||
} else {
|
} else {
|
||||||
// Since the default stop behaviour results in the timer
|
t->stop();
|
||||||
// being removed, we must remove it here, so that the iterator
|
|
||||||
// lives well. Another option would be to add it to another
|
|
||||||
// list, and then just go through that list and stop them all.
|
|
||||||
it = m_timerlist.erase(it);
|
|
||||||
t.stop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timer::addTimer(Timer *timer) {
|
|
||||||
assert(timer);
|
|
||||||
int interval = timer->getInterval();
|
|
||||||
// interval timers have their timeout change every time they are started!
|
|
||||||
timeval tm;
|
|
||||||
if (interval != 0) {
|
|
||||||
tm.tv_sec = timer->getStartTime().tv_sec;
|
|
||||||
tm.tv_usec = timer->getStartTime().tv_usec;
|
|
||||||
|
|
||||||
// now convert to interval
|
|
||||||
tm.tv_sec = interval - (tm.tv_sec % interval) - 1;
|
|
||||||
tm.tv_usec = 1000000 - tm.tv_usec;
|
|
||||||
if (tm.tv_usec == 1000000) {
|
|
||||||
tm.tv_usec = 0;
|
|
||||||
tm.tv_sec += 1;
|
|
||||||
}
|
|
||||||
timer->setTimeout(tm);
|
|
||||||
}
|
|
||||||
|
|
||||||
// set timeval to the time-of-trigger
|
|
||||||
timer->makeEndTime(tm);
|
|
||||||
|
|
||||||
// timer list is sorted by trigger time (i.e. start plus timeout)
|
|
||||||
TimerList::iterator it = m_timerlist.begin();
|
|
||||||
TimerList::iterator it_end = m_timerlist.end();
|
|
||||||
for (; it != it_end; ++it) {
|
|
||||||
timeval trig;
|
|
||||||
(*it)->makeEndTime(trig);
|
|
||||||
|
|
||||||
if ((trig.tv_sec > tm.tv_sec) ||
|
|
||||||
(trig.tv_sec == tm.tv_sec &&
|
|
||||||
trig.tv_usec >= tm.tv_usec)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_timerlist.insert(it, timer);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Command<void> *DelayedCmd::parse(const std::string &command,
|
Command<void> *DelayedCmd::parse(const std::string &command,
|
||||||
const std::string &args, bool trusted) {
|
const std::string &args, bool trusted) {
|
||||||
|
@ -280,7 +230,7 @@ Command<void> *DelayedCmd::parse(const std::string &command,
|
||||||
if (cmd == 0)
|
if (cmd == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
int delay = 200000;
|
int delay = 200;
|
||||||
StringUtil::fromString<int>(args.c_str() + err, delay);
|
StringUtil::fromString<int>(args.c_str() + err, delay);
|
||||||
|
|
||||||
return new DelayedCmd(cmd, delay);
|
return new DelayedCmd(cmd, delay);
|
||||||
|
@ -294,10 +244,7 @@ DelayedCmd::DelayedCmd(const RefCount<Slot<void> > &cmd, unsigned int timeout) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DelayedCmd::initTimer(unsigned int timeout) {
|
void DelayedCmd::initTimer(unsigned int timeout) {
|
||||||
timeval to;
|
m_timer.setTimeout(timeout * FbTime::IN_MILLISECONDS);
|
||||||
to.tv_sec = timeout/1000000;
|
|
||||||
to.tv_usec = timeout % 1000000;
|
|
||||||
m_timer.setTimeout(to);
|
|
||||||
m_timer.fireOnce(true);
|
m_timer.fireOnce(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,9 +254,4 @@ void DelayedCmd::execute() {
|
||||||
m_timer.start();
|
m_timer.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Timer::removeTimer(Timer *timer) {
|
|
||||||
assert(timer);
|
|
||||||
m_timerlist.remove(timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end namespace FbTk
|
} // end namespace FbTk
|
||||||
|
|
|
@ -27,26 +27,13 @@
|
||||||
|
|
||||||
#include "RefCount.hh"
|
#include "RefCount.hh"
|
||||||
#include "Command.hh"
|
#include "Command.hh"
|
||||||
|
#include "FbTime.hh"
|
||||||
#ifdef HAVE_CTIME
|
|
||||||
#include <ctime>
|
|
||||||
#else
|
|
||||||
#include <time.h>
|
|
||||||
#endif
|
|
||||||
#include <list>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif //HAVE_CONFIG_H
|
#endif //HAVE_CONFIG_H
|
||||||
|
|
||||||
#ifdef HAVE_INTTYPES_H
|
#include <string>
|
||||||
#include <inttypes.h>
|
|
||||||
#endif // HAVE_INTTYPES_H
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
namespace FbTk {
|
namespace FbTk {
|
||||||
|
|
||||||
|
@ -57,24 +44,21 @@ class Timer {
|
||||||
public:
|
public:
|
||||||
Timer();
|
Timer();
|
||||||
explicit Timer(const RefCount<Slot<void> > &handler);
|
explicit Timer(const RefCount<Slot<void> > &handler);
|
||||||
virtual ~Timer();
|
~Timer();
|
||||||
|
|
||||||
void fireOnce(bool once) { m_once = once; }
|
void fireOnce(bool once) { m_once = once; }
|
||||||
/// set timeout
|
void setTimeout(uint64_t timeout);
|
||||||
void setTimeout(time_t val);
|
|
||||||
/// set timeout
|
|
||||||
void setTimeout(const timeval &val);
|
|
||||||
void setTimeout(unsigned int secs, unsigned int usecs);
|
|
||||||
void setCommand(const RefCount<Slot<void> > &cmd);
|
void setCommand(const RefCount<Slot<void> > &cmd);
|
||||||
|
|
||||||
template<typename Functor>
|
template<typename Functor>
|
||||||
void setFunctor(const Functor &functor)
|
void setFunctor(const Functor &functor) {
|
||||||
{ setCommand(RefCount<Slot<void> >(new SlotImpl<Functor, void>(functor))); }
|
setCommand(RefCount<Slot<void> >(new SlotImpl<Functor, void>(functor)));
|
||||||
void setInterval(int val) { m_interval = val; }
|
}
|
||||||
/// start timing
|
|
||||||
|
void setInterval(int seconds) { m_interval = seconds; }
|
||||||
void start();
|
void start();
|
||||||
/// stop timing
|
|
||||||
void stop();
|
void stop();
|
||||||
/// update all timers
|
|
||||||
static void updateTimers(int file_descriptor);
|
static void updateTimers(int file_descriptor);
|
||||||
|
|
||||||
int isTiming() const { return m_timing; }
|
int isTiming() const { return m_timing; }
|
||||||
|
@ -82,38 +66,29 @@ public:
|
||||||
|
|
||||||
int doOnce() const { return m_once; }
|
int doOnce() const { return m_once; }
|
||||||
|
|
||||||
const timeval &getTimeout() const { return m_timeout; }
|
uint64_t getTimeout() const { return m_timeout; }
|
||||||
const timeval &getStartTime() const { return m_start; }
|
uint64_t getStartTime() const { return m_start; }
|
||||||
void makeEndTime(timeval &tm) const;
|
uint64_t getEndTime() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// force a timeout
|
/// force a timeout
|
||||||
void fireTimeout();
|
void fireTimeout();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// add a timer to the static list
|
|
||||||
static void addTimer(Timer *timer);
|
|
||||||
/// remove a timer from the static list
|
|
||||||
static void removeTimer(Timer *timer);
|
|
||||||
|
|
||||||
typedef std::list<Timer *> TimerList;
|
|
||||||
static TimerList m_timerlist; ///< list of all timers, sorted by next trigger time (start + timeout)
|
|
||||||
|
|
||||||
RefCount<Slot<void> > m_handler; ///< what to do on a timeout
|
RefCount<Slot<void> > m_handler; ///< what to do on a timeout
|
||||||
|
|
||||||
bool m_timing; ///< clock running?
|
bool m_timing; ///< clock running?
|
||||||
bool m_once; ///< do timeout only once?
|
bool m_once; ///< do timeout only once?
|
||||||
int m_interval; ///< Is an interval-only timer (e.g. clock)
|
int m_interval; ///< Is an interval-only timer (e.g. clock), in seconds
|
||||||
// note that intervals only take note of the seconds, not microseconds
|
|
||||||
|
|
||||||
timeval m_start; ///< start time
|
uint64_t m_start; ///< start time in microseconds
|
||||||
timeval m_timeout; ///< time length
|
uint64_t m_timeout; ///< time length in microseconds
|
||||||
};
|
};
|
||||||
|
|
||||||
/// executes a command after a specified timeout
|
/// executes a command after a specified timeout
|
||||||
class DelayedCmd: public Command<void> {
|
class DelayedCmd: public Command<void> {
|
||||||
public:
|
public:
|
||||||
DelayedCmd(const RefCount<Slot<void> > &cmd, unsigned int timeout = 200000);
|
DelayedCmd(const RefCount<Slot<void> > &cmd, unsigned int timeout = 200);
|
||||||
|
|
||||||
// this constructor has inverted order of parameters to avoid ambiguity with the previous
|
// this constructor has inverted order of parameters to avoid ambiguity with the previous
|
||||||
// constructor
|
// constructor
|
||||||
|
|
|
@ -279,7 +279,7 @@ Slit::Slit(BScreen &scr, FbTk::Layer &layer, const char *filename)
|
||||||
// move the frame out of sight for a moment
|
// move the frame out of sight for a moment
|
||||||
frame.window.move(-frame.window.width(), -frame.window.height());
|
frame.window.move(-frame.window.width(), -frame.window.height());
|
||||||
// setup timer
|
// setup timer
|
||||||
m_timer.setTimeout(200); // default timeout
|
m_timer.setTimeout(200L * FbTk::FbTime::IN_MILLISECONDS); // default timeout
|
||||||
m_timer.fireOnce(true);
|
m_timer.fireOnce(true);
|
||||||
FbTk::RefCount<FbTk::Command<void> > toggle_hidden(new FbTk::SimpleCommand<Slit>(*this, &Slit::toggleHidden));
|
FbTk::RefCount<FbTk::Command<void> > toggle_hidden(new FbTk::SimpleCommand<Slit>(*this, &Slit::toggleHidden));
|
||||||
m_timer.setCommand(toggle_hidden);
|
m_timer.setCommand(toggle_hidden);
|
||||||
|
|
|
@ -258,7 +258,7 @@ Toolbar::Toolbar(BScreen &scrn, FbTk::Layer &layer, size_t width):
|
||||||
frame.grab_x = frame.grab_y = 0;
|
frame.grab_x = frame.grab_y = 0;
|
||||||
|
|
||||||
// setup hide timer
|
// setup hide timer
|
||||||
m_hide_timer.setTimeout(Fluxbox::instance()->getAutoRaiseDelay());
|
m_hide_timer.setTimeout(Fluxbox::instance()->getAutoRaiseDelay() * FbTk::FbTime::IN_MILLISECONDS);
|
||||||
FbTk::RefCount<FbTk::Command<void> > toggle_hidden(new FbTk::SimpleCommand<Toolbar>(*this, &Toolbar::toggleHidden));
|
FbTk::RefCount<FbTk::Command<void> > toggle_hidden(new FbTk::SimpleCommand<Toolbar>(*this, &Toolbar::toggleHidden));
|
||||||
m_hide_timer.setCommand(toggle_hidden);
|
m_hide_timer.setCommand(toggle_hidden);
|
||||||
m_hide_timer.fireOnce(true);
|
m_hide_timer.fireOnce(true);
|
||||||
|
|
|
@ -55,8 +55,11 @@ void TooltipWindow::raiseTooltip() {
|
||||||
|
|
||||||
resize(m_lastText);
|
resize(m_lastText);
|
||||||
reconfigTheme();
|
reconfigTheme();
|
||||||
int h = theme()->iconbarTheme().text().font().height() + theme()->bevelWidth() * 2;
|
|
||||||
int w = theme()->iconbarTheme().text().font().textWidth(m_lastText) + theme()->bevelWidth() * 2;
|
FbTk::Font& font = theme()->iconbarTheme().text().font();
|
||||||
|
|
||||||
|
int h = font.height() + theme()->bevelWidth() * 2;
|
||||||
|
int w = font.textWidth(m_lastText) + theme()->bevelWidth() * 2;
|
||||||
|
|
||||||
Window root_ret; // not used
|
Window root_ret; // not used
|
||||||
Window window_ret; // not used
|
Window window_ret; // not used
|
||||||
|
@ -91,11 +94,11 @@ void TooltipWindow::raiseTooltip() {
|
||||||
show();
|
show();
|
||||||
clear();
|
clear();
|
||||||
// TODO: make this use a TextButton like TextDialog does
|
// TODO: make this use a TextButton like TextDialog does
|
||||||
theme()->iconbarTheme().text().font().drawText(*this, screen().screenNumber(),
|
font.drawText(*this, screen().screenNumber(),
|
||||||
theme()->iconbarTheme().text().textGC(),
|
theme()->iconbarTheme().text().textGC(),
|
||||||
m_lastText,
|
m_lastText,
|
||||||
theme()->bevelWidth(),
|
theme()->bevelWidth(),
|
||||||
theme()->bevelWidth() + theme()->iconbarTheme().text().font().ascent());
|
theme()->bevelWidth() + font.ascent());
|
||||||
}
|
}
|
||||||
|
|
||||||
void TooltipWindow::updateText(const FbTk::BiDiString& text) {
|
void TooltipWindow::updateText(const FbTk::BiDiString& text) {
|
||||||
|
|
|
@ -47,7 +47,7 @@ public:
|
||||||
/// Sets the delay before the window pops up
|
/// Sets the delay before the window pops up
|
||||||
void setDelay(int delay) {
|
void setDelay(int delay) {
|
||||||
m_delay = delay;
|
m_delay = delay;
|
||||||
m_timer.setTimeout(delay);
|
m_timer.setTimeout(delay * FbTk::FbTime::IN_MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hide();
|
void hide();
|
||||||
|
|
|
@ -416,7 +416,7 @@ void FluxboxWindow::init() {
|
||||||
|
|
||||||
updateMWMHintsFromClient(*m_client);
|
updateMWMHintsFromClient(*m_client);
|
||||||
|
|
||||||
m_timer.setTimeout(fluxbox.getAutoRaiseDelay());
|
m_timer.setTimeout(fluxbox.getAutoRaiseDelay() * FbTk::FbTime::IN_MILLISECONDS);
|
||||||
FbTk::RefCount<FbTk::Command<void> > raise_cmd(new FbTk::SimpleCommand<FluxboxWindow>(*this,
|
FbTk::RefCount<FbTk::Command<void> > raise_cmd(new FbTk::SimpleCommand<FluxboxWindow>(*this,
|
||||||
&FluxboxWindow::raise));
|
&FluxboxWindow::raise));
|
||||||
m_timer.setCommand(raise_cmd);
|
m_timer.setCommand(raise_cmd);
|
||||||
|
@ -538,9 +538,7 @@ void FluxboxWindow::init() {
|
||||||
|
|
||||||
m_workspacesig.emit(*this);
|
m_workspacesig.emit(*this);
|
||||||
|
|
||||||
struct timeval now;
|
m_creation_time = FbTk::FbTime::now();
|
||||||
gettimeofday(&now, NULL);
|
|
||||||
m_creation_time = now.tv_sec;
|
|
||||||
|
|
||||||
frame().frameExtentSig().emit();
|
frame().frameExtentSig().emit();
|
||||||
|
|
||||||
|
@ -1049,15 +1047,10 @@ void FluxboxWindow::grabButtons() {
|
||||||
void FluxboxWindow::reconfigure() {
|
void FluxboxWindow::reconfigure() {
|
||||||
|
|
||||||
applyDecorations();
|
applyDecorations();
|
||||||
|
|
||||||
setFocusFlag(m_focused);
|
setFocusFlag(m_focused);
|
||||||
|
|
||||||
moveResize(frame().x(), frame().y(), frame().width(), frame().height());
|
moveResize(frame().x(), frame().y(), frame().width(), frame().height());
|
||||||
|
m_timer.setTimeout(Fluxbox::instance()->getAutoRaiseDelay() * FbTk::FbTime::IN_MILLISECONDS);
|
||||||
m_timer.setTimeout(Fluxbox::instance()->getAutoRaiseDelay());
|
|
||||||
|
|
||||||
updateButtons();
|
updateButtons();
|
||||||
|
|
||||||
frame().reconfigure();
|
frame().reconfigure();
|
||||||
menu().reconfigure();
|
menu().reconfigure();
|
||||||
|
|
||||||
|
@ -2200,14 +2193,14 @@ void FluxboxWindow::configureRequestEvent(XConfigureRequestEvent &cr) {
|
||||||
// don't let misbehaving clients (e.g. MPlayer) move/resize their windows
|
// don't let misbehaving clients (e.g. MPlayer) move/resize their windows
|
||||||
// just after creation if the user has a saved position/size
|
// just after creation if the user has a saved position/size
|
||||||
if (m_creation_time) {
|
if (m_creation_time) {
|
||||||
struct timeval now;
|
|
||||||
gettimeofday(&now, NULL);
|
uint64_t now = FbTk::FbTime::now();
|
||||||
|
|
||||||
Remember& rinst = Remember::instance();
|
Remember& rinst = Remember::instance();
|
||||||
|
|
||||||
if (now.tv_sec > m_creation_time + 1)
|
if (now > (m_creation_time + FbTk::FbTime::IN_SECONDS)) {
|
||||||
m_creation_time = 0;
|
m_creation_time = 0;
|
||||||
else if (rinst.isRemembered(*client, Remember::REM_MAXIMIZEDSTATE) ||
|
} else if (rinst.isRemembered(*client, Remember::REM_MAXIMIZEDSTATE) ||
|
||||||
rinst.isRemembered(*client, Remember::REM_FULLSCREENSTATE)) {
|
rinst.isRemembered(*client, Remember::REM_FULLSCREENSTATE)) {
|
||||||
cr.value_mask = cr.value_mask & ~(CWWidth | CWHeight);
|
cr.value_mask = cr.value_mask & ~(CWWidth | CWHeight);
|
||||||
cr.value_mask = cr.value_mask & ~(CWX | CWY);
|
cr.value_mask = cr.value_mask & ~(CWX | CWY);
|
||||||
|
@ -2300,23 +2293,18 @@ void FluxboxWindow::keyPressEvent(XKeyEvent &ke) {
|
||||||
// e.g., typed the command in a terminal
|
// e.g., typed the command in a terminal
|
||||||
if (ks == XK_KP_Enter || ks == XK_Return) {
|
if (ks == XK_KP_Enter || ks == XK_Return) {
|
||||||
// we'll actually reset the time for this one
|
// we'll actually reset the time for this one
|
||||||
m_last_keypress_time.tv_sec = 0;
|
m_last_keypress_time = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// otherwise, make a note that the user is typing
|
// otherwise, make a note that the user is typing
|
||||||
gettimeofday(&m_last_keypress_time, 0);
|
m_last_keypress_time = FbTk::FbTime::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FluxboxWindow::isTyping() const {
|
bool FluxboxWindow::isTyping() const {
|
||||||
timeval now;
|
|
||||||
if (gettimeofday(&now, NULL) == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
unsigned int diff = 1000*(now.tv_sec - m_last_keypress_time.tv_sec);
|
uint64_t diff = FbTk::FbTime::now() - m_last_keypress_time;
|
||||||
diff += (now.tv_usec - m_last_keypress_time.tv_usec)/1000;
|
return ((diff / 1000) < screen().noFocusWhileTypingDelay());
|
||||||
|
|
||||||
return (diff < screen().noFocusWhileTypingDelay());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FluxboxWindow::buttonPressEvent(XButtonEvent &be) {
|
void FluxboxWindow::buttonPressEvent(XButtonEvent &be) {
|
||||||
|
|
|
@ -33,11 +33,11 @@
|
||||||
|
|
||||||
#include "FbTk/DefaultValue.hh"
|
#include "FbTk/DefaultValue.hh"
|
||||||
#include "FbTk/Timer.hh"
|
#include "FbTk/Timer.hh"
|
||||||
|
#include "FbTk/FbTime.hh"
|
||||||
#include "FbTk/EventHandler.hh"
|
#include "FbTk/EventHandler.hh"
|
||||||
#include "FbTk/LayerItem.hh"
|
#include "FbTk/LayerItem.hh"
|
||||||
#include "FbTk/Signal.hh"
|
#include "FbTk/Signal.hh"
|
||||||
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
@ -529,14 +529,15 @@ private:
|
||||||
// state and hint signals
|
// state and hint signals
|
||||||
FbTk::Signal<FluxboxWindow &> m_workspacesig, m_statesig, m_layersig, m_hintsig;
|
FbTk::Signal<FluxboxWindow &> m_workspacesig, m_statesig, m_layersig, m_hintsig;
|
||||||
|
|
||||||
time_t m_creation_time;
|
uint64_t m_creation_time;
|
||||||
|
uint64_t m_last_keypress_time;
|
||||||
|
FbTk::Timer m_timer;
|
||||||
|
|
||||||
// Window states
|
// Window states
|
||||||
bool moving, resizing, m_initialized;
|
bool moving, resizing, m_initialized;
|
||||||
|
|
||||||
WinClient *m_attaching_tab;
|
WinClient *m_attaching_tab;
|
||||||
|
|
||||||
FbTk::Timer m_timer;
|
|
||||||
Display *display; /// display connection
|
Display *display; /// display connection
|
||||||
|
|
||||||
int m_button_grab_x, m_button_grab_y; // handles last button press event for move
|
int m_button_grab_x, m_button_grab_y; // handles last button press event for move
|
||||||
|
@ -545,8 +546,6 @@ private:
|
||||||
int m_last_resize_h, m_last_resize_w; // handles height/width for resize "window"
|
int m_last_resize_h, m_last_resize_w; // handles height/width for resize "window"
|
||||||
int m_last_pressed_button;
|
int m_last_pressed_button;
|
||||||
|
|
||||||
timeval m_last_keypress_time;
|
|
||||||
|
|
||||||
unsigned int m_workspace_number;
|
unsigned int m_workspace_number;
|
||||||
unsigned long m_current_state; // NormalState | IconicState | Withdrawn
|
unsigned long m_current_state; // NormalState | IconicState | Withdrawn
|
||||||
|
|
||||||
|
|
|
@ -306,7 +306,7 @@ Fluxbox::Fluxbox(int argc, char **argv,
|
||||||
// because it could affect ongoing menu stuff so we need to reconfig in
|
// because it could affect ongoing menu stuff so we need to reconfig in
|
||||||
// the next event "round".
|
// the next event "round".
|
||||||
FbTk::RefCount<FbTk::Command<void> > reconfig_cmd(new FbTk::SimpleCommand<Fluxbox>(*this, &Fluxbox::timed_reconfigure));
|
FbTk::RefCount<FbTk::Command<void> > reconfig_cmd(new FbTk::SimpleCommand<Fluxbox>(*this, &Fluxbox::timed_reconfigure));
|
||||||
m_reconfig_timer.setTimeout(0, 1);
|
m_reconfig_timer.setTimeout(1);
|
||||||
m_reconfig_timer.setCommand(reconfig_cmd);
|
m_reconfig_timer.setCommand(reconfig_cmd);
|
||||||
m_reconfig_timer.fireOnce(true);
|
m_reconfig_timer.fireOnce(true);
|
||||||
|
|
||||||
|
@ -363,7 +363,6 @@ Fluxbox::Fluxbox(int argc, char **argv,
|
||||||
screens.push_back(i);
|
screens.push_back(i);
|
||||||
|
|
||||||
// find out, on what "screens" fluxbox should run
|
// find out, on what "screens" fluxbox should run
|
||||||
// FIXME(php-coder): maybe it worths moving this code to main.cc, where command line is parsed?
|
|
||||||
for (i = 1; i < m_argc; i++) {
|
for (i = 1; i < m_argc; i++) {
|
||||||
if (! strcmp(m_argv[i], "-screen")) {
|
if (! strcmp(m_argv[i], "-screen")) {
|
||||||
if ((++i) >= m_argc) {
|
if ((++i) >= m_argc) {
|
||||||
|
@ -507,8 +506,11 @@ void Fluxbox::initScreen(BScreen *screen) {
|
||||||
|
|
||||||
|
|
||||||
void Fluxbox::eventLoop() {
|
void Fluxbox::eventLoop() {
|
||||||
|
|
||||||
Display *disp = display();
|
Display *disp = display();
|
||||||
|
|
||||||
while (!m_shutdown) {
|
while (!m_shutdown) {
|
||||||
|
|
||||||
if (XPending(disp)) {
|
if (XPending(disp)) {
|
||||||
XEvent e;
|
XEvent e;
|
||||||
XNextEvent(disp, &e);
|
XNextEvent(disp, &e);
|
||||||
|
@ -524,8 +526,9 @@ void Fluxbox::eventLoop() {
|
||||||
handleEvent(&e);
|
handleEvent(&e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
FbTk::Timer::updateTimers(ConnectionNumber(disp)); //handle all timers
|
FbTk::Timer::updateTimers(ConnectionNumber(disp));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -553,9 +556,11 @@ void Fluxbox::ungrab() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fluxbox::handleEvent(XEvent * const e) {
|
void Fluxbox::handleEvent(XEvent * const e) {
|
||||||
|
|
||||||
_FB_USES_NLS;
|
_FB_USES_NLS;
|
||||||
m_last_event = *e;
|
m_last_event = *e;
|
||||||
|
|
||||||
|
|
||||||
// it is possible (e.g. during moving) for a window
|
// it is possible (e.g. during moving) for a window
|
||||||
// to mask all events to go to it
|
// to mask all events to go to it
|
||||||
if ((m_masked == e->xany.window) && m_masked_window) {
|
if ((m_masked == e->xany.window) && m_masked_window) {
|
||||||
|
|
|
@ -61,10 +61,7 @@ public:
|
||||||
FbTk::RefCount<FbTk::Command<void> > cmd(new FbTk::SimpleCommand<App>
|
FbTk::RefCount<FbTk::Command<void> > cmd(new FbTk::SimpleCommand<App>
|
||||||
(*this,
|
(*this,
|
||||||
&App::demandAttention));
|
&App::demandAttention));
|
||||||
timeval t;
|
m_timer.setTimeout(5 * FbTk::FbTime::IN_SECONDS);
|
||||||
t.tv_sec = 5;
|
|
||||||
t.tv_usec = 0;
|
|
||||||
m_timer.setTimeout(t);
|
|
||||||
m_timer.setCommand(cmd);
|
m_timer.setCommand(cmd);
|
||||||
m_timer.fireOnce(false);
|
m_timer.fireOnce(false);
|
||||||
m_timer.start();
|
m_timer.start();
|
||||||
|
|
|
@ -52,10 +52,7 @@ public:
|
||||||
FbTk::RefCount<FbTk::Command> cmd(new FbTk::SimpleCommand<App>
|
FbTk::RefCount<FbTk::Command> cmd(new FbTk::SimpleCommand<App>
|
||||||
(*this,
|
(*this,
|
||||||
&App::updateTitle));
|
&App::updateTitle));
|
||||||
timeval t;
|
m_timer.setTimeout(150 * FbTk::FbTime::IN_MILLISECONDS);
|
||||||
t.tv_sec = 0;
|
|
||||||
t.tv_usec = 150000;
|
|
||||||
m_timer.setTimeout(t);
|
|
||||||
m_timer.setCommand(cmd);
|
m_timer.setCommand(cmd);
|
||||||
m_timer.fireOnce(false);
|
m_timer.fireOnce(false);
|
||||||
m_timer.start();
|
m_timer.start();
|
||||||
|
|
Loading…
Reference in a new issue