"Fossies" - the Fresh Open Source Software Archive

Member "gambas-3.16.3/gb.gtk/src/main.cpp" (7 Sep 2021, 14761 Bytes) of package /linux/misc/gambas-3.16.3.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "main.cpp": 3.16.2_vs_3.16.3.

    1 /***************************************************************************
    2 
    3   main.cpp
    4 
    5   (c) 2004-2006 - Daniel Campos Fernández <dcamposf@gmail.com>
    6 
    7   This program is free software; you can redistribute it and/or modify
    8   it under the terms of the GNU General Public License as published by
    9   the Free Software Foundation; either version 2, or (at your option)
   10   any later version.
   11 
   12   This program is distributed in the hope that it will be useful,
   13   but WITHOUT ANY WARRANTY; without even the implied warranty of
   14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15   GNU General Public License for more details.
   16 
   17   You should have received a copy of the GNU General Public License
   18   along with this program; if not, write to the Free Software
   19   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
   20   MA 02110-1301, USA.
   21 
   22 ***************************************************************************/
   23 
   24 #define __MAIN_C
   25 
   26 #include <stdio.h>
   27 
   28 #include "main.h"
   29 #include "gb.image.h"
   30 #include "gb.gtk.h"
   31 #include "watcher.h"
   32 #include "gglarea.h"
   33 #include "gkey.h"
   34 
   35 #include "x11.h"
   36 #include "desktop.h"
   37 #include "CScreen.h"
   38 #include "CStyle.h"
   39 #include "CDraw.h"
   40 #include "CConst.h"
   41 #include "CColor.h"
   42 #include "CFont.h"
   43 #include "CKey.h"
   44 #include "CPicture.h"
   45 #include "CImage.h"
   46 #include "CClipboard.h"
   47 #include "CMouse.h"
   48 #include "CDialog.h"
   49 #include "CWatcher.h"
   50 #include "CWidget.h"
   51 #include "CDrawingArea.h"
   52 #include "CContainer.h"
   53 #include "CPanel.h"
   54 #include "CMenu.h"
   55 #include "CWindow.h"
   56 #include "CButton.h"
   57 #include "CTextBox.h"
   58 #include "CTextArea.h"
   59 #include "CSlider.h"
   60 #include "CTabStrip.h"
   61 #include "CTrayIcon.h"
   62 #include "cprinter.h"
   63 #include "csvgimage.h"
   64 #include "canimation.h"
   65 
   66 #include <gtk/gtk.h>
   67 #include <string.h>
   68 
   69 GB_CLASS CLASS_Control;
   70 GB_CLASS CLASS_ContainerChildren;
   71 GB_CLASS CLASS_UserControl;
   72 GB_CLASS CLASS_UserContainer;
   73 GB_CLASS CLASS_Picture;
   74 GB_CLASS CLASS_Image;
   75 GB_CLASS CLASS_DrawingArea;
   76 GB_CLASS CLASS_Menu;
   77 GB_CLASS CLASS_Window;
   78 GB_CLASS CLASS_Printer;
   79 GB_CLASS CLASS_SvgImage;
   80 
   81 static void hook_lang(char *lang, int rtl1);
   82 static bool hook_error(int code, char *error, char *where, bool can_ignore);
   83 static void hook_quit(void);
   84 static void hook_main(int *argc, char ***argv);
   85 static void hook_timer(GB_TIMER *timer,bool on);
   86 static void hook_wait(int duration);
   87 static void hook_post(void);
   88 static int hook_loop();
   89 static void hook_watch(int fd, int type, void *callback, intptr_t param);
   90 
   91 static bool _post_check = false;
   92 static bool _must_check_quit = false;
   93 
   94 static bool _application_keypress = false;
   95 static GB_FUNCTION _application_keypress_func;
   96 
   97 static void *_old_hook_main;
   98 
   99 bool MAIN_display_x11 = FALSE;
  100 int MAIN_scale = 0;
  101 bool MAIN_debug_busy = false;
  102 bool MAIN_rtl = false;
  103 
  104 //-------------------------------------------------------------------------
  105 
  106 static void GTK_CreateControl(CWIDGET *ob, void *parent, GtkWidget *widget)
  107 {
  108     gControl *ctrl;
  109     bool recreate;
  110     
  111     if (!parent)
  112     {
  113         recreate = true;
  114         ctrl = ob->widget;
  115         ctrl->parent()->remove(ctrl);
  116         ctrl->createBorder(widget);
  117     }
  118     else
  119     {
  120         recreate = false;
  121         ctrl = new gControl(CONTAINER(parent));
  122         ctrl->border = widget;
  123     }
  124     
  125     ctrl->widget = ctrl->border;
  126     InitControl(ctrl, ob);
  127     ctrl->realize();
  128     ctrl->_has_input_method = TRUE;
  129     
  130     if (recreate)
  131         ctrl->updateGeometry(true);
  132 }
  133 
  134 static GtkWidget *GTK_CreateGLArea(void *_object, void *parent, void (*init)(GtkWidget *))
  135 {
  136     gControl *ctrl = new gGLArea(CONTAINER(parent), init);
  137     InitControl(ctrl, (CWIDGET *)_object);
  138     //WIDGET->onExpose = Darea_Expose;
  139     return ctrl->widget;
  140 }
  141 
  142 static void *GTK_CreatePicture(cairo_surface_t *surf, int w, int h)
  143 {
  144     gPicture *p = new gPicture(surf);
  145     
  146     if (w > 0 && h > 0)
  147     {
  148         gPicture *p2 = p->stretch(w, h, true);
  149         p->unref();
  150         p = p2;
  151     }
  152     
  153     return CPICTURE_create(p);
  154 }
  155 
  156 static int GTK_GetDesktopScale(void)
  157 {
  158     return MAIN_scale;
  159 }
  160 
  161 
  162 //-------------------------------------------------------------------------
  163 
  164 extern "C"
  165 {
  166 
  167 const GB_INTERFACE *GB_PTR EXPORT;
  168 IMAGE_INTERFACE IMAGE EXPORT;
  169 GEOM_INTERFACE GEOM EXPORT;
  170 
  171 static void declare_tray_icon()
  172 {
  173     GB.Component.Declare(TrayIconsDesc);
  174     GB.Component.Declare(TrayIconDesc);
  175 }
  176 
  177 GB_DESC *GB_CLASSES[] EXPORT =
  178 {
  179     ScreenDesc,
  180     ScreensDesc,
  181     DesktopDesc,
  182     ApplicationDesc,
  183     StyleDesc,
  184     CSelectDesc,
  185     CAlignDesc,
  186     CArrangeDesc,
  187     CBorderDesc,
  188     CScrollDesc,
  189     CColorDesc,
  190     CFontsDesc,
  191     CFontDesc,
  192     CKeyDesc,
  193     CImageDesc,
  194     CPictureDesc,
  195     AnimationDesc,
  196     CClipboardDesc,
  197     CDragDesc,
  198     CCursorDesc,
  199     CMouseDesc,
  200     CPointerDesc,
  201     CDialogDesc,
  202     CWatcherDesc,
  203     CWidgetDesc,
  204     ContainerChildrenDesc,
  205     ContainerDesc,
  206     CDrawingAreaDesc,
  207     UserControlDesc,
  208     UserContainerDesc,
  209     CPanelDesc,
  210     CHBoxDesc,
  211     CVBoxDesc,
  212     CHPanelDesc,
  213     CVPanelDesc,
  214     CMenuDesc,
  215     CMenuChildrenDesc,
  216     CWindowMenusDesc,
  217     CWindowControlsDesc,
  218     CWindowDesc,
  219     CWindowsDesc,
  220     CFormDesc,
  221     SliderDesc,
  222     ScrollBarDesc,
  223     CButtonDesc,
  224     CToggleButtonDesc,
  225     CCheckBoxDesc,
  226     CRadioButtonDesc,
  227     CToolButtonDesc,
  228     CTextBoxSelectionDesc,
  229     CTextBoxDesc,
  230     CTextAreaDesc,
  231     CTextAreaSelectionDesc,
  232     CComboBoxDesc,
  233     CComboBoxItemDesc,
  234     CTabStripDesc,
  235     CTabStripContainerDesc,
  236     CTabStripContainerChildrenDesc,
  237     CPluginDesc,
  238     PrinterDesc,
  239     SvgImageDesc,
  240     NULL
  241 };
  242 
  243 #ifdef GTK3
  244 void *GB_GTK3_1[] EXPORT =
  245 #else
  246 void *GB_GTK_1[] EXPORT =
  247 #endif
  248 {
  249     (void *)GTK_INTERFACE_VERSION,
  250     (void *)GTK_CreateControl,
  251     (void *)GTK_CreateGLArea,
  252     (void *)GTK_CreatePicture,
  253     (void *)GTK_GetDesktopScale,
  254     NULL
  255 };
  256 
  257 const char *GB_INCLUDE EXPORT = "gb.draw,gb.gui.base";
  258 
  259 int EXPORT GB_INIT(void)
  260 {
  261     char *env;
  262 
  263     env = getenv("GB_GUI_BUSY");
  264     if (env && atoi(env))
  265         MAIN_debug_busy = true;
  266 
  267     putenv((char *)"GTK_OVERLAY_SCROLLING=0");
  268     
  269     GB.Hook(GB_HOOK_QUIT, (void *)hook_quit);
  270     _old_hook_main = GB.Hook(GB_HOOK_MAIN, (void *)hook_main);
  271     GB.Hook(GB_HOOK_WAIT, (void *)hook_wait);
  272     GB.Hook(GB_HOOK_TIMER,(void *)hook_timer);
  273     GB.Hook(GB_HOOK_WATCH,(void *)hook_watch);
  274     GB.Hook(GB_HOOK_POST,(void*)hook_post);
  275     GB.Hook(GB_HOOK_ERROR,(void*)hook_error);
  276     GB.Hook(GB_HOOK_LANG,(void*)hook_lang);
  277     GB.Hook(GB_HOOK_LOOP, (void *)hook_loop);
  278 
  279     GB.Component.Load("gb.draw");
  280     GB.Component.Load("gb.image");
  281     GB.Component.Load("gb.gui.base");
  282 
  283     GB.GetInterface("gb.image", IMAGE_INTERFACE_VERSION, &IMAGE);
  284     GB.GetInterface("gb.geom", GEOM_INTERFACE_VERSION, &GEOM);
  285 
  286     GB.Signal.MustCheck(SIGCHLD);
  287     
  288     IMAGE.SetDefaultFormat(GB_IMAGE_RGBA);
  289     DRAW_init();
  290 
  291     CWatcher::init();
  292 
  293     CLASS_Control = GB.FindClass("Control");
  294     CLASS_ContainerChildren = GB.FindClass("ContainerChildren");
  295     CLASS_UserControl = GB.FindClass("UserControl");
  296     CLASS_UserContainer = GB.FindClass("UserContainer");
  297     CLASS_Window = GB.FindClass("Window");
  298     CLASS_Menu = GB.FindClass("Menu");
  299     CLASS_Picture = GB.FindClass("Picture");
  300     //CLASS_Drawing = GB.FindClass("Drawing");
  301     CLASS_DrawingArea = GB.FindClass("DrawingArea");
  302     CLASS_Printer = GB.FindClass("Printer");
  303     CLASS_Image = GB.FindClass("Image");
  304     CLASS_SvgImage = GB.FindClass("SvgImage");
  305 
  306 #if !defined(GLIB_VERSION_2_36)
  307     g_type_init();
  308 #endif /* !defined(GLIB_VERSION_2_36) */
  309 
  310     hook_lang(GB.System.Language(), GB.System.IsRightToLeft());
  311 
  312     return -1;
  313 }
  314 
  315 void EXPORT GB_EXIT()
  316 {
  317     CWatcher::exit();
  318 }
  319 
  320 int EXPORT GB_INFO(const char *key, void **value)
  321 {
  322     if (MAIN_display_x11)
  323     {
  324         if (!strcasecmp(key, "DISPLAY"))
  325         {
  326             *value = (void *)gdk_x11_display_get_xdisplay(gdk_display_get_default());
  327             return TRUE;
  328         }
  329         else if (!strcasecmp(key, "ROOT_WINDOW"))
  330         {
  331             *value = (void *)gdk_x11_get_default_root_xwindow();
  332             return TRUE;
  333         }
  334     }
  335 
  336     if (!strcasecmp(key, "GET_HANDLE"))
  337     {
  338         *value = (void *)CWIDGET_get_handle;
  339         return TRUE;
  340     }
  341     else if (!strcasecmp(key, "SET_EVENT_FILTER"))
  342     {
  343         *value = (void *)gApplication::setEventFilter;
  344         return TRUE;
  345     }
  346     else if (!strcasecmp(key, "TIME"))
  347     {
  348         *value = (void *)(intptr_t)gtk_get_current_event_time(); //gdk_x11_display_get_user_time(gdk_display_get_default());
  349         return TRUE;
  350     }
  351     else if (!strcasecmp(key, "DECLARE_TRAYICON"))
  352     {
  353         *value = (void *)declare_tray_icon;
  354         return TRUE;
  355     }
  356     else
  357         return FALSE;
  358 }
  359 
  360 static void activate_main_window(intptr_t)
  361 {
  362     if (gMainWindow::_active)
  363         gtk_window_present(GTK_WINDOW(gMainWindow::_active->topLevel()->border));
  364 }
  365 
  366 void EXPORT GB_SIGNAL(int signal, void *param)
  367 {
  368     static GtkWidget *save_popup_grab = NULL;
  369 
  370     switch(signal)
  371     {
  372         case GB_SIGNAL_DEBUG_BREAK:
  373             if (gApplication::_popup_grab)
  374             {
  375                 save_popup_grab = gApplication::_popup_grab;
  376                 gApplication::ungrabPopup();
  377             }
  378             break;
  379 
  380         case GB_SIGNAL_DEBUG_FORWARD:
  381             //while (qApp->activePopupWidget())
  382             //  delete qApp->activePopupWidget();
  383             if (gdk_display_get_default())
  384             gdk_display_sync(gdk_display_get_default());
  385             break;
  386 
  387         case GB_SIGNAL_DEBUG_CONTINUE:
  388             GB.Post((GB_CALLBACK)activate_main_window, 0);
  389             if (save_popup_grab)
  390             {
  391                 gApplication::_popup_grab = save_popup_grab;
  392                 save_popup_grab = NULL;
  393                 gApplication::grabPopup();
  394             }
  395             break;
  396     }
  397 }
  398 
  399 } // extern "C"
  400 
  401 void hook_quit (void)
  402 {
  403     GB_FUNCTION func;
  404 
  405     while (gtk_events_pending())
  406         gtk_main_iteration();
  407 
  408     if (GB.ExistClass("TrayIcons"))
  409     {
  410         if (!GB.GetFunction(&func, (void *)GB.FindClass("TrayIcons"), "DeleteAll", NULL, NULL))
  411             GB.Call(&func, 0, FALSE);
  412     }
  413 
  414     if (!GB.GetFunction(&func, (void *)GB.FindClass("_Gui"), "_Quit", NULL, NULL))
  415         GB.Call(&func, 0, FALSE);
  416 
  417     CWINDOW_delete_all();
  418     gControl::postDelete();
  419 
  420     //CWatcher::Clear();
  421     gApplication::exit();
  422 
  423     #ifdef GDK_WINDOWING_X11
  424         if (MAIN_display_x11)
  425             X11_exit();
  426   #endif
  427 }
  428 
  429 static bool global_key_event_handler(int type)
  430 {
  431     GB.Call(&_application_keypress_func, 0, FALSE);
  432     return GB.Stopped();
  433 }
  434 
  435 static void hook_main(int *argc, char ***argv)
  436 {
  437     static bool init = false;
  438     char *env;
  439 
  440     if (init)
  441         return;
  442 
  443     env = getenv("GB_X11_INIT_THREADS");
  444     if (env && atoi(env))
  445         XInitThreads();
  446 
  447     gtk_init(argc, argv);
  448     gApplication::init(argc, argv);
  449     gApplication::setDefaultTitle(GB.Application.Title());
  450     gDesktop::init();
  451 
  452     gApplication::onEnterEventLoop = GB.Debug.EnterEventLoop;
  453     gApplication::onLeaveEventLoop = GB.Debug.LeaveEventLoop;
  454 
  455     MAIN_scale = gDesktop::scale();
  456     #ifdef GDK_WINDOWING_X11
  457         #ifdef GTK3
  458         if (GDK_IS_X11_DISPLAY(gdk_display_get_default()))
  459         #endif
  460         {
  461             X11_init(gdk_x11_display_get_xdisplay(gdk_display_get_default()), gdk_x11_get_default_root_xwindow());
  462             MAIN_display_x11 = TRUE;
  463         }
  464   #endif
  465 
  466     if (GB.GetFunction(&_application_keypress_func, (void *)GB.Application.StartupClass(), "Application_KeyPress", "", "") == 0)
  467     {
  468         _application_keypress = true;
  469         gApplication::onKeyEvent = global_key_event_handler;
  470     }
  471 
  472     init = true;
  473     
  474     CALL_HOOK_MAIN(_old_hook_main, argc, argv);
  475 }
  476 
  477 /*static void raise_timer(GB_TIMER *timer)
  478 {
  479     GB.RaiseTimer(timer);
  480     GB.Unref(POINTER(&timer));
  481 }*/
  482 
  483 typedef
  484     struct {
  485         int source;
  486         GTimer *timer;
  487         int timeout;
  488         }
  489     MyTimerId;
  490 
  491 gboolean hook_timer_function(GB_TIMER *timer)
  492 {
  493     if (timer->id)
  494     {
  495         GB.RaiseTimer(timer);
  496 
  497         if (timer->id)
  498         {
  499             MyTimerId *id = (MyTimerId *)timer->id;
  500             GTimer *t = id->timer;
  501             int elapsed = (int)(g_timer_elapsed(t, NULL) * 1000) - id->timeout;
  502             int next = timer->delay - elapsed;
  503             if (next < 10)
  504                 next = 10;
  505             id->timeout = next;
  506             g_timer_start(t);
  507             id->source = g_timeout_add(next, (GSourceFunc)hook_timer_function,(gpointer)timer);
  508             //timer->id = (intptr_t)g_timeout_add(next, (GSourceFunc)hook_timer_function,(gpointer)timer);
  509             //fprintf(stderr, "elapsed = %d  delay = %d  next = %d\n", elapsed, timer->delay, next);
  510         }
  511     }
  512 
  513     return false;
  514 }
  515 
  516 static void hook_timer(GB_TIMER *timer,bool on)
  517 {
  518     if (timer->id)
  519     {
  520         MyTimerId *id = (MyTimerId *)timer->id;
  521         g_source_remove(id->source);
  522         g_timer_destroy(id->timer);
  523         g_free(id);
  524         timer->id = 0;
  525     }
  526 
  527     if (on)
  528     {
  529         MyTimerId *id = g_new(MyTimerId, 1);
  530         id->timer = g_timer_new();
  531         id->timeout = timer->delay;
  532         id->source = (intptr_t)g_timeout_add(timer->delay,(GSourceFunc)hook_timer_function,(gpointer)timer);
  533         timer->id = (intptr_t)id;
  534         return;
  535     }
  536 }
  537 
  538 static void hook_post(void)
  539 {
  540     _post_check = true;
  541 }
  542 
  543 void MAIN_check_quit()
  544 {
  545     _must_check_quit = true;
  546 }
  547 
  548 static int hook_loop()
  549 {
  550     gControl::postDelete();
  551     _must_check_quit = true;
  552 
  553     for(;;)
  554     {
  555         if (_must_check_quit)
  556         {
  557             if (gApplication::mustQuit())
  558                 break;
  559             if (CWINDOW_must_quit() && CWatcher::count() == 0 && gTrayIcon::visibleCount() == 0)
  560                 break;
  561             _must_check_quit = false;
  562         }
  563         MAIN_do_iteration(false);
  564     }
  565 
  566     hook_quit();
  567 
  568   return 0;
  569 }
  570 
  571 static void hook_wait(int duration)
  572 {
  573     static bool _warning = FALSE;
  574     
  575     if (gDrawingArea::inAnyDrawEvent())
  576     {
  577         GB.Error("Wait is forbidden during a repaint event");
  578         return;
  579     }
  580 
  581     if (duration && gKey::isValid())
  582     {
  583         if (!_warning)
  584         {
  585             fprintf(stderr, "gb.gtk: warning: calling the event loop during a keyboard event handler is ignored\n");
  586             _warning = TRUE;
  587         }
  588         return;
  589     }
  590 
  591     if (duration == 0)
  592     {
  593         while (gtk_events_pending())
  594             MAIN_do_iteration(false);
  595     }
  596     else
  597         MAIN_do_iteration(duration > 0);
  598 }
  599 
  600 static void hook_watch(int fd, int type, void *callback, intptr_t param)
  601 {
  602     CWatcher::Add(fd,type,callback,param);
  603 }
  604 
  605 static bool hook_error(int code, char *error, char *where, bool can_ignore)
  606 {
  607     gMainWindow *active;
  608     GtkWidget *dialog;
  609     char *msg;
  610     char scode[16];
  611     gint res;
  612 
  613     if (code > 0)
  614         sprintf(scode, " (#%d)", code);
  615     else
  616         *scode = 0;
  617     
  618     msg = g_strconcat("<b>This application has raised an unexpected error and must abort.</b>\n\n", error, scode, ".\n\n<tt>", where, "</tt>", NULL);
  619 
  620     dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_NONE, NULL);
  621     gtk_message_dialog_set_markup(GTK_MESSAGE_DIALOG(dialog), msg);
  622     if (can_ignore)
  623         gtk_dialog_add_button(GTK_DIALOG(dialog), GB.Translate("Ignore"), 2);
  624     gtk_dialog_add_button(GTK_DIALOG(dialog), GB.Translate("Close"), 1);
  625     
  626     active = gDesktop::activeWindow();
  627     if (active)
  628     gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(active->border));
  629     
  630     res = gtk_dialog_run(GTK_DIALOG(dialog));
  631     
  632     gtk_widget_destroy(dialog);
  633     
  634     g_free(msg);
  635     return (res == 2);
  636 }
  637 
  638 static void cb_update_lang(gControl *control)
  639 {
  640     if (control->isVisible() && control->isContainer())
  641         ((gContainer*)control)->performArrange();
  642 }
  643 
  644 static void hook_lang(char *lang, int rtl)
  645 {
  646     MAIN_rtl = rtl;
  647 
  648     if (rtl)
  649         gtk_widget_set_default_direction(GTK_TEXT_DIR_RTL);
  650     else
  651         gtk_widget_set_default_direction(GTK_TEXT_DIR_LTR);
  652     
  653     gApplication::forEachControl(cb_update_lang);
  654 }
  655 
  656 void MAIN_do_iteration_just_events()
  657 {
  658     if (gtk_events_pending())
  659         gtk_main_iteration_do(false);
  660 }
  661 
  662 void MAIN_do_iteration(bool do_not_block)
  663 {
  664     gApplication::_loopLevel++;
  665 
  666     if (do_not_block)
  667     {
  668         if (gtk_events_pending())
  669             gtk_main_iteration();
  670     }
  671     else
  672         gtk_main_iteration_do(true);
  673 
  674     gApplication::_loopLevel--;
  675 
  676     if (_post_check)
  677     {
  678         _post_check = false;
  679         GB.CheckPost();
  680     }
  681 
  682     gControl::postDelete();
  683     gContainer::postArrange();
  684 }
  685