Sometimes GTK modal dialogs are not modal --- bug or feature? - gtk

When I create a custom dialog in GTK (both, GTK2 or GTK3) and set it to be modal, all input to other windows of my application is ignored. This works nearly always, but it fails under certain conditions.
When I add a ScrolledWindow containing a TreeView to my dialog, it still works as supposed. But if I fill the TreeView with entries until the ScrolledWindow starts to display its scroll bars --- the modality is suddenly lost and I can click on my other windows!
Here is the most basic example I was able to set up. It's written in Vala, but you'll get the idea:
class MyDialog: Gtk.Dialog {
public MyDialog() {
this.modal = true;
var data = new Gtk.ListStore(1, typeof(string));
// increase this number -- the dialog is not modal anymore!
for (int i=0; i<2; ++i) {
Gtk.TreeIter current;
data.append(out current);
data.set(current, 0, "Lorem Ipsum");
}
var render = new Gtk.CellRendererText();
var column = new Gtk.TreeViewColumn();
column.pack_start(render, true);
column.add_attribute(render, "text", 0);
var treeview = new Gtk.TreeView.with_model(data);
treeview.append_column(column);
treeview.show();
var scroll = new Gtk.ScrolledWindow(null, null);
scroll.set_size_request(100, 100);
scroll.add(treeview);
scroll.show();
(this.get_content_area() as Gtk.Box).add(scroll);
}
}
int main (string[] args) {
Gtk.init (ref args);
var window = new Gtk.Window();
window.set_default_size(350, 170);
window.destroy.connect(Gtk.main_quit);
var button = new Gtk.Button.with_label("Click me!");
button.clicked.connect(() => {
var dialog = new MyDialog();
dialog.set_transient_for(window);
dialog.run();
dialog.destroy();
});
window.add(button);
window.show_all();
Gtk.main();
return 0;
}
Compile it with:
valac --pkg gtk+-3.0 main.vala
Am I missing something? Is this behaviour wanted? Or is it a bug? If so, is there a workaround?
EDIT: I investigated a bit further: The problem disappears when the overlay-scrollbars from Ubuntu are uninstalled. So It's not solved yet, but I know where I have to report this...

Definitely a bug. Post a bug report and/or upgrade your GTK+ lib.

Related

Add style when creating button with script Unity ui toolkit

So I want to add a lot of buttons with a script. I want to style them, but I can't find a method to do so.
I want to do something like
Button current = new Button();
current.addStyle("button-style");
Is this possible?
UNITY UI TOOLKIT
When a button is clicked I run a function
public void displayChildrenIcons(GameObject parent, string type)
{
var root = GetComponent<UIDocument>().rootVisualElement;
var displayArea = root.Q<VisualElement>("options");
displayArea.Clear();
for (int i = 0; i < parent.transform.childCount; i++)
{
Button current = new Button();
//How do I style this button before adding it?
displayArea.Add(current);
}
}
Check out the class IStyle. You can create one of these variables and change it so you can customimze style. Then assign it with Button.style = IStle;
public IStyle iStyle = new();
Button current = new();
curent.style = bStyle;
displayArea.Add(current);

How to make StackSwitcher tabs closeable Gtk/Vala

