#include "osgui_gtk.inl"
#include "oscontrol_gtk.inl"
#include "osbutton_gtk.inl"
#include "oscombo_gtk.inl"
#include "osedit_gtk.inl"
#include "osglobals_gtk.inl"
#include "osmenu_gtk.inl"
#include "ospanel_gtk.inl"
#include "oswindow_gtk.inl"
#include "../oswindow.h"
#include "../oswindow.inl"
#include "../oscontrol.inl"
#include "../ostabstop.inl"
#include <core/arrpt.h>
#include <core/arrst.h>
#include <core/event.h>
#include <core/heap.h>
#include <sewer/cassert.h>
#if !defined(__GTK3__)
#error This file is only for GTK Toolkit
#endif
struct _oswindow_t
{
OSControl control;
OSMenu *menu;
GMainLoop *runloop;
uint32_t modal_return;
uint32_t flags;
gui_role_t role;
GtkAccelGroup *accel;
OSPanel *main_panel;
gint signal_delete;
gint signal_config;
gint signal_keypre;
gint signal_keyrel;
gint signal_state;
Listener *OnMoved;
Listener *OnResize;
Listener *OnClose;
OSTabStop tabstop;
ArrSt(OSHotKey) *hotkeys;
bool_t destroy_main_view;
bool_t is_resizable;
bool_t resize_event;
gint current_width;
gint current_height;
gint minimun_width;
gint minimun_height;
};
static GtkApplication *i_GTK_APP = NULL;
static GdkPixbuf *i_APP_ICON = NULL;
static bool_t i_APP_TERMINATE = FALSE;
static bool_t i_close(OSWindow *window, const gui_close_t close_origin)
{
bool_t closed = TRUE;
cassert_no_null(window);
if (close_origin == ekGUI_CLOSE_INTRO)
closed = _ostabstop_can_close_window(&window->tabstop);
if (closed == TRUE && window->OnClose != NULL)
{
EvWinClose params;
params.origin = close_origin;
listener_event(window->OnClose, ekGUI_EVENT_WND_CLOSE, window, ¶ms, &closed, OSWindow, EvWinClose, bool_t);
}
if (closed == TRUE)
gtk_widget_hide(window->control.widget);
return closed;
}
static gboolean i_OnClose(GtkWidget *widget, GdkEvent *event, OSWindow *window)
{
cassert_no_null(window);
cassert_unref(window->control.widget == widget, widget);
unref(event);
i_close(window, ekGUI_CLOSE_BUTTON);
return TRUE;
}
static uint32_t i_menubar_required_width(const OSWindow *window)
{
cassert_no_null(window);
if (window->is_resizable == TRUE)
return window->current_width - 5;
else
return window->current_width;
}
static uint32_t i_menubar_current_height(const OSWindow *window)
{
cassert_no_null(window);
if (window->menu != NULL)
return _osmenu_menubar_height(window->menu);
else
return 0;
}
static gboolean i_OnConfigure(GtkWidget *widget, GdkEventConfigure *event, OSWindow *window)
{
if (i_APP_TERMINATE == TRUE)
return FALSE;
cassert_no_null(window);
cassert_unref(window->control.widget == widget, widget);
if (window->resize_event == FALSE)
{
window->resize_event = TRUE;
return FALSE;
}
if (window->current_width > 0 && (window->current_width != event->width || window->current_height != event->height))
{
if (window->is_resizable == TRUE && window->OnResize != NULL)
{
EvSize params;
EvSize result;
uint32_t mheight = i_menubar_current_height(window);
params.width = (real32_t)event->width;
params.height = (real32_t)(event->height - mheight);
listener_event(window->OnResize, ekGUI_EVENT_WND_SIZING, window, ¶ms, &result, OSWindow, EvSize, EvSize);
listener_event(window->OnResize, ekGUI_EVENT_WND_SIZE, window, &result, NULL, OSWindow, EvSize, void);
if (result.width > params.width)
{
GdkGeometry hints;
window->minimun_width = (gint)result.width;
hints.min_width = window->minimun_width;
hints.min_height = window->minimun_height;
gtk_window_set_geometry_hints(GTK_WINDOW(window->control.widget), window->control.widget, &hints, (GdkWindowHints)GDK_HINT_MIN_SIZE);
}
if (result.height > params.height)
{
GdkGeometry hints;
window->minimun_height = (gint)result.height + mheight;
hints.min_width = window->minimun_width;
hints.min_height = window->minimun_height;
gtk_window_set_geometry_hints(GTK_WINDOW(window->control.widget), window->control.widget, &hints, (GdkWindowHints)GDK_HINT_MIN_SIZE);
}
window->current_width = (gint)result.width;
window->current_height = (gint)result.height + mheight;
if (window->menu != NULL)
_osmenu_menubar(window->menu, window, i_menubar_required_width(window));
}
else
{
window->current_width = event->width;
window->current_height = event->height;
}
}
else
{
if (window->OnMoved != NULL)
{
EvPos p;
p.x = (real32_t)event->x;
p.y = (real32_t)event->y;
listener_event(window->OnMoved, ekGUI_EVENT_WND_MOVED, window, &p, NULL, OSWindow, EvPos, void);
}
_ostabstop_restore(&window->tabstop);
}
return FALSE;
}
static gboolean i_OnKeyPress(GtkWidget *widget, GdkEventKey *event, OSWindow *window)
{
guint key = 0;
cassert_no_null(window);
cassert_no_null(event);
key = event->keyval;
switch (key)
{
case GDK_KEY_Tab:
if (_ostabstop_capture_tab(&window->tabstop) == FALSE)
{
_ostabstop_next(&window->tabstop, TRUE);
return TRUE;
}
else
{
return FALSE;
}
case GDK_KEY_ISO_Left_Tab:
if (_ostabstop_capture_tab(&window->tabstop) == FALSE)
{
_ostabstop_prev(&window->tabstop, TRUE);
return TRUE;
}
else
{
return FALSE;
}
case GDK_KEY_Escape:
if (window->flags & ekWINDOW_ESC)
{
i_close(window, ekGUI_CLOSE_ESC);
return TRUE;
}
break;
case GDK_KEY_Return:
case GDK_KEY_KP_Enter:
if (_ostabstop_capture_return(&window->tabstop) == FALSE)
{
if (window->tabstop.defbutton != NULL)
{
GtkWidget *focus = gtk_window_get_focus(GTK_WINDOW(widget));
GtkWidget *bfocus = _osbutton_focus_widget(window->tabstop.defbutton);
if (gtk_widget_get_can_focus(bfocus) == TRUE)
gtk_window_set_focus(GTK_WINDOW(widget), bfocus);
_osbutton_command(window->tabstop.defbutton);
_osglobals_restore_focus(widget, focus);
}
if (window->flags & ekWINDOW_RETURN)
{
i_close(window, ekGUI_CLOSE_INTRO);
return TRUE;
}
}
else
{
return FALSE;
}
break;
default:
break;
}
if (window->hotkeys != NULL)
{
vkey_t key = _osgui_vkey(event->keyval);
uint32_t modifiers = _osgui_modifiers(event->state);
if (_oswindow_hotkey_process(window, window->hotkeys, key, modifiers) == TRUE)
return TRUE;
}
return FALSE;
}
static gboolean i_OnKeyRelease(GtkWidget *widget, GdkEventKey *event, OSWindow *window)
{
guint key = 0;
cassert_no_null(event);
unref(widget);
unref(window);
key = event->keyval;
if (key == GDK_KEY_Alt_L || key == GDK_KEY_Alt_R)
return TRUE;
else
return FALSE;
}
static ___INLINE GtkWidget *i_gtk_window(const uint32_t flags)
{
GtkWidget *window = NULL;
if (flags & ekWINDOW_OFFSCREEN)
{
window = gtk_offscreen_window_new();
}
else
{
window = gtk_application_window_new(i_GTK_APP);
gtk_window_set_decorated(GTK_WINDOW(window), (flags & ekWINDOW_TITLE) ? TRUE : FALSE);
}
return window;
}
static gboolean i_OnWindowState(GtkWindow *widget, GdkEventWindowState *event, OSWindow *window)
{
cassert_no_null(event);
cassert_no_null(widget);
if (event->new_window_state & GDK_WINDOW_STATE_FOCUSED)
_ostabstop_restore(&window->tabstop);
return FALSE;
}
OSWindow *oswindow_create(const uint32_t flags)
{
OSWindow *window = heap_new0(OSWindow);
GtkWidget *widget = i_gtk_window(flags);
GtkWidget *box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
gtk_widget_show(box);
gtk_container_add(GTK_CONTAINER(widget), box);
_oscontrol_init(cast(window, OSControl), ekGUI_TYPE_WINDOW, widget, widget, FALSE);
window->flags = flags;
window->role = ENUM_MAX(gui_role_t);
window->destroy_main_view = TRUE;
window->is_resizable = (flags & ekWINDOW_RESIZE) == ekWINDOW_RESIZE ? TRUE : FALSE;
window->resize_event = TRUE;
_ostabstop_init(&window->tabstop, window);
gtk_window_set_resizable(GTK_WINDOW(window->control.widget), (gboolean)window->is_resizable);
if ((flags & ekWINDOW_MIN) == 0)
{
}
window->signal_delete = g_signal_connect(G_OBJECT(widget), "delete-event", G_CALLBACK(i_OnClose), (gpointer)window);
window->signal_config = g_signal_connect(G_OBJECT(widget), "configure-event", G_CALLBACK(i_OnConfigure), (gpointer)window);
window->signal_keypre = g_signal_connect(G_OBJECT(widget), "key-press-event", G_CALLBACK(i_OnKeyPress), (gpointer)window);
window->signal_keyrel = g_signal_connect(G_OBJECT(widget), "key-release-event", G_CALLBACK(i_OnKeyRelease), (gpointer)window);
window->signal_state = g_signal_connect(G_OBJECT(widget), "window-state-event", G_CALLBACK(i_OnWindowState), (gpointer)window);
if (i_APP_ICON != NULL)
{
gtk_window_set_icon(GTK_WINDOW(window->control.widget), i_APP_ICON);
}
return window;
}
OSWindow *oswindow_managed(void *native_ptr)
{
cassert(FALSE);
unref(native_ptr);
return NULL;
}
#if defined(__ASSERTS__)
static void i_count(GtkWidget *widget, gpointer data)
{
uint32_t *n = cast(data, uint32_t);
unref(widget);
*n += 1;
}
static uint32_t i_num_children(GtkWidget *widget)
{
uint32_t n = 0;
cassert(GTK_IS_CONTAINER(widget));
gtk_container_foreach(GTK_CONTAINER(widget), i_count, (gpointer)&n);
return n;
}
#endif
void oswindow_destroy(OSWindow **window)
{
cassert_no_null(window);
cassert_no_null(*window);
cassert((*window)->menu == NULL);
gtk_widget_hide((*window)->control.widget);
g_signal_handler_disconnect(G_OBJECT((*window)->control.widget), (*window)->signal_delete);
g_signal_handler_disconnect(G_OBJECT((*window)->control.widget), (*window)->signal_config);
g_signal_handler_disconnect(G_OBJECT((*window)->control.widget), (*window)->signal_keypre);
g_signal_handler_disconnect(G_OBJECT((*window)->control.widget), (*window)->signal_keyrel);
g_signal_handler_disconnect(G_OBJECT((*window)->control.widget), (*window)->signal_state);
if ((*window)->destroy_main_view == TRUE && (*window)->main_panel != NULL)
{
OSPanel *panel = (*window)->main_panel;
oswindow_detach_panel(*window, panel);
_ospanel_destroy(&panel);
}
cassert((*window)->main_panel == NULL);
if ((*window)->accel != NULL)
{
gtk_window_remove_accel_group(GTK_WINDOW((*window)->control.widget), (*window)->accel);
g_object_unref((*window)->accel);
}
listener_destroy(&(*window)->OnMoved);
listener_destroy(&(*window)->OnResize);
listener_destroy(&(*window)->OnClose);
_oswindow_hotkey_destroy(&(*window)->hotkeys);
_ostabstop_remove(&(*window)->tabstop);
cassert(i_num_children((*window)->control.widget) == 1);
cassert(i_num_children(gtk_bin_get_child(GTK_BIN((*window)->control.widget))) == 0);
g_object_unref((*window)->control.widget);
heap_delete(window, OSWindow);
}
void oswindow_OnMoved(OSWindow *window, Listener *listener)
{
cassert_no_null(window);
listener_update(&window->OnMoved, listener);
}
void oswindow_OnResize(OSWindow *window, Listener *listener)
{
cassert_no_null(window);
listener_update(&window->OnResize, listener);
}
void oswindow_OnClose(OSWindow *window, Listener *listener)
{
cassert_no_null(window);
listener_update(&window->OnClose, listener);
}
void oswindow_title(OSWindow *window, const char_t *text)
{
cassert_no_null(window);
gtk_window_set_title(GTK_WINDOW(window->control.widget), cast_const(text, gchar));
}
void oswindow_edited(OSWindow *window, const bool_t is_edited)
{
unref(window);
unref(is_edited);
cassert(FALSE);
}
void oswindow_movable(OSWindow *window, const bool_t is_movable)
{
unref(window);
unref(is_movable);
cassert(FALSE);
}
void oswindow_z_order(OSWindow *window, OSWindow *below_window)
{
cassert_no_null(window);
unref(window);
unref(below_window);
cassert(FALSE);
}
void oswindow_alpha(OSWindow *window, const real32_t alpha)
{
unref(window);
unref(alpha);
cassert(FALSE);
}
void oswindow_enable_mouse_events(OSWindow *window, const bool_t enabled)
{
unref(window);
unref(enabled);
cassert(FALSE);
}
void oswindow_hotkey(OSWindow *window, const vkey_t key, const uint32_t modifiers, Listener *listener)
{
cassert_no_null(window);
_oswindow_hotkey_set(&window->hotkeys, key, modifiers, listener);
}
void oswindow_taborder(OSWindow *window, OSControl *control)
{
cassert_no_null(window);
_ostabstop_list_add(&window->tabstop, control);
if (control == NULL)
{
window->tabstop.defbutton = _oswindow_apply_default_button(window, window->tabstop.defbutton);
}
}
void oswindow_tabcycle(OSWindow *window, const bool_t cycle)
{
cassert_no_null(window);
window->tabstop.cycle = cycle;
}
gui_focus_t oswindow_tabstop(OSWindow *window, const bool_t next)
{
cassert_no_null(window);
if (next == TRUE)
return _ostabstop_next(&window->tabstop, FALSE);
else
return _ostabstop_prev(&window->tabstop, FALSE);
}
gui_focus_t oswindow_focus(OSWindow *window, OSControl *control)
{
cassert_no_null(window);
cassert_no_null(control);
return _ostabstop_move(&window->tabstop, control);
}
OSControl *oswindow_get_focus(const OSWindow *window)
{
cassert_no_null(window);
return window->tabstop.current;
}
gui_tab_t oswindow_info_focus(const OSWindow *window, void **next_ctrl)
{
cassert_no_null(window);
return _ostabstop_info_focus(&window->tabstop, next_ctrl);
}
void oswindow_attach_panel(OSWindow *window, OSPanel *panel)
{
GtkWidget *box = NULL;
cassert_no_null(window);
cassert(window->main_panel == NULL);
box = gtk_bin_get_child(GTK_BIN(window->control.widget));
gtk_box_pack_end(GTK_BOX(box), cast(panel, OSControl)->widget, TRUE, TRUE, 0);
window->main_panel = panel;
}
void oswindow_detach_panel(OSWindow *window, OSPanel *panel)
{
GtkWidget *box = NULL;
cassert_no_null(window);
cassert(window->main_panel == panel);
box = gtk_bin_get_child(GTK_BIN(window->control.widget));
gtk_container_remove(GTK_CONTAINER(box), cast(panel, OSControl)->widget);
window->main_panel = NULL;
}
void oswindow_attach_window(OSWindow *parent_window, OSWindow *child_window)
{
unref(parent_window);
unref(child_window);
cassert(FALSE);
}
void oswindow_detach_window(OSWindow *parent_window, OSWindow *child_window)
{
unref(parent_window);
unref(child_window);
cassert(FALSE);
}
void oswindow_launch(OSWindow *window, OSWindow *parent_window)
{
cassert_no_null(window);
window->resize_event = FALSE;
if (parent_window != NULL)
{
gtk_window_set_transient_for(GTK_WINDOW(window->control.widget), GTK_WINDOW(parent_window->control.widget));
window->role = ekGUI_ROLE_OVERLAY;
}
else
{
window->role = ekGUI_ROLE_MAIN;
}
gtk_widget_show(window->control.widget);
_ostabstop_restore(&window->tabstop);
}
void oswindow_hide(OSWindow *window, OSWindow *parent_window)
{
cassert_no_null(window);
unref(parent_window);
window->role = ENUM_MAX(gui_role_t);
gtk_window_set_transient_for(GTK_WINDOW(window->control.widget), NULL);
gtk_widget_hide(window->control.widget);
}
uint32_t oswindow_launch_modal(OSWindow *window, OSWindow *parent_window)
{
cassert_no_null(window);
cassert(window->runloop == NULL);
_ostabstop_restore(&window->tabstop);
gtk_window_set_modal(GTK_WINDOW(window->control.widget), TRUE);
window->resize_event = FALSE;
window->role = ekGUI_ROLE_MODAL;
window->runloop = g_main_loop_new(NULL, FALSE);
if (parent_window != NULL)
gtk_window_set_transient_for(GTK_WINDOW(window->control.widget), GTK_WINDOW(parent_window->control.widget));
gtk_widget_show(window->control.widget);
g_main_loop_run(window->runloop);
g_main_loop_unref(window->runloop);
gtk_window_set_transient_for(GTK_WINDOW(window->control.widget), NULL);
if (parent_window != NULL)
_ostabstop_restore(&parent_window->tabstop);
window->runloop = NULL;
return window->modal_return;
}
void oswindow_stop_modal(OSWindow *window, const uint32_t return_value)
{
cassert_no_null(window);
cassert_no_null(window->runloop);
cassert(g_main_loop_is_running(window->runloop) == TRUE);
window->modal_return = return_value;
window->role = ENUM_MAX(gui_role_t);
if (!(window->flags & ekWINDOW_MODAL_NOHIDE))
gtk_widget_hide(window->control.widget);
g_main_loop_quit(window->runloop);
gtk_window_set_modal(GTK_WINDOW(window->control.widget), FALSE);
}
void oswindow_get_origin(const OSWindow *window, real32_t *x, real32_t *y)
{
gint wx, wy;
cassert_no_null(window);
cassert_no_null(x);
cassert_no_null(y);
gtk_window_get_position(GTK_WINDOW(window->control.widget), &wx, &wy);
if (*x == REAL32_MAX && *y == REAL32_MAX)
{
*x = (real32_t)wx;
*y = (real32_t)wy;
}
else
{
gint gx, gy;
GdkWindow *gdkwindow = gtk_widget_get_window(window->control.widget);
gdk_window_get_geometry(gdkwindow, &gx, &gy, NULL, NULL);
*x = (real32_t)wx + (real32_t)gx + *x;
*y = (real32_t)wy + (real32_t)gy + *y;
}
}
void oswindow_origin(OSWindow *window, const real32_t x, const real32_t y)
{
cassert_no_null(window);
window->resize_event = FALSE;
gtk_window_move(GTK_WINDOW(window->control.widget), (gint)x, (gint)y);
}
void oswindow_get_size(const OSWindow *window, real32_t *width, real32_t *height)
{
gint w, h;
cassert_no_null(window);
cassert_no_null(width);
cassert_no_null(height);
gtk_window_get_size(GTK_WINDOW(window->control.widget), &w, &h);
*width = (real32_t)w;
*height = (real32_t)h;
}
static void i_update_menu_size(OSWindow *window)
{
GtkRequisition msize;
cassert_no_null(window);
if (window->menu != NULL)
{
GtkWidget *wmenu = _osmenu_menubar(window->menu, window, i_menubar_required_width(window));
gtk_widget_get_preferred_size(wmenu, &msize, NULL);
}
else
{
msize.width = 0;
msize.height = 0;
}
if (window->is_resizable == TRUE)
{
window->resize_event = FALSE;
gtk_widget_set_size_request(window->control.widget, -1, -1);
gtk_window_resize(GTK_WINDOW(window->control.widget), window->current_width, window->current_height + msize.height);
}
else
{
gtk_widget_set_size_request(window->control.widget, window->current_width, window->current_height + msize.height);
}
}
void oswindow_size(OSWindow *window, const real32_t width, const real32_t height)
{
cassert_no_null(window);
if (window->is_resizable == TRUE)
{
window->resize_event = FALSE;
gtk_window_resize(GTK_WINDOW(window->control.widget), (gint)width, (gint)height);
window->minimun_width = -1;
window->minimun_height = -1;
}
else
{
gtk_widget_set_size_request(window->control.widget, (gint)width, (gint)height);
}
window->current_width = (gint)width;
window->current_height = (gint)height;
i_update_menu_size(window);
}
void oswindow_set_default_pushbutton(OSWindow *window, OSButton *button)
{
cassert_no_null(window);
window->tabstop.defbutton = _oswindow_apply_default_button(window, button);
}
void oswindow_set_cursor(OSWindow *window, Cursor *cursor)
{
GdkWindow *gdkwindow = NULL;
cassert_no_null(window);
gdkwindow = gtk_widget_get_window(window->control.widget);
gdk_window_set_cursor(gdkwindow, cast(cursor, GdkCursor));
}
void oswindow_property(OSWindow *window, const gui_prop_t property, const void *value)
{
cassert_no_null(window);
unref(value);
switch (property)
{
case ekGUI_PROP_CHILDREN:
window->destroy_main_view = FALSE;
break;
cassert_default();
}
}
void _oswindow_widget_set_focus(OSWindow *window, OSWidget *widget)
{
OSControl *control = NULL;
cassert_no_null(widget);
unref(window);
control = cast(g_object_get_data(G_OBJECT(widget), "OSControl"), OSControl);
cassert_no_null(control);
if (control->type == ekGUI_TYPE_EDITBOX)
{
if (_osedit_autosel(cast(control, OSEdit)) == FALSE)
{
#if GTK_CHECK_VERSION(3, 16, 0)
if (GTK_IS_ENTRY(widget))
{
gtk_entry_grab_focus_without_selecting((GTK_ENTRY(widget)));
return;
}
#endif
}
}
else if (control->type == ekGUI_TYPE_COMBOBOX)
{
#if GTK_CHECK_VERSION(3, 16, 0)
cassert(GTK_IS_ENTRY(widget));
gtk_entry_grab_focus_without_selecting((GTK_ENTRY(widget)));
return;
#endif
}
gtk_widget_grab_focus(GTK_WIDGET(widget));
}
static void i_get_controls(GtkWidget *widget, gpointer data)
{
OSControl *control = cast(g_object_get_data(G_OBJECT(widget), "OSControl"), OSControl);
if (control != NULL)
{
ArrPt(OSControl) *controls = cast(data, ArrPt(OSControl));
if (arrpt_find(controls, control, OSControl) == UINT32_MAX)
arrpt_append(controls, control, OSControl);
}
if (GTK_IS_CONTAINER(widget) == TRUE)
gtk_container_foreach(GTK_CONTAINER(widget), i_get_controls, data);
}
void _oswindow_find_all_controls(OSWindow *window, ArrPt(OSControl) *controls)
{
cassert_no_null(window);
cassert(arrpt_size(controls, OSControl) == 0);
gtk_container_foreach(GTK_CONTAINER(window->control.widget), i_get_controls, (gpointer)controls);
}
const ArrPt(OSControl) *_oswindow_get_all_controls(const OSWindow *window)
{
cassert_no_null(window);
return window->tabstop.controls;
}
void _oswindow_set_app(void *app, void *icon)
{
cassert(i_GTK_APP == NULL);
cassert(i_APP_ICON == NULL);
i_GTK_APP = cast(app, GtkApplication);
i_APP_ICON = cast(icon, GdkPixbuf);
}
void _oswindow_set_app_terminate(void)
{
cassert(i_APP_TERMINATE == FALSE);
i_APP_TERMINATE = TRUE;
}
void _oswindow_set_menubar(OSWindow *window, OSMenu *menu)
{
GtkWidget *box = NULL, *wmenu = NULL;
cassert_no_null(window);
cassert(window->menu == NULL);
box = gtk_bin_get_child(GTK_BIN(window->control.widget));
cassert(i_num_children(box) == 1);
wmenu = _osmenu_menubar(menu, window, i_menubar_required_width(window));
gtk_box_pack_start(GTK_BOX(box), wmenu, FALSE, FALSE, 0);
cassert(i_num_children(box) == 2);
gtk_widget_show_all(wmenu);
window->menu = menu;
if (window->accel == NULL)
{
window->accel = gtk_accel_group_new();
gtk_window_add_accel_group(GTK_WINDOW(window->control.widget), window->accel);
}
_osmenu_set_accel(window->menu, window->accel);
i_update_menu_size(window);
cassert(i_num_children(box) == 2);
}
void _oswindow_unset_menubar(OSWindow *window, OSMenu *menu)
{
cassert_no_null(window);
cassert(window->menu == menu);
if (menu != NULL)
{
GtkWidget *box = NULL, *wmenu = NULL;
cassert(window->accel != NULL);
box = gtk_bin_get_child(GTK_BIN(window->control.widget));
cassert(i_num_children(box) == 2);
wmenu = _osmenu_menubar_unlink(menu, window);
gtk_widget_hide(wmenu);
_osmenu_unset_accel(menu, window->accel);
gtk_container_remove(GTK_CONTAINER(box), wmenu);
cassert(i_num_children(box) == 1);
window->menu = NULL;
i_update_menu_size(window);
}
}
void _oswindow_unset_focus(OSWindow *window)
{
cassert_no_null(window);
if (window->tabstop.tablist != NULL)
{
if (window->role == ekGUI_ROLE_OVERLAY)
{
if (i_close(window, ekGUI_CLOSE_DEACT) == TRUE)
window->role = ENUM_MAX(gui_role_t);
}
}
}
GtkAccelGroup *_oswindow_accel(const OSWindow *window)
{
cassert_no_null(window);
return window->accel;
}
static ___INLINE OSWindow *i_root(GtkWidget *widget)
{
GtkWidget *root_widget = NULL;
cassert_no_null(widget);
root_widget = gtk_widget_get_ancestor(widget, GTK_TYPE_WINDOW);
if (root_widget != NULL)
{
OSControl *control = cast(g_object_get_data(G_OBJECT(root_widget), "OSControl"), OSControl);
cassert_no_null(control);
cassert(control->type == ekGUI_TYPE_WINDOW);
return cast(control, OSWindow);
}
return NULL;
}
bool_t _oswindow_mouse_down(OSControl *control)
{
OSWindow *window = NULL;
cassert_no_null(control);
window = i_root(control->widget);
if (window != NULL)
return _ostabstop_mouse_down(&window->tabstop, control);
return TRUE;
}
void _oswindow_release_transient_focus(OSControl *control)
{
OSWindow *window = NULL;
cassert_no_null(control);
window = i_root(control->widget);
if (window != NULL)
_ostabstop_release_transient(&window->tabstop, control);
}