static void gui_get_screen_size(GtkLayout* screen, gint* width, gint* height) { if(screen == NULL) { *width = gdk_screen_width(); *height = gdk_screen_height(); } else { gtk_layout_get_size(screen, (guint*)width, (guint*)height); } }
int gui_height(GtkLayout* screen) { if(screen) { guint width; guint height; gtk_layout_get_size(screen, &width, &height); return (int)height; } else { return gdk_screen_height(); } }
int clip_GTK_LAYOUTGETSIZE(ClipMachine * cm) { C_widget *clay = _fetch_cw_arg(cm); guint width; guint height; CHECKCWID(clay,GTK_IS_LAYOUT); gtk_layout_get_size(GTK_LAYOUT(clay->widget), &width, &height); _clip_storni(cm, width , 2, 0); _clip_storni(cm, height, 3, 0); return 0; err: return 1; }
gboolean FloatingWindow::on_status_bar_motion_notify (GdkEventMotion *event) { if (resizing_window) { gw_destroy_source (resize_event_id); resize_event_id = g_timeout_add_full(G_PRIORITY_DEFAULT, 200, GSourceFunc(on_resize_timeout), gpointer(this), NULL); gtk_widget_hide (vbox_client); guint layout_width, layout_height; gtk_layout_get_size (GTK_LAYOUT (layout), &layout_width, &layout_height); gint event_x = event->x_root; gint event_y = event->y_root; if (previous_root_x >= 0) { bool resize_box = false; if (event_x != previous_root_x) { guint new_width = my_gdk_rectangle.width + event_x - previous_root_x; // Window should not become too narrow, or too wide for the screen. if (new_width >= 100) { if ((my_gdk_rectangle.x + new_width) <= layout_width) { my_gdk_rectangle.width = new_width; resize_box = true; } } } if (event_y != previous_root_y) { guint new_height = my_gdk_rectangle.height + event_y - previous_root_y; // Window should not become too short, or too tall for the screen. if (new_height >= 100) { if ((my_gdk_rectangle.y + new_height) <= layout_height) { my_gdk_rectangle.height = new_height; resize_box = true; } } } if (resize_box) { gtk_widget_set_size_request (vbox_window, my_gdk_rectangle.width, my_gdk_rectangle.height); } } previous_root_x = event_x; previous_root_y = event_y; } return false; }
gboolean FloatingWindow::on_title_bar_motion_notify (GdkEventMotion *event) { if (dragging_window) { guint layout_width, layout_height; gtk_layout_get_size (GTK_LAYOUT (layout), &layout_width, &layout_height); gint event_x = event->x_root; gint event_y = event->y_root; if (previous_root_x >= 0) { bool move_box = false; if (event_x != previous_root_x) { guint new_x = my_gdk_rectangle.x + event_x - previous_root_x; // The window does not move beyond the left or right side if (new_x >= 0) { if ((new_x + my_gdk_rectangle.width) <= layout_width) { my_gdk_rectangle.x = new_x; move_box = true; } } } if (event_y != previous_root_y) { guint new_y = my_gdk_rectangle.y + event_y - previous_root_y; // The window does not move beyond the top or bottom. if (new_y >= 0) { if ((new_y + my_gdk_rectangle.height) <= layout_height) { my_gdk_rectangle.y = new_y; move_box = true; } } } if (move_box) { rectangle_set (my_gdk_rectangle); } } previous_root_x = event_x; previous_root_y = event_y; } return false; }
void FloatingWindow::display(bool startup) // Does the bookkeeping necessary for displaying the floating box. // startup: whether the box is started at program startup. { // Settings. extern Settings *settings; // The parameters of all the windows. WindowData window_parameters(false); // Clear the new window's position. my_gdk_rectangle.x = 0; my_gdk_rectangle.y = 0; my_gdk_rectangle.width = 0; my_gdk_rectangle.height = 0; // At program startup extract the position and size of the window from the general configuration. // It does not matter whether the space for the window is already taken up by another window, // because the user wishes to use the coordinates that he has set for this window. for (unsigned int i = 0; i < window_parameters.widths.size(); i++) { if ((window_parameters.ids[i] == window_id) && (window_parameters.titles[i] == title) && startup) { my_gdk_rectangle.x = window_parameters.x_positions[i]; my_gdk_rectangle.y = window_parameters.y_positions[i]; my_gdk_rectangle.width = window_parameters.widths[i]; my_gdk_rectangle.height = window_parameters.heights[i]; } } // Reject zero width and zero height values on startup. if ((my_gdk_rectangle.width == 0) || (my_gdk_rectangle.height == 0)) startup = false; // When a new window needs to be allocated, there are a few steps to be taken. if (!startup) { // Step 1: The area rectangle where the window should fit in is defined. GdkRectangle area_rectangle; area_rectangle.x = 0; area_rectangle.y = 0; area_rectangle.width = 0; area_rectangle.height = 0; { guint width, height; gtk_layout_get_size (GTK_LAYOUT (layout), &width, &height); area_rectangle.width = width; area_rectangle.height = height; } // Step 2: An available region is made of that whole area. GdkRegion *available_region = gdk_region_rectangle(&area_rectangle); // Step 3: The regions of each of the open windows is substracted from the available region. for (unsigned int i = 0; i < settings->session.open_floating_windows.size(); i++) { FloatingWindow * floating_window = (FloatingWindow *) settings->session.open_floating_windows[i]; GdkRectangle rectangle = floating_window->rectangle_get(); GdkRegion *region = gdk_region_rectangle(&rectangle); gdk_region_subtract(available_region, region); gdk_region_destroy(region); } // Step 4: The rectangles that the area region consists of are requested, // and the biggest suitable rectangle is chosen for the window. // A rectangle is considered suitable if it has at least 10% of the width, and 10% of the height of the area rectangle. GdkRectangle *gdk_rectangles = NULL; gint rectangle_count = 0; gdk_region_get_rectangles(available_region, &gdk_rectangles, &rectangle_count); for (int i = 0; i < rectangle_count; ++i) { GdkRectangle & rectangle = gdk_rectangles[i]; if (rectangle.width >= (area_rectangle.width / 10)) { if (rectangle.height >= (area_rectangle.height / 10)) { if ((rectangle.width * rectangle.height) > (my_gdk_rectangle.width * my_gdk_rectangle.height)) { my_gdk_rectangle = rectangle; } } } } g_free(gdk_rectangles); // Step 5: The available region is destroyed. gdk_region_destroy(available_region); // Step 6: If no area big enough is found, then the window that takes most space in the area is chosen, // the longest side is halved, and the new window is put in that freed area. if ((my_gdk_rectangle.width == 0) || (my_gdk_rectangle.height == 0)) { FloatingWindow * resize_window_pointer = NULL; int largest_size = 0; for (unsigned int i = 0; i < settings->session.open_floating_windows.size(); i++) { FloatingWindow *floating_window = (FloatingWindow *) settings->session.open_floating_windows[i]; GdkRectangle rectangle = floating_window->rectangle_get (); int size = rectangle.width * rectangle.height; if (size > largest_size) { resize_window_pointer = floating_window; largest_size = size; } } if (resize_window_pointer) { GdkRectangle resize_window_rectangle = resize_window_pointer->rectangle_get(); my_gdk_rectangle = resize_window_pointer->rectangle_get(); if (resize_window_rectangle.width > resize_window_rectangle.height) { resize_window_rectangle.width /= 2; my_gdk_rectangle.width /= 2; my_gdk_rectangle.x += resize_window_rectangle.width; } else { resize_window_rectangle.height /= 2; my_gdk_rectangle.height /= 2; my_gdk_rectangle.y += resize_window_rectangle.height; } resize_window_pointer->rectangle_set (resize_window_rectangle); } } } // Add the window to the layout and set its position and size. gtk_layout_put (GTK_LAYOUT (layout), vbox_window, my_gdk_rectangle.x, my_gdk_rectangle.y); rectangle_set (my_gdk_rectangle); // Store a pointer to this window in the Session. settings->session.open_floating_windows.push_back(gpointer (this)); }