/** * @brief 初始化窗口管理器图形相关 * * @param framebuffer_path framebuffer设备路径 * @param top_margin 配置项 屏幕上方留白的像素 * @param down_margin 配置项 屏幕下方留白的像素 * @param left_margin 配置项 屏幕左方留白的像素 * @param right_margin 配置项 屏幕右方留白的像素 * * @return 成功返回0 否则返回-1 **/ static si_t graph_init(char* framebuffer_path, si_t top_margin, si_t down_margin, si_t left_margin, si_t right_margin) { struct graphics_device* gd_ptr = NULL; /* 初始化屏幕 */ screen_init(framebuffer_path); /* 设置颜色的限制 */ screen_color_limit(); /** * 初始化窗口管理器的图形设备 **/ global_wm.gd_handler = engine_graphics_device_init(0, 0, global_screen.width, global_screen.height, 0,0,0,0,0); if(0 == global_wm.gd_handler) { EGUI_PRINT_ERROR("failed to init window manager graph device."); return -1; } gd_ptr = (struct graphics_device*)global_wm.gd_handler; gd_ptr->screen.memory_addr = global_screen.memory_addr; gd_ptr->screen.buffer_addr = NULL; gd_ptr->screen.video_access_mode = VIDEO_ACCESS_MODE_DIRECT; /** * 初始化窗口区域 **/ rectangle_set(&global_wm.work_area, 0 + left_margin, 0 + top_margin, global_screen.width - left_margin - right_margin, global_screen.height - top_margin - down_margin); /** 绘制桌面 **/ engine_set_color(global_wm.gd_handler, global_wm.backcolor.r, global_wm.backcolor.g, global_wm.backcolor.b, global_wm.backcolor.a); engine_fill_rectangle(global_wm.gd_handler, global_wm.work_area.x, global_wm.work_area.y, global_wm.work_area.width, global_wm.work_area.height); return 0; }
extern si_t send_widget_resize_message(struct egui_uds* uds_ptr, union message* msg, si_t window_descripter, si_t x_axis, si_t y_axis, si_t x_size, si_t y_size) { union message msg_to_be_sent; struct rectangle area = {0}; copy_message(msg, &msg_to_be_sent); rectangle_set(&area, x_axis, y_axis, x_size, y_size); message_set_widget_resize(&msg_to_be_sent, window_descripter, &area); return comm_send_message(uds_ptr, &msg_to_be_sent); }
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 window_info_resize(struct window_info* win_info_ptr, si_t x, si_t y, si_t w, si_t h) { /* 窗口区域 */ rectangle_set(&win_info_ptr->area, x - frame_size, y - frame_size - title_bar_size, w + 2 * frame_size, h + 2 * frame_size + title_bar_size); /* 用户工作区域 */ rectangle_set(&win_info_ptr->work_area, x, y, w, h); /* 菜单按钮区域 */ rectangle_set(&win_info_ptr->menu_button_area, x, y - title_bar_size, title_bar_size, title_bar_size); /* 标题栏区域 */ rectangle_set(&win_info_ptr->title_bar_area, x + title_bar_size, y - title_bar_size, w - 2 * title_bar_size, title_bar_size); /* 最小化按钮区域 */ if(win_info_ptr->minimize_enable == 1) { rectangle_set(&win_info_ptr->minimize_button_area, x + w - 3 * title_bar_size, y - title_bar_size, title_bar_size, title_bar_size); win_info_ptr->title_bar_area.width -= title_bar_size; } /* 最大化按钮区域 */ if(win_info_ptr->maximize_enable == 1) { rectangle_set(&win_info_ptr->maximize_button_area, x + w - 2 * title_bar_size, y - title_bar_size, title_bar_size, title_bar_size); win_info_ptr->title_bar_area.width -= title_bar_size; } /* 退出按钮区域 */ rectangle_set(&win_info_ptr->close_button_area, x + w - title_bar_size, y - title_bar_size, title_bar_size, title_bar_size); }
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)); }