apprt/gtk-ng: resize overlay
parent
e34248a2ad
commit
c6abf65dd1
|
|
@ -202,6 +202,18 @@ pub const Surface = extern struct {
|
|||
url_left: *gtk.Label = undefined,
|
||||
url_right: *gtk.Label = undefined,
|
||||
|
||||
/// The resize label shown when resizing the surface.
|
||||
size_label: *gtk.Label = undefined,
|
||||
|
||||
/// The idle source that tracks our resize label.
|
||||
size_idler: ?c_uint = null,
|
||||
|
||||
/// If non-null this is a timer for dismissing the resize overlay.
|
||||
size_timer: ?c_uint = null,
|
||||
|
||||
/// Set to true after the first resize event.
|
||||
size_first: bool = true,
|
||||
|
||||
/// The apprt Surface.
|
||||
rt_surface: ApprtSurface = undefined,
|
||||
|
||||
|
|
@ -511,6 +523,86 @@ pub const Surface = extern struct {
|
|||
};
|
||||
}
|
||||
|
||||
fn resizeOverlaySchedule(self: *Self) void {
|
||||
const priv = self.private();
|
||||
const config = priv.config orelse return;
|
||||
switch (config.get().@"resize-overlay") {
|
||||
.never => return,
|
||||
.always => {},
|
||||
.@"after-first" => if (priv.size_first) {
|
||||
priv.size_first = false;
|
||||
return;
|
||||
},
|
||||
}
|
||||
|
||||
// We set this in case we reload our config later to after-first
|
||||
// so we don't miss a tick.
|
||||
priv.size_first = false;
|
||||
|
||||
// When updating a widget, wait until GTK is "idle", i.e. not in the middle
|
||||
// of doing any other updates. Since we are called in the middle of resizing
|
||||
// GTK is doing a lot of work rearranging all of the widgets. Not doing this
|
||||
// results in a lot of warnings from GTK and _horrible_ flickering of the
|
||||
// resize overlay.
|
||||
if (priv.size_idler != null) return;
|
||||
priv.size_idler = glib.idleAdd(resizeOverlayIdle, self);
|
||||
}
|
||||
|
||||
fn resizeOverlayIdle(ud: ?*anyopaque) callconv(.c) c_int {
|
||||
const self: *Self = @ptrCast(@alignCast(ud orelse return 0));
|
||||
const priv = self.private();
|
||||
|
||||
// No matter what our idler is complete with this callback
|
||||
priv.size_idler = null;
|
||||
|
||||
// We need config from here on out
|
||||
const config = if (priv.config) |c| c.get() else return 0;
|
||||
|
||||
var buf: [32]u8 = undefined;
|
||||
const text = text: {
|
||||
const surface = priv.core_surface orelse return 0;
|
||||
const grid_size = surface.size.grid();
|
||||
break :text std.fmt.bufPrintZ(
|
||||
&buf,
|
||||
"{d} x {d}",
|
||||
.{
|
||||
grid_size.columns,
|
||||
grid_size.rows,
|
||||
},
|
||||
) catch |err| {
|
||||
log.warn("unable to format text: {}", .{err});
|
||||
return 0;
|
||||
};
|
||||
};
|
||||
|
||||
// The resize overlay widget already exists, just update it.
|
||||
priv.size_label.setText(text.ptr);
|
||||
priv.size_label.as(gtk.Widget).setVisible(1);
|
||||
//setPosition(label, &self.config);
|
||||
|
||||
if (priv.size_timer) |timer| {
|
||||
if (glib.Source.remove(timer) == 0) {
|
||||
log.warn("unable to remove size overlay timer", .{});
|
||||
}
|
||||
}
|
||||
|
||||
priv.size_timer = glib.timeoutAdd(
|
||||
config.@"resize-overlay-duration".asMilliseconds(),
|
||||
resizeOverlayTimerExpired,
|
||||
self,
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fn resizeOverlayTimerExpired(ud: ?*anyopaque) callconv(.c) c_int {
|
||||
const self: *Self = @ptrCast(@alignCast(ud orelse return 0));
|
||||
const priv = self.private();
|
||||
priv.size_timer = null;
|
||||
priv.size_label.as(gtk.Widget).setVisible(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------
|
||||
// Libghostty Callbacks
|
||||
|
||||
|
|
@ -641,6 +733,9 @@ pub const Surface = extern struct {
|
|||
.width = 111,
|
||||
.height = 111,
|
||||
};
|
||||
priv.size_idler = null;
|
||||
priv.size_timer = null;
|
||||
priv.size_first = true;
|
||||
|
||||
// If our configuration is null then we get the configuration
|
||||
// from the application.
|
||||
|
|
@ -861,6 +956,14 @@ pub const Surface = extern struct {
|
|||
|
||||
// Some other initialization steps
|
||||
self.initUrlOverlay();
|
||||
self.initResizeOverlay();
|
||||
}
|
||||
|
||||
fn initResizeOverlay(self: *Self) void {
|
||||
const priv = self.private();
|
||||
const overlay = priv.overlay;
|
||||
const label = priv.size_label.as(gtk.Widget);
|
||||
overlay.addOverlay(label);
|
||||
}
|
||||
|
||||
fn initUrlOverlay(self: *Self) void {
|
||||
|
|
@ -905,6 +1008,18 @@ pub const Surface = extern struct {
|
|||
v.unref();
|
||||
priv.im_context = null;
|
||||
}
|
||||
if (priv.size_idler) |v| {
|
||||
if (glib.Source.remove(v) == 0) {
|
||||
log.warn("unable to remove resize overlay idler", .{});
|
||||
}
|
||||
priv.size_idler = null;
|
||||
}
|
||||
if (priv.size_timer) |v| {
|
||||
if (glib.Source.remove(v) == 0) {
|
||||
log.warn("unable to remove resize overlay timer", .{});
|
||||
}
|
||||
priv.size_timer = null;
|
||||
}
|
||||
|
||||
gtk.Widget.disposeTemplate(
|
||||
self.as(gtk.Widget),
|
||||
|
|
@ -1556,6 +1671,11 @@ pub const Surface = extern struct {
|
|||
surface.sizeCallback(priv.size) catch |err| {
|
||||
log.warn("error in size callback err={}", .{err});
|
||||
};
|
||||
|
||||
// If we have resize overlays enabled, setup an idler
|
||||
// to show that. We do this in an idle tick because doing it
|
||||
// during the resize results in flickering.
|
||||
self.resizeOverlaySchedule();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1669,6 +1789,7 @@ pub const Surface = extern struct {
|
|||
class.bindTemplateChildPrivate("gl_area", .{});
|
||||
class.bindTemplateChildPrivate("url_left", .{});
|
||||
class.bindTemplateChildPrivate("url_right", .{});
|
||||
class.bindTemplateChildPrivate("size_label", .{});
|
||||
|
||||
// Properties
|
||||
gobject.ext.registerProperties(class, &.{
|
||||
|
|
|
|||
|
|
@ -22,3 +22,11 @@ label.url-overlay.left {
|
|||
label.url-overlay.right {
|
||||
border-radius: 6px 0px 0px 0px;
|
||||
}
|
||||
|
||||
label.size-overlay {
|
||||
padding: 4px 8px 4px 8px;
|
||||
border-radius: 6px 6px 6px 6px;
|
||||
outline-style: solid;
|
||||
outline-width: 1px;
|
||||
outline-color: #555555;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,3 +42,18 @@ Label url_right {
|
|||
valign: end;
|
||||
label: bind template.mouse-hover-url;
|
||||
}
|
||||
|
||||
// The label that shows the resize information
|
||||
Label size_label {
|
||||
styles [
|
||||
"size-overlay",
|
||||
]
|
||||
|
||||
visible: false;
|
||||
focusable: false;
|
||||
focus-on-click: false;
|
||||
justify: center;
|
||||
selectable: false;
|
||||
halign: center;
|
||||
valign: center;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue