How to prevent GtkWindow growing? - c

This is my codes:
#include<gtk/gtk.h>
int main(int argc,char**argv)
{
GtkWidget* window, *button, *grid;
gtk_init(&argc,&argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window),100,100);
g_signal_connect(G_OBJECT(window),"destroy",G_CALLBACK(gtk_main_quit),NULL);
//gtk_container_set_border_width(GTK_CONTAINER(window),10);
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
grid = gtk_grid_new();
button = gtk_button_new_with_label("1");
gtk_grid_attach(GTK_GRID(grid), button, 0,0, 100, 1);
gtk_grid_set_column_homogeneous(GTK_GRID(grid), TRUE);
gtk_grid_set_row_homogeneous(GTK_GRID(grid), TRUE);
button = gtk_button_new_with_label("1");
gtk_grid_attach(GTK_GRID(grid), button,0, 1, 10, 1);
gtk_container_add(GTK_CONTAINER(window), grid);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
the result of this codes is :
gtk_grid_attach(GTK_GRID(grid), button,0, 1, 100, 1)
When I change gtk_grid_attach(GTK_GRID(grid), button,0, 1, 100, 1) to gtk_grid_attach(GTK_GRID(grid), button,0, 1, 200, 1)
Then the result of this code is:
gtk_grid_attach(GTK_GRID(grid), button,0, 1, 200, 1)
Why does the width of window increase? I find that the size of window may be varied with the function gtk_grid_attach(). So how to solve it?

Why does the width of window increase?
You have used
gtk_grid_set_column_homogeneous(GTK_GRID(grid), TRUE);
gtk_grid_set_row_homogeneous(GTK_GRID(grid), TRUE);
Which means that each cell in the grid will have equal width and height, which will be the same as the largest widget embedded. So If you have more cells, the grid will grow further and thus the window width increases
I find that the size of window may be varied with the function gtk_grid_attach(). So how to solve it?
I don't know what's your usecase is. But you could unset the homogeneous properties and/or use a real grid width and height when attaching children.

Related

Xlib: resize window containing a pixmap

Related to how-to-resize-a-pixmap-with-xlib.
As it was concluded in the abovementioned topic, it's impossible to resize a pixmap. What about window, after pixmap is copied into it? In the example below, everything is good up to the point where the window is being resized. The icon is drawn after it's copied into the window, but is lost after the window is resized. Am I missing something here or there really is no way whatsoever to resize pixmap content?
Context: trying to add the client icons into the tabs for the dwm's tab patch.
unsigned int px_w, px_h, dummy_i;
Window icon_w, dummy_w;
Pixmap getWindowIcon (Window *w) {
XWMHints *wmh;
Pixmap pxmp = NULL;
if(wmh = XGetWMHints(dpy, w)) {
pxmp = wmh->icon_pixmap;
XFree(wmh);
}
return pxmp;
}
Pixmap client_icon = getWindowIcon(current_window); // current_window is already existing Window instance
// find the pixmap dimensions and store in px_w, px_h:
XGetGeometry(dpy, client_icon, &dummy_w, &dummy_i, &dummy_i, &px_w, &px_h, &dummy_i, &dummy_i );
icon_w = XCreateSimpleWindow(dpy, root_window, 0, 0, px_w, px_h, 0, 0, color);
XMapRaised(dpy, icon_w);
// copy pixmap to the newly created win:
XCopyArea(dpy, client_icon, icon_w, cellDC.gc, 0, 0, px_w, px_h, 0, 0);
// resize - after which the pixmap is lost in the window:
XResizeWindow(dpy, icon_w, px_w+1, px_h+1);

Setting the size of gtk scale

I've got problems with gtk scale.
I've got fixed widget where I placed horizontal scale. The problem is that the scale is very small and I don't know how to resize it to for example 100 pixels.
Below is my code:
wind = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(wind), 300, 300);
fixed = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(wind), fixed);
button = gtk_button_new_with_label("button1");
gtk_fixed_put(GTK_FIXED(fixed), button, 10, 20);
button2 = gtk_button_new_with_label("button2");
gtk_fixed_put(GTK_FIXED(fixed), button2, 200, 20);
scale = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0, 100, 1);
gtk_fixed_put(GTK_FIXED(fixed), scale, 100, 40);
and here is how it looks like:
The scale is in the middle of the window and shows 0 value.
Ok, I found the solution by myself:
g_object_set(scale, "width-request", 200, NULL);

Trying to populate a GtkComboBox with model in C

