/* Copyright (C) 2001-2006, William Joseph. All Rights Reserved. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "window.h" #include #include "pointer.h" #include "accelerator.h" inline void CHECK_RESTORE(ui::Widget w) { if (gpointer_to_int(g_object_get_data(G_OBJECT(w), "was_mapped")) != 0) { w.show(); } } inline void CHECK_MINIMIZE(ui::Widget w) { g_object_set_data(G_OBJECT(w), "was_mapped", gint_to_pointer(gtk_widget_get_visible(w))); w.hide(); } static gboolean main_window_iconified(ui::Widget widget, GdkEventWindowState *event, gpointer data) { if ((event->changed_mask & (GDK_WINDOW_STATE_ICONIFIED | GDK_WINDOW_STATE_WITHDRAWN)) != 0) { if ((event->new_window_state & (GDK_WINDOW_STATE_ICONIFIED | GDK_WINDOW_STATE_WITHDRAWN)) != 0) { CHECK_MINIMIZE(ui::Widget::from(data)); } else { CHECK_RESTORE(ui::Widget::from(data)); } } return FALSE; } unsigned int connect_floating(ui::Window main_window, ui::Window floating) { return main_window.connect("window_state_event", G_CALLBACK(main_window_iconified), floating); } gboolean destroy_disconnect_floating(ui::Window widget, gpointer data) { g_signal_handler_disconnect(G_OBJECT(data), gpointer_to_int(g_object_get_data(G_OBJECT(widget), "floating_handler"))); return FALSE; } gboolean floating_window_delete_present(ui::Window floating, GdkEventFocus *event, ui::Window main_window) { if (gtk_window_is_active(floating) || gtk_window_is_active(main_window)) { gtk_window_present(main_window); } return FALSE; } guint connect_floating_window_delete_present(ui::Window floating, ui::Window main_window) { return floating.connect("delete_event", G_CALLBACK(floating_window_delete_present), main_window); } gboolean floating_window_destroy_present(ui::Window floating, ui::Window main_window) { if (gtk_window_is_active(floating) || gtk_window_is_active(main_window)) { gtk_window_present(main_window); } return FALSE; } guint connect_floating_window_destroy_present(ui::Window floating, ui::Window main_window) { return floating.connect("destroy", G_CALLBACK(floating_window_destroy_present), main_window); } ui::Window create_floating_window(const char *title, ui::Window parent) { ui::Window window = ui::Window(ui::window_type::TOP); gtk_window_set_title(window, title); if (parent) { gtk_window_set_transient_for(window, parent); connect_floating_window_destroy_present(window, parent); g_object_set_data(G_OBJECT(window), "floating_handler", gint_to_pointer(connect_floating(parent, window))); window.connect("destroy", G_CALLBACK(destroy_disconnect_floating), parent); } return window; } void destroy_floating_window(ui::Window window) { window.destroy(); } gint window_realize_remove_sysmenu(ui::Widget widget, gpointer data) { gdk_window_set_decorations(gtk_widget_get_window(widget), (GdkWMDecoration) (GDK_DECOR_ALL | GDK_DECOR_MENU)); return FALSE; } gboolean persistent_floating_window_delete(ui::Window floating, GdkEvent *event, ui::Window main_window) { floating.hide(); return TRUE; } ui::Window create_persistent_floating_window(const char *title, ui::Window main_window) { auto window = create_floating_window(title, main_window); gtk_widget_set_events(window, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK); connect_floating_window_delete_present(window, main_window); window.connect("delete_event", G_CALLBACK(persistent_floating_window_delete), 0); #if 0 if ( g_multimon_globals.m_bStartOnPrimMon && g_multimon_globals.m_bNoSysMenuPopups ) { window.connect( "realize", G_CALLBACK( window_realize_remove_sysmenu ), 0 ); } #endif return window; } gint window_realize_remove_minmax(ui::Widget widget, gpointer data) { gdk_window_set_decorations(gtk_widget_get_window(widget), (GdkWMDecoration) (GDK_DECOR_ALL | GDK_DECOR_MINIMIZE | GDK_DECOR_MAXIMIZE)); return FALSE; } void window_remove_minmax(ui::Window window) { window.connect("realize", G_CALLBACK(window_realize_remove_minmax), 0); } ui::ScrolledWindow create_scrolled_window(ui::Policy hscrollbar_policy, ui::Policy vscrollbar_policy, int border) { auto scr = ui::ScrolledWindow(ui::New); scr.show(); gtk_scrolled_window_set_policy(scr, (GtkPolicyType) hscrollbar_policy, (GtkPolicyType) vscrollbar_policy); gtk_scrolled_window_set_shadow_type(scr, GTK_SHADOW_IN); gtk_container_set_border_width(GTK_CONTAINER(scr), border); return scr; } gboolean window_focus_in_clear_focus_widget(ui::Window widget, GdkEventKey *event, gpointer data) { gtk_window_set_focus(widget, NULL); return FALSE; } guint window_connect_focus_in_clear_focus_widget(ui::Window window) { return window.connect("focus_in_event", G_CALLBACK(window_focus_in_clear_focus_widget), NULL); } void window_get_position(ui::Window window, WindowPosition &position) { ASSERT_MESSAGE(window, "error saving window position"); gtk_window_get_position(window, &position.x, &position.y); gtk_window_get_size(window, &position.w, &position.h); } void window_set_position(ui::Window window, const WindowPosition &position) { gtk_window_set_gravity(window, GDK_GRAVITY_STATIC); GdkScreen *screen = gdk_screen_get_default(); if (position.x < 0 || position.y < 0 || position.x > gdk_screen_get_width(screen) || position.y > gdk_screen_get_height(screen)) { gtk_window_set_position(window, GTK_WIN_POS_CENTER_ON_PARENT); } else { gtk_window_move(window, position.x, position.y); } gtk_window_set_default_size(window, position.w, position.h); } void WindowPosition_String::Import(WindowPosition &position, const char *value) { if (sscanf(value, "%d %d %d %d", &position.x, &position.y, &position.w, &position.h) != 4) { position = WindowPosition(c_default_window_pos); // ensure sane default value for window position } } void WindowPosition_String::Export(const WindowPosition &self, const Callback &returnz) { char buffer[64]; sprintf(buffer, "%d %d %d %d", self.x, self.y, self.w, self.h); returnz(buffer); } void WindowPositionTracker_String::Import(WindowPositionTracker &self, const char *value) { WindowPosition position; WindowPosition_String::Import(position, value); self.setPosition(position); } void WindowPositionTracker_String::Export(const WindowPositionTracker &self, const Callback &returnz) { WindowPosition_String::Export(self.getPosition(), returnz); } gboolean WindowPositionTracker::configure(ui::Widget widget, GdkEventConfigure *event, WindowPositionTracker *self) { self->m_position = WindowPosition(event->x, event->y, event->width, event->height); return FALSE; } void WindowPositionTracker::sync(ui::Window window) { window_set_position(window, m_position); } void WindowPositionTracker::connect(ui::Window window) { sync(window); window.connect("configure_event", G_CALLBACK(configure), this); } const WindowPosition &WindowPositionTracker::getPosition() const { return m_position; } void WindowPositionTracker::setPosition(const WindowPosition &position) { m_position = position; }