I am trying to make a Stack and StackSwitcher whose pages associated tabs can be added and deleted dynamically. To delete the associated widget in the stack and the tab in the StackSwitcher, I want to have a small delete button in the tab. I have found an example similar to this in the gtk3-widget-factory, screenshot shown below.
However, this uses a Notebook and I would like to be able to use the Stack/StackSwitcher setup instead of a Notebook (I don't like how the Notebook creates a background to its pages). I can't figure out how to change the widget that is displayed in the StackSwitcher for each page in the Stack. My intuition is that I should just be able to replace the Label in the StackSwitcher with a Box that has been packed with a Label and Button that has a callback that goes and removes the page and the tab. But I am not able to do this with how I am currently creating the pages of the Stack, which is by calling stack.add_titled(). The StackSwitcher that has been assigned to that stack just automatically picks up the labels with no way of editing them that I have found.
Is there a way to do this for a Stack and StackSwitcher? If not, I would also appreciate some advice for doing it with a Notebook as I have not even been able to recreate what I saw in the widget factory (above). This is the code that I have attempting to recreate it:
void main (string[] args) {
Gtk.init (ref args);
var window = new Window ();
window.title = "Example Program";
window.border_width = 10;
window.window_position = WindowPosition.CENTER;
window.set_default_size (350, 70);
window.destroy.connect (Gtk.main_quit);
Notebook note = new Notebook();
Box tabBox = new Box(Orientation.HORIZONTAL, 0);
Label tabLabel = new Label("Closable Tab");
Button closeButton = new Button.from_icon_name("window-close-symbolic", IconSize.BUTTON);
tabBox.pack_start(tabLabel, false, false, 0);
tabBox.pack_start(closeButton, false, false, 0);
Label displayLabel = new Label("this page should be closeable");
note.append_page(displayLabel, tabBox);
window.add(note);
window.show_all();
Gtk.main ();
}
which just creates an empty Notebook tab like this:
and I don't get any error messages about creating that tab failing so I don't know what to do. Any help is appreciated.

Adding an element after clicking on a button

I was trying to learn Vala by programming a very simple application and I stumbled over a problem, that I was unable to resolve on my own.
The program shows simply a button Init and on click it should add a Button X to the Grid container. Unfortunately, the contents of the Grid container remain empty and I don't know why.
Even more confusing is, that adding the Button right in the constructor works as expected.
So what I'm doing wrong here?
using Gtk;
class MyWindow: Gtk.Window {
private Gtk.Grid mGrid;
public MyWindow() {
var init=new Gtk.Button.with_label("Init");
init.clicked.connect((t)=>{
stdout.printf("Init");
mGrid.attach(new Gtk.Button.with_label("X"),0,0,1,1);
});
var box=new Gtk.Box(VERTICAL,0);
mGrid=new Gtk.Grid();
//mGrid.attach(new Gtk.Button.with_label("X"),0,0,1,1);
box.add(init);
box.add(mGrid);
this.add(box);
this.show_all();
}
}
int main(string[] args) {
Gtk.init(ref args);
new MyWindow();
Gtk.main();
return 0;
}
With the GTK+ toolkit widgets are hidden by default. Although you have this.show_all (), the button is created afterwards and is hidden. Changing the callback from:
init.clicked.connect((t)=>{
stdout.printf("Init");
mGrid.attach(new Gtk.Button.with_label("X"),0,0,1,1);
});
to something like:
init.clicked.connect((t)=>{
stdout.printf("Init");
var my_button = new Gtk.Button.with_label("X");
my_button.show_all ();
mGrid.attach(my_button,0,0,1,1);
});
now works.

ckeditor + smartgwt modal window + dialog dropdown gains focus but does not show options

I am using the ckEditor along with GWT and SmartGWT. I have a problem that whenever the ckEditor displays a dialog (e.g. link button, table button), although the items in the dialog gain focus (input texts work fine, I can write inside them), the dropdowns (select elements) when clicking on them, do not expand to show their option items (they expand only when they have focus and user hits "spacebar"). This happens only in firefox and chrome (latest versions) while on IE11 it works as expected.
Note that I am already aware of the "focus" problem existing if a ckEditor instance exists in a GWT/jquery modal and I have already included a fix:
$wnd.CKEDITOR.on('dialogDefinition', function (evt) {
var dialog = evt.data.definition.dialog;
dialog.on('show', function () {
var element = this.getElement();
var labelledby = element.getAttribute('aria-labelledby');
var nativeElement = $wnd.document.querySelector("[aria-labelledby='" + labelledby + "']");
nativeElement.onclick = function (evt) {
if ((evt.target.tagName == "INPUT" || evt.target.tagName == "SELECT" || evt.target.tagName == "TEXTAREA") &&
-1 != evt.target.className.indexOf("cke_dialog_ui_input")) {
evt.target.focus();
};
}
});
});
Any hint how I can make the dropdowns to behave correctly? To me it looks like the dropdown element does not receive the click event (although on click it gets focus) or somehow the event's propagation stops unexpectedly.
EDIT
Forgot to mention that the problem appears if the ckEditor instance is inside a modal SmartGWT window. More specifically if I set
Window win = new Window(); //com.smartgwt.client.widgets.Window
win.setIsModal(false);
and then add the DynamicForm form which contains the ckEditor item on that window then the dialog dropdowns work fine, however if I set
win.setIsModal(true);
I get the faulty behavior described above
In case anyone else has the same problem with me, the solution is to call win.hideClickMask() upon show event of the dialog. This can be achieved in many ways depending on how ckEditor is integrated with SmartGWT. In my implementation this is achieved by overriding onDialogShow() as below:
final CKEditor ckEditor = new CKEditor(conf) {
#Override
public void onDialogShow() {
// to overcome the problem that smartgwt modality obstruct the dropdowns of a ckeditor dialog to be pressed
final NodeList<Element> allWindowsWithModalMask = findAllWindowsWithModalMask();
if(allWindowsWithModalMask != null ) {
for(int i =0; i<allWindowsWithModalMask.getLength(); i++) {
Element el = allWindowsWithModalMask.getItem(i);
String id = el.getAttribute("eventproxy");
if(Canvas.getById(id) != null) {
hideClickMask(Canvas.getById(id).getOrCreateJsObj());
}
}
}
}
};
and
protected native NodeList<Element> findAllWindowsWithModalMask() /*-{
return $wnd.document.querySelectorAll("[class='windowBackground']");
}-*/;
protected native void hideClickMask(JavaScriptObject windowCanvas) /*-{
windowCanvas.hideClickMask();
}-*/;

How to load an accelerators map from a file using GTK3 in Vala?

I'm making a text editor using GTK3 in Vala. I have a Gtk.MenuBar in a Gtk.Window and I want to use accelerators to easily activate its Gtk.MenuItems. But I want the user to be able to change the key combinations, so I'm loading the accelerators specifications from a file using the method Gtk.AccelMap.load("accels"). However, after calling this method, the accelerators are not loaded: the menu items don't have AccelLabels and are not activated when I press the key combinations. Here are the two files I'm working on. The first file contains a small version of my application (to show what I'm trying to do) and the second one is the accels file from which I load the accels specifications, and they must be in the same directory.
main.vala
// Compile me with: valac main.vala -o main --pkg gtk+-3.0
public class MyWindow: Gtk.Window {
public MyWindow() {
this.set_default_size(500, 500);
var main_box = new Gtk.VBox(false, 0);
this.add(main_box);
var accel_group = new Gtk.AccelGroup();
this.add_accel_group(accel_group);
// Load the accelerators from the file
Gtk.AccelMap.load("accels");
// Create the action
var quit_action = new Gtk.Action("file-quit", "Quit", "Quit the application", null);
quit_action.activate.connect(()=>{
Gtk.main_quit();
});
quit_action.set_accel_group(accel_group);
quit_action.set_accel_path("<MyWindow>/File/Quit");
// Menubar
var menubar = new Gtk.MenuBar();
main_box.pack_start(menubar, false, false, 0);
var file = new Gtk.MenuItem.with_label("File");
menubar.add(file);
var file_menu = new Gtk.Menu();
file.set_submenu(file_menu);
var quit_mi = (Gtk.MenuItem)quit_action.create_menu_item();
file_menu.append(quit_mi);
// Label
var label = new Gtk.Label("My Window");
main_box.pack_start(label, true, true, 0);
this.destroy.connect(Gtk.main_quit);
}
}
int main(string[] args) {
Gtk.init(ref args);
var win = new MyWindow();
win.show_all();
Gtk.main();
return 0;
}
"accels" file
; main GtkAccelMap rc-file -*- scheme -*-
; this file is an automated accelerator map dump
;
; (gtk_accel_path "<MyWindow>/File/Quit" "<Control>q")
So, why is this not working? What do I have to do before or after loading the accel file?
PS: I don't want to use a Gtk.UIManager.
See : https://docs.xfce.org/faq#keyboard_related
"
This functionality has been disabled since GTK3 which means that Xfce apps that have migrated to GTK3 (such as xfce4-terminal) do not support it.
Refer to specific app's documentation to learn how to configure its shortcuts.
"