Browse Source

Wayland: Further improved implementation of menu windows

Tall menus now work also as single popup window and show the correct selected item.

Groups of popups with a menutitle, an associated menuwindow, and possibly submenus
are constructed around the menuwindow, the menutitle being a child popup of the
menuwindow. This positions these popup groups better than before.
pull/624/head
ManoloFLTK 2 years ago
parent
commit
9210e3efbf
  1. 33
      src/Fl_Menu.cxx
  2. 4
      src/Fl_Window_Driver.H
  3. 104
      src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx

33
src/Fl_Menu.cxx

@ -123,8 +123,9 @@ class menutitle : public window_with_items {
void draw() FL_OVERRIDE; void draw() FL_OVERRIDE;
public: public:
menutitle *extra; // additional menutitle window when the 1st one is covered by a menuwindow menutitle *extra; // additional menutitle window when the 1st one is covered by a menuwindow
menutitle(int X, int Y, int W, int H, const Fl_Menu_Item*); menutitle(int X, int Y, int W, int H, const Fl_Menu_Item*, bool menubar = false);
~menutitle(); ~menutitle();
bool in_menubar;
}; };
// each vertical menu has one of these: // each vertical menu has one of these:
@ -136,6 +137,7 @@ class menuwindow : public window_with_items {
int handle_part1(int); int handle_part1(int);
int handle_part2(int e, int ret); int handle_part2(int e, int ret);
static Fl_Window *parent_; static Fl_Window *parent_;
static int display_height_;
public: public:
menutitle* title; menutitle* title;
int handle(int) FL_OVERRIDE; int handle(int) FL_OVERRIDE;
@ -160,6 +162,7 @@ public:
}; };
Fl_Window *menuwindow::parent_ = NULL; Fl_Window *menuwindow::parent_ = NULL;
int menuwindow::display_height_ = 0;
/** /**
\cond DriverDev \cond DriverDev
@ -167,8 +170,10 @@ Fl_Window *menuwindow::parent_ = NULL;
\{ \{
*/ */
/** The Fl_Window from which currently displayed popups originate. */ /** The Fl_Window from which currently displayed popups originate.
Fl_Window *Fl_Window_Driver::menu_parent() { Optionally, gives also the height of the display containing this window */
Fl_Window *Fl_Window_Driver::menu_parent(int *display_height) {
if (display_height) *display_height = menuwindow::display_height_;
return menuwindow::parent_; return menuwindow::parent_;
} }
@ -209,6 +214,13 @@ int Fl_Window_Driver::menu_selected(Fl_Window *win) {
return (mwin ? mwin->selected : -1); return (mwin ? mwin->selected : -1);
} }
/** Returns whether win is a non-menubar menutitle */
bool Fl_Window_Driver::is_floating_title(Fl_Window *win) {
if (!win->menu_window()) return false;
Fl_Window *mwin = ((window_with_items*)win)->as_menuwindow();
return !mwin && !((menutitle*)win)->in_menubar;
}
/** Create a menutitle window with same content and size as another one and another ordinate. /** Create a menutitle window with same content and size as another one and another ordinate.
*/ */
Fl_Window *Fl_Window_Driver::extra_menutitle(Fl_Window *old, int Y) { Fl_Window *Fl_Window_Driver::extra_menutitle(Fl_Window *old, int Y) {
@ -336,13 +348,14 @@ void Fl_Menu_Item::draw(int x, int y, int w, int h, const Fl_Menu_* m,
fl_draw_shortcut = 0; fl_draw_shortcut = 0;
} }
menutitle::menutitle(int X, int Y, int W, int H, const Fl_Menu_Item* L) : menutitle::menutitle(int X, int Y, int W, int H, const Fl_Menu_Item* L, bool inbar) :
window_with_items(X, Y, W, H, L) { window_with_items(X, Y, W, H, L) {
end(); end();
set_modal(); set_modal();
clear_border(); clear_border();
set_menu_window(); set_menu_window();
extra = NULL; extra = NULL;
in_menubar = inbar;
} }
menutitle::~menutitle() { menutitle::~menutitle() {
@ -476,7 +489,7 @@ menuwindow::menuwindow(const Fl_Menu_Item* m, int X, int Y, int Wp, int Hp,
if (menubar_title) { if (menubar_title) {
int dy = Fl::box_dy(button->box())+1; int dy = Fl::box_dy(button->box())+1;
int ht = button->h()-dy*2; int ht = button->h()-dy*2;
title = new menutitle(tx, ty-ht-dy, Wtitle, ht, t); title = new menutitle(tx, ty-ht-dy, Wtitle, ht, t, true);
} else { } else {
int dy = 2; int dy = 2;
int ht = Htitle+2*BW+3; int ht = Htitle+2*BW+3;
@ -682,6 +695,14 @@ struct menustate {
}; };
static menustate* p=0; static menustate* p=0;
void Fl_Window_Driver::scroll_to_selected_item(Fl_Window *win) {
if (!p || !win->menu_window()) return;
menuwindow *mwin = ((window_with_items*)win)->as_menuwindow();
if (mwin && p->item_number > 0) {
mwin->autoscroll(p->item_number);
}
}
// return 1 if the coordinates are inside any of the menuwindows // return 1 if the coordinates are inside any of the menuwindows
int menustate::is_inside(int mx, int my) { int menustate::is_inside(int mx, int my) {
int i; int i;
@ -972,6 +993,8 @@ const Fl_Menu_Item* Fl_Menu_Item::pulldown(
Y += Fl::event_y_root()-Fl::event_y(); Y += Fl::event_y_root()-Fl::event_y();
menuwindow::parent_ = Fl::first_window(); menuwindow::parent_ = Fl::first_window();
} }
int XX, YY, WW;
Fl::screen_xywh(XX, YY, WW, menuwindow::display_height_, menuwindow::parent_->screen_num());
menuwindow mw(this, X, Y, W, H, initial_item, title, menubar); menuwindow mw(this, X, Y, W, H, initial_item, title, menubar);
Fl::grab(mw); Fl::grab(mw);
menustate pp; p = &pp; menustate pp; p = &pp;

4
src/Fl_Window_Driver.H

@ -192,13 +192,15 @@ public:
// when that's not the case, as with Wayland. // when that's not the case, as with Wayland.
virtual void reposition_menu_window(int x, int y); virtual void reposition_menu_window(int x, int y);
virtual void menu_window_area(int &X, int &Y, int &W, int &H, int nscreen = -1); virtual void menu_window_area(int &X, int &Y, int &W, int &H, int nscreen = -1);
static Fl_Window *menu_parent(); static Fl_Window *menu_parent(int *display_height = NULL);
static Fl_Window *menu_leftorigin(Fl_Window*); static Fl_Window *menu_leftorigin(Fl_Window*);
static Fl_Window *menu_title(Fl_Window*); static Fl_Window *menu_title(Fl_Window*);
static int menu_itemheight(Fl_Window*); static int menu_itemheight(Fl_Window*);
static int menu_bartitle(Fl_Window*); static int menu_bartitle(Fl_Window*);
static int menu_selected(Fl_Window*); static int menu_selected(Fl_Window*);
static Fl_Window *extra_menutitle(Fl_Window *old, int Y); static Fl_Window *extra_menutitle(Fl_Window *old, int Y);
static bool is_floating_title(Fl_Window *);
static void scroll_to_selected_item(Fl_Window *);
virtual fl_uintptr_t os_id() { return 0; } virtual fl_uintptr_t os_id() { return 0; }
}; };

104
src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx

@ -885,6 +885,7 @@ static const struct xdg_toplevel_listener xdg_toplevel_listener = {
struct win_positioner { struct win_positioner {
struct wld_window *window; struct wld_window *window;
int x, y; int x, y;
Fl_Window *child_popup;
}; };
@ -894,10 +895,12 @@ static void popup_configure(void *data, struct xdg_popup *xdg_popup, int32_t x,
//printf("popup_configure %p asked:%dx%d got:%dx%d\n",window->fl_win, win_pos->x,win_pos->y, x,y); //printf("popup_configure %p asked:%dx%d got:%dx%d\n",window->fl_win, win_pos->x,win_pos->y, x,y);
//fprintf(stderr, "popup_configure: popup=%p data=%p xid=%p fl_win=%p\n", xdg_popup, data, window, window->fl_win); //fprintf(stderr, "popup_configure: popup=%p data=%p xid=%p fl_win=%p\n", xdg_popup, data, window, window->fl_win);
Fl_Window_Driver::driver(window->fl_win)->wait_for_expose_value = 0; Fl_Window_Driver::driver(window->fl_win)->wait_for_expose_value = 0;
int XX, YY, WW, HH; int HH;
Fl::screen_xywh(XX, YY, WW, HH, window->fl_win->screen_num()); Fl_Window_Driver::menu_parent(&HH);
if (window->fl_win->h() > HH && y < win_pos->y) { // A menu taller than the display if (window->fl_win->h() > HH && y != win_pos->y) { // A menu taller than the display
window->state = (y - win_pos->y); window->state = (y - win_pos->y);
// make selected item visible, if there's one
Fl_Window_Driver::scroll_to_selected_item(window->fl_win);
} else if (Fl_Window_Driver::menu_title(window->fl_win) && y < win_pos->y) { } else if (Fl_Window_Driver::menu_title(window->fl_win) && y < win_pos->y) {
// A menuwindow below a menutitle has been placed higher to avoid display bottom. // A menuwindow below a menutitle has been placed higher to avoid display bottom.
// The workaround here creates an extra menutitle above the menuwindow. // The workaround here creates an extra menutitle above the menuwindow.
@ -922,6 +925,7 @@ static void popup_done(void *data, struct xdg_popup *xdg_popup) {
struct win_positioner *win_pos = (struct win_positioner *)data; struct win_positioner *win_pos = (struct win_positioner *)data;
struct wld_window *window = win_pos->window; struct wld_window *window = win_pos->window;
//fprintf(stderr, "popup_done: popup=%p data=%p xid=%p fl_win=%p\n", xdg_popup, data, window, window->fl_win); //fprintf(stderr, "popup_done: popup=%p data=%p xid=%p fl_win=%p\n", xdg_popup, data, window, window->fl_win);
if (win_pos->child_popup) win_pos->child_popup->hide();
xdg_popup_destroy(xdg_popup); xdg_popup_destroy(xdg_popup);
delete win_pos; delete win_pos;
// The sway compositor calls popup_done directly and hides the menu // The sway compositor calls popup_done directly and hides the menu
@ -1017,6 +1021,15 @@ static const char *get_prog_name() {
with the same size and content as the hidden menutitle and to map it just above with the same size and content as the hidden menutitle and to map it just above
the menuwindow so it becomes visible. the menuwindow so it becomes visible.
Groups of popups that begin with a menutitle, the associated menuwindow, and optionally
a submenu window and that don't belong to an Fl_Menu_Bar are processed differently:
the menuwindow is mapped first, and the menutitle is mapped second above it as a child popup.
Fl_Window_Driver::is_floating_title() detects when such a menutitle is created,
global variable previous_floatingtitle is assigned the value of this menutitle, and
the menutitle is mapped only after the menuwindow has been mapped, as a child of it.
This positions the popup group in the display better in relation to where the popup
was created.
In case 2) above, a tall popup is mapped with XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y In case 2) above, a tall popup is mapped with XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y
which puts its top at the display top border. The Wayland system then calls the which puts its top at the display top border. The Wayland system then calls the
popup_configure() callback function with the x,y coordinates of the top left corner popup_configure() callback function with the x,y coordinates of the top left corner
@ -1027,24 +1040,35 @@ static const char *get_prog_name() {
Function Fl_Wayland_Window_Driver::menu_window_area() sets the top of the display to Function Fl_Wayland_Window_Driver::menu_window_area() sets the top of the display to
a value such that function Fl_Wayland_Window_Driver::reposition_menu_window(), called by a value such that function Fl_Wayland_Window_Driver::reposition_menu_window(), called by
menuwindow::autoscroll(int n), ensures that menu item #n is visible. menuwindow::autoscroll(int n), ensures that menu item #n is visible.
Fl_Wayland_Window_Driver::scroll_to_selected_item() scrolls the tall popup so its selected
item, when there's one, is visible.
*/ */
// A menutitle to be mapped later as the child of a menuwindow
static Fl_Window *previous_floatingtitle = NULL;
static int tall_popup = 0; // to support tall menu buttons
static void process_menu_or_tooltip(struct wld_window *new_window) { static bool process_menu_or_tooltip(struct wld_window *new_window) {
// a menu window or tooltip // a menu window or tooltip
new_window->kind = Fl_Wayland_Window_Driver::POPUP; new_window->kind = Fl_Wayland_Window_Driver::POPUP;
Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver(); Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
Fl_Window *pWindow = new_window->fl_win; Fl_Window *pWindow = new_window->fl_win;
new_window->xdg_surface = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base, new_window->wl_surface); new_window->xdg_surface = xdg_wm_base_get_xdg_surface(scr_driver->xdg_wm_base, new_window->wl_surface);
xdg_surface_add_listener(new_window->xdg_surface, &xdg_surface_listener, new_window); xdg_surface_add_listener(new_window->xdg_surface, &xdg_surface_listener, new_window);
struct xdg_positioner *positioner = xdg_wm_base_create_positioner(scr_driver->xdg_wm_base); if (Fl_Window_Driver::is_floating_title(pWindow)) {
//xdg_positioner_get_version(positioner) <== gives 1 under Debian previous_floatingtitle = pWindow;
struct win_positioner *win_pos = new struct win_positioner; return true;
win_pos->window = new_window; }
tall_popup = 0;
if (pWindow->menu_window() && !Fl_Window_Driver::menu_title(pWindow)) {
int HH;
Fl_Window_Driver::menu_parent(&HH);
if (pWindow->h() > HH) tall_popup = 1;
}
Fl_Window *menu_origin = NULL; Fl_Window *menu_origin = NULL;
if (pWindow->menu_window()) { if (pWindow->menu_window()) {
menu_origin = Fl_Window_Driver::menu_leftorigin(pWindow); menu_origin = Fl_Window_Driver::menu_leftorigin(pWindow);
if (!menu_origin ) menu_origin = Fl_Window_Driver::menu_title(pWindow); if (!menu_origin && !previous_floatingtitle) menu_origin = Fl_Window_Driver::menu_title(pWindow);
} }
Fl_Widget *target = (pWindow->tooltip_window() ? Fl_Tooltip::current() : NULL); Fl_Widget *target = (pWindow->tooltip_window() ? Fl_Tooltip::current() : NULL);
if (!target) target = Fl_Window_Driver::menu_parent(); if (!target) target = Fl_Window_Driver::menu_parent();
@ -1057,12 +1081,15 @@ static void process_menu_or_tooltip(struct wld_window *new_window) {
float f = Fl::screen_scale(parent_win->screen_num()); float f = Fl::screen_scale(parent_win->screen_num());
//fprintf(stderr, "menu parent_win=%p pos:%dx%d size:%dx%d\n", parent_win, pWindow->x(), pWindow->y(), pWindow->w(), pWindow->h()); //fprintf(stderr, "menu parent_win=%p pos:%dx%d size:%dx%d\n", parent_win, pWindow->x(), pWindow->y(), pWindow->w(), pWindow->h());
//printf("window=%p menutitle=%p bartitle=%d leftorigin=%p y=%d\n", pWindow, Fl_Window_Driver::menu_title(pWindow), Fl_Window_Driver::menu_bartitle(pWindow), Fl_Window_Driver::menu_leftorigin(pWindow), pWindow->y()); //printf("window=%p menutitle=%p bartitle=%d leftorigin=%p y=%d\n", pWindow, Fl_Window_Driver::menu_title(pWindow), Fl_Window_Driver::menu_bartitle(pWindow), Fl_Window_Driver::menu_leftorigin(pWindow), pWindow->y());
if (Fl_Window_Driver::menu_title(pWindow)) { struct xdg_positioner *positioner = xdg_wm_base_create_positioner(scr_driver->xdg_wm_base);
//xdg_positioner_get_version(positioner) <== gives 1 under Debian and Sway
int popup_x, popup_y;
if (Fl_Window_Driver::menu_title(pWindow) && Fl_Window_Driver::menu_bartitle(pWindow)) {
xdg_positioner_set_anchor_rect(positioner, 0, 0, Fl_Window_Driver::menu_title(pWindow)->w(), Fl_Window_Driver::menu_title(pWindow)->h()); xdg_positioner_set_anchor_rect(positioner, 0, 0, Fl_Window_Driver::menu_title(pWindow)->w(), Fl_Window_Driver::menu_title(pWindow)->h());
win_pos->x = 0; popup_x = 0;
win_pos->y = Fl_Window_Driver::menu_title(pWindow)->h(); popup_y = Fl_Window_Driver::menu_title(pWindow)->h();
} else { } else {
int popup_x = pWindow->x() * f, popup_y = pWindow->y() * f; popup_x = pWindow->x() * f, popup_y = pWindow->y() * f;
if (popup_x + pWindow->w() * f < 0) popup_x = - pWindow->w() * f; if (popup_x + pWindow->w() * f < 0) popup_x = - pWindow->w() * f;
if (menu_origin) { if (menu_origin) {
popup_x -= menu_origin->x() * f; popup_x -= menu_origin->x() * f;
@ -1075,8 +1102,7 @@ static void process_menu_or_tooltip(struct wld_window *new_window) {
if (parent_xid->kind == Fl_Wayland_Window_Driver::DECORATED) if (parent_xid->kind == Fl_Wayland_Window_Driver::DECORATED)
libdecor_frame_translate_coordinate(parent_xid->frame, popup_x, popup_y, &popup_x, &popup_y); libdecor_frame_translate_coordinate(parent_xid->frame, popup_x, popup_y, &popup_x, &popup_y);
xdg_positioner_set_anchor_rect(positioner, popup_x, popup_y, 1, 1); xdg_positioner_set_anchor_rect(positioner, popup_x, popup_y, 1, 1);
win_pos->x = popup_x; popup_y++;
win_pos->y = popup_y + 1;
} }
xdg_positioner_set_size(positioner, pWindow->w() * f , pWindow->h() * f ); xdg_positioner_set_size(positioner, pWindow->w() * f , pWindow->h() * f );
xdg_positioner_set_anchor(positioner, XDG_POSITIONER_ANCHOR_BOTTOM_LEFT); xdg_positioner_set_anchor(positioner, XDG_POSITIONER_ANCHOR_BOTTOM_LEFT);
@ -1089,6 +1115,11 @@ static void process_menu_or_tooltip(struct wld_window *new_window) {
} }
xdg_positioner_set_constraint_adjustment(positioner, constraint); xdg_positioner_set_constraint_adjustment(positioner, constraint);
new_window->xdg_popup = xdg_surface_get_popup(new_window->xdg_surface, parent_xdg, positioner); new_window->xdg_popup = xdg_surface_get_popup(new_window->xdg_surface, parent_xdg, positioner);
struct win_positioner *win_pos = new struct win_positioner;
win_pos->window = new_window;
win_pos->x = popup_x;
win_pos->y = popup_y;
win_pos->child_popup = NULL;
//printf("create xdg_popup=%p data=%p xid=%p fl_win=%p\n",new_window->xdg_popup,win_pos,new_window,new_window->fl_win); //printf("create xdg_popup=%p data=%p xid=%p fl_win=%p\n",new_window->xdg_popup,win_pos,new_window,new_window->fl_win);
xdg_positioner_destroy(positioner); xdg_positioner_destroy(positioner);
xdg_popup_add_listener(new_window->xdg_popup, &popup_listener, win_pos); xdg_popup_add_listener(new_window->xdg_popup, &popup_listener, win_pos);
@ -1098,12 +1129,14 @@ static void process_menu_or_tooltip(struct wld_window *new_window) {
//libdecor_frame_popup_grab(parent_xid->frame, scr_driver->get_seat_name()); //libdecor_frame_popup_grab(parent_xid->frame, scr_driver->get_seat_name());
} }
wl_surface_commit(new_window->wl_surface); wl_surface_commit(new_window->wl_surface);
return false;
} }
void Fl_Wayland_Window_Driver::makeWindow() void Fl_Wayland_Window_Driver::makeWindow()
{ {
struct wld_window *new_window; struct wld_window *new_window;
bool is_floatingtitle;
Fl_Wayland_Screen_Driver::output *output; Fl_Wayland_Screen_Driver::output *output;
wait_for_expose_value = 1; wait_for_expose_value = 1;
@ -1134,7 +1167,7 @@ void Fl_Wayland_Window_Driver::makeWindow()
} }
if (pWindow->menu_window() || pWindow->tooltip_window()) { // a menu window or tooltip if (pWindow->menu_window() || pWindow->tooltip_window()) { // a menu window or tooltip
process_menu_or_tooltip(new_window); is_floatingtitle = process_menu_or_tooltip(new_window);
} else if ( pWindow->border() && !pWindow->parent() ) { // a decorated window } else if ( pWindow->border() && !pWindow->parent() ) { // a decorated window
new_window->kind = DECORATED; new_window->kind = DECORATED;
@ -1219,7 +1252,31 @@ void Fl_Wayland_Window_Driver::makeWindow()
Fl::e_number = old_event; Fl::e_number = old_event;
pWindow->redraw(); pWindow->redraw();
// make sure each popup is mapped with its constraints before mapping next popup // make sure each popup is mapped with its constraints before mapping next popup
if (pWindow->menu_window()) pWindow->wait_for_expose(); if (pWindow->menu_window() && !is_floatingtitle) {
pWindow->wait_for_expose();
if (previous_floatingtitle) { // map the menutitle popup now as child of pWindow
struct wld_window *xid = fl_wl_xid(previous_floatingtitle);
struct xdg_positioner *positioner = xdg_wm_base_create_positioner(scr_driver->xdg_wm_base);
xdg_positioner_set_anchor_rect(positioner, 0, 0, 1, 1);
float f = Fl::screen_scale(Fl_Window_Driver::menu_parent()->screen_num());
xdg_positioner_set_size(positioner, previous_floatingtitle->w() * f , previous_floatingtitle->h() * f );
xdg_positioner_set_anchor(positioner, XDG_POSITIONER_ANCHOR_TOP_LEFT);
xdg_positioner_set_gravity(positioner, XDG_POSITIONER_GRAVITY_TOP_RIGHT);
xid->xdg_popup = xdg_surface_get_popup(xid->xdg_surface, new_window->xdg_surface, positioner);
xdg_positioner_destroy(positioner);
struct win_positioner *win_pos = new struct win_positioner;
win_pos->window = xid;
win_pos->x = 0;
win_pos->y = 0;
xdg_popup_add_listener(xid->xdg_popup, &popup_listener, win_pos);
wl_surface_commit(xid->wl_surface);
previous_floatingtitle->wait_for_expose();
struct win_positioner *parent_win_pos =
(struct win_positioner*)xdg_popup_get_user_data(new_window->xdg_popup);
parent_win_pos->child_popup = previous_floatingtitle;
previous_floatingtitle = NULL;
}
}
} }
Fl_Wayland_Window_Driver::type_for_resize_window_between_screens Fl_Wayland_Window_Driver::data_for_resize_window_between_screens_ = {0, false}; Fl_Wayland_Window_Driver::type_for_resize_window_between_screens Fl_Wayland_Window_Driver::data_for_resize_window_between_screens_ = {0, false};
@ -1658,6 +1715,7 @@ void Fl_Wayland_Window_Driver::reposition_menu_window(int x, int y) {
win_pos->window = xid_menu; win_pos->window = xid_menu;
win_pos->x = popup_x; win_pos->x = popup_x;
win_pos->y = popup_y; win_pos->y = popup_y;
win_pos->child_popup = NULL;
xdg_popup_add_listener(xid_menu->xdg_popup, &popup_listener, win_pos); xdg_popup_add_listener(xid_menu->xdg_popup, &popup_listener, win_pos);
wl_surface_commit(xid_menu->wl_surface); wl_surface_commit(xid_menu->wl_surface);
wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display); // necessary with sway wl_display_roundtrip(Fl_Wayland_Screen_Driver::wl_display); // necessary with sway
@ -1672,10 +1730,9 @@ void Fl_Wayland_Window_Driver::reposition_menu_window(int x, int y) {
void Fl_Wayland_Window_Driver::menu_window_area(int &X, int &Y, int &W, int &H, int nscreen) { void Fl_Wayland_Window_Driver::menu_window_area(int &X, int &Y, int &W, int &H, int nscreen) {
Fl_Window *parent = Fl_Window_Driver::menu_parent(); int HH;
Fl_Window *parent = Fl_Window_Driver::menu_parent(&HH);
if (parent) { if (parent) {
int XX, YY, WW, HH;
Fl::screen_xywh(XX, YY, WW, HH, parent->screen_num());
if (pWindow->menu_window() && pWindow->h() > HH) { if (pWindow->menu_window() && pWindow->h() > HH) {
// tall menu: set top (Y) and bottom (Y+H) bounds relatively to reference window // tall menu: set top (Y) and bottom (Y+H) bounds relatively to reference window
int ih = Fl_Window_Driver::menu_itemheight(pWindow); int ih = Fl_Window_Driver::menu_itemheight(pWindow);
@ -1686,9 +1743,14 @@ void Fl_Wayland_Window_Driver::menu_window_area(int &X, int &Y, int &W, int &H,
if (origin) { // has left parent if (origin) { // has left parent
int selected = fl_max(Fl_Window_Driver::menu_selected(origin), 0); int selected = fl_max(Fl_Window_Driver::menu_selected(origin), 0);
Y = origin->y() + (selected + 0.5) * ih; Y = origin->y() + (selected + 0.5) * ih;
} else { } else if (!Fl_Window_Driver::menu_bartitle(pWindow)) { // tall menu button
static int y_offset = 0;
if (tall_popup == 1) y_offset = pWindow->y()- ih;
Y = 1.5 * ih + y_offset;
} else { // has a menutitle
Y = 1.5 * ih; Y = 1.5 * ih;
} }
tall_popup++;
} else { // position the menu window by wayland constraints } else { // position the menu window by wayland constraints
X = -50000; X = -50000;
Y = -50000; Y = -50000;

Loading…
Cancel
Save