Skip to content

Commit

Permalink
#1761 move idle user detection to a mixin
Browse files Browse the repository at this point in the history
git-svn-id: https://xpra.org/svn/Xpra/trunk@18574 3bb7dfac-3a0b-4e04-842a-767bc560f471
  • Loading branch information
totaam committed Feb 24, 2018
1 parent df28600 commit 4da5118
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 75 deletions.
80 changes: 5 additions & 75 deletions src/xpra/server/source/client_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,11 @@
from xpra.server.source.dbus_mixin import DBUS_Mixin
from xpra.server.source.windows_mixin import WindowsMixin
from xpra.server.source.encodings_mixin import EncodingsMixin
from xpra.server.source.idle_mixin import IdleMixin
from xpra.make_thread import start_thread
from xpra.os_util import monotonic_time
from xpra.util import merge_dicts, flatten_dict, notypedict, get_screen_info, envint, envbool, \
AtomicInteger, XPRA_IDLE_NOTIFICATION_ID
from xpra.util import merge_dicts, flatten_dict, notypedict, get_screen_info, envint, envbool, AtomicInteger

GRACE_PERCENT = envint("XPRA_GRACE_PERCENT", 90)
AV_SYNC_DELTA = envint("XPRA_AV_SYNC_DELTA", 0)
BANDWIDTH_DETECTION = envbool("XPRA_BANDWIDTH_DETECTION", True)