I'm really new to C and GTK+ so my problem might be painfully obvious. I have tried to follow examples and tutorials found all over the net.
I want a combo box with three values, the middle one being the default. I can successfully set it up using Glade but I have decided to rewrite everything in C. The combobox is drawn but it is empty/blank. I don't know what I am doing wrong.
...
GtkTreeIter iter;
GtkListStore *liststore;
GtkWidget *combo;
liststore = gtk_list_store_new(1, G_TYPE_STRING);
gtk_list_store_insert_with_values (liststore, &iter, 0, 0, "Don't install.", -1);
gtk_list_store_insert_with_values (liststore, &iter, 1, 0, "This user only.", -1);
gtk_list_store_insert_with_values (liststore, &iter, 2, 0, "All users.", -1);
combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(liststore));
gtk_combo_box_set_active (GTK_COMBO_BOX(combo), 1);
...
gtk_grid_attach (GTK_GRID(grid), combo, 2, 4, 1, 1);
...
In your original code you correctly bound the data model to the combo box but you did not specified how the model should be presented (that is the view part of the whole model-view concept). This is what the GtkCellLayout is supposed to provide.
To give you an idea on why this added complexity is useful, here is an example that shows how to use the model to have custom background (this is bad UX and, depending on your theme, the background color can be totally ignored). I think the most difficult thing is avoiding memory leaks, so I added some comment on this regard:
#include <gtk/gtk.h>
int main(int argc, char **argv)
{
GtkWidget *window;
GtkListStore *liststore;
GtkWidget *combo;
GtkCellRenderer *column;
gtk_init(&argc, &argv);
liststore = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
gtk_list_store_insert_with_values(liststore, NULL, -1,
0, "red",
1, "Don't install.",
-1);
gtk_list_store_insert_with_values(liststore, NULL, -1,
0, "green",
1, "This user only.",
-1);
gtk_list_store_insert_with_values(liststore, NULL, -1,
0, "yellow",
1, "All users.",
-1);
combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(liststore));
/* liststore is now owned by combo, so the initial reference can
* be dropped */
g_object_unref(liststore);
column = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), column, TRUE);
/* column does not need to be g_object_unref()ed because it
* is GInitiallyUnowned and the floating reference has been
* passed to combo by the gtk_cell_layout_pack_start() call. */
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), column,
"cell-background", 0,
"text", 1,
NULL);
gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 1);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_container_add(GTK_CONTAINER(window), combo);
/* Also combo is GInitiallyUnowned and it is now owned
by window after the gtk_container_add() call. */
gtk_widget_show_all(window);
gtk_main();
return 0;
}
But if you intend to use only strings in your combo box, the code can be stripped down by leveraging GtkComboBoxText:
#include <gtk/gtk.h>
int main(int argc, char **argv)
{
GtkWidget *window, *combo;
gtk_init(&argc, &argv);
combo = gtk_combo_box_text_new();
gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), NULL, "Don't install.");
gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), NULL, "This user only.");
gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), NULL, "All users");
gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 1);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_container_add(GTK_CONTAINER(window), combo);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
I think I found the solution.
I had to insert a cell renderer into the combo box. I added this code between creating the combobox and setting the default active value.
GtkCellRenderer *combocell = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(combo), combocell, TRUE );
gtk_cell_layout_set_attributes( GTK_CELL_LAYOUT(combo), combocell, "text", 0, NULL );
I still don't understand this and I have no idea what attributes are suppose to go with GtkCellLayout or how they work. Any supplemental reading would greatly be appreciated.

GTK and scrolling text view

