/* * Copyright 2022 Olaf Wintermann * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include #include #include #include #include #include #include #include "window.h" #include "main.h" #include "settings.h" #include #include static XtAppContext app; static Display *display; static Widget toplevel_window; static char *open_file_arg; static int event_pipe[2]; static String fallback[] = { "*renderTable: rt", "*rt*fontType: FONT_IS_XFT", "*rt*fontName: Sans", "*rt*fontSize: 9", "*pbbutton.shadowThickness: 1", "*pbbutton.highlightThickness: 1", "*XmText.baseTranslations: #override\\n" \ "Ctrl~Alt~Metav: paste-clipboard()\\n" \ "Ctrl~Alt~Metac: copy-clipboard()\\n" \ "Ctrl~Alt~Metax: cut-clipboard()\\n" \ "Ctrl~Alt~Metau: delete-to-start-of-line()\\n", "*XmTextField.baseTranslations: #override\\n" \ "Ctrl~Alt~Metav: paste-clipboard()\\n" \ "Ctrl~Alt~Metac: copy-clipboard()\\n" \ "Ctrl~Alt~Metax: cut-clipboard()\\n" \ "Ctrl~Alt~Metau: delete-to-start-of-line()\\n", NULL }; static String langProc(Display *dp, String xnl, XtPointer closure) { setlocale(LC_ALL, xnl); setlocale(LC_NUMERIC, "C"); return setlocale(LC_ALL, NULL); } typedef struct EventLoopCB { XtWorkProc proc; XtPointer data; } EventLoopCB; static void input_proc(XtPointer data, int *source, XtInputId *iid) { EventLoopCB cb[16]; ssize_t r = read(event_pipe[0], cb, sizeof(EventLoopCB)*16); size_t n = r / sizeof(EventLoopCB); for(int i=0;i 1) { struct stat s; if(stat(argv[1], &s)) { fprintf(stderr, "Cannot open file: %s\n", argv[1]); perror(""); return 1; } open_file_arg = argv[1]; } // load settings if(load_config()) { return 1; } // try single instance open if(open_file_arg) { char *instance_path = InstanceFilePath(display); int instance_fd = ConnectToInstance(instance_path); free(instance_path); if(instance_fd >= 0) { write(instance_fd, "open ", 5); write(instance_fd, open_file_arg, strlen(open_file_arg)); write(instance_fd, "\n", 1); close(instance_fd); return 0; } } XtAppAddInput( app, event_pipe[0], (XtPointer)XtInputReadMask, input_proc, NULL); MainWindow *window = WindowCreate(display); toplevel_window = window->window; // random numbers used for creating tmp dirs and for random playback srand(time(NULL)); WindowShow(window); AppMainLoop(app); return 0; } XtAppContext* GetAppContext(void) { return &app; } void ApplicationExit(void) { XtAppSetExitFlag(app); } void AppExecProc(XtWorkProc proc, XtPointer data) { EventLoopCB cb; cb.proc = proc; cb.data = data; write(event_pipe[1], &cb, sizeof(cb)); } char* GetOpenFileArg(void) { return open_file_arg; } void CleanOpenFileArg(void) { open_file_arg = NULL; } static Window app_player_window = 0; void SetPlayerWindow(Window w) { app_player_window = w; } /* * Extended Xt main loop, that also handles external window events */ void AppMainLoop(XtAppContext app) { while(!XtAppGetExitFlag(app)) { XEvent event; XtAppNextEvent(app, &event); if(app_player_window != 0 && event.xany.window == app_player_window) { WindowHandlePlayerEvent(GetMainWindow(), &event); } else { XtDispatchEvent(&event); } } }