- Created window placement window for wlroots env

This commit is contained in:
trigg 2020-10-19 11:47:59 +00:00
parent 7ae801ba2d
commit c6bb3fb123
7 changed files with 261 additions and 63 deletions

View file

@ -6,7 +6,7 @@ import logging
class DraggableWindow(Gtk.Window):
def __init__(self, x=0, y=0, w=300, h=300, message="Message"):
def __init__(self, x=0, y=0, w=300, h=300, message="Message",settings=None):
Gtk.Window.__init__(self, type=Gtk.WindowType.POPUP)
if w < 100:
w = 100
@ -16,6 +16,7 @@ class DraggableWindow(Gtk.Window):
self.y = y
self.w = w
self.h = h
self.settings=settings
self.message = message
self.set_size_request(50, 50)
@ -127,3 +128,8 @@ class DraggableWindow(Gtk.Window):
context.rectangle(0, sh - 32, sw, 32)
context.fill()
def get_coords(self):
(x, y) = self.placement_window.get_position()
(w, h) = self.placement_window.get_size()
return (x,y,w,h)

View file

@ -0,0 +1,137 @@
import gi
gi.require_version("Gtk", "3.0")
import cairo
from gi.repository import Gtk, Gdk, GtkLayerShell
import logging
class DraggableWindowWayland(Gtk.Window):
def __init__(self, x=0, y=0, w=300, h=300, message="Message", settings=None):
Gtk.Window.__init__(self, type=Gtk.WindowType.TOPLEVEL)
if w < 100:
w = 100
if h < 100:
h = 100
self.x = x
self.y = y
self.w = w
self.h = h
self.settings=settings
self.message = message
self.set_size_request(50, 50)
self.connect('draw', self.draw)
self.connect('motion-notify-event', self.drag)
self.connect('button-press-event', self.button_press)
self.connect('button-release-event', self.button_release)
self.set_app_paintable(True)
self.monitor = 0
self.drag_type = None
self.drag_x = 0
self.drag_y = 0
GtkLayerShell.init_for_window(self)
GtkLayerShell.set_layer(self, GtkLayerShell.Layer.TOP)
GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.LEFT, True)
GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.RIGHT, True)
GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.BOTTOM, True)
GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.TOP, True)
self.show_all()
#self.force_location()
def force_location(self):
(sx, sy)= self.get_size()
if self.x < 0:
self.x=0
if self.y < 0:
self.y=0
if self.x + self.w > sx:
self.x = sx - self.w
if self.y + self.h > sy:
self.y = sy - self.h
self.queue_draw()
def drag(self, w, event):
if event.state & Gdk.ModifierType.BUTTON1_MASK:
if self.drag_type == 1:
# Center is move
self.x += event.x - self.drag_x
self.y += event.y - self.drag_y
self.drag_x = event.x
self.drag_y = event.y
self.force_location()
elif self.drag_type == 2:
# Right edge
self.w += event.x - self.drag_x
self.drag_x = event.x
self.force_location()
elif self.drag_type == 3:
# Bottom edge
self.h += event.y - self.drag_y
self.drag_y = event.y
self.force_location()
else:
# Bottom Right
self.w += event.x - self.drag_x
self.h += event.y - self.drag_y
self.drag_x = event.x
self.drag_y = event.y
self.force_location()
def button_press(self, w, event):
px = event.x - self.x
py = event.y - self.y
if not self.drag_type:
self.drag_type = 1
# Where in the window did we press?
if px < 20 and py<20:
self.settings.change_placement(None)
if py > self.h - 32:
self.drag_type += 2
if px > self.w - 32:
self.drag_type += 1
self.drag_x = event.x
self.drag_y = event.y
def button_release(self, w, event):
self.drag_type = None
def draw(self, widget, context):
context.translate(self.x, self.y)
context.save()
context.rectangle(0,0,self.w,self.h)
context.clip()
context.set_source_rgba(1.0, 1.0, 0.0, 0.7)
# Don't layer drawing over each other, always replace
context.set_operator(cairo.OPERATOR_SOURCE)
context.paint()
# Get size of window
# Draw text
context.set_source_rgba(0.0, 0.0, 0.0, 1.0)
xb, yb, w, h, dx, dy = context.text_extents(self.message)
context.move_to(self.w / 2 - w / 2, self.h / 2 - h / 2)
context.show_text(self.message)
# Draw resizing edges
context.set_source_rgba(0.0, 0.0, 1.0, 0.5)
context.rectangle(self.w - 32, 0, 32, self.h)
context.fill()
context.rectangle(0, self.h - 32, self.w, 32)
context.fill()
# Draw Done!
context.set_source_rgba(0.0, 1.0, 0.0, 0.5)
context.rectangle(0, 0, 20,20)
context.fill()
context.restore()
def get_coords(self):
return (self.x,self.y,self.w,self.h)

View file

@ -65,7 +65,7 @@ class OverlayWindow(Gtk.Window):
GtkLayerShell.set_anchor(self, GtkLayerShell.Edge.TOP, True)
def draw(self, widget, context):
pass
self.do_draw(context)
def do_draw(self, context):
pass
@ -98,38 +98,47 @@ class OverlayWindow(Gtk.Window):
self.get_window().shape_combine_region(None, 0, 0)
def force_location(self):
self.set_decorated(False)
self.set_keep_above(True)
display = Gdk.Display.get_default()
if "get_monitor" in dir(display):
monitor = display.get_monitor(self.monitor)
geometry = monitor.get_geometry()
scale_factor = monitor.get_scale_factor()
if not self.floating:
w = scale_factor * geometry.width
h = scale_factor * geometry.height
x = geometry.x
y = geometry.y
self.resize(w, h)
self.move(x, y)
if not self.is_wayland:
self.set_decorated(False)
self.set_keep_above(True)
display = Gdk.Display.get_default()
if "get_monitor" in dir(display):
monitor = display.get_monitor(self.monitor)
geometry = monitor.get_geometry()
scale_factor = monitor.get_scale_factor()
if not self.floating:
w = scale_factor * geometry.width
h = scale_factor * geometry.height
x = geometry.x
y = geometry.y
self.resize(w, h)
self.move(x, y)
else:
self.move(self.x, self.y)
self.resize(self.w, self.h)
else:
self.move(self.x, self.y)
self.resize(self.w, self.h)
else:
if not self.floating:
screen = display.get_default_screen()
w = screen.width()
h = screen.height()
x = 0
y = 0
else:
self.move(self.x, self.y)
self.resize(self.w, self.h)
if not self.floating:
screen = display.get_default_screen()
w = screen.width()
h = screen.height()
x = 0
y = 0
else:
self.move(self.x, self.y)
self.resize(self.w, self.h)
if not self.floating:
(w,h) = self.get_size()
self.w = w
self.h = h
self.redraw()
def redraw(self):
gdkwin = self.get_window()
if not self.floating:
(w,h) = self.get_size()
self.w = w
self.h = h
if gdkwin:
if not self.compositing or self.force_xshape:

View file

@ -118,14 +118,30 @@ class TextOverlayWindow(OverlayWindow):
self.attachment[id] = pix
self.redraw()
def draw(self, widget, ctx):
self.do_draw(ctx)
def do_draw(self, context):
self.context = context
context.set_antialias(cairo.ANTIALIAS_GOOD)
(w, h) = self.get_size()
# Make background transparent
context.set_source_rgba(0.0, 0.0, 0.0, 0.0)
context.set_operator(cairo.OPERATOR_SOURCE)
context.paint()
context.save()
if self.is_wayland:
# Special case!
# The window is full-screen regardless of what the user has selected. Because Wayland
# We need to set a clip and a transform to imitate original behaviour
w = self.w
h = self.h
context.translate(self.x, self.y)
context.rectangle(0,0,w,h)
context.clip()
cy = h
tnow = time.time()
@ -155,18 +171,19 @@ class TextOverlayWindow(OverlayWindow):
if cy <= 0:
# We've done enough
break
if self.is_wayland:
context.restore()
def draw_attach(self, y, url):
(w, h) = self.get_size()
if url in self.attachment and self.attachment[url]:
pix = self.attachment[url]
iw = pix.get_width()
ih = pix.get_height()
iw = min(iw, w)
ih = min(ih, (h * .7))
iw = min(iw, self.w)
ih = min(ih, (self.h * .7))
(ax, ay, aw, ah) = get_aspected_size(pix, iw, ih)
self.col(self.bg_col)
self.context.rectangle(0, y - ah, w, ah)
self.context.rectangle(0, y - ah, self.w, ah)
self.context.fill()
self.context.set_operator(cairo.OPERATOR_OVER)
@ -176,13 +193,12 @@ class TextOverlayWindow(OverlayWindow):
return y
def draw_text(self, y, text):
(w, h) = self.get_size()
layout = self.create_pango_layout(text)
layout.set_markup(text, -1)
attr = layout.get_attributes()
layout.set_width(Pango.SCALE * w)
layout.set_width(Pango.SCALE * self.w)
layout.set_spacing(Pango.SCALE * 3)
if(self.text_font):
font = Pango.FontDescription(
@ -190,7 +206,7 @@ class TextOverlayWindow(OverlayWindow):
layout.set_font_description(font)
tw, th = layout.get_pixel_size()
self.col(self.bg_col)
self.context.rectangle(0, y - th, w, th)
self.context.rectangle(0, y - th, self.w, th)
self.context.fill()
self.context.set_operator(cairo.OPERATOR_OVER)
self.col(self.fg_col)

View file

@ -3,6 +3,7 @@ gi.require_version("Gtk", "3.0")
import json
from configparser import ConfigParser
from .draggable_window import DraggableWindow
from .draggable_window_wayland import DraggableWindowWayland
from .settings import SettingsWindow
from gi.repository import Gtk, Gdk, Pango
import logging
@ -189,10 +190,10 @@ class TextSettingsWindow(SettingsWindow):
config.set("text", "monitor", self.monitor)
config.set("text", "enabled", "%d" % (int(self.enabled)))
config.set("text", "floating", "%s" % (int(self.floating)))
config.set("text", "floating_x", "%s" % (self.floating_x))
config.set("text", "floating_y", "%s" % (self.floating_y))
config.set("text", "floating_w", "%s" % (self.floating_w))
config.set("text", "floating_h", "%s" % (self.floating_h))
config.set("text", "floating_x", "%s" % (int(self.floating_x)))
config.set("text", "floating_y", "%s" % (int(self.floating_y)))
config.set("text", "floating_w", "%s" % (int(self.floating_w)))
config.set("text", "floating_h", "%s" % (int(self.floating_h)))
config.set("text", "channel", self.channel)
config.set("text", "guild", self.guild)
config.set("text", "bg_col", json.dumps(self.bg_col))
@ -394,22 +395,31 @@ class TextSettingsWindow(SettingsWindow):
def change_placement(self, button):
if self.placement_window:
(x, y) = self.placement_window.get_position()
(w, h) = self.placement_window.get_size()
(x,y,w,h) = self.placement_window.get_coords()
self.floating_x = x
self.floating_y = y
self.floating_w = w
self.floating_h = h
self.overlay.set_floating(True, x, y, w, h)
self.save_config()
button.set_label("Place Window")
if not self.overlay.is_wayland:
button.set_label("Place Window")
self.placement_window.close()
self.placement_window = None
else:
self.placement_window = DraggableWindow(
x=self.floating_x, y=self.floating_y, w=self.floating_w, h=self.floating_h, message="Place & resize this window then press Save!")
button.set_label("Save this position")
if self.overlay.is_wayland:
self.placement_window = DraggableWindowWayland(
x=self.floating_x, y=self.floating_y,
w=self.floating_w, h=self.floating_h,
message="Place & resize this window then press Green!",settings=self)
else:
self.placement_window = DraggableWindow(
x=self.floating_x, y=self.floating_y,
w=self.floating_w, h=self.floating_h,
message="Place & resize this window then press Save!",settings=self)
if not self.overlay.is_wayland:
button.set_label("Save this position")
def change_align_type_edge(self, button):
if button.get_active():

View file

@ -144,12 +144,26 @@ class VoiceOverlayWindow(OverlayWindow):
def do_draw(self, context):
self.context = context
context.set_antialias(cairo.ANTIALIAS_GOOD)
# Get size of window
(w, h) = self.get_size()
# Make background transparent
self.set_wind_col()
# Don't layer drawing over each other, always replace
context.set_operator(cairo.OPERATOR_SOURCE)
context.paint()
context.save()
if self.is_wayland:
# Special case!
# The window is full-screen regardless of what the user has selected. Because Wayland
# We need to set a clip and a transform to imitate original behaviour
w = self.w
h = self.h
context.translate(self.x, self.y)
context.rectangle(0,0,w,h)
context.clip()
context.set_operator(cairo.OPERATOR_OVER)
if not self.connected:
return
@ -183,8 +197,6 @@ class VoiceOverlayWindow(OverlayWindow):
pass # Not in list
self.users_to_draw.insert(0, self_user)
# Get size of window
(w, h) = self.get_size()
# Calculate height needed to show overlay
height = (len(self.users_to_draw) * self.avatar_size) + \
(len(self.users_to_draw) + 1) * self.icon_spacing
@ -203,6 +215,8 @@ class VoiceOverlayWindow(OverlayWindow):
rh += self.avatar_size + self.icon_spacing
# Don't hold a ref
if self.is_wayland:
context.restore()
self.context = None
def recv_avatar(self, id, pix):
@ -226,7 +240,6 @@ class VoiceOverlayWindow(OverlayWindow):
# Set the key with no value to avoid spamming requests
self.avatars[user["id"]] = None
(w, h) = self.get_size()
c = None
mute = False
deaf = False
@ -243,14 +256,14 @@ class VoiceOverlayWindow(OverlayWindow):
if self.align_right:
if not self.icon_only:
self.draw_text(
context, user["friendlyname"], w - self.avatar_size - self.horz_edge_padding, y)
context, user["friendlyname"], self.w - self.avatar_size - self.horz_edge_padding, y)
self.draw_avatar_pix(
context, pix, w - self.avatar_size - self.horz_edge_padding, y, c)
context, pix, self.w - self.avatar_size - self.horz_edge_padding, y, c)
if deaf:
self.draw_deaf(context, w - self.avatar_size -
self.draw_deaf(context, self.w - self.avatar_size -
self.horz_edge_padding, y)
elif mute:
self.draw_mute(context, w - self.avatar_size -
self.draw_mute(context, self.w - self.avatar_size -
self.horz_edge_padding, y)
else:
if not self.icon_only:

View file

@ -3,6 +3,7 @@ gi.require_version("Gtk", "3.0")
import json
from configparser import ConfigParser
from .draggable_window import DraggableWindow
from .draggable_window_wayland import DraggableWindowWayland
from .settings import SettingsWindow
from gi.repository import Gtk, Gdk, Pango
import logging
@ -340,24 +341,30 @@ class VoiceSettingsWindow(SettingsWindow):
def change_placement(self, button):
if self.placement_window:
(x, y) = self.placement_window.get_position()
(w, h) = self.placement_window.get_size()
(x,y,w,h) = self.placement_window.get_coords()
self.floating_x = x
self.floating_y = y
self.floating_w = w
self.floating_h = h
self.overlay.set_floating(True, x, y, w, h)
self.save_config
button.set_label("Place Window")
if not self.overlay.is_wayland:
button.set_label("Place Window")
self.placement_window.close()
self.placement_window = None
else:
self.placement_window = DraggableWindow(
x=self.floating_x, y=self.floating_y,
w=self.floating_w, h=self.floating_h,
message="Place & resize this window then press Save!")
button.set_label("Save this position")
if self.overlay.is_wayland:
self.placement_window = DraggableWindowWayland(
x=self.floating_x, y=self.floating_y,
w=self.floating_w, h=self.floating_h,
message="Place & resize this window then press Green!",settings=self)
else:
self.placement_window = DraggableWindow(
x=self.floating_x, y=self.floating_y,
w=self.floating_w, h=self.floating_h,
message="Place & resize this window then press Save!",settings=self)
if not self.overlay.is_wayland:
button.set_label("Save this position")
def change_align_type_edge(self, button):
if button.get_active():