updating changelog
[drnoksnes] / platform / sdlvhildon.cpp
1 #if CONF_HD
2
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <string.h>
6
7 #include <X11/Xlib.h>
8 #include <X11/Xutil.h>
9 #include <X11/Xatom.h>
10 #include <SDL.h>
11 #include <SDL_syswm.h>
12
13 #include "sdlv.h"
14 #include "hgw.h"
15
16 #define DIE(format, ...) do { \
17                 fprintf(stderr, "Died at %s:%d: ", __FILE__, __LINE__ ); \
18                 fprintf(stderr, format "\n", ## __VA_ARGS__); \
19                 abort(); \
20         } while (0);
21
22 static const char * hdAtomNames[] = {
23         "_HILDON_NON_COMPOSITED_WINDOW",
24         "_HILDON_STACKABLE_WINDOW",
25         "_NET_WM_STATE",
26         "_NET_WM_STATE_FULLSCREEN",
27         "_NET_WM_WINDOW_TYPE",
28         "_NET_WM_WINDOW_TYPE_NORMAL",
29         "_NET_WM_WINDOW_TYPE_DIALOG",
30         "_HILDON_WM_WINDOW_TYPE_ANIMATION_ACTOR",
31         "_HILDON_ANIMATION_CLIENT_READY",
32         "_HILDON_ANIMATION_CLIENT_MESSAGE_SHOW",        
33         "_HILDON_ANIMATION_CLIENT_MESSAGE_POSITION",
34         "_HILDON_ANIMATION_CLIENT_MESSAGE_ROTATION",
35         "_HILDON_ANIMATION_CLIENT_MESSAGE_SCALE",
36         "_HILDON_ANIMATION_CLIENT_MESSAGE_ANCHOR",
37         "_HILDON_ANIMATION_CLIENT_MESSAGE_PARENT",
38         "_HILDON_WM_WINDOW_TYPE_REMOTE_TEXTURE",
39         "_HILDON_TEXTURE_CLIENT_MESSAGE_SHM",
40         "_HILDON_TEXTURE_CLIENT_MESSAGE_DAMAGE",
41         "_HILDON_TEXTURE_CLIENT_MESSAGE_SHOW",
42         "_HILDON_TEXTURE_CLIENT_MESSAGE_POSITION",
43         "_HILDON_TEXTURE_CLIENT_MESSAGE_OFFSET",
44         "_HILDON_TEXTURE_CLIENT_MESSAGE_SCALE",
45         "_HILDON_TEXTURE_CLIENT_MESSAGE_PARENT",
46         "_HILDON_TEXTURE_CLIENT_READY",
47         ""
48 };
49
50 static bool hd_ok = false;
51
52 Atom hdAtomsValues[ATOM_COUNT];
53
54 SDL_SysWMinfo WMinfo;
55
56 static void hd_setup_stackable_window();
57
58 void hdSetup()
59 {
60         SDL_VERSION(&WMinfo.version);
61         if (!SDL_GetWMInfo(&WMinfo)) {
62                 DIE("Bad SDL version");
63         }
64
65         Display * display = WMinfo.info.x11.display;
66
67         if (!hd_ok) {
68                 XInternAtoms(display, (char**)hdAtomNames, ATOM_COUNT, True, hdAtomsValues);
69
70                 if (HDATOM(_HILDON_NON_COMPOSITED_WINDOW) == None) {
71                         printf("Hildon Desktop seems not be loaded, since %s is not defined",
72                                 "_HILDON_NON_COMPOSITED_WINDOW");
73                         return;
74                 }
75
76                 if (hgwLaunched || true) {
77                         hd_setup_stackable_window();
78                 }
79
80                 hd_ok = true;
81         }
82 };
83
84 /** Enables or disables the Hildon NonCompositedWindow property */
85 void hdSetNonCompositing(bool enable)
86 {
87         Display *display;
88         Window window;
89         int one = 1;
90
91         WMinfo.info.x11.lock_func();
92         display = WMinfo.info.x11.display;
93         window = WMinfo.info.x11.fswindow;
94
95         if (enable) {
96                 XUnmapWindow(display, window);
97                 XChangeProperty(display, window, HDATOM(_HILDON_NON_COMPOSITED_WINDOW),
98                         XA_INTEGER, 32, PropModeReplace,
99                         (unsigned char *) &one, 1);
100                 XMapWindow(display, window);
101         } else {
102                 XDeleteProperty(display, window,
103                         HDATOM(_HILDON_NON_COMPOSITED_WINDOW));
104         }
105
106         WMinfo.info.x11.unlock_func();
107 }
108
109 static Atom get_window_type(Display *dpy, Window win)
110 {
111         Atom window_type = None;
112         Atom actual_type;
113         int actual_format;
114         unsigned long nitems, bytes_after;
115         unsigned char *prop_return = NULL;
116
117     if(Success == XGetWindowProperty(dpy, win, HDATOM(_NET_WM_WINDOW_TYPE),
118                                                                 0L, sizeof(Atom),
119                                      False, XA_ATOM, &actual_type,
120                                      &actual_format, &nitems, &bytes_after,
121                                      &prop_return) && prop_return) {
122                 window_type = *(Atom *)prop_return;
123                 XFree(prop_return);
124         }
125
126         return window_type;
127 }
128
129 static Window find_launcher_window(Display *display, Window start)
130 {
131         Window root, parent, *children;
132         unsigned int count, i;
133
134         if (XQueryTree(display, start, &root, &parent, &children, &count)) {
135                 XClassHint class_hints;
136                 for (i = 0; i < count; i++) {
137                         Window cur = children[i];
138                         Window sub = find_launcher_window(display, cur);
139                         if (sub) return sub;
140
141                         if (XGetClassHint(display, cur, &class_hints)) {
142                                 if (strcasecmp(class_hints.res_class, "drnoksnes_startup") == 0) {
143                                         XFree(class_hints.res_name);
144                                         XFree(class_hints.res_class);
145
146                                         if (get_window_type(display, cur) != 
147                                                 HDATOM(_NET_WM_WINDOW_TYPE_NORMAL)) {
148                                                 continue;
149                                         }
150
151                                         XFree(children);
152
153                                         return cur;
154                                 }
155                                 XFree(class_hints.res_name);
156                                 XFree(class_hints.res_class);
157                         }
158                 }
159                 XFree(children);
160         }
161         
162         return 0;
163 }
164
165 /** Finds the drnoksnes_startup window. */
166 static Window find_launcher_window(Display *display)
167 {
168         return find_launcher_window(display,
169                 RootWindow(display, DefaultScreen(display)));
170 }
171
172 /** Converts the aux SDL windows into tops of the HildonWindowStack */
173 static void hd_setup_stackable_window()
174 {
175         Display *display;
176         Window window;
177         Atom atom;
178         XWMHints *hints;
179         XClassHint *chint;
180         XSetWindowAttributes xattr;
181         int one = 1;
182
183 #if 0
184         WMinfo.info.x11.lock_func();
185         display = WMinfo.info.x11.display;
186
187         Window launcher = find_launcher_window(display);
188
189         if (!launcher) {
190                 printf("HD: Games startup window was not found\n");
191                 return;
192         }
193
194         hints = XGetWMHints(display, launcher);
195         //hints->input = True;
196         hints->flags = (hints->flags & WindowGroupHint)/* | InputHint*/;
197         
198         chint = XAllocClassHint();
199         chint->res_name = chint->res_class = strdup("drnoksnes");
200
201         window = WMinfo.info.x11.fswindow;
202         XSetTransientForHint(display, window, launcher);
203         XSetWMHints(display, window, hints);
204         XSetClassHint(display, window, chint);
205         atom = HDATOM(_NET_WM_WINDOW_TYPE_NORMAL);
206         XChangeProperty(display, window, HDATOM(_NET_WM_WINDOW_TYPE),
207                 XA_ATOM, 32, PropModeReplace,
208                 (unsigned char *) &atom, 1);
209         xattr.override_redirect = False;
210         XChangeWindowAttributes(display, window, CWOverrideRedirect, &xattr);
211         atom = HDATOM(_NET_WM_STATE_FULLSCREEN);
212         XChangeProperty(display, window, HDATOM(_NET_WM_STATE),
213                 XA_ATOM, 32, PropModeReplace,
214                 (unsigned char *) &atom, 1);
215         XChangeProperty(display, window, HDATOM(_HILDON_STACKABLE_WINDOW),
216                 XA_INTEGER, 32, PropModeReplace,
217                 (unsigned char *) &one, 1);
218
219         free(chint->res_name);
220         XFree(chint);
221         XFree(hints);
222
223         WMinfo.info.x11.unlock_func();
224 #endif
225 }
226
227 void hdSetupFullscreen(bool enable)
228 {
229         Display *display = WMinfo.info.x11.display;
230         Window window = WMinfo.info.x11.wmwindow;
231
232 #if 0
233         WMinfo.info.x11.lock_func();
234
235         /* So we hide the SDL nonfullscreen window when in fullscreen mode. */
236         if (enable) {
237                 XUnmapWindow(display, window);
238         } else {
239                 XMapWindow(display, window);
240         }
241
242         WMinfo.info.x11.unlock_func();
243 #endif
244 }
245
246 #endif