- Created window placement window for wlroots env
This commit is contained in:
parent
7ae801ba2d
commit
c6bb3fb123
7 changed files with 261 additions and 63 deletions
|
|
@ -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)
|
||||
|
|
|
|||
137
discover_overlay/draggable_window_wayland.py
Normal file
137
discover_overlay/draggable_window_wayland.py
Normal 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)
|
||||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue