有没有以类似于在C中使用GTK的小部件的方式打开/查看/与其他程序交互?

时间:2016-08-06 22:43:30

标签: c gtk

所以,在Linux中,我试图让一个基于GTK的程序打开另一个程序,但不是在自己的窗口中打开它,我想把它放在第一个笔记本的新页面中程序。我不知道从哪里开始。以前有人做过这样的事,或者有什么建议吗?

*编辑/更新(2017年1月14日): 我刚刚回过头来搞乱代码,并遇到了障碍。让我先说一下:当我开始这件事时,我知道c的绝对基础知识。我可以毫无困难地写一个花哨的问候世界,但那是关于它的。我用谷歌搜索到了这一点,我不知道我在做什么。我会提前为过于冗长的评论和木头主题道歉,这是为了帮助我保持我认为它的工作方式并且分别在内部笑话中。

我现在已经停止尝试从gtk程序中打开程序了。无论如何,这段代码的想法是它应该监视在桌面上打开的窗口,获取它们的id,并使用它将所述窗口放入gtk套接字然后将其放入笔记本的新选项卡中。我宁愿只能在任何使用X的现有Linux桌面环境上运行它,而不是尝试重写任何DE组件。我也无法修改在桌面上打开窗口的程序代码而不是这个。如果有人能告诉我为什么这段代码不起作用,那将非常有帮助。我也很乐意接受人们想要提供的任何编码指针。正如我所说,我是一个新手。

