1/*
2 * Xephyr - A kdrive X server that runs in a host X window.
3 *          Authored by Matthew Allum <mallum@o-hand.com>
4 *
5 * Copyright © 2004 Nokia
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Nokia not be used in
12 * advertising or publicity pertaining to distribution of the software without
13 * specific, written prior permission. Nokia makes no
14 * representations about the suitability of this software for any purpose.  It
15 * is provided "as is" without express or implied warranty.
16 *
17 * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL NOKIA BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
24 */
25
26#ifdef HAVE_DIX_CONFIG_H
27#include <dix-config.h>
28#endif
29#include "ephyr.h"
30#include "ephyrlog.h"
31#include "glx_extinit.h"
32
33extern Window EphyrPreExistingHostWin;
34extern Bool EphyrWantGrayScale;
35extern Bool EphyrWantResize;
36extern Bool EphyrWantNoHostGrab;
37extern Bool kdHasPointer;
38extern Bool kdHasKbd;
39extern Bool ephyr_glamor, ephyr_glamor_gles2, ephyr_glamor_skip_present;
40
41extern Bool ephyrNoXV;
42
43void processScreenOrOutputArg(const char *screen_size, const char *output, char *parent_id);
44void processOutputArg(const char *output, char *parent_id);
45void processScreenArg(const char *screen_size, char *parent_id);
46
47int
48main(int argc, char *argv[], char *envp[])
49{
50    hostx_use_resname(basename(argv[0]), 0);
51    return dix_main(argc, argv, envp);
52}
53
54void
55InitCard(char *name)
56{
57    EPHYR_DBG("mark");
58    KdCardInfoAdd(&ephyrFuncs, 0);
59}
60
61void
62InitOutput(ScreenInfo * pScreenInfo, int argc, char **argv)
63{
64    KdInitOutput(pScreenInfo, argc, argv);
65}
66
67void
68InitInput(int argc, char **argv)
69{
70    KdKeyboardInfo *ki;
71    KdPointerInfo *pi;
72
73    KdAddKeyboardDriver(&EphyrKeyboardDriver);
74    KdAddPointerDriver(&EphyrMouseDriver);
75
76    if (!kdHasKbd) {
77        ki = KdNewKeyboard();
78        if (!ki)
79            FatalError("Couldn't create Xephyr keyboard\n");
80        ki->driver = &EphyrKeyboardDriver;
81        KdAddKeyboard(ki);
82    }
83
84    if (!kdHasPointer) {
85        pi = KdNewPointer();
86        if (!pi)
87            FatalError("Couldn't create Xephyr pointer\n");
88        pi->driver = &EphyrMouseDriver;
89        KdAddPointer(pi);
90    }
91
92    KdInitInput();
93}
94
95void
96CloseInput(void)
97{
98    KdCloseInput();
99}
100
101#if INPUTTHREAD
102/** This function is called in Xserver/os/inputthread.c when starting
103    the input thread. */
104void
105ddxInputThreadInit(void)
106{
107}
108#endif
109
110#ifdef DDXBEFORERESET
111void
112ddxBeforeReset(void)
113{
114}
115#endif
116
117void
118ddxUseMsg(void)
119{
120    KdUseMsg();
121
122    ErrorF("\nXephyr Option Usage:\n");
123    ErrorF("-parent <XID>        Use existing window as Xephyr root win\n");
124    ErrorF("-sw-cursor           Render cursors in software in Xephyr\n");
125    ErrorF("-fullscreen          Attempt to run Xephyr fullscreen\n");
126    ErrorF("-output <NAME>       Attempt to run Xephyr fullscreen (restricted to given output geometry)\n");
127    ErrorF("-grayscale           Simulate 8bit grayscale\n");
128    ErrorF("-resizeable          Make Xephyr windows resizeable\n");
129#ifdef GLAMOR
130    ErrorF("-glamor              Enable 2D acceleration using glamor\n");
131    ErrorF("-glamor_gles2        Enable 2D acceleration using glamor (with GLES2 only)\n");
132    ErrorF("-glamor-skip-present Skip presenting the output when using glamor (for internal testing optimization)\n");
133#endif
134    ErrorF
135        ("-fakexa              Simulate acceleration using software rendering\n");
136    ErrorF("-verbosity <level>   Set log verbosity level\n");
137    ErrorF("-noxv                do not use XV\n");
138    ErrorF("-name [name]         define the name in the WM_CLASS property\n");
139    ErrorF
140        ("-title [title]       set the window title in the WM_NAME property\n");
141    ErrorF("-no-host-grab        Disable grabbing the keyboard and mouse.\n");
142    ErrorF("\n");
143}
144
145void
146processScreenOrOutputArg(const char *screen_size, const char *output, char *parent_id)
147{
148    KdCardInfo *card;
149
150    InitCard(0);                /*Put each screen on a separate card */
151    card = KdCardInfoLast();
152
153    if (card) {
154        KdScreenInfo *screen;
155        unsigned long p_id = 0;
156        Bool use_geometry;
157
158        screen = KdScreenInfoAdd(card);
159        KdParseScreen(screen, screen_size);
160        screen->driver = calloc(1, sizeof(EphyrScrPriv));
161        if (!screen->driver)
162            FatalError("Couldn't alloc screen private\n");
163
164        if (parent_id) {
165            p_id = strtol(parent_id, NULL, 0);
166        }
167
168        use_geometry = (strchr(screen_size, '+') != NULL);
169        EPHYR_DBG("screen number:%d\n", screen->mynum);
170        hostx_add_screen(screen, p_id, screen->mynum, use_geometry, output);
171    }
172    else {
173        ErrorF("No matching card found!\n");
174    }
175}
176
177void
178processScreenArg(const char *screen_size, char *parent_id)
179{
180    processScreenOrOutputArg(screen_size, NULL, parent_id);
181}
182
183void
184processOutputArg(const char *output, char *parent_id)
185{
186    processScreenOrOutputArg("100x100+0+0", output, parent_id);
187}
188
189int
190ddxProcessArgument(int argc, char **argv, int i)
191{
192    static char *parent = NULL;
193
194    EPHYR_DBG("mark argv[%d]='%s'", i, argv[i]);
195
196    if (!strcmp(argv[i], "-parent")) {
197        if (i + 1 < argc) {
198            int j;
199
200            /* If parent is specified and a screen argument follows, don't do
201             * anything, let the -screen handling init the rest */
202            for (j = i; j < argc; j++) {
203                if (!strcmp(argv[j], "-screen")) {
204                    parent = argv[i + 1];
205                    return 2;
206                }
207            }
208
209            processScreenArg("100x100", argv[i + 1]);
210            return 2;
211        }
212
213        UseMsg();
214        exit(1);
215    }
216    else if (!strcmp(argv[i], "-screen")) {
217        if ((i + 1) < argc) {
218            processScreenArg(argv[i + 1], parent);
219            parent = NULL;
220            return 2;
221        }
222
223        UseMsg();
224        exit(1);
225    }
226    else if (!strcmp(argv[i], "-output")) {
227        if (i + 1 < argc) {
228            processOutputArg(argv[i + 1], NULL);
229            return 2;
230        }
231
232        UseMsg();
233        exit(1);
234    }
235    else if (!strcmp(argv[i], "-sw-cursor")) {
236        hostx_use_sw_cursor();
237        return 1;
238    }
239    else if (!strcmp(argv[i], "-host-cursor")) {
240        /* Compatibility with the old command line argument, now the default. */
241        return 1;
242    }
243    else if (!strcmp(argv[i], "-fullscreen")) {
244        hostx_use_fullscreen();
245        return 1;
246    }
247    else if (!strcmp(argv[i], "-grayscale")) {
248        EphyrWantGrayScale = 1;
249        return 1;
250    }
251    else if (!strcmp(argv[i], "-resizeable")) {
252        EphyrWantResize = 1;
253        return 1;
254    }
255#ifdef GLAMOR
256    else if (!strcmp (argv[i], "-glamor")) {
257        ephyr_glamor = TRUE;
258        ephyrFuncs.initAccel = ephyr_glamor_init;
259        ephyrFuncs.enableAccel = ephyr_glamor_enable;
260        ephyrFuncs.disableAccel = ephyr_glamor_disable;
261        ephyrFuncs.finiAccel = ephyr_glamor_fini;
262        return 1;
263    }
264    else if (!strcmp (argv[i], "-glamor_gles2")) {
265        ephyr_glamor = TRUE;
266        ephyr_glamor_gles2 = TRUE;
267        ephyrFuncs.initAccel = ephyr_glamor_init;
268        ephyrFuncs.enableAccel = ephyr_glamor_enable;
269        ephyrFuncs.disableAccel = ephyr_glamor_disable;
270        ephyrFuncs.finiAccel = ephyr_glamor_fini;
271        return 1;
272    }
273    else if (!strcmp (argv[i], "-glamor-skip-present")) {
274        ephyr_glamor_skip_present = TRUE;
275        return 1;
276    }
277#endif
278    else if (!strcmp(argv[i], "-fakexa")) {
279        ephyrFuncs.initAccel = ephyrDrawInit;
280        ephyrFuncs.enableAccel = ephyrDrawEnable;
281        ephyrFuncs.disableAccel = ephyrDrawDisable;
282        ephyrFuncs.finiAccel = ephyrDrawFini;
283        return 1;
284    }
285    else if (!strcmp(argv[i], "-verbosity")) {
286        if (i + 1 < argc && argv[i + 1][0] != '-') {
287            int verbosity = atoi(argv[i + 1]);
288
289            LogSetParameter(XLOG_VERBOSITY, verbosity);
290            EPHYR_LOG("set verbosiry to %d\n", verbosity);
291            return 2;
292        }
293        else {
294            UseMsg();
295            exit(1);
296        }
297    }
298    else if (!strcmp(argv[i], "-noxv")) {
299        ephyrNoXV = TRUE;
300        EPHYR_LOG("no XVideo enabled\n");
301        return 1;
302    }
303    else if (!strcmp(argv[i], "-name")) {
304        if (i + 1 < argc && argv[i + 1][0] != '-') {
305            hostx_use_resname(argv[i + 1], 1);
306            return 2;
307        }
308        else {
309            UseMsg();
310            return 0;
311        }
312    }
313    else if (!strcmp(argv[i], "-title")) {
314        if (i + 1 < argc && argv[i + 1][0] != '-') {
315            hostx_set_title(argv[i + 1]);
316            return 2;
317        }
318        else {
319            UseMsg();
320            return 0;
321        }
322    }
323    else if (argv[i][0] == ':') {
324        hostx_set_display_name(argv[i]);
325    }
326    /* Xnest compatibility */
327    else if (!strcmp(argv[i], "-display")) {
328        hostx_set_display_name(argv[i + 1]);
329        return 2;
330    }
331    else if (!strcmp(argv[i], "-sync") ||
332             !strcmp(argv[i], "-full") ||
333             !strcmp(argv[i], "-sss") || !strcmp(argv[i], "-install")) {
334        return 1;
335    }
336    else if (!strcmp(argv[i], "-bw") ||
337             !strcmp(argv[i], "-class") ||
338             !strcmp(argv[i], "-geometry") || !strcmp(argv[i], "-scrns")) {
339        return 2;
340    }
341    /* end Xnest compat */
342    else if (!strcmp(argv[i], "-no-host-grab")) {
343        EphyrWantNoHostGrab = 1;
344        return 1;
345    }
346    else if (!strcmp(argv[i], "-sharevts") ||
347             !strcmp(argv[i], "-novtswitch")) {
348        return 1;
349    }
350    else if (!strcmp(argv[i], "-layout")) {
351        return 2;
352    }
353
354    return KdProcessArgument(argc, argv, i);
355}
356
357void
358OsVendorInit(void)
359{
360    EPHYR_DBG("mark");
361
362    if (SeatId)
363        hostx_use_sw_cursor();
364
365    if (hostx_want_host_cursor())
366        ephyrFuncs.initCursor = &ephyrCursorInit;
367
368    if (serverGeneration == 1) {
369        if (!KdCardInfoLast()) {
370            processScreenArg("640x480", NULL);
371        }
372        hostx_init();
373    }
374}
375
376KdCardFuncs ephyrFuncs = {
377    ephyrCardInit,              /* cardinit */
378    ephyrScreenInitialize,      /* scrinit */
379    ephyrInitScreen,            /* initScreen */
380    ephyrFinishInitScreen,      /* finishInitScreen */
381    ephyrCreateResources,       /* createRes */
382    ephyrScreenFini,            /* scrfini */
383    ephyrCardFini,              /* cardfini */
384
385    0,                          /* initCursor */
386
387    0,                          /* initAccel */
388    0,                          /* enableAccel */
389    0,                          /* disableAccel */
390    0,                          /* finiAccel */
391
392    ephyrGetColors,             /* getColors */
393    ephyrPutColors,             /* putColors */
394
395    ephyrCloseScreen,           /* closeScreen */
396};
397