Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] a floating window widget for Variety #87

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
5 changes: 0 additions & 5 deletions variety.desktop.in
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,19 @@ Keywords=Wallpaper;Changer;Change;Download;Downloader;Variety;
[Desktop Action Next]
Exec=variety --next
_Name=Next
OnlyShowIn=Unity;

[Desktop Action Previous]
Exec=variety --previous
_Name=Previous
OnlyShowIn=Unity;

[Desktop Action PauseResume]
Exec=variety --toggle-pause
_Name=Pause / Resume
OnlyShowIn=Unity;

[Desktop Action History]
Exec=variety --history
_Name=History
OnlyShowIn=Unity;

[Desktop Action Preferences]
Exec=variety --preferences
_Name=Preferences
OnlyShowIn=Unity;
107 changes: 107 additions & 0 deletions variety/FloatingWindow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#!/usr/bin/env python

import os
import gi
import cairo

gi.require_version('Gtk', '3.0')

from gi.repository import Gtk, Gdk, GObject

class FloatingWindow(Gtk.Window):
__gtype_name__ = "FloatingWindow"

def __init__(self, parent=None):
super().__init__()

self.running = True
self.parent = parent

if os.environ.get('XDG_SESSION_TYPE') != 'wayland': # Movement tracking doesn't work on Wayland :(
self.set_decorated(False)
self.set_accept_focus(True)
self.set_title('Variety')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ideally we won't see the title anywhere, but probably still makes sense to use a descriptive one for this specific window - e.g. "Variety Control"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The title is always shown on GNOME/Wayland since it doesn't seem undecorated windows are able to move themselves.

self.set_resizable(False)
self.set_default_size(48, 48)

self.connect('draw', self.draw)

# Try rgba mode if compositing is on
screen = self.get_screen()
visual = screen.get_rgba_visual()
if visual and screen.is_composited():
self.set_visual(visual)
self.set_opacity(0.8)

self.set_app_paintable(True)

self._eventbox = Gtk.EventBox()
self._eventbox.set_visible(True)

# Handle button press & left mouse button
self._eventbox.set_events(Gdk.EventMask.BUTTON_PRESS_MASK |
Gdk.EventMask.BUTTON1_MOTION_MASK |
Gdk.EventMask.SCROLL_MASK)
self._eventbox.connect('motion-notify-event', self.handle_drag)
self._eventbox.connect('button-press-event', self.handle_click)
self._eventbox.connect('scroll-event', self.handle_scroll)

self._image = Gtk.Image.new_from_icon_name("variety", Gtk.IconSize.DIALOG)
self._eventbox.add(self._image)

self.add(self._eventbox)
self.show_all()

self._last_offset = None

def draw(self, widget, context):
"""
Draws the window with transparent window background.
"""
# Based off https://gist.github.com/KurtJacobson/374c8cb83aee4851d39981b9c7e2c22c
context.set_source_rgba(0, 0, 0, 0)
context.set_operator(cairo.OPERATOR_SOURCE)
context.paint()
context.set_operator(cairo.OPERATOR_OVER)

def handle_click(self, widget, event, data=None):
"""
Handles mouse click:

1) Find the offset from the cursor to the widget to assist with dragging.
We want to allow dragging in the way that the cursor is at the same position
relative to the window when the window moves (instead of moving with the cursor
always at the top left).
2) Bring up the Variety Menu when right-clicked or double-clicked.
"""
self._last_offset = (event.x, event.y)

if event.button != 1 or event.type == Gdk.EventType._2BUTTON_PRESS:
# This program can run as a standalone app too for testing :)
if self.parent:
self.parent.ind.menu.popup_at_pointer(event)
else:
print('Not showing menu; we were started in a standalone fashion.')

def handle_drag(self, widget, event, data=None):
"""
Handles drag movement when the left mouse button is pressed down.
"""
if self._last_offset:
current_x, current_y = self.get_position()
offset_x, offset_y = self._last_offset
x = current_x + event.x - offset_x
y = current_y + event.y - offset_y
self.move(x, y)

def handle_scroll(self, widget, event, data=None):
"""
Handles scrolling to change the wallpaper.
"""
if self.parent:
self.parent.handle_scroll(event.direction)

if __name__ == "__main__":
w = FloatingWindow()
w.show()
Gtk.main()
15 changes: 13 additions & 2 deletions variety/VarietyWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
from variety.QuotesEngine import QuotesEngine
from variety.QuoteWriter import QuoteWriter
from variety import indicator
from variety.FloatingWindow import FloatingWindow

DL_FOLDER_FILE = ".variety_download_folder"

Expand Down Expand Up @@ -116,6 +117,7 @@ def start(self, cmdoptions):
self.about = None
self.preferences_dialog = None
self.ind = None
self.floating_window = None

try:
if Gio.SettingsSchemaSource.get_default().lookup("org.gnome.desktop.background", True):
Expand Down Expand Up @@ -1297,10 +1299,13 @@ def select_random_images(self, count):
return all_images[:count]

def on_indicator_scroll(self, indicator, steps, direction):
self.on_indicator_scroll_throttled(indicator, steps, direction)
self.handle_scroll(direction)

@debounce(seconds=0.3)
def on_indicator_scroll_throttled(self, indicator, steps, direction):
def handle_scroll(self, direction):
"""
Handles scrolling to change the wallpaper (indicator and floating widget).
"""
if direction == Gdk.ScrollDirection.SMOOTH:
return

Expand Down Expand Up @@ -2062,6 +2067,10 @@ def parse_options(arguments, report_errors=True):
"--preferences", "--show-preferences", action="store_true", dest="preferences",
help=_("Show Preferences dialog"))

parser.add_option(
"-F", "--floating", action="store_true", dest="floating",
help=_("Show mini floating window (useful on systems without indicator / tray support)"))

parser.add_option(
"--selector", "--show-selector", action="store_true", dest="selector",
help=_("Show manual wallpaper selector - the thumbnail bar filled with images from the active image sources"))
Expand Down Expand Up @@ -2151,6 +2160,8 @@ def _process_command():
self.show_hide_wallpaper_selector()
if options.preferences:
self.on_mnu_preferences_activate()
if options.floating:
self.floating_window = FloatingWindow(self)

if options.quotes_fast_forward:
self.next_quote(bypass_history=True)
Expand Down