This is what I have so far
GtkWidget* createConsoleBox()
{
GtkWidget* textArea = gtk_text_view_new();
GtkWidget* scrollbar = gtk_vscrollbar_new(gtk_text_view_get_vadjustment(GTK_TEXT_VIEW(textArea)));
GtkWidget* textEntry = gtk_entry_new();
GtkWidget* console = gtk_table_new(3, 2, FALSE);
gtk_table_attach_defaults(GTK_TABLE(console), textArea, 0, 1, 0, 1);
gtk_table_attach_defaults(GTK_TABLE(console), scrollbar, 1, 2, 0, 1);
gtk_table_attach_defaults(GTK_TABLE(console), textEntry, 0, 2, 1, 2);
return console;
}
I want the text view to be scrollable as the text begins to fill the box, but the box keeps on expanding to accommodate more text. How to do I limit the size of the text view and create a scrollable text view.
Thanks in advance :-)
I'm afraid you've misunderstood how scrollbars work in GTK; usually you don't create a scrollbar directly, but you place the widget you would like to scroll in a GtkScrolledWindow. This creates scrollbars automatically and connects them to the widget inside the scrolled window; in your case, the text view.
Here's what your createConsoleBox() function should look like:
GtkWidget* createConsoleBox()
{
GtkWidget* textArea = gtk_text_view_new();
GtkWidget* scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
GtkWidget* textEntry = gtk_entry_new();
GtkWidget* console = gtk_table_new(3, 1, FALSE);
gtk_container_add(GTK_CONTAINER(scrolledwindow), textArea);
gtk_table_attach_defaults(GTK_TABLE(console), scrolledwindow, 0, 1, 0, 1);
gtk_table_attach_defaults(GTK_TABLE(console), textEntry, 0, 1, 1, 2);
return console;
}
What you experience is the result of the widget asking more space to its parent container.
Unless the parent container has some rules forbidding the expansion, it will give as much space as child widget asks.
A common way to avoid this is to set a given size for the child widget with gtk_widget_set_size_request(), followed by some way to make sure the parent can give shrink or grow, depending on the parent properties.
This sample code show one way to accomplish this.
#include <gtk/gtk.h>
GtkWidget* createConsoleBox()
{
GtkWidget* textArea = gtk_text_view_new();
GtkWidget* scrollbar= gtk_vscrollbar_new(gtk_text_view_get_vadjustment(GTK_TEXT_VIEW(textArea)));
GtkWidget* textEntry = gtk_entry_new();
GtkWidget* console = gtk_table_new(3, 2, FALSE);
gtk_table_attach_defaults(GTK_TABLE(console), textArea, 0, 1, 0, 1);
gtk_table_attach_defaults(GTK_TABLE(console), scrollbar, 1, 2, 0, 1);
gtk_table_attach_defaults(GTK_TABLE(console), textEntry, 0, 2, 1, 2);
//This code sets the preferred size for the widget, so it does not ask for extra space
gtk_widget_set_size_request(textArea, 320, 240);
return console;
}
int main(int argc,char* argv[]){
GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Simple Sample");
gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);// does not matter this size
gtk_container_add(GTK_CONTAINER(window), createConsoleBox());
gtk_widget_show_all(window);
gtk_window_set_resizable(GTK_WINDOW(window),FALSE);//because of this
gtk_main();
return 0;
}
gtk_window_set_resizable() is meant to make the window un-resizeable by the user (the App can still resize it), but has the extra propertie of tighting up the window to the size of its child widget. Each GtkContainer has it way of setting up expansion, tighness, etc. Is only matter of experimentation to find the right one for your needs.
If the window resizable property had been set to TRUE, the textarea would still have the given size for it, the container would just put a lot of extra space between the individual widgets inside the GtkTable.

GtkStatusIcon drawing issue

i'm using gtk+-2.0 in C. and i have to write a digit upon my tray icon. i do it such way:
static GdkPixbuf * transform_pixbuf(GdkPixbuf *pixbuf) {
cairo_t *cr;
int width = gdk_pixbuf_get_width(pixbuf);
int height = gdk_pixbuf_get_height(pixbuf);
GdkPixmap *pixmap = gdk_pixmap_new(NULL, width, height, 24);
cr = gdk_cairo_create(pixmap);
gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
cairo_paint(cr);
cairo_select_font_face (cr, "serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
cairo_set_font_size (cr, 15.0);
cairo_set_source_rgb (cr, 1.0, 0, 0);
cairo_move_to (cr, 10, 20);
cairo_show_text (cr, "8");
cairo_destroy(cr);
GdkPixbuf *pixbuf_new = gdk_pixbuf_get_from_drawable(NULL, pixmap, NULL,
0, 0, 0, 0, width, height);
return pixbuf_new;
}
where GdkPixbuf *pixbuf is GdkPixbuf i want to set in tray. i can draw a digit, but the icon's background became "dancing" - .
i guess the problem is in gdk_pixmap_new's depth argument, because the icon has 32bit format, but 32 isn't valid argument for this function. in such case i have followin warning and no icon in the tray:
Gdk-WARNING **: Using Cairo rendering requires the drawable argument to
have a specified colormap. All windows have a colormap,
however, pixmaps only have colormap by default if they
were created with a non-NULL window argument. Otherwise
a colormap must be set on them with gdk_drawable_set_colormap
Gdk-WARNING **: /build/buildd/gtk+2.0-2.24.4/gdk/gdkpixbuf-drawable.c:1249: Source drawable has no colormap; either pass in a colormap, or set the colormap on the drawable with gdk_drawable_set_colormap()
Suggest me, please...
i've solved my problem with workaround. the problem was in creating pixmap - it was "dirty" from it's "born". the solution is in to not use pixmap, but create cairo context via the functions: http://www.gtkforums.com/viewtopic.php?t=5204

Resources