Skip to content

Commit

Permalink
binding display for OSD, 90% done
Browse files Browse the repository at this point in the history
  • Loading branch information
kozec committed Jun 3, 2017
1 parent ce201a7 commit ce2e0d4
Show file tree
Hide file tree
Showing 5 changed files with 239 additions and 34 deletions.
12 changes: 7 additions & 5 deletions generate_svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def calculate(self, gen):

def place(self, gen, root):
e = SVGEditor.add_element(root, "rect",
style = "opacity:1;fill-opacity:1.0;stroke-width:2.0;",
style = "opacity:1;fill-opacity:0.0;stroke-width:2.0;",
fill="#000000",
stroke="#06a400",
id = "box_%s" % (self.name,),
Expand Down Expand Up @@ -259,17 +259,19 @@ def __init__(self):
boxes.append(box_bcs)


box_left = Box(self.PADDING, self.PADDING, Align.LEFT | Align.TOP,
"left", min_height = self.full_height * 0.5)
box_left = Box(self.PADDING, self.PADDING, Align.LEFT | Align.TOP, "left",
min_height = self.full_height * 0.5,
min_width = self.full_width * 0.2)
box_left.add("LEFT", Action.AC_TRIGGER, profile.triggers.get(profile.LEFT))
box_left.add("LB", Action.AC_BUTTON, profile.buttons.get(SCButtons.LB))
box_left.add("LGRIP", Action.AC_BUTTON, profile.buttons.get(SCButtons.LGRIP))
box_left.add("LPAD", Action.AC_PAD, profile.pads.get(profile.LEFT))
boxes.append(box_left)


box_right = Box(self.PADDING, self.PADDING, Align.RIGHT | Align.TOP,
"right", min_height = self.full_height * 0.5)
box_right = Box(self.PADDING, self.PADDING, Align.RIGHT | Align.TOP, "right",
min_height = self.full_height * 0.5,
min_width = self.full_width * 0.2)
box_right.add("RIGHT", Action.AC_TRIGGER, profile.triggers.get(profile.RIGHT))
box_right.add("RB", Action.AC_BUTTON, profile.buttons.get(SCButtons.RB))
box_right.add("RGRIP", Action.AC_BUTTON, profile.buttons.get(SCButtons.RGRIP))
Expand Down
32 changes: 17 additions & 15 deletions images/binding-display.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion scc/gui/svg_widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def __init__(self, app, filename, init_hilighted=True):

self.current_svg = open(filename, "r").read().decode("utf-8")
self.image_width = 1
self.image_height = 1
self.image = Gtk.Image()
self.parse_image()
if init_hilighted:
Expand All @@ -58,7 +59,8 @@ def parse_image(self):
"""
tree = ET.fromstring(self.current_svg.encode("utf-8"))
SVGWidget.find_areas(tree, (0, 0), self.areas)
self.image_width = float(tree.attrib["width"])
self.image_width = float(tree.attrib["width"])
self.image_height = float(tree.attrib["height"])


def on_mouse_click(self, trash, event):
Expand Down
37 changes: 24 additions & 13 deletions scc/osd/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,24 +255,35 @@ def make_window_clicktrough(self):
X.destroy_region (dpy, reg)


def compute_position(self):
""" Adjusts position for currently active screen (display) """
x, y = self.position
def get_active_screen_geometry(self):
"""
Returns geometry of active screen or None if active screen
cannot be determined.
"""
screen = self.get_window().get_screen()
active_window = screen.get_active_window()
width, height = self.get_window_size()
if active_window:
monitor = screen.get_monitor_at_window(active_window)
if monitor is not None:
geometry = screen.get_monitor_geometry(monitor)
if x < 0:
x = x + geometry.x + geometry.width - width
else:
x = x + geometry.x
if y < 0:
y = y + geometry.y + geometry.height - height
else:
y = geometry.y + y
return screen.get_monitor_geometry(monitor)
return None


def compute_position(self):
""" Adjusts position for currently active screen (display) """
x, y = self.position
width, height = self.get_window_size()
geometry = self.get_active_screen_geometry()
if geometry:
if x < 0:
x = x + geometry.x + geometry.width - width
else:
x = x + geometry.x
if y < 0:
y = y + geometry.y + geometry.height - height
else:
y = geometry.y + y

return x, y


Expand Down
188 changes: 188 additions & 0 deletions scc/osd/binding_display.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
#!/usr/bin/env python2
"""
SC-Controller - OSD Launcher
Display launcher with phone-like keyboard that user can use to select
application (list is generated using xdg) and start it.
Reuses styles from OSD Menu and OSD Dialog
"""
from __future__ import unicode_literals
from scc.tools import _, set_logging_level

from gi.repository import Gtk, Gio, Gdk, GdkX11, GdkPixbuf, Pango
from scc.constants import STICK_PAD_MIN, STICK_PAD_MAX, SCButtons
from scc.constants import LEFT, RIGHT, SAME, STICK
from scc.paths import get_share_path, get_config_path
from scc.menu_data import MenuData, MenuItem
from scc.tools import point_in_gtkrect
from scc.lib import xwrappers as X
from scc.config import Config
from scc.gui.svg_widget import SVGWidget, SVGEditor
from scc.gui.daemon_manager import DaemonManager
from scc.osd.timermanager import TimerManager
from scc.osd import OSDWindow
import os, sys, re, logging
log = logging.getLogger("osd.binds")


class BindingDisplay(OSDWindow, TimerManager):

def __init__(self, config=None):
self.bdisplay = os.path.join(get_config_path(), 'binding-display.svg')
if not os.path.exists(self.bdisplay):
# Prefer image in ~/.config/scc, but load default one as fallback
self.bdisplay = os.path.join(get_share_path(), "images", 'binding-display.svg')

OSDWindow.__init__(self, "osd-keyboard")
TimerManager.__init__(self)
self.daemon = None
self.config = config or Config()
self.group = None
self.limits = {}
self.background = None

self._eh_ids = []
self._stick = 0, 0

self.c = Gtk.Box()
self.c.set_name("osd-keyboard-container")


def _create_background(self):
self.background = SVGWidget(self, self.args.image, init_hilighted=False)
self._pack()


def _pack(self):
self.c.add(self.background)
self.add(self.c)


def use_daemon(self, d):
"""
Allows (re)using already existing DaemonManager instance in same process
"""
self.daemon = d
self._cononect_handlers()
self.on_daemon_connected(self.daemon)


def _add_arguments(self):
OSDWindow._add_arguments(self)
self.argparser.add_argument('image', type=str, nargs="?",
default = self.bdisplay, help="keyboard image to use")


def compute_position(self):
"""
Unlike other OSD windows, this one is scaled to 80% of screen size
and centered in on active screen.
"""
x, y = 10, 10
iw, ih = self.background.image_width, self.background.image_height
geometry = self.get_active_screen_geometry()
if geometry:
width = geometry.width * 0.8
height = int(float(ih) / float(iw) * float(width))
self.background.set_size_request(width, height)
x = geometry.x + ((geometry.width - width) / 2)
y = geometry.y + ((geometry.height - height) / 2)
return x, y


def recolor(self):
#iw, ih = self.background.image_width, self.background.image_height
#geometry = self.get_active_screen_geometry()
#if geometry:
# scale = (geometry.width * 0.8) / float(iw)
# editor = self.background.edit()
# SVGEditor.scale(SVGEditor.get_element(editor, "image"), scale)
# editor.commit()
self.background.edit().commit()
self.move(*self.compute_position())


def parse_argumets(self, argv):
if not OSDWindow.parse_argumets(self, argv):
return False
return True


def _cononect_handlers(self):
self._eh_ids += [
( self.daemon, self.daemon.connect('dead', self.on_daemon_died) ),
( self.daemon, self.daemon.connect('error', self.on_daemon_died) ),
( self.daemon, self.daemon.connect('alive', self.on_daemon_connected) ),
]


def run(self):
self.daemon = DaemonManager()
self._cononect_handlers()
OSDWindow.run(self)


def on_daemon_died(self, *a):
log.error("Daemon died")
self.quit(2)


def on_failed_to_lock(self, error):
log.error("Failed to lock input: %s", error)
self.quit(3)


def on_daemon_connected(self, *a):
def success(*a):
log.info("Sucessfully locked input")
pass

c = self.choose_controller(self.daemon)
if c is None or not c.is_connected():
# There is no controller connected to daemon
self.on_failed_to_lock("Controller not connected")
return

self._eh_ids += [ (c, c.connect('event', self.on_event)) ]
# Lock everything
locks = [ LEFT, RIGHT, STICK, "STICKPRESS" ] + [ b.name for b in SCButtons ]
c.lock(success, self.on_failed_to_lock, *locks)


def quit(self, code=-1):
if self.get_controller():
self.get_controller().unlock_all()
for source, eid in self._eh_ids:
source.disconnect(eid)
self._eh_ids = []
OSDWindow.quit(self, code)


def show(self, *a):
if self.background is None:
self._create_background()
OSDWindow.show(self, *a)
self.timer('recolor', 0.1, self.recolor)


def on_event(self, daemon, what, data):
"""
Called when button press, button release or stick / pad update is
send by daemon.
"""
pass


def main():
m = BindingDisplay()
if not m.parse_argumets(sys.argv):
sys.exit(1)
m.run()
sys.exit(m.get_exit_code())


if __name__ == "__main__":
from scc.tools import init_logging
init_logging()
main()

0 comments on commit ce2e0d4

Please sign in to comment.