5826fdcf8c
* NEW: The menu editor layout has been redesigned. * NEW: Cut, copy & paste is possible now in the menu editor. [GB.GTK] * BUG: Basic controls events are correctly sent again when a modal dialog is displayed. * NEW: ListBox.Border is a new property to set if the control border must be displayed or not. [GB.QT4] * NEW: ListBox.Border is a new property to set if the control border must be displayed or not. git-svn-id: svn://localhost/gambas/trunk@3057 867c0c6c-44f3-4631-809d-bfa615b0a4ec
875 lines
18 KiB
C++
875 lines
18 KiB
C++
/***************************************************************************
|
|
|
|
gapplication.cpp
|
|
|
|
(c) 2004-2006 - Daniel Campos Fernández <dcamposf@gmail.com>
|
|
|
|
This program 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, or (at your option)
|
|
any later version.
|
|
|
|
This program 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 this program; if not, write to the Free Software
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
***************************************************************************/
|
|
|
|
#include <ctype.h>
|
|
#include <time.h>
|
|
|
|
#include "widgets.h"
|
|
#include "widgets_private.h"
|
|
#include "gapplication.h"
|
|
#include "gtrayicon.h"
|
|
#include "gdesktop.h"
|
|
#include "gkey.h"
|
|
#include "gmenu.h"
|
|
#include "gmessage.h"
|
|
#include "gdialog.h"
|
|
#include "gclipboard.h"
|
|
#include "gmouse.h"
|
|
#include "gmainwindow.h"
|
|
|
|
//#define DEBUG_IM 1
|
|
|
|
/*************************************************************************
|
|
|
|
gKey
|
|
|
|
**************************************************************************/
|
|
|
|
bool gKey::_valid = false;
|
|
bool gKey::_no_input_method = false;
|
|
GdkEventKey gKey::_event;
|
|
GtkIMContext *gKey::_im_context = NULL;
|
|
gControl *gKey::_im_control = NULL;
|
|
char *_im_text = NULL;
|
|
|
|
const char *gKey::text()
|
|
{
|
|
if (!_valid)
|
|
return 0;
|
|
else
|
|
return _event.string;
|
|
}
|
|
|
|
int gKey::code()
|
|
{
|
|
if (!_valid)
|
|
return 0;
|
|
else
|
|
return _event.keyval;
|
|
}
|
|
|
|
int gKey::state()
|
|
{
|
|
if (!_valid)
|
|
return 0;
|
|
else
|
|
return _event.state;
|
|
}
|
|
|
|
bool gKey::alt()
|
|
{
|
|
return state() & GDK_MOD1_MASK || code() == GDK_Alt_L || code() == GDK_Alt_R;
|
|
}
|
|
|
|
bool gKey::control()
|
|
{
|
|
return state() & GDK_CONTROL_MASK || code() == GDK_Control_L || code() == GDK_Control_R;
|
|
}
|
|
|
|
bool gKey::meta()
|
|
{
|
|
return state() & GDK_MOD2_MASK || code() == GDK_Meta_L || code() == GDK_Meta_R;
|
|
}
|
|
|
|
bool gKey::normal()
|
|
{
|
|
return (state() & 0xFF) != 0;
|
|
}
|
|
|
|
bool gKey::shift()
|
|
{
|
|
return state() & GDK_SHIFT_MASK || code() == GDK_Shift_L || code() == GDK_Shift_R;
|
|
}
|
|
|
|
int gKey::fromString(char *str)
|
|
{
|
|
char *lstr;
|
|
int key;
|
|
|
|
lstr = g_ascii_strup(str, -1);
|
|
key = gdk_keyval_from_name(lstr);
|
|
g_free(lstr);
|
|
if (key) return key;
|
|
|
|
lstr = g_ascii_strdown(str, -1);
|
|
key = gdk_keyval_from_name(lstr);
|
|
g_free(lstr);
|
|
if (key) return key;
|
|
|
|
key = gdk_keyval_from_name(str);
|
|
return key;
|
|
}
|
|
|
|
void gKey::disable()
|
|
{
|
|
if (!_valid)
|
|
return;
|
|
|
|
_valid = false;
|
|
_event.keyval = 0;
|
|
_event.state = 0;
|
|
g_free(_event.string);
|
|
}
|
|
|
|
bool gKey::enable(gControl *control, GdkEventKey *event)
|
|
{
|
|
bool filter;
|
|
|
|
//if (widget != _im_widget)
|
|
// return true;
|
|
|
|
if (_valid)
|
|
disable();
|
|
|
|
_valid = true;
|
|
_event = *event;
|
|
|
|
if (_event.type == GDK_KEY_PRESS && !_no_input_method && control == _im_control)
|
|
{
|
|
#if DEBUG_IM
|
|
fprintf(stderr, "gKey::enable: event->string = '%s'\n", event->string);
|
|
#endif
|
|
filter = gtk_im_context_filter_keypress(_im_context, &_event);
|
|
#if DEBUG_IM
|
|
fprintf(stderr, "gKey::enable: filter -> %d event->string = '%s'\n", filter, event->string);
|
|
#endif
|
|
}
|
|
else
|
|
filter = false;
|
|
|
|
if (filter && _im_text)
|
|
{
|
|
_event.string = g_strdup(_im_text);
|
|
//_event.keyval = 0;
|
|
filter = false;
|
|
}
|
|
else
|
|
_event.string = g_strdup(_event.string);
|
|
|
|
if (!filter)
|
|
{
|
|
//#if DEBUG_IM
|
|
//fprintf(stderr, "gKey::enable: gtk_im_context_reset\n");
|
|
//#endif
|
|
//gtk_im_context_reset(_im_context);
|
|
if (_im_text)
|
|
{
|
|
g_free(_im_text);
|
|
_im_text = NULL;
|
|
}
|
|
}
|
|
|
|
//fprintf(stderr, "gKey::enable: --> %d\n", filter);
|
|
return filter;
|
|
}
|
|
|
|
static void cb_im_commit(GtkIMContext *context, const gchar *str, gpointer pointer)
|
|
{
|
|
#if DEBUG_IM
|
|
fprintf(stderr, "cb_im_commit: %s\n", str);
|
|
#endif
|
|
|
|
if (_im_text)
|
|
g_free(_im_text);
|
|
|
|
_im_text = g_strdup(str);
|
|
}
|
|
|
|
void gKey::init()
|
|
{
|
|
_im_context = gtk_im_multicontext_new();
|
|
g_signal_connect (_im_context, "commit", G_CALLBACK(cb_im_commit), NULL);
|
|
}
|
|
|
|
void gKey::exit()
|
|
{
|
|
disable();
|
|
if (_im_text)
|
|
g_free(_im_text);
|
|
g_object_unref(_im_context);
|
|
}
|
|
|
|
void gKey::setActiveControl(gControl *control)
|
|
{
|
|
if (_im_control)
|
|
{
|
|
if (!_no_input_method)
|
|
{
|
|
#if DEBUG_IM
|
|
fprintf(stderr, "gtm_im_context_focus_out\n");
|
|
#endif
|
|
gtk_im_context_set_client_window (_im_context, 0);
|
|
gtk_im_context_focus_out(_im_context);
|
|
}
|
|
_im_control = NULL;
|
|
_no_input_method = false;
|
|
}
|
|
|
|
if (control)
|
|
{
|
|
_im_control = control;
|
|
_no_input_method = control->noInputMethod();
|
|
|
|
if (!_no_input_method)
|
|
{
|
|
gtk_im_context_set_client_window (_im_context, _im_control->widget->window);
|
|
gtk_im_context_focus_in(_im_context);
|
|
gtk_im_context_reset(_im_context);
|
|
#if DEBUG_IM
|
|
fprintf(stderr, "gtm_im_context_focus_in\n");
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|
|
/**************************************************************************
|
|
|
|
Global event handler
|
|
|
|
**************************************************************************/
|
|
|
|
static bool check_button(gControl *w)
|
|
{
|
|
return w && w->isVisible() && w->enabled();
|
|
}
|
|
|
|
#if 0
|
|
static GtkWindowGroup *get_window_group(GtkWidget *widget)
|
|
{
|
|
GtkWidget *toplevel = NULL;
|
|
|
|
if (widget)
|
|
toplevel = gtk_widget_get_toplevel(widget);
|
|
|
|
if (GTK_IS_WINDOW (toplevel))
|
|
return gtk_window_get_group(GTK_WINDOW (toplevel));
|
|
else
|
|
return gtk_window_get_group(NULL);
|
|
}
|
|
#endif
|
|
|
|
/*static gboolean close_dialog(GtkButton *button)
|
|
{
|
|
gtk_button_clicked(button);
|
|
return FALSE;
|
|
}*/
|
|
|
|
static void gambas_handle_event(GdkEvent *event)
|
|
{
|
|
GtkWidget *widget;
|
|
GtkWidget *grab;
|
|
gControl *control;
|
|
int x, y, xc, yc;
|
|
bool real;
|
|
|
|
if (gApplication::_close_next_window)
|
|
{
|
|
widget = gtk_get_event_widget(event);
|
|
if (widget)
|
|
{
|
|
//fprintf(stderr, "type: %s\n", G_OBJECT_TYPE_NAME(widget));
|
|
if (!strcmp(G_OBJECT_TYPE_NAME(gtk_widget_get_toplevel(widget)), "GtkPrintUnixDialog"))
|
|
{
|
|
//fprintf(stderr, "event: %d\n", event->type);
|
|
if (event->type == GDK_MAP)
|
|
{
|
|
widget = gtk_window_get_default_widget(GTK_WINDOW(gtk_widget_get_toplevel(widget)));
|
|
if (widget && GTK_IS_BUTTON(widget))
|
|
{
|
|
gApplication::_close_next_window = false;
|
|
gtk_button_clicked(GTK_BUTTON(widget));
|
|
//g_timeout_add(0, (GSourceFunc)close_dialog, GTK_BUTTON(widget));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!((event->type >= GDK_MOTION_NOTIFY && event->type <= GDK_LEAVE_NOTIFY) || event->type == GDK_SCROLL))
|
|
goto __HANDLE_EVENT;
|
|
|
|
widget = gtk_get_event_widget(event);
|
|
real = true;
|
|
|
|
while (widget)
|
|
{
|
|
control = (gControl *)g_object_get_data(G_OBJECT(widget), "gambas-control");
|
|
if (control)
|
|
break;
|
|
widget = widget->parent;
|
|
real = false;
|
|
}
|
|
|
|
if (!widget || !control)
|
|
goto __HANDLE_EVENT;
|
|
|
|
/*switch ((int)event->type)
|
|
{
|
|
case GDK_ENTER_NOTIFY:
|
|
fprintf(stderr, "ENTER: %p %s\n", control, control ? control->name() : 0);
|
|
break;
|
|
|
|
case GDK_LEAVE_NOTIFY:
|
|
fprintf(stderr, "LEAVE: %p %s\n", control, control ? control->name() : 0);
|
|
break;
|
|
}*/
|
|
|
|
grab = gtk_grab_get_current();
|
|
if (grab && grab != widget)
|
|
goto __HANDLE_EVENT;
|
|
|
|
//group = get_window_group(widget);
|
|
//if (group != gApplication::currentGroup())
|
|
// goto __HANDLE_EVENT;
|
|
|
|
if (event->type != GDK_ENTER_NOTIFY)
|
|
{
|
|
if (gApplication::_leave)
|
|
{
|
|
if (event->type != GDK_LEAVE_NOTIFY || gApplication::_leave != control)
|
|
gApplication::_leave->emit(SIGNAL(gApplication::_leave->onEnterLeave), gEvent_Leave);
|
|
gApplication::_leave = NULL;
|
|
}
|
|
}
|
|
|
|
switch ((int)event->type)
|
|
{
|
|
case GDK_ENTER_NOTIFY:
|
|
|
|
//gApplication::dispatchEnterLeave(control);
|
|
if (gApplication::_leave == control)
|
|
gApplication::_leave = NULL;
|
|
else if (gApplication::_enter != control)
|
|
{
|
|
gApplication::_enter = control;
|
|
control->emit(SIGNAL(control->onEnterLeave), gEvent_Enter);
|
|
}
|
|
break;
|
|
|
|
case GDK_LEAVE_NOTIFY:
|
|
if (gdk_events_pending())
|
|
gApplication::_leave = control;
|
|
else
|
|
{
|
|
if (gApplication::_enter == control)
|
|
gApplication::_enter = NULL;
|
|
control->emit(SIGNAL(control->onEnterLeave), gEvent_Leave);
|
|
}
|
|
break;
|
|
|
|
case GDK_BUTTON_PRESS:
|
|
case GDK_2BUTTON_PRESS:
|
|
case GDK_BUTTON_RELEASE:
|
|
|
|
gApplication::_event_time = event->button.time;
|
|
|
|
if (control->onMouseEvent)
|
|
{
|
|
control->getScreenPos(&xc, &yc);
|
|
x = (int)event->button.x_root - xc;
|
|
y = (int)event->button.y_root - yc;
|
|
|
|
gMouse::validate();
|
|
gMouse::setStart(x, y);
|
|
gMouse::setMouse(x, y, event->button.button, event->button.state);
|
|
//gMouse::setValid(1,(int)event->x,(int)event->y,event->button,event->state,data->screenX(),data->screenY());
|
|
switch ((int)event->type)
|
|
{
|
|
case GDK_BUTTON_PRESS:
|
|
control->onMouseEvent(control, gEvent_MousePress);
|
|
break;
|
|
|
|
case GDK_2BUTTON_PRESS:
|
|
control->onMouseEvent(control, gEvent_MouseDblClick);
|
|
break;
|
|
|
|
case GDK_BUTTON_RELEASE:
|
|
control->onMouseEvent(control, gEvent_MouseRelease);
|
|
if (control->_grab)
|
|
gApplication::exitLoop(control);
|
|
break;
|
|
}
|
|
|
|
gMouse::invalidate();
|
|
|
|
if (event->button.button == 3 && event->type == GDK_BUTTON_PRESS)
|
|
control->onMouseEvent(control, gEvent_MouseMenu);
|
|
}
|
|
break;
|
|
|
|
case GDK_MOTION_NOTIFY:
|
|
|
|
gApplication::_event_time = event->motion.time;
|
|
|
|
if (control->onMouseEvent && (control->isTracking() || (event->motion.state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK))))
|
|
{
|
|
control->getScreenPos(&xc, &yc);
|
|
x = (int)event->motion.x_root - xc;
|
|
y = (int)event->motion.y_root - yc;
|
|
|
|
gMouse::validate();
|
|
gMouse::setMouse(x, y, 0, event->motion.state);
|
|
control->onMouseEvent(control, gEvent_MouseMove);
|
|
//if (data->acceptDrops() && gDrag::checkThreshold(data, gMouse::x(), gMouse::y(), gMouse::startX(), gMouse::startY()))
|
|
if ((event->motion.state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK))
|
|
//&& (abs(gMouse::x() - gMouse::y()) + abs(gMouse::startX() - gMouse::startY())) > 8)
|
|
&& gDrag::checkThreshold(control, gMouse::x(), gMouse::y(), gMouse::startX(), gMouse::startY()))
|
|
{
|
|
control->onMouseEvent(control, gEvent_MouseDrag);
|
|
}
|
|
gMouse::invalidate();
|
|
}
|
|
break;
|
|
|
|
case GDK_SCROLL:
|
|
|
|
gApplication::_event_time = event->scroll.time;
|
|
|
|
if (control->onMouseEvent)
|
|
{
|
|
int dt, ort;
|
|
|
|
control->getScreenPos(&xc, &yc);
|
|
x = (int)event->scroll.x_root - xc;
|
|
y = (int)event->scroll.y_root - yc;
|
|
|
|
switch (event->scroll.direction)
|
|
{
|
|
case GDK_SCROLL_DOWN: dt = -1; ort = 1; break;
|
|
case GDK_SCROLL_LEFT: dt = -1; ort = 0; break;
|
|
case GDK_SCROLL_RIGHT: dt = 1; ort = 0; break;
|
|
case GDK_SCROLL_UP: default: dt = 1; ort = 1; break;
|
|
}
|
|
|
|
gMouse::validate();
|
|
gMouse::setMouse(x, y, 0, event->scroll.state);
|
|
gMouse::setWheel(dt, ort);
|
|
control->onMouseEvent(control, gEvent_MouseWheel);
|
|
gMouse::invalidate();
|
|
}
|
|
break;
|
|
|
|
case GDK_KEY_PRESS:
|
|
{
|
|
bool cancel = false;
|
|
|
|
gApplication::_event_time = event->key.time;
|
|
control = gDesktop::activeControl();
|
|
|
|
if (control)
|
|
{
|
|
if (!gKey::enable(control, &event->key))
|
|
{
|
|
if (gApplication::onKeyEvent)
|
|
cancel = gApplication::onKeyEvent(gEvent_KeyPress);
|
|
if (!cancel && control->onKeyEvent)
|
|
{
|
|
//fprintf(stderr, "gEvent_KeyPress on %p %s\n", control, control->name());
|
|
cancel = control->onKeyEvent(control, gEvent_KeyPress);
|
|
}
|
|
}
|
|
gKey::disable();
|
|
|
|
if (cancel)
|
|
return;
|
|
|
|
if (event->key.keyval == GDK_Escape)
|
|
{
|
|
if (control->_grab)
|
|
{
|
|
gApplication::exitLoop(control);
|
|
return;
|
|
}
|
|
|
|
gMainWindow *win = control->window();
|
|
if (check_button(win->_cancel))
|
|
{
|
|
win->_cancel->animateClick(false);
|
|
return;
|
|
}
|
|
}
|
|
else if (event->key.keyval == GDK_Return || event->key.keyval == GDK_KP_Enter)
|
|
{
|
|
gMainWindow *win = control->window();
|
|
if (check_button(win->_default))
|
|
{
|
|
win->_default->animateClick(false);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case GDK_KEY_RELEASE:
|
|
|
|
gApplication::_event_time = event->key.time;
|
|
control = gDesktop::activeControl();
|
|
|
|
if (control)
|
|
{
|
|
if (!gKey::enable(control, &event->key))
|
|
control->emit(SIGNAL(control->onKeyEvent), gEvent_KeyRelease);
|
|
gKey::disable();
|
|
|
|
if (event->key.keyval == GDK_Escape)
|
|
{
|
|
gMainWindow *win = control->window();
|
|
if (check_button(win->_cancel))
|
|
win->_cancel->animateClick(true);
|
|
}
|
|
else if (event->key.keyval == GDK_Return || event->key.keyval == GDK_KP_Enter)
|
|
{
|
|
gMainWindow *win = control->window();
|
|
if (check_button(win->_default))
|
|
win->_default->animateClick(true);
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
__HANDLE_EVENT:
|
|
|
|
gtk_main_do_event(event);
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************
|
|
|
|
gApplication
|
|
|
|
**************************************************************************/
|
|
|
|
int appEvents;
|
|
GtkTooltips *app_tooltips_handle;
|
|
bool app_tooltips=true;
|
|
gFont *app_tooltips_font=NULL;
|
|
|
|
bool gApplication::_busy = false;
|
|
char *gApplication::_title = NULL;
|
|
int gApplication::_loopLevel = 0;
|
|
int gApplication::_tooltip_delay = 500; // GTK+ default
|
|
void *gApplication::_loop_owner = 0;
|
|
GtkWindowGroup *gApplication::_group = NULL;
|
|
gControl *gApplication::_enter = NULL;
|
|
gControl *gApplication::_leave = NULL;
|
|
bool (*gApplication::onKeyEvent)(int) = NULL;
|
|
guint32 gApplication::_event_time = 0;
|
|
bool gApplication::_close_next_window = false;
|
|
|
|
GtkTooltips* gApplication::tipHandle()
|
|
{
|
|
return app_tooltips_handle;
|
|
}
|
|
|
|
bool gApplication::toolTips()
|
|
{
|
|
return app_tooltips;
|
|
}
|
|
|
|
void gApplication::setToolTipsFont(gFont *ft)
|
|
{
|
|
GList *chd;
|
|
PangoFontDescription *desc;
|
|
|
|
gFont::set(&app_tooltips_font, ft->copy());
|
|
|
|
if (ft)
|
|
desc = pango_context_get_font_description(ft->ct);
|
|
else
|
|
desc = NULL;
|
|
|
|
gtk_widget_modify_font(app_tooltips_handle->tip_window,desc);
|
|
|
|
chd=gtk_container_get_children(GTK_CONTAINER(app_tooltips_handle->tip_window));
|
|
if (chd)
|
|
{
|
|
do { gtk_widget_modify_font(GTK_WIDGET(chd->data),desc);
|
|
} while (chd->next);
|
|
g_list_free(chd);
|
|
}
|
|
}
|
|
|
|
gFont *gApplication::toolTipsFont()
|
|
{
|
|
return app_tooltips_font;
|
|
}
|
|
|
|
void gApplication::enableTooltips(bool vl)
|
|
{
|
|
if (vl)
|
|
gtk_tooltips_enable(app_tooltips_handle);
|
|
else
|
|
gtk_tooltips_disable(app_tooltips_handle);
|
|
}
|
|
|
|
void gApplication::setToolTipsDelay(int vl)
|
|
{
|
|
if (vl < 50)
|
|
vl = 50;
|
|
else if (vl > 10000)
|
|
vl = 10000;
|
|
|
|
_tooltip_delay = vl;
|
|
gtk_tooltips_set_delay(app_tooltips_handle, vl);
|
|
}
|
|
|
|
void gApplication::suspendEvents(bool vl)
|
|
{
|
|
if (!vl) appEvents=3; //all
|
|
else appEvents=1; //user
|
|
}
|
|
|
|
void gApplication::enableEvents()
|
|
{
|
|
appEvents=0;
|
|
}
|
|
|
|
bool gApplication::userEvents()
|
|
{
|
|
if (appEvents) return false;
|
|
return true;
|
|
}
|
|
|
|
bool gApplication::allEvents()
|
|
{
|
|
if (appEvents & 2) return false;
|
|
return true;
|
|
}
|
|
|
|
void gApplication::init(int *argc,char ***argv)
|
|
{
|
|
appEvents=0;
|
|
|
|
gtk_init(argc,argv);
|
|
|
|
gdk_event_handler_set((GdkEventFunc)gambas_handle_event, NULL, NULL);
|
|
|
|
app_tooltips_handle = gtk_tooltips_new();
|
|
g_object_ref(G_OBJECT(app_tooltips_handle));
|
|
gtk_tooltips_force_window (app_tooltips_handle);
|
|
app_tooltips_font = new gFont(app_tooltips_handle->tip_window);
|
|
|
|
gClipboard::init();
|
|
gKey::init();
|
|
_loop_owner = 0;
|
|
}
|
|
|
|
void gApplication::exit()
|
|
{
|
|
if (_title)
|
|
g_free(_title);
|
|
|
|
gKey::exit();
|
|
gTrayIcon::exit();
|
|
gDesktop::exit();
|
|
gMessage::exit();
|
|
gDialog::exit();
|
|
gFont::assign(&app_tooltips_font);
|
|
gFont::exit();
|
|
gt_exit();
|
|
}
|
|
|
|
int gApplication::controlCount()
|
|
{
|
|
GList *iter;
|
|
int ct=1;
|
|
|
|
if (!gControl::controlList()) return 0;
|
|
|
|
iter=g_list_first(gControl::controlList());
|
|
while (iter->next)
|
|
{
|
|
ct++;
|
|
iter=iter->next;
|
|
}
|
|
|
|
return ct;
|
|
}
|
|
|
|
gControl* gApplication::controlItem(GtkWidget *wid)
|
|
{
|
|
GList *iter;
|
|
|
|
if (!wid) return NULL;
|
|
|
|
if (gControl::controlList())
|
|
{
|
|
iter=g_list_first(gControl::controlList());
|
|
|
|
while (iter)
|
|
{
|
|
if (((gControl*)iter->data)->border == wid )
|
|
return (gControl*)iter->data;
|
|
|
|
if (((gControl*)iter->data)->widget == wid )
|
|
return (gControl*)iter->data;
|
|
|
|
iter=iter->next;
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
gControl* gApplication::controlItem(int index)
|
|
{
|
|
GList *iter;
|
|
|
|
if (!gControl::controlList()) return NULL;
|
|
iter=g_list_nth(gControl::controlList(),index);
|
|
if (!iter) return NULL;
|
|
return (gControl*)iter->data;
|
|
}
|
|
|
|
void gApplication::setBusy(bool b)
|
|
{
|
|
GList *iter;
|
|
gControl *control;
|
|
|
|
if (b == _busy)
|
|
return;
|
|
|
|
_busy = b;
|
|
|
|
iter = g_list_first(gControl::controlList());
|
|
|
|
while (iter)
|
|
{
|
|
control = (gControl *)iter->data;
|
|
|
|
if (control->mustUpdateCursor())
|
|
control->setMouse(control->mouse());
|
|
|
|
iter = g_list_next(iter);
|
|
}
|
|
|
|
}
|
|
|
|
static bool _dirty = false;
|
|
|
|
static gboolean update_geometry(void *data)
|
|
{
|
|
GList *iter;
|
|
gControl *control;
|
|
|
|
if (gContainer::_arrangement_level)
|
|
return true;
|
|
|
|
_dirty = false;
|
|
//g_debug(">>>> update_geometry");
|
|
iter = g_list_first(gControl::controlList());
|
|
while (iter)
|
|
{
|
|
control = (gControl *)iter->data;
|
|
control->updateGeometry();
|
|
iter = iter->next;
|
|
}
|
|
//g_debug("<<<<");
|
|
|
|
return false;
|
|
}
|
|
|
|
void gApplication::setDirty()
|
|
{
|
|
if (_dirty)
|
|
return;
|
|
|
|
_dirty = true;
|
|
g_timeout_add(0, (GSourceFunc)update_geometry, NULL);
|
|
}
|
|
|
|
void gApplication::setDefaultTitle(const char *title)
|
|
{
|
|
if (_title)
|
|
g_free(_title);
|
|
_title = g_strdup(title);
|
|
}
|
|
|
|
GtkWindowGroup *gApplication::enterGroup()
|
|
{
|
|
gControl *control = _enter;
|
|
GtkWindowGroup *oldGroup = _group;
|
|
_group = gtk_window_group_new();
|
|
|
|
_enter = _leave = NULL;
|
|
|
|
while (control)
|
|
{
|
|
control->emit(SIGNAL(control->onEnterLeave), gEvent_Leave);
|
|
control = control->parent();
|
|
}
|
|
|
|
return oldGroup;
|
|
}
|
|
|
|
void gApplication::exitGroup(GtkWindowGroup *oldGroup)
|
|
{
|
|
g_object_unref(_group);
|
|
_group = oldGroup;
|
|
}
|
|
|
|
void gApplication::enterLoop(void *owner, bool showIt)
|
|
{
|
|
void *old_owner = _loop_owner;
|
|
int l = _loopLevel;
|
|
GtkWindowGroup *oldGroup;
|
|
|
|
oldGroup = enterGroup();
|
|
|
|
if (showIt) ((gControl *)owner)->show();
|
|
|
|
_loopLevel++;
|
|
_loop_owner = owner;
|
|
|
|
do
|
|
{
|
|
do_iteration(false);
|
|
}
|
|
while (_loopLevel > l);
|
|
|
|
_loop_owner = old_owner;
|
|
|
|
exitGroup(oldGroup);
|
|
}
|
|
|
|
void gApplication::exitLoop(void *owner)
|
|
{
|
|
if (!hasLoop(owner))
|
|
return;
|
|
|
|
if (_loopLevel > 0)
|
|
_loopLevel--;
|
|
}
|
|
|
|
GtkWindowGroup *gApplication::currentGroup()
|
|
{
|
|
if (_group)
|
|
return _group;
|
|
else
|
|
return gtk_window_get_group(NULL);
|
|
}
|