我用这个编译它(这里的撇号实际上应该是后退,所以 DON' T JUST COPY PASTE THIS!):
gcc 'pkg-config --cflags gtk+-3.0' -o LogTest logtest.c -lX11 'pkg-config --libs gtk+-3.0 gtk+-x11-3.0 gmodule-2.0'

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <math.h>
#include <ctype.h>
#include <gtk/gtk.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gtk/gtkx.h>
#include <X11/Xlibint.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>

#define WOOD "Lumber"

int plywood(int argc, char **argv, int pipe[2])//Not sure what the variables are for, but they are referenced by the gtk initialiser.
{

    close (pipe[1]);//Close the input pipe, sinse we won't be using it.


    //Variables, remember "GtkWidget" acts like a variable type.
    GtkWidget *window_main;//Main window, holds everything.
    GtkWidget *box_main;//Main box, seperates/holds the main notebook.
    GtkWidget *notebook_main;//Main notebook for main things.
    GtkWidget *label_running;//Label for the running notebook.
    GtkWidget *label_open;//
    GtkWidget *notebook_running;//Notebook for running programs.
    GtkWidget *box_running;//Box for containing the running notebook within a tab in the main notebook.
    GtkWidget *ev_box_socket;//This acts to help glue the socket to the box.
    Window xid;//Holds the window id for the program comming from woodglue that we are putting into the running notebook (after some finagling).
    Window check = 0;//Holds the last window id makes sure we are not doing the same thing twice.
    GtkWidget *socket;//This is the thing we stuff the external window into.
    GtkWidget *box_socket;//This holds the socket for input into the other box, to goin the notebook.
    Window plywood = 0;//holds the window id for plywood. it should be the first one to come in.
    GtkWidget *box_placeholder;//This box is a place holder.
    int ftc = 0;//This helps to record what run of the loop we are on.
    double test;

    //Start GTK
    gtk_init(&argc, &argv);//Sets the  groundwork for all of the gtk funtions and such.


    //Making Labels
    label_running = gtk_label_new("Open Windows");//Creats a label with the text "Open Windows".

    gtk_widget_set_hexpand(GTK_WIDGET(label_running), TRUE);//Tells the label to expand in thehorizontal direction if it can.

    label_open = gtk_label_new("test");//Creats a label with the text "test".

    gtk_widget_set_hexpand(GTK_WIDGET(label_open), TRUE);//


    //running programs box
    box_running = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);//Makes a new box, puts it in the variable.


    //Active Programs notebook
    notebook_running = gtk_notebook_new();//Creates a new notebook and puts it into the variable.

    box_placeholder = gtk_button_box_new(GTK_ORIENTATION_VERTICAL);

    gtk_notebook_insert_page(GTK_NOTEBOOK(notebook_running), GTK_WIDGET(box_placeholder), GTK_WIDGET(label_open), 0);//Inserts a placeholder tab into the running notebook.

    gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook_running), GTK_POS_BOTTOM);//Tells the running notebook to put its tabs on the bottom.



    //Main Notebook
    notebook_main = gtk_notebook_new();//Makes a new notebook, the thing with the tabs, and places it in "notebook_main".

    gtk_notebook_insert_page(GTK_NOTEBOOK(notebook_main), GTK_WIDGET(box_running), GTK_WIDGET(label_running), 0);//Puts the running box into the main notebook and names the tab with the running label. Places it withid 0.


    //Main Box
    box_main = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);//Creates and puts a new horizontal box into the "box_main" variable with "0" pixles spacing its contents.


    //Building the darn window
    window_main = gtk_window_new(GTK_WINDOW_TOPLEVEL);//Creates and places the main window,"wood_GUI" into the variable "window_main".

    gtk_window_set_title(GTK_WINDOW(window_main), WOOD);//Names window_main after the latest version, defined by "WOOD".

    gtk_window_set_default_size(GTK_WINDOW(window_main), 800, 480);//Window size in pixles (object, width, hight).

    gtk_container_set_border_width(GTK_CONTAINER(window_main), 0);//Sets the border width of "window_main" to "0", making it as small as possible.

    gtk_window_set_position(GTK_WINDOW(window_main), GTK_WIN_POS_CENTER_ALWAYS);//Tells the "window_main" to always apear in the center of the screen.


    //Packing
    gtk_box_pack_start(GTK_BOX(box_running), GTK_WIDGET(notebook_running), TRUE, TRUE, 0);//Puts the running notebook into the running box lest it expand and tells it to fill the space. Also places it in the first slot.

    gtk_box_pack_start(GTK_BOX(box_main), GTK_WIDGET(notebook_main), TRUE, TRUE, 0);//In order, this selects "box_main" and places "nootebook_main" within it, left to right or top to bottom, depending on box orientation; it then sets its ability to expand if given extra space to "TRUE" and its directive to fill the space it is givin to "TRUE"; Finnally, it sets the spacing between sections in the box to "0".

    gtk_container_add(GTK_CONTAINER(window_main), box_main);//Adds "box_main" to the "window_main" container.


    //Connect signals
    g_signal_connect(window_main, "delete_event", G_CALLBACK(gtk_main_quit), NULL);//This makes sure the program closes when the window is closed. No idea how it works.


    //Show what we made.
    gtk_widget_show_all(window_main);//Shows the window. All widgets within shown by default.


    printf("\n\nAbout to start GTK loop.\n\n");

    //Loop
    for(;;)//Forever...
    {

        //gtk_main_iteration_do(0);//Handle the next gtk event. 

        read(pipe[0], &xid, sizeof(xid));//Read the window id into xid from the pipe.

        //printf("\n\nAbout to run GTK loop.\n\n");


        if(xid != 0 && xid != check && xid != plywood)//If the xid is not 0, and not the same as the last one, and not the plywood window...
        {
            test = xid;


            printf("\n\nRead a valid id, it was %lf.\n\n", test);

            if(ftc != 0)//If this is not the first run...
            {
                socket = gtk_socket_new();//Creates a new socket.

                ev_box_socket = gtk_event_box_new();//Creates a new event box for the socket.

                box_socket = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);//creates a new box for the event box.

                gtk_container_add(GTK_CONTAINER(ev_box_socket), socket);//Puts the socket into the socket event box.

                gtk_container_add(GTK_CONTAINER(box_socket), ev_box_socket);//Puts the socket event box into the socket box.

                gtk_box_pack_start(GTK_BOX(box_socket), GTK_WIDGET(ev_box_socket), TRUE, TRUE, 0);

                gtk_notebook_insert_page(GTK_NOTEBOOK(notebook_running), GTK_WIDGET(box_socket), GTK_WIDGET(label_open), 1);//Adds a pag with the prepared socket box and socket.

                gtk_socket_add_id(GTK_SOCKET(socket), xid);//Places the id into the socket.

                check = xid;//Sets thecheck to the previous id.

                gtk_widget_show_all(notebook_running);//Shows everything in the running notebook.
            }   

            else if(ftc == 0)//If this is the first run...
            {
                plywood = xid;//Sets the first window id recived as our window id.

                ftc = 1;//Sets second run.

                printf("\n\nJust had first run of valid ID.\n\n");

            }

            else if(ftc == 1)//If this is the second run...
            {
                gtk_notebook_remove_page(GTK_NOTEBOOK(notebook_running), 0);//Remove the placeholder page in the running notebook.

                ftc = 2;//Set third+ run.

                printf("\n\nJust had second run of valid ID.\n\n");
            }

            printf("\n\nFinnished a run of valid ID.\n\n");
        }




        gtk_main_iteration_do(0);
    }

    printf("\n\nOut of the GTK loop, don't know how that happened.\n\n");

    //gtk_main();//This is the basic premade GTK loop.


    return 0;//Ends the main function.
}

