xfreerdp: remove backbuffer window in RemoteApp mode
[platform/upstream/freerdp.git] / client / X11 / xf_window.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * X11 Windows
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include <X11/Xutil.h>
21
22 #include "xf_window.h"
23
24 /* Extended Window Manager Hints: http://standards.freedesktop.org/wm-spec/wm-spec-1.3.html */
25
26 #define MWM_HINTS_DECORATIONS           (1L << 1)
27 #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
28
29 struct _PropMotifWmHints
30 {
31         unsigned long flags;
32         unsigned long functions;
33         unsigned long decorations;
34         long inputMode;
35         unsigned long status;
36 };
37 typedef struct _PropMotifWmHints PropMotifWmHints;
38
39 void window_fullscreen(xfInfo* xfi, xfWindow* window, boolean fullscreen)
40 {
41         if (fullscreen)
42         {
43                 if (window->decorations)
44                         window_show_decorations(xfi, window, False);
45
46                 XSetInputFocus(xfi->display, window->handle, RevertToParent, CurrentTime);
47                 window->fullscreen = True;
48         }
49 }
50
51 /* http://tronche.com/gui/x/xlib/window-information/XGetWindowProperty.html */
52
53 boolean window_GetProperty(xfInfo* xfi, Window window, char* name, int length,
54                 unsigned long* nitems, unsigned long* bytes, uint8** prop)
55 {
56         int status;
57         Atom property;
58         Atom actual_type;
59         int actual_format;
60
61         property = XInternAtom(xfi->display, name, True);
62
63         if (property == None)
64                 return False;
65
66         status = XGetWindowProperty(xfi->display, window,
67                         property, 0, length, False, AnyPropertyType,
68                         &actual_type, &actual_format, nitems, bytes, prop);
69
70         if (status != Success)
71                 return False;
72
73         return True;
74 }
75
76 boolean window_GetCurrentDesktop(xfInfo* xfi)
77 {
78         boolean status;
79         unsigned long nitems;
80         unsigned long bytes;
81         unsigned char* prop;
82
83         status = window_GetProperty(xfi, DefaultRootWindow(xfi->display),
84                         "_NET_CURRENT_DESKTOP", 1, &nitems, &bytes, &prop);
85
86         if (status != True)
87                 return False;
88
89         xfi->current_desktop = (int) *prop;
90         xfree(prop);
91
92         return True;
93 }
94
95 boolean window_GetWorkArea(xfInfo* xfi)
96 {
97         long* plong;
98         boolean status;
99         unsigned long nitems;
100         unsigned long bytes;
101         unsigned char* prop;
102
103         status = window_GetProperty(xfi, DefaultRootWindow(xfi->display),
104                         "_NET_WORKAREA", 32 * 4, &nitems, &bytes, &prop);
105
106         if (status != True)
107                 return False;
108
109         window_GetCurrentDesktop(xfi);
110
111         plong = (long*) prop;
112
113         xfi->workArea.x = plong[xfi->current_desktop * 4 + 0];
114         xfi->workArea.y = plong[xfi->current_desktop * 4 + 1];
115         xfi->workArea.width = plong[xfi->current_desktop * 4 + 2];
116         xfi->workArea.height = plong[xfi->current_desktop * 4 + 3];
117         xfree(prop);
118
119         return True;
120 }
121
122 void window_show_decorations(xfInfo* xfi, xfWindow* window, boolean show)
123 {
124         Atom atom;
125         PropMotifWmHints hints;
126
127         hints.decorations = 0;
128         hints.flags = MWM_HINTS_DECORATIONS;
129
130         atom = XInternAtom(xfi->display, "_MOTIF_WM_HINTS", True);
131
132         if (!atom)
133         {
134                 printf("window_show_decorations: failed to obtain atom _MOTIF_WM_HINTS\n");
135                 return;
136         }
137         else
138         {
139                 if (show != True)
140                 {
141                         XChangeProperty(xfi->display, window->handle, atom, atom, 32,
142                                 PropModeReplace, (uint8*) &hints, PROP_MOTIF_WM_HINTS_ELEMENTS);
143                 }
144         }
145
146         window->decorations = show;
147 }
148
149 xfWindow* desktop_create(xfInfo* xfi, char* name)
150 {
151         xfWindow* window;
152
153         window = (xfWindow*) xzalloc(sizeof(xfWindow));
154
155         if (window != NULL)
156         {
157                 int input_mask;
158                 XSizeHints* size_hints;
159                 XClassHint* class_hints;
160
161                 window->decorations = True;
162                 window->fullscreen = False;
163
164                 window->handle = XCreateWindow(xfi->display, RootWindowOfScreen(xfi->screen),
165                         xfi->workArea.x, xfi->workArea.y, xfi->width, xfi->height, 0, xfi->depth, InputOutput, xfi->visual,
166                         CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
167                         CWBorderPixel, &xfi->attribs);
168
169                 class_hints = XAllocClassHint();
170
171                 if (class_hints != NULL)
172                 {
173                         if (name != NULL)
174                                 class_hints->res_name = name;
175
176                         class_hints->res_class = "freerdp";
177                         XSetClassHint(xfi->display, window->handle, class_hints);
178                         XFree(class_hints);
179                 }
180
181                 size_hints = XAllocSizeHints();
182
183                 if (size_hints)
184                 {
185                         size_hints->flags = PMinSize | PMaxSize;
186                         size_hints->min_width = size_hints->max_width = xfi->width;
187                         size_hints->min_height = size_hints->max_height = xfi->height;
188                         XSetWMNormalHints(xfi->display, window->handle, size_hints);
189                         XFree(size_hints);
190                 }
191
192                 input_mask =
193                         KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
194                         VisibilityChangeMask | FocusChangeMask | StructureNotifyMask |
195                         PointerMotionMask | ExposureMask;
196
197                 XSelectInput(xfi->display, window->handle, input_mask);
198                 XMapWindow(xfi->display, window->handle);
199         }
200
201         return window;
202 }
203
204 xfWindow* xf_CreateWindow(xfInfo* xfi, int x, int y, int width, int height, char* name)
205 {
206         xfWindow* window;
207
208         window = (xfWindow*) xzalloc(sizeof(xfWindow));
209
210         window->width = width;
211         window->height = height;
212
213         if (window != NULL)
214         {
215                 XGCValues gcv;
216                 int input_mask;
217                 XSizeHints* size_hints;
218                 XClassHint* class_hints;
219
220                 window->decorations = False;
221                 window->fullscreen = False;
222
223                 window->handle = XCreateWindow(xfi->display, RootWindowOfScreen(xfi->screen),
224                         x, y, window->width, window->height, 0, xfi->depth, InputOutput, xfi->visual,
225                         CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
226                         CWBorderPixel, &xfi->attribs);
227
228                 window_show_decorations(xfi, window, window->decorations);
229
230                 class_hints = XAllocClassHint();
231
232                 if (class_hints != NULL)
233                 {
234                         class_hints->res_name = "rail";
235                         class_hints->res_class = "freerdp";
236                         XSetClassHint(xfi->display, window->handle, class_hints);
237                         XFree(class_hints);
238                 }
239
240                 size_hints = XAllocSizeHints();
241
242                 if (size_hints)
243                 {
244                         size_hints->flags = PMinSize | PMaxSize;
245                         size_hints->min_width = size_hints->max_width = window->width;
246                         size_hints->min_height = size_hints->max_height = window->height;
247                         XSetWMNormalHints(xfi->display, window->handle, size_hints);
248                         XFree(size_hints);
249                 }
250
251                 input_mask =
252                         KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
253                         VisibilityChangeMask | FocusChangeMask | StructureNotifyMask |
254                         PointerMotionMask | ExposureMask;
255
256                 XSelectInput(xfi->display, window->handle, input_mask);
257                 XMapWindow(xfi->display, window->handle);
258
259                 memset(&gcv, 0, sizeof(gcv));
260                 window->gc = XCreateGC(xfi->display, window->handle, GCGraphicsExposures, &gcv);
261                 window->surface = XCreatePixmap(xfi->display, window->handle, window->width, window->height, xfi->depth);
262
263                 XStoreName(xfi->display, window->handle, name);
264
265                 xf_MoveWindow(xfi, window, x, y, width, height);
266         }
267
268         return window;
269 }
270
271 void xf_MoveWindow(xfInfo* xfi, xfWindow* window, int x, int y, int width, int height)
272 {
273         XSizeHints* size_hints;
274         XWindowChanges changes;
275
276         changes.x = x;
277         changes.y = y;
278         changes.width = width;
279         changes.height = height;
280
281         XConfigureWindow(xfi->display, window->handle, CWX | CWY | CWWidth | CWHeight, &changes);
282
283         window->width = width;
284         window->height = height;
285         XFreePixmap(xfi->display, window->surface);
286         window->surface = XCreatePixmap(xfi->display, window->handle, window->width, window->height, xfi->depth);
287
288         size_hints = XAllocSizeHints();
289
290         if (size_hints)
291         {
292                 size_hints->flags = PMinSize | PMaxSize;
293                 size_hints->min_width = size_hints->max_width = window->width;
294                 size_hints->min_height = size_hints->max_height = window->height;
295                 XSetWMNormalHints(xfi->display, window->handle, size_hints);
296                 XFree(size_hints);
297         }
298 }
299
300 void xf_DestroyWindow(xfInfo* xfi, xfWindow* window)
301 {
302         XFreeGC(xfi->display, window->gc);
303         XFreePixmap(xfi->display, window->surface);
304         XUnmapWindow(xfi->display, window->handle);
305         XDestroyWindow(xfi->display, window->handle);
306         xfree(window);
307 }