Expand All @@ -61,7 +60,7 @@
items are picked off by the separate 'encode' thread (see 'encode_loop')
and added to the damage_packet_queue.
"""
class ClientConnection(AudioMixin, MMAP_Connection, ClipboardConnection, FilePrintMixin, NetworkStateMixin, ClientInfoMixin, DBUS_Mixin, WindowsMixin, EncodingsMixin):
class ClientConnection(AudioMixin, MMAP_Connection, ClipboardConnection, FilePrintMixin, NetworkStateMixin, ClientInfoMixin, DBUS_Mixin, WindowsMixin, EncodingsMixin, IdleMixin):

def __init__(self, protocol, disconnect_cb, idle_add, timeout_add, source_remove, setting_changed,
idle_timeout, idle_timeout_cb, idle_grace_timeout_cb,
Expand Down Expand Up @@ -107,6 +106,7 @@ def __init__(self, protocol, disconnect_cb, idle_add, timeout_add, source_remove
DBUS_Mixin.__init__(self, dbus_control)
WindowsMixin.__init__(self, get_transient_for, get_focus, get_cursor_data_cb, get_window_id, window_filters)
EncodingsMixin.__init__(self, core_encodings, encodings, default_encoding, scaling_control, default_quality, default_min_quality, default_speed, default_min_speed)
IdleMixin.__init__(self, idle_timeout, idle_timeout_cb, idle_grace_timeout_cb)
global counter
self.counter = counter.increase()
self.close_event = Event()
Expand All @@ -117,16 +117,6 @@ def __init__(self, protocol, disconnect_cb, idle_add, timeout_add, source_remove
self.timeout_add = timeout_add
self.source_remove = source_remove
self.setting_changed = setting_changed
self.idle = False
self.idle_timeout = idle_timeout
self.idle_timeout_cb = idle_timeout_cb
self.idle_grace_timeout_cb = idle_grace_timeout_cb
#grace duration is at least 10 seconds:
self.idle_grace_duration = max(10, int(self.idle_timeout*(100-GRACE_PERCENT)//100))
self.idle_timer = None
self.idle_grace_timer = None
self.schedule_idle_grace_timeout()
self.schedule_idle_timeout()
self.socket_dir = socket_dir
self.unix_socket_paths = unix_socket_paths
self.log_disconnect = log_disconnect
Expand Down Expand Up @@ -159,7 +149,6 @@ def __repr__(self):

def init_vars(self):
self.hello_sent = False

self.info_namespace = False
self.send_notifications = False
self.send_notifications_actions = False
Expand Down Expand Up @@ -247,51 +236,6 @@ def update_bandwidth_limits(self):
ws.bandwidth_limit = max(1, bandwidth_limit*weight//total_weight)


def user_event(self):
timeoutlog("user_event()")
self.last_user_event = monotonic_time()
self.schedule_idle_grace_timeout()
self.schedule_idle_timeout()
if self.idle:
self.no_idle()
try:
self.notification_callbacks.pop(XPRA_IDLE_NOTIFICATION_ID)
except KeyError:
pass
else:
self.notify_close(XPRA_IDLE_NOTIFICATION_ID)


def schedule_idle_timeout(self):
timeoutlog("schedule_idle_timeout() idle_timer=%s, idle_timeout=%s", self.idle_timer, self.idle_timeout)
if self.idle_timer:
self.source_remove(self.idle_timer)
self.idle_timer = None
if self.idle_timeout>0:
self.idle_timer = self.timeout_add(self.idle_timeout*1000, self.idle_timedout)

def schedule_idle_grace_timeout(self):
timeoutlog("schedule_idle_grace_timeout() grace timer=%s, idle_timeout=%s", self.idle_grace_timer, self.idle_timeout)
if self.idle_grace_timer:
self.source_remove(self.idle_grace_timer)
self.idle_grace_timer = None
if self.idle_timeout>0 and not self.is_closed():
grace = self.idle_timeout - self.idle_grace_duration
self.idle_grace_timer = self.timeout_add(max(0, int(grace*1000)), self.idle_grace_timedout)

def idle_grace_timedout(self):
self.idle_grace_timer = None
timeoutlog("idle_grace_timedout() callback=%s", self.idle_grace_timeout_cb)
self.idle_grace_timeout_cb(self)

def idle_timedout(self):
self.idle_timer = None
timeoutlog("idle_timedout() callback=%s", self.idle_timeout_cb)
self.idle_timeout_cb(self)
if not self.is_closed():
self.schedule_idle_timeout()


def parse_hello(self, c):
self.ui_client = c.boolget("ui_client", True)
self.wants_encodings = c.boolget("wants_encodings", self.ui_client)
Expand Down Expand Up @@ -512,8 +456,6 @@ def send_hello(self, server_capabilities):
def get_info(self):
info = {
"protocol" : "xpra",
"idle_time" : int(monotonic_time()-self.last_user_event),
"idle" : self.idle,
"desktop_size" : self.desktop_size or "",
"desktops" : self.desktops,
"desktop_names" : self.desktop_names,
Expand Down Expand Up @@ -567,17 +509,12 @@ def get_features_info(self):
info = {}
def battr(k, prop):
info[k] = bool(getattr(self, prop))
for prop in ("lock", "share", "randr_notify",
"system_tray"):
for prop in ("lock", "share", "randr_notify", "system_tray"):
battr(prop, prop)
for prop, name in {
"send_notifications" : "notifications",
}.items():
battr(name, prop)
for prop, name in {
"file_size_limit" : "file-size-limit",
}.items():
info[name] = getattr(self, prop)
dcinfo = info.setdefault("double_click", {})
for prop, name in {
"double_click_time" : "time",
Expand Down Expand Up @@ -698,10 +635,3 @@ def updated_desktop_size(self, root_w, root_h, max_w, max_h):
def show_desktop(self, show):
if self.show_desktop_allowed and self.hello_sent:
self.send_async("show-desktop", show)

def refresh(self, wid, window, opts):
if not self.can_send_window(window):
return
self.cancel_damage(wid)
w, h = window.get_dimensions()
self.damage(wid, window, 0, 0, w, h, opts)
93 changes: 93 additions & 0 deletions src/xpra/server/source/idle_mixin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# -*- coding: utf-8 -*-
# This file is part of Xpra.
# Copyright (C) 2010-2018 Antoine Martin <[email protected]>
# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
# later version. See the file COPYING for details.

from xpra.log import Logger
log = Logger("timeout")

from xpra.util import envint, XPRA_IDLE_NOTIFICATION_ID
from xpra.os_util import monotonic_time
from xpra.server.source.stub_source_mixin import StubSourceMixin

GRACE_PERCENT = envint("XPRA_GRACE_PERCENT", 90)


class IdleMixin(StubSourceMixin):

def __init__(self, idle_timeout, idle_timeout_cb, idle_grace_timeout_cb):
self.idle_timeout = idle_timeout
self.idle_timeout_cb = idle_timeout_cb
self.idle_grace_timeout_cb = idle_grace_timeout_cb
self.last_user_event = monotonic_time()
#grace duration is at least 10 seconds:
self.idle_grace_duration = max(10, int(self.idle_timeout*(100-GRACE_PERCENT)//100))
self.idle = False
self.idle_timer = None
self.idle_grace_timer = None
self.schedule_idle_grace_timeout()
self.schedule_idle_timeout()

def cleanup(self):
self.cancel_idle_grace_timeout()
self.cancel_idle_timeout()

def get_info(self):
return {
"idle_time" : int(monotonic_time()-self.last_user_event),
"idle" : self.idle,
}


def user_event(self):
log("user_event()")
self.last_user_event = monotonic_time()
self.cancel_idle_grace_timeout()
self.schedule_idle_grace_timeout()
self.cancel_idle_timeout()
self.schedule_idle_timeout()
if self.idle:
self.no_idle()
try:
self.notification_callbacks.pop(XPRA_IDLE_NOTIFICATION_ID)
except KeyError:
pass
else:
self.notify_close(XPRA_IDLE_NOTIFICATION_ID)


def cancel_idle_timeout(self):
it = self.idle_timer
if it:
self.idle_timer = None
self.source_remove(it)

def schedule_idle_timeout(self):
log("schedule_idle_timeout() idle_timer=%s, idle_timeout=%s", self.idle_timer, self.idle_timeout)
if self.idle_timeout>0:
self.idle_timer = self.timeout_add(self.idle_timeout*1000, self.idle_timedout)

def cancel_idle_grace_timeout(self):
igt = self.idle_grace_timer
if igt:
self.idle_grace_timer = None
self.source_remove(igt)

def schedule_idle_grace_timeout(self):
log("schedule_idle_grace_timeout() grace timer=%s, idle_timeout=%s", self.idle_grace_timer, self.idle_timeout)
if self.idle_timeout>0 and not self.is_closed():
grace = self.idle_timeout - self.idle_grace_duration
self.idle_grace_timer = self.timeout_add(max(0, int(grace*1000)), self.idle_grace_timedout)

def idle_grace_timedout(self):
self.idle_grace_timer = None
log("idle_grace_timedout() callback=%s", self.idle_grace_timeout_cb)
self.idle_grace_timeout_cb(self)

def idle_timedout(self):
self.idle_timer = None
log("idle_timedout() callback=%s", self.idle_timeout_cb)
self.idle_timeout_cb(self)
if not self.is_closed():
self.schedule_idle_timeout()
6 changes: 6 additions & 0 deletions src/xpra/server/source/stub_source_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ class StubSourceMixin(object):
def cleanup(self):
pass

def is_closed(self):
return False

def parse_client_caps(self, c):
pass

Expand All @@ -18,5 +21,8 @@ def get_caps(self):
def get_info(self):
return {}

def user_event(self):
pass

def may_notify(self, *args, **kwargs):
pass

0 comments on commit 4da5118

Please sign in to comment.