1 /*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "NativeSubWindow.h"
17 #include "apigen-codec-common/X11Support.h"
18
19 #include <stdio.h>
20
WaitForMapNotify(Display * d,XEvent * e,char * arg)21 static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg) {
22 if (e->type == MapNotify && e->xmap.window == (Window)arg) {
23 return 1;
24 }
25 return 0;
26 }
27
WaitForConfigureNotify(Display * d,XEvent * e,char * arg)28 static Bool WaitForConfigureNotify(Display *d, XEvent *e, char *arg) {
29 if (e->type == ConfigureNotify && e->xmap.window == (Window)arg) {
30 return 1;
31 }
32 return 0;
33 }
34
35 static Display *s_display = NULL;
36
createSubWindow(FBNativeWindowType p_window,int x,int y,int width,int height,SubWindowRepaintCallback repaint_callback,void * repaint_callback_param,int hideWindow)37 EGLNativeWindowType createSubWindow(FBNativeWindowType p_window,
38 int x,
39 int y,
40 int width,
41 int height,
42 SubWindowRepaintCallback repaint_callback,
43 void* repaint_callback_param,
44 int hideWindow) {
45 auto x11 = getX11Api();
46 // The call to this function is protected by a lock
47 // in FrameBuffer so it is safe to check and initialize s_display here
48 if (!s_display) {
49 s_display = x11->XOpenDisplay(NULL);
50 }
51
52 XSetWindowAttributes wa;
53 wa.event_mask = StructureNotifyMask;
54 wa.override_redirect = True;
55 Window win = x11->XCreateWindow(s_display,
56 p_window,
57 x,
58 y,
59 width,
60 height,
61 0,
62 CopyFromParent,
63 CopyFromParent,
64 CopyFromParent,
65 CWEventMask,
66 &wa);
67 if (!hideWindow) {
68 x11->XMapWindow(s_display,win);
69 x11->XSetWindowBackground(s_display, win, BlackPixel(s_display, 0));
70 XEvent e;
71 x11->XIfEvent(s_display, &e, WaitForMapNotify, (char *)win);
72 }
73 return win;
74 }
75
destroySubWindow(EGLNativeWindowType win)76 void destroySubWindow(EGLNativeWindowType win) {
77 if (!s_display) {
78 return;
79 }
80
81 getX11Api()->XDestroyWindow(s_display, win);
82 }
83
moveSubWindow(FBNativeWindowType p_parent_window,EGLNativeWindowType p_sub_window,int x,int y,int width,int height)84 int moveSubWindow(FBNativeWindowType p_parent_window,
85 EGLNativeWindowType p_sub_window,
86 int x,
87 int y,
88 int width,
89 int height) {
90 // This value is set during create, so if it is still null, simply
91 // return because the global state is corrupted
92 if (!s_display) {
93 return false;
94 }
95
96 auto x11 = getX11Api();
97
98 // Make sure something has changed, otherwise XIfEvent will block and
99 // freeze the emulator.
100 XWindowAttributes attrs;
101 if (!x11->XGetWindowAttributes(s_display, p_sub_window, &attrs)) {
102 return false;
103 }
104 if (x == attrs.x && y == attrs.y &&
105 width == attrs.width && height == attrs.height) {
106 // Technically, resizing was a success because it was unneeded.
107 return true;
108 }
109
110 // This prevents flicker on resize.
111 x11->XSetWindowBackgroundPixmap(s_display, p_sub_window, None);
112
113 int ret = x11->XMoveResizeWindow(
114 s_display,
115 p_sub_window,
116 x,
117 y,
118 width,
119 height);
120
121 XEvent e;
122 x11->XIfEvent(s_display, &e, WaitForConfigureNotify, (char *)p_sub_window);
123
124 return ret;
125 }
126