Renamed package to ion1, and made it conflict with package 'ion'.
[ion1.git] / src / main.c
blob3f2aecad2df702293283bf778a1d448bad985d44
1 /*
2 * ion/main.c
4 * Copyright (c) Tuomo Valkonen 1999-2001.
5 * See the included file LICENSE for details.
6 */
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <unistd.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <fcntl.h>
15 #include <libtu/util.h>
16 #include <libtu/optparser.h>
18 #include <X11/Xlib.h>
20 #include "common.h"
21 #include "screen.h"
22 #include "config.h"
23 #include "event.h"
24 #include "cursor.h"
25 #include "signal.h"
26 #include "binding.h"
27 #include "readconfig.h"
28 #include "global.h"
29 #include "confws.h"
30 #include "draw.h"
31 #include "modules.h"
32 #include "exec.h"
35 /*{{{ Global variables and optparser data */
38 WGlobal wglobal;
41 /* Options. Getopt is not used because getopt_long is quite gnu-specific
42 * and they don't know of '-display foo' -style args anyway.
43 * Instead, I've reinvented the wheel in libtu :(.
45 static OptParserOpt opts[]={
46 {OPT_ID('d'), "display", OPT_ARG, "host:dpy.scr", "X display to use"},
47 {'c', "cfgfile", OPT_ARG, "config_file", "Configuration file"},
48 {OPT_ID('o'), "onescreen", 0, NULL, "Manage default screen only"},
49 {'i', "clientId", OPT_ARG, "client_id", "Session manager client id"},
50 {'r', "restore", OPT_ARG, "state_file", "Ion state file"},
51 {0, NULL, 0, NULL, NULL}
55 static const char ion_usage_tmpl[]=
56 "Usage: $p [options]\n\n$o\n";
59 static const char ion_about[]=
60 "Ion " ION_VERSION ", copyright (c) Tuomo Valkonen 1999-2001.\n"
61 "This program may be copied and modified under the terms of the "
62 "Artistic License.\n";
65 static OptParserCommonInfo ion_cinfo={
66 ION_VERSION,
67 ion_usage_tmpl,
68 ion_about
72 /*}}}*/
75 /*{{{ Main & init */
78 static bool initialize(const char *display, const char *cfgfile,
79 bool onescreen);
81 extern InputHandler default_input_handler;
83 int main(int argc, char*argv[])
85 int opt;
86 const char *cfgfile=NULL;
87 bool onescreen=FALSE;
89 libtu_init(argv[0]);
91 wglobal.argc=argc;
92 wglobal.argv=argv;
93 wglobal.dpy=NULL;
94 wglobal.display=NULL;
95 wglobal.current_wswindow=NULL;
96 wglobal.previous=NULL;
97 wglobal.grab_holder=NULL;
98 wglobal.input_mode=INPUT_NORMAL;
99 wglobal.dblclick_delay=CF_DBLCLICK_DELAY;
100 wglobal.resize_delay=CF_RESIZE_DELAY;
101 wglobal.opaque_resize=FALSE;
102 wglobal.opmode=OPMODE_INIT;
103 wglobal.screens=NULL;
104 wglobal.current_screen=NULL;
105 wglobal.previous_protect=0;
106 wglobal.client_id=NULL;
107 wglobal.state_file=NULL;
108 wglobal.input_handler=&default_input_handler;
109 memset(wglobal.shortcuts, 0, sizeof(wglobal.shortcuts));
111 /* The rest don't need to be initialized here */
113 optparser_init(argc, argv, OPTP_MIDLONG, opts, &ion_cinfo);
115 while((opt=optparser_get_opt())){
116 switch(opt){
117 case OPT_ID('d'):
118 wglobal.display=scopy(optparser_get_arg());
119 if(wglobal.display==NULL){
120 warn_err();
121 return EXIT_FAILURE;
123 break;
124 case 'c':
125 cfgfile=optparser_get_arg();
126 break;
127 case OPT_ID('o'):
128 onescreen=TRUE;
129 break;
130 case 'i':
131 wglobal.client_id=scopy(optparser_get_arg());
132 break;
133 case 'r':
134 wglobal.state_file=scopy(optparser_get_arg());
135 break;
136 default:
137 optparser_print_error();
138 return EXIT_FAILURE;
142 if(!initialize(wglobal.display, cfgfile, onescreen))
143 return EXIT_FAILURE;
145 wglobal.opmode=OPMODE_NORMAL;
147 /*close(0);
148 open("/dev/null", O_RDONLY);*/
150 mainloop();
152 /* The code should never return here */
153 return EXIT_SUCCESS;
156 extern void debug_dump_thing(WThing *thing);
157 static bool load_initial_workspaces()
159 WScreen *scr;
161 FOR_ALL_SCREENS(scr){
162 postinit_graphics(scr);
163 read_workspaces(scr);
164 postinit_screen(scr);
166 return TRUE;
169 static bool initialize(const char*display, const char *cfgfile,
170 bool onescreen)
172 Display *dpy;
173 WScreen *scr, *prev=NULL;
174 int i, dscr, nscr;
175 bool res;
177 /* Open the display. */
178 dpy=XOpenDisplay(display);
180 if(dpy==NULL){
181 warn("Could not connect to X display '%s'", XDisplayName(display));
182 return FALSE;
185 if(onescreen){
186 dscr=DefaultScreen(dpy);
187 nscr=dscr+1;
188 }else{
189 dscr=0;
190 nscr=ScreenCount(dpy);
193 /* Initialize */
194 wglobal.dpy=dpy;
196 wglobal.conn=ConnectionNumber(dpy);
197 wglobal.win_context=XUniqueContext();
199 wglobal.atom_wm_state=XInternAtom(dpy, "WM_STATE", False);
200 wglobal.atom_wm_change_state=XInternAtom(dpy, "WM_CHANGE_STATE", False);
201 wglobal.atom_wm_protocols=XInternAtom(dpy, "WM_PROTOCOLS", False);
202 wglobal.atom_wm_delete=XInternAtom(dpy, "WM_DELETE_WINDOW", False);
203 wglobal.atom_wm_take_focus=XInternAtom(dpy, "WM_TAKE_FOCUS", False);
204 wglobal.atom_wm_colormaps=XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False);
205 wglobal.atom_frame_id=XInternAtom(dpy, "_PWM_FRAME_ID", False);
206 wglobal.atom_workspace=XInternAtom(dpy, "_ION_WORKSPACE", False);
207 wglobal.atom_selection=XInternAtom(dpy, "_ION_SELECTION_STRING", False);
209 trap_signals();
211 init_bindings();
212 load_cursors();
214 for(i=dscr; i<nscr; i++){
215 scr=preinit_screen(i);
217 if(scr==NULL)
218 continue;
220 preinit_graphics(scr);
222 if(prev==NULL){
223 wglobal.screens=scr;
224 }else{
225 LINK_ITEM_AFTER((WThing*)wglobal.screens, (WThing*)prev,
226 (WThing*)scr, t_next, t_prev);
229 prev=scr;
232 if(prev==NULL){
233 if(nscr-dscr>1)
234 warn("Could not find a screen to manage.");
235 return FALSE;
238 if(!read_config(cfgfile))
239 goto configfail;
241 if(wglobal.main_bindmap.nbindings==0 ||
242 wglobal.moveres_bindmap.nbindings==0)
243 goto configfail;
245 CALL_ALT_B_ARG(res, load_initial_workspaces, ());
247 CALL_HOOKS(init_done_hook);
249 /*atexit(deinit);*/
251 return TRUE;
253 configfail:
254 #define MSG \
255 "Unable to load configuration or inadequate binding configurations. " \
256 "Refusing to start.\nYou *must* install proper configuration files " \
257 "either in ~/.ion or "ETCDIR"/ion to use Ion."
259 warn(MSG);
260 setup_environ(DefaultScreen(dpy));
261 XCloseDisplay(dpy);
262 wm_do_exec("xmessage 'ion: " MSG "'");
263 return FALSE;
267 /*}}}*/
270 /*{{{ Deinit */
272 void deinit()
274 Display *dpy;
275 WScreen *scr;
277 wglobal.opmode=OPMODE_DEINIT;
279 if(wglobal.dpy==NULL)
280 return;
282 unload_modules();
284 FOR_ALL_SCREENS(scr){
285 write_workspaces(scr);
286 /*CALL_ALT_B_ARG(res, write_workspaces, (scr));*/
287 deinit_screen(scr);
290 dpy=wglobal.dpy;
291 wglobal.dpy=NULL;
293 XCloseDisplay(dpy);
296 /*}}}*/