Skip to content

Commit ea5bfae

Browse files
committed
Fix rotation for Gtk4
1 parent f220c93 commit ea5bfae

File tree

2 files changed

+65
-15
lines changed

2 files changed

+65
-15
lines changed

include/ALabel.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ class ALabel : public AModule, public Gtk::Widget {
5151

5252
private:
5353
void handleMenu(std::string cmd) const;
54+
uint rotate_{0};
5455
};
5556

5657
} // namespace waybar

src/ALabel.cpp

+64-15
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,19 @@ ALabel::ALabel(const Json::Value& config, const std::string& name, const std::st
3939
label_.set_width_chars(config_["min-length"].asUInt());
4040
}
4141

42-
uint rotate = 0;
4342
if (config_["rotate"].isUInt()) {
44-
rotate = config["rotate"].asUInt();
45-
if (not(rotate == 0 || rotate == 90 || rotate == 180 || rotate == 270))
46-
spdlog::error("'rotate' is only supported in 90 degree increments {} is not valid.", rotate);
47-
// TODO
43+
rotate_ = config["rotate"].asUInt() % 360;
44+
if (not(rotate_ == 0 || rotate_ == 90 || rotate_ == 180 || rotate_ == 270)) {
45+
spdlog::error(
46+
"'rotate' is only supported in 90 degree increments {} is not valid. Falling back to 0.",
47+
rotate_);
48+
rotate_ = 0;
49+
}
4850
}
4951

5052
if (config_["align"].isDouble()) {
5153
auto align = config_["align"].asFloat();
52-
if (rotate == 90 || rotate == 270) {
54+
if (rotate_ == 90 || rotate_ == 270) {
5355
label_.set_yalign(align);
5456
} else {
5557
label_.set_xalign(align);
@@ -235,21 +237,68 @@ Gtk::Widget& ALabel::child() {
235237
return const_cast<Gtk::Widget&>(const_cast<const ALabel*>(this)->child());
236238
}
237239

238-
Gtk::SizeRequestMode ALabel::get_request_mode_vfunc() const { return child().get_request_mode(); }
240+
// Test if the angle is vertical
241+
static bool isVertical(uint angle) { return angle == 90 || angle == 270; }
242+
243+
Gtk::SizeRequestMode ALabel::get_request_mode_vfunc() const {
244+
auto mode = child().get_request_mode();
245+
if (isVertical(rotate_)) {
246+
// we need to use the opposite mode from the child
247+
switch (mode) {
248+
case Gtk::SizeRequestMode::HEIGHT_FOR_WIDTH:
249+
return Gtk::SizeRequestMode::WIDTH_FOR_HEIGHT;
250+
case Gtk::SizeRequestMode::WIDTH_FOR_HEIGHT:
251+
return Gtk::SizeRequestMode::HEIGHT_FOR_WIDTH;
252+
default:
253+
return mode;
254+
}
255+
} else {
256+
return mode;
257+
}
258+
}
239259

240260
void ALabel::measure_vfunc(Gtk::Orientation orientation, int for_size, int& minimum, int& natural,
241261
int& minimum_baseline, int& natural_baseline) const {
242-
return child().measure(orientation, for_size, minimum, natural, minimum_baseline,
243-
natural_baseline);
262+
bool vertical = isVertical(rotate_);
263+
if (vertical) {
264+
// the rotation is perpindicular, so we need to reverse the orientation.
265+
if (orientation == Gtk::Orientation::HORIZONTAL) {
266+
orientation = Gtk::Orientation::VERTICAL;
267+
} else {
268+
orientation = Gtk::Orientation::HORIZONTAL;
269+
}
270+
}
271+
child().measure(orientation, for_size, minimum, natural, minimum_baseline, natural_baseline);
272+
if (vertical) {
273+
// If we are rotated, the baseline doesn't make sense
274+
minimum_baseline = -1;
275+
natural_baseline = -1;
276+
}
244277
}
245278
void ALabel::size_allocate_vfunc(int width, int height, int baseline) {
246-
Gtk::Allocation allocation;
247-
allocation.set_x(0);
248-
allocation.set_y(0);
249-
allocation.set_width(width);
250-
allocation.set_height(height);
279+
// I can't find a C++ wrapper for Gsk
280+
GskTransform* transform = nullptr;
281+
if (rotate_ != 0) {
282+
// In order to rotate about the center, we need to translate to the center of the
283+
// allocation, rotate, then translate back
284+
float centerx = static_cast<float>(width) / 2.0f;
285+
float centery = static_cast<float>(height) / 2.0f;
286+
Gdk::Graphene::Point point{centerx, centery};
287+
transform = gsk_transform_translate(nullptr, point.gobj());
288+
transform = gsk_transform_rotate(transform, rotate_);
289+
if (isVertical(rotate_)) {
290+
point.set_y(-centery);
291+
point.set_x(-centerx);
292+
} else {
293+
point.set_x(-centerx);
294+
point.set_y(-centery);
295+
}
296+
transform = gsk_transform_translate(transform, point.gobj());
297+
}
298+
299+
// For some reason there isn't a gtkmm equivalent of this
300+
gtk_widget_allocate(GTK_WIDGET(child().gobj()), width, height, baseline, transform);
251301

252-
child().size_allocate(allocation, baseline);
253302
if (menu_) {
254303
// We need to present the menu as part of this function
255304
menu_->present();

0 commit comments

Comments
 (0)