gambas-source-code/gb.gtk/src/main.cpp
Benoît Minisini 23dd0b0299 [DEVELOPMENT ENVIRONMENT]
* BUG: Do not search text inside form anymore.

[INTERPRETER]
* BUG: The startup class is not global anymore, so that it does not 
  conflict with anythign having the same name in components. The 
  interpreter API that was returning the startup class has been updated
  to reflect that change.
* BUG: File.Name("/a/b/") now returns a void string instead of returning 
  "b", to be coherent with File.Dir().

[GB.DESKTOP]
* NEW: Use the new API returning the startup class.

[GB.FORM]
* BUG: Setting DirView.Root with a path ending with a slash does not crash
  anymore.

[GB.GTK]
* NEW: Use the new API returning the startup class.

[GB.QT4]
* NEW: Use the new API returning the startup class.

[GB.SIGNAL]
* NEW: Use the new API returning the startup class.


git-svn-id: svn://localhost/gambas/trunk@3267 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2010-10-15 00:23:11 +00:00

508 lines
11 KiB
C++

/***************************************************************************
main.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.
***************************************************************************/
#define __MAIN_C
#include <stdio.h>
#include "gmemory.h"
#include "main.h"
#include "gb.image.h"
#include "gb.gtk.h"
#include "watcher.h"
#include "x11.h"
#include "CScreen.h"
#include "CDraw.h"
#include "CConst.h"
#include "CColor.h"
#include "CFont.h"
#include "CKey.h"
#include "CPicture.h"
#include "CImage.h"
#include "CClipboard.h"
#include "CMouse.h"
#include "CMessage.h"
#include "CDialog.h"
#include "CWatcher.h"
#include "CWidget.h"
#include "CProgress.h"
#include "CDrawingArea.h"
#include "CContainer.h"
#include "CFrame.h"
#include "CMenu.h"
#include "CWindow.h"
#include "CLabel.h"
#include "CButton.h"
#include "CPictureBox.h"
#include "CTextBox.h"
#include "CTextArea.h"
#include "CListBox.h"
#include "CTreeView.h"
#include "CSlider.h"
#include "CTabStrip.h"
#include "CTrayIcon.h"
#include "CScrollView.h"
#include "CSpinBox.h"
#include "CSplitter.h"
#include "CStock.h"
#include "CIconView.h"
#include "CGridView.h"
#include "CSeparator.h"
#include "cprinter.h"
#include "csvgimage.h"
#include <gtk/gtk.h>
#include <string.h>
GB_CLASS CLASS_Picture;
GB_CLASS CLASS_Image;
GB_CLASS CLASS_DrawingArea;
GB_CLASS CLASS_Menu;
GB_CLASS CLASS_Window;
GB_CLASS CLASS_Printer;
GB_CLASS CLASS_SvgImage;
static void my_lang(char *lang,int rtl1);
static void my_error(int code,char *error,char *where);
static void my_quit (void);
static void my_main(int *argc, char **argv);
static void my_timer(GB_TIMER *timer,bool on);
static void my_wait(int duration);
static void my_post(void);
static int my_loop();
static void my_watch(int fd, int type, void *callback, intptr_t param);
static bool post_Check=false;
static bool _application_keypress = false;
static GB_FUNCTION _application_keypress_func;
int MAIN_scale = 0;
extern "C"
{
GB_INTERFACE GB EXPORT;
IMAGE_INTERFACE IMAGE EXPORT;
GB_DESC *GB_CLASSES[] EXPORT =
{
CDesktopDesc,
CApplicationTooltipDesc,
CApplicationDesc,
CSelectDesc,
CAlignDesc,
CArrangeDesc,
CBorderDesc,
CScrollDesc,
CLineDesc,
CFillDesc,
CColorDesc,
CFontsDesc,
CFontDesc,
CKeyDesc,
CImageDesc,
CPictureDesc,
CClipboardDesc,
CDragDesc,
CCursorDesc,
CMouseDesc,
CMessageDesc,
CDialogDesc,
CWatcherDesc,
CWidgetDesc,
CChildrenDesc,
CContainerDesc,
CDrawingAreaDesc,
CFrameDesc,
CHSplitDesc,
CVSplitDesc,
CUserControlDesc,
CUserContainerDesc,
CPanelDesc,
CHBoxDesc,
CVBoxDesc,
CHPanelDesc,
CVPanelDesc,
CMenuDesc,
CMenuChildrenDesc,
CTrayIconDesc,
CTrayIconsDesc,
CWindowMenusDesc,
CWindowControlsDesc,
CWindowTypeDesc,
CWindowDesc,
CWindowsDesc,
CFormDesc,
CProgressDesc,
CLabelDesc,
CTextLabelDesc,
CSliderDesc,
CScrollBarDesc,
CButtonDesc,
CToggleButtonDesc,
CCheckBoxDesc,
CRadioButtonDesc,
CToolButtonDesc,
CPictureBoxDesc,
CMovieBoxDesc,
CListBoxDesc,
CListBoxItemDesc,
CTextBoxSelectionDesc,
CTextBoxDesc,
CTextAreaDesc,
CTextAreaSelectionDesc,
CComboBoxDesc,
CComboBoxItemDesc,
CListViewItemDesc,
CListViewDesc,
CTreeViewItemDesc,
CTreeViewDesc,
CIconViewItemDesc,
CIconViewDesc,
CColumnViewItemDesc,
CColumnViewColumnDesc,
CColumnViewColumnsDesc,
CColumnViewDesc,
CTabStripDesc,
CTabDesc,
CTabChildrenDesc,
CPluginDesc,
CScrollViewDesc,
CSpinBoxDesc,
CSeparatorDesc,
CGridViewItemDesc,
CGridViewDataDesc,
CGridViewColumnDesc,
CGridViewRowDesc,
CGridViewColumnsDesc,
CGridViewRowsDesc,
CGridViewDesc,
CStockDesc,
PrinterDesc,
SvgImageDesc,
NULL
};
void *GB_GTK_1[] EXPORT =
{
(void *)GTK_INTERFACE_VERSION,
(void *)my_main,
(void *)GTK_GetPicture,
(void *)GTK_GetImage,
(void *)CGRIDVIEW_footer,
(void *)CGRIDVIEW_column_footer_text,
(void *)CGRIDVIEW_columns_get,
(void *)DRAW_get_drawable,
(void *)DRAW_get_style,
(void *)DRAW_get_state,
(void *)DRAW_get_shadow,
(void *)DRAW_set_state,
(void *)DRAW_set_shadow,
NULL
};
const char *GB_INCLUDE EXPORT = "gb.draw";
int EXPORT GB_INIT(void)
{
GB.Hook(GB_HOOK_QUIT, (void *)my_quit);
GB.Hook(GB_HOOK_MAIN, (void *)my_main);
GB.Hook(GB_HOOK_WAIT, (void *)my_wait);
GB.Hook(GB_HOOK_LOOP, (void *)my_loop);
GB.Hook(GB_HOOK_TIMER,(void *)my_timer);
GB.Hook(GB_HOOK_WATCH,(void *)my_watch);
GB.Hook(GB_HOOK_POST,(void*)my_post);
GB.Hook(GB_HOOK_ERROR,(void*)my_error);
GB.Hook(GB_HOOK_LANG,(void*)my_lang);
// Thanks again to GTK+ 2.18 :-(
#if GTK_MAJOR_VERSION >= 2 && GTK_MINOR_VERSION >= 18
//putenv((char *)"GDK_NATIVE_WINDOWS=1");
#endif
GB.LoadComponent("gb.draw");
GB.GetInterface("gb.image", IMAGE_INTERFACE_VERSION, &IMAGE);
IMAGE.SetDefaultFormat(GB_IMAGE_RGBA);
DRAW_init();
CWatcher::init();
//CLASS_Control = GB.FindClass("Control");
//CLASS_Container = GB.FindClass("Container");
//CLASS_UserControl = GB.FindClass("UserControl");
//CLASS_UserContainer = GB.FindClass("UserContainer");
CLASS_Window = GB.FindClass("Window");
CLASS_Menu = GB.FindClass("Menu");
CLASS_Picture = GB.FindClass("Picture");
//CLASS_Drawing = GB.FindClass("Drawing");
CLASS_DrawingArea = GB.FindClass("DrawingArea");
CLASS_Printer = GB.FindClass("Printer");
CLASS_Image = GB.FindClass("Image");
CLASS_SvgImage = GB.FindClass("SvgImage");
return -1;
}
void EXPORT GB_EXIT()
{
CWatcher::exit();
}
int EXPORT GB_INFO(const char *key, void **value)
{
if (!strcasecmp(key, "DISPLAY"))
{
#ifdef GDK_WINDOWING_X11
#ifndef GAMBAS_DIRECTFB
*value = (void *)gdk_x11_display_get_xdisplay(gdk_display_get_default());
#else
// For DirectFB
*value=0;
stub("DIRECTFB/EXPORT GB_INFO");
#endif
#else
// For Win32
*value=0;
stub("no-X11/EXPORT GB_INFO");
#endif
return TRUE;
}
else if (!strcasecmp(key, "ROOT_WINDOW"))
{
#ifdef GDK_WINDOWING_X11
#ifndef GAMBAS_DIRECTFB
*value = (void *)gdk_x11_get_default_root_xwindow();
#else
// For DirectFB
*value=0;
stub("DIRECTFB/EXPORT GB_INFO");
#endif
#else
// For Win32
*value=0;
stub("no-X11/EXPORT GB_INFO");
#endif
return TRUE;
}
else
return FALSE;
}
}
void my_quit (void)
{
CWINDOW *win=WINDOW_get_main();
gApplication::suspendEvents(false);
if (win)
{
while (gtk_events_pending ()) gtk_main_iteration();
if (win->ob.widget) ((gMainWindow*)win->ob.widget)->destroy();
while (gtk_events_pending ()) gtk_main_iteration();
}
}
static bool global_key_event_handler(int type)
{
GB.Call(&_application_keypress_func, 0, FALSE);
return GB.Stopped();
}
static void my_main(int *argc, char **argv)
{
static bool init = false;
if (init)
return;
gApplication::init(argc, &argv);
gApplication::setDefaultTitle(GB.Application.Title());
gDesktop::init();
MAIN_scale = gDesktop::scale();
#ifdef GDK_WINDOWING_X11
X11_init(gdk_x11_display_get_xdisplay(gdk_display_get_default()), gdk_x11_get_default_root_xwindow());
#endif
if (GB.GetFunction(&_application_keypress_func, (void *)GB.Application.StartupClass(), "Application_KeyPress", "", "") == 0)
{
_application_keypress = true;
gApplication::onKeyEvent = global_key_event_handler;
}
init = true;
}
/*static void raise_timer(GB_TIMER *timer)
{
GB.RaiseTimer(timer);
GB.Unref(POINTER(&timer));
}*/
typedef
struct {
GTimer *timer;
int timeout;
}
MyTimerTag;
gboolean my_timer_function(GB_TIMER *timer)
{
if (timer->id)
{
GB.RaiseTimer(timer);
if (timer->id)
{
MyTimerTag *tag = (MyTimerTag *)timer->tag;
GTimer *t = tag->timer;
int elapsed = (int)(g_timer_elapsed(t, NULL) * 1000) - tag->timeout;
int next = timer->delay - elapsed;
if (next < 10)
next = 10;
tag->timeout = next;
g_timer_start(t);
timer->id = (intptr_t)g_timeout_add(next, (GSourceFunc)my_timer_function,(gpointer)timer);
//fprintf(stderr, "elapsed = %d delay = %d next = %d\n", elapsed, timer->delay, next);
}
}
return false;
}
static void my_timer(GB_TIMER *timer,bool on)
{
if (timer->id) {
MyTimerTag *tag = (MyTimerTag *)timer->tag;
g_source_remove(timer->id);
g_timer_destroy(tag->timer);
g_free(tag);
timer->id = 0;
timer->tag = 0;
}
if (on)
{
MyTimerTag *tag = g_new(MyTimerTag, 1);
tag->timer = g_timer_new();
tag->timeout = timer->delay;
timer->tag = (intptr_t)tag;
timer->id = (intptr_t)g_timeout_add(timer->delay,(GSourceFunc)my_timer_function,(gpointer)timer);
return;
}
}
static void my_post(void)
{
post_Check=true;
}
static bool must_quit(void)
{
//fprintf(stderr, "must_quit: %p %d\n", WINDOW_get_main(), CWatcher::count());
return !WINDOW_get_main() && CWatcher::count() == 0; // && in_event_loop;
}
static int my_loop()
{
gControl::cleanRemovedControls();
while (!must_quit())
do_iteration(false);
while (gtk_events_pending ()) gtk_main_iteration();
CWatcher::Clear();
gApplication::exit();
return 0;
}
static void my_wait(int duration)
{
do_iteration(true, true);
}
static void my_watch(int fd, int type, void *callback, intptr_t param)
{
CWatcher::Add(fd,type,callback,param);
}
static void my_error(int code,char *error,char *where)
{
char *showstr;
char scode[10];
sprintf(scode,"%d",code);
showstr=g_strconcat("<b>This application has raised an unexpected<br>error and must abort.</b><p>[", scode, "] ", error, ".\n", where, (void *)NULL);
gMessage::setTitle(GB.Application.Title());
gMessage::showError(showstr,NULL,NULL,NULL);
g_free(showstr);
}
static void my_lang(char *lang,int rtl)
{
int bucle, ct;
gControl *iter;
if (rtl==1)
gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL);
else
gtk_widget_set_default_direction(GTK_TEXT_DIR_LTR);
ct=gApplication::controlCount();
for (bucle=0;bucle<ct;bucle++)
{
iter=gApplication::controlItem(bucle);
if (iter->isVisible() && iter->isContainer())
((gContainer*)iter)->performArrange();
}
}
void do_iteration(bool do_not_block, bool do_not_sleep)
{
struct timespec mywait;
gApplication::_loopLevel++;
if (do_not_block)
{
if (gtk_events_pending ())
gtk_main_iteration_do (false);
else if (!do_not_sleep)
{
mywait.tv_sec=0;
mywait.tv_nsec=100000;
nanosleep(&mywait,NULL);
}
}
else
gtk_main_iteration_do(true);
gApplication::_loopLevel--;
if (post_Check) { post_Check=false; GB.CheckPost(); }
gControl::cleanRemovedControls();
}