i want to change default close, maximize, minimize buttons' icon. So i need to get default buttons.
In gtk3, i used gtk_header_bar_set_show_close_button to enable default button, and used gtk_container_get_children(header_bar) to get children widget
GtkWidget *header_bar = gtk_header_bar_new();
gtk_header_bar_set_has_subtitle(GTK_HEADER_BAR(header_bar), FALSE);
gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(header_bar), TRUE);
gtk_window_set_titlebar(GTK_WINDOW(window), header_bar);
GList *children = gtk_container_get_children(header_bar);
if(children == NULL) {
exit(-1);
}
GList *children always is NULL.
How can I get it like gtk inspector?
gtk inscpector screenshot
Resolve:
should use gtk_container_forall to get "internal" children
Related
I'm testing an non-e4 RCP application using SWTBot and I need to change the size of my view. (Move the sash-bar)
I unsuccessfully tried
Resize my view using SWTBot (no such api)
Resize my view using Eclipse 3 API (no supported)
Resize my view using underlying e4 model (resizing not working)
e4 model seams to be promising, but I'm missing something, so it doesn't work.
I can
Get MPart of my view: view = ePartService.findPart(ID)
Get MTrimmedWindow: window = (view as EObject).eContainer as MTrimmedWindow
I can't
locale correct MPartSashContainer
move sash-bar with setContainerData()
I would like to know
How can I move from MPart to its direct parent (e.g. MPartStack)
Why common EObject methods like eContainer() are not present on M... objects?
Ok, I found a solution myself.
The thing is, that the view is not a part of the e4 UI-Tree. view.eContainer is directly the MWindow. To be placed at the right spot the view is connected to the MPlaceholder, that is a part of the e4 UI-Tree and has getParent() != null.
In order to resize a view the steps are:
Show view
Find MPlaceholder of the view
Find MPartStack and `MPartSashContainer´ object
Set containerData
Redraw widget (yes, auto-update seam not to work in this case)
Example:
EModelService modelService = PlatformUI.getWorkbench().getService(EModelService.class);
EPartService partService = PlatformUI.getWorkbench().getService(EPartService.class);
// Show view
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
page.showView(MyView.ID, null, IWorkbenchPage.VIEW_ACTIVATE);
MPart view = partService.findPart(MyView.ID);
// view.getParent() => null, because 'view' is not a part of the e4 UI-model!
// It is connected to the Model using MPlaceholder
// Let's find the placeholder
MWindow window = (MWindow)(((EObject)eView).eContainer);
MPlaceholder placeholder = modelService.findPlaceholderFor(window, view);
MUIElement element = placeholder;
MPartStack partStack = null;
while (element != null) {
// This may not suite your configuration of views/stacks/sashes
if (element instanceof MPartStack && ((Object)element.parent) instanceof MPartSashContainer) {
partStack = (MPartStack)element;
break;
}
element = element.parent;
}
}
if (partStack == null) { /* handle error */ }
// Now let's change the width weights
for (MUIElement element : partStack.getParent().getChildren()) {
if (element == partStack) {
element.setContainerData("50"); // Width for my view
} else {
element.setContainerData("25"); // Widths for other views & editors
}
}
// Surprisingly I had to redraw tho UI manually
// There is for sure a better way to do it. Here is my (quick & very dirty):
partStack.toBeRendered = false
partStack.toBeRendered = true
I am using a Gtk EventBox which holds an image to receive mouse click events on the image. Once the image is clicked, the EventBox is set insensitive. However, since this results in the EventBox being "grayed out", the colors of my image become pale as well. I really don't like this. Is there any way to disable this kind of behaviour of Gtk widgets?
Code example:
var ebox = new EventBox ();
var img = new Image ();
img.set_from_file ("my_image.png");
img.show ();
ebox.add (img);
ebox.button_press_event.connect ( () => { ebox.set_sensitive (false); return true; } );
you could subclass the widget, add a virtual method do_draw(), and draw your image there.
Currently in my application I'm grabing the pointer to know when user clicks outside of some of my first window's widgets to hide my second window. Unfortunately if I grab the pointer then user needs to click outside of my application twice to set focus on another window.
When window gets focus I grab the pointer:
this.focus_in_event.connect(()=>{
var pointer = Gdk.Display.get_default ().get_device_manager ().get_client_pointer ();
pointer.grab (this.get_window (), Gdk.GrabOwnership.NONE, true,
Gdk.EventMask.BUTTON_PRESS_MASK, null, Gdk.CURRENT_TIME);
Gtk.device_grab_add (this, pointer, false);
return false;
});
When a click events occurs and some of window's widgets didn't 'lock' the pointer:
this.button_press_event.connect ( ()=>{
if (!lock_mouse_click) {
var pointer = Gdk.Display.get_default ().get_device_manager ().get_client_pointer ();
Gtk.device_grab_remove (this, pointer);
pointer.ungrab (Gdk.CURRENT_TIME);
feed_view.hide ();
}
lock_mouse_click = false;
return false;
});
What I would like to do is to "peek" at the pointer instead of stealing the mouse events outside of my application.
My code in vala but you may answer me in any language that uses gtk.
why dont you use "enter-notify-signal" ? when apointer enter your widget's window, create a on/off switch somewhere and use it in "button-press-signal". if its on when button is pressed do somethin, if its off do something else
So I have a cell table with click event selection model working fine.
I later found out you can press UP and DOWN arrows to get the highlighted row to change, but the awful thing is you have to press Space for it to actually call the SelectionChangeEvent.
I am trying to cheat my way a little, by catching the UP and DOWN events and firing the SPACE event. Sadly it doesn't work :(
Here is my code any help would be appreciated!
table.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
table.sinkEvents(Event.KEYUP);
table.sinkEvents(Event.KEYDOWN);
table.sinkEvents(32);
table.addHandler(new KeyUpHandler(){
#Override
public void onKeyUp(KeyUpEvent event)
{
System.out.println(event.getNativeKeyCode());
if(event.getNativeEvent().getKeyCode() == 40)
{
// down is pressed
int i = rows.getFilterList().indexOf(selectionModel.getLastSelectedObject())+1;
if(i >= 0 && i < rows.getFilterList().size())
{
// selectionModel.setSelected(selectionModel.getLastSelectedObject(), false);
// selectionModel.setSelected(rows.getFilterList().get(i), true);
// SelectionChangeEvent.fire(selectionModel);
System.out.println("firing native event space");
DomEvent.fireNativeEvent(Document.get().createKeyUpEvent(false, false, false, false, 32), table);
}
}
else if(event.getNativeEvent().getKeyCode() == 38)
{
// up is pressed
int i = rows.getFilterList().indexOf(selectionModel.getLastSelectedObject())-1;
if(i >= 0 && i < rows.getFilterList().size())
{
// selectionModel.setSelected(selectionModel.getLastSelectedObject(), false);
// selectionModel.setSelected(rows.getFilterList().get(i), true);
// SelectionChangeEvent.fire(selectionModel);
System.out.println("firing native event space");
DomEvent.fireNativeEvent(Document.get().createKeyUpEvent(false, false, false, false, 32), table);
}
}
}
}, KeyUpEvent.getType());
32 is assumingly the NativeEvent for space, my console prints something like:
40
firing native event space
32
so assumingly the event type 32 is being called for the object table.
I check if the object is selected, because on the right hand side of the screen I have additional information being pulled out from a list, since the cell table doesn't show all the information. I want it so when I press UP and DOWN the RHS information changes and I dont have to press SPACE to prompt the info change
Ideally you would poke into the selection internals. Specifically the DefaultKeyboardSelectionHandler is the default implementation of keyboard navigation and the DefaultSelectionEventManager is the default implementation of selection actions using spacebar/clicks (they are both CellPreviewEvent.Handlers).
Anyway, you can force the keyboard selection to be bound to the underlying SelectionModel by using setKeyboardSelectionPolicy(KeyboardSelectionPolicy.BOUND_TO_SELECTION). It should be fine for your use case. Much like what is done for the CellList showcase sample (the selection API is the same across cell widgets).
I have a crossplatform app that has a gtk.StatusIcon sitting in the tray, and a right click context menu. The problem is: on Windows machines the placement of the menu is awful. The top of the menu starts at the mouse pointer and so most of the menu extends below the bottom of the screen. This can then be scrolled up and is usable, but it is a bit of a pain for the user.
Another related question, is it possible to make the menu disappear if the user clicks somewhere else on the screen?
To avoid this "scrolling menu" problem on Windows you need to replace gtk.status_icon_position_menu with None in "popup-menu" signal callback.
def popup_menu_cb(status_icon, button, activate_time, menu):
menu.popup(None, None, None, button, activate_time)
The menu will show on the mouse cursor but that's how all windows programs do it.
Don't know how to hide it though... the only thing I found to work is pressing a mouse button on the menu and releasing it outside. :P
You can hide the popup when the mouse moves away by enabling the leave_notify and enter_notify events on the popup. Then use these to set and clear a time stamp. Then in a timer callback created with gobject.timeout_add() check to see if the mouse has been away from the popup menu for a certain amount of time. If it has then hide() the popup and clear the timer.
Here are the event and timer call backs I'm using:
. . .
self.mouse_in_tray_menu = None
gobject.timeout_add(500, self.check_hide_popup)
. . .
def on_tray_menu_enter_notify_event(self, widget, event, data = None):
self.mouse_in_tray_menu = None
def on_tray_menu_leave_notify_event(self, widget, event, data = None):
self.mouse_in_tray_menu = event.time + 1 # Timeout in 1 sec
def check_hide_popup(self, data = None):
if self.mouse_in_tray_menu and self.mouse_in_tray_menu < time.time():
self.tray_menu.hide()
self.mouse_in_tray_menu = None
return True # Keep the timer callback running
You don't have to keep the timer running all the time but it is easier and I am also using it for other things. The calls to enter_notify and leave_notify are somewhat erratic so the timer is necessary.
BTW, this is really only necessary in Windows because in Linux you can click elsewhere and the popup will close.
I found a solution to fix the popup menu won't hide problem on windows.
Just add following code (my code is in C but you can change it to python or whatever) before popping up the menu:
GtkWidget *hidden_window;
hidden_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_resizable (GTK_WINDOW (hidden_window), FALSE);
gtk_window_set_decorated (GTK_WINDOW (hidden_window), FALSE);
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (hidden_window), TRUE);
gtk_window_set_skip_pager_hint (GTK_WINDOW (hidden_window), TRUE);
gtk_widget_set_size_request (hidden_window, 0, 0);
gtk_window_set_transient_for (GTK_WINDOW (hidden_window), GTK_WINDOW (widget)); //widget is your main window, this is to hide dummy window from taskbar
gtk_window_set_position (GTK_WINDOW (hidden_window), GTK_WIN_POS_MOUSE);
gtk_widget_set_events (hidden_window, GDK_FOCUS_CHANGE_MASK);
g_signal_connect (G_OBJECT (hidden_window),
"focus-out-event",
G_CALLBACK (on_hidden_window_focus_out),
NULL);
gtk_widget_show_all (hidden_window);
gtk_widget_grab_focus (hidden_window);
also add this function:
static void on_hidden_window_focus_out(GtkWidget *widget,
GdkEventFocus *event,
gpointer data)
{
gtk_widget_destroy (widget);
}
The idea is to create a 1x1 top level window at mouse position and grab the focus, and add destroy function when focus out.