//woodglue function
int woodglue(int argc, char **argv, int pipe[2])//This checks for events that relate to windows being created on the desktop.
{

    close (pipe[0]);//Close the input pipe since we won't be using it here.


    //Variables
    Display *dpy;//This will hold the default display identifier, neccisary for almost all x functions.
    Window root;//Declares a window variable called root for holding the window id of the root window.
    Window xid;//This will hold thewindow id for the windows that have mapped themselves to the display withen the root window.
    XEvent ev;//This is a structure for holding event passed to us by the X server.
    double test = 0;
    /* 
    For referance of the XEvent structure, some of its components are also structures. (Do not uncoment.) :

    typedef union _XEvent {
        int type;   // must not be changed
        XAnyEvent xany;
        XKeyEvent xkey;
        XButtonEvent xbutton;
        XMotionEvent xmotion;
        XCrossingEvent xcrossing;
        XFocusChangeEvent xfocus;
        XExposeEvent xexpose;
        XGraphicsExposeEvent xgraphicsexpose;
        XNoExposeEvent xnoexpose;
        XVisibilityEvent xvisibility;
        XCreateWindoEvent xcreatewindow;
        XDestroyWindowEvent xdestroywindow;
        XUnmapEvent xunmap;
        XMapEvent xmap;
        XMapRequestEvent xmaprequest;
        XReparentEvent xreparent;
        XConfigureEvent xconfigure;
        XGravityEvent xgravity;
        XResizeRequestEvent xresizerequest;
        XConfigureRequestEvent xconfigurerequest;
        XCirculateEvent xcirculate;
        XCirculateRequestEvent xcirculaterequest;
        XPropertyEvent xproperty;
        XSelectionClearEvent xselectionclear;
        XSelectionRequestEvent xselectionrequest;
        XSelectionEvent xselection;
        XColormapEvent xcolormap;
        XClientMessageEvent xclient;
        XMappingEvent xmapping;
        XErrorEvent xerror;
        XKeymapEvent xkeymap;
        long pad[24];
    }XEvent;
    */



    if(!(dpy = XOpenDisplay(0x0)))//If the display does not return, 
    {
        printf("\n\nX couldn't connect to the display.\n\n");

        return 1;//return error.
    }

    root = DefaultRootWindow(dpy);//Collects the id of the default root window.

    XSelectInput(dpy, root, SubstructureNotifyMask);//Tells the root window that we want to get events  that relate to changes in the substructure.

    printf("\n\nX connected to the display.\n\n");

    for(;;)//Forever,
    {

        XNextEvent(dpy, &ev);//This throws the next event in the que int the "ev" structure thing.

        printf("\n\nThe x loop just ran.\n\n");

        if(ev.type == MapNotify)// && ev.xcreatewindow.parent == root)//If the event type is a notification of a window being mapped to the root window, and its parent is the root (as of right now, I am not sure that all the windows we are looking for have root as the parent, so that is disabled),
        {   
            printf("\n\nJust got a map notify event.\n\n");

            xid = ev.xcreatewindow.window;//place the window id of the created window into "xid".

            write(pipe[1], &xid, sizeof(xid));//write the id, however long it is, into the input stream, sending it to plywood. Unknown if this pauses the loop.

            test = xid;

            printf("\n\nJust sent the window id, it was %lf\n\n", test);

            xid = 0;
        }


    }//And then we loop to check the next event.

    return 0;//I assume we need this, but maybe not for X...
}




//Main Function
int main (int argc, char **argv)//Forks the program and sets up the i/o stream.
{

    pid_t pid;//This variable serves to identify the program during a fork, a value of 0 represents the child proccess, where 1 is the parent.

    int pipe[2];//This initializes the file stream for use between the two versions of the program.

    pid = fork();//Forks the program, creating an additional iteration with pid = 0

    if(pid == (pid_t) 0)//If this is the child proccess,
    {
        printf("\n\nChild started.\n\n");

        plywood(argc, argv, pipe);//launch the plywood function, passing the starting varibles as well as the file stream "pipe".
    }

    else if(pid == (pid_t) 1)//Else for the parent proccess,
    {
        printf("\n\nParent Started.\n\n");

        woodglue(argc, argv, pipe);//launch the woodglue function, passing the starting varibles as well as the file stream "pipe".
    }

    else
    {

    }

    return 0;

}

1 个答案:

答案 0 :(得分:0)

查看GtkPlug and GtkSocket widgets,但要注意它们会阻止您的程序跨平台移植。大多数窗口系统都不支持这个;只有X。