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 "X11Support.h"
18
19 #include <stdio.h>
20
21 namespace {
22
WaitForMapNotify(Display * d,XEvent * e,char * arg)23 static Bool WaitForMapNotify(Display *d, XEvent *e, char *arg) {
24 if (e->type == MapNotify && e->xmap.window == (Window)arg) {
25 return 1;
26 }
27 return 0;
28 }
29
WaitForConfigureNotify(Display * d,XEvent * e,char * arg)30 static Bool WaitForConfigureNotify(Display *d, XEvent *e, char *arg) {
31 if (e->type == ConfigureNotify && e->xmap.window == (Window)arg) {
32 return 1;
33 }
34 return 0;
35 }
36
37 static Display *s_display = NULL;
38
39 } // namespace
40
createSubWindow(FBNativeWindowType p_window,int x,int y,int width,int height,float dpr,SubWindowRepaintCallback repaint_callback,void * repaint_callback_param,int hideWindow)41 EGLNativeWindowType createSubWindow(FBNativeWindowType p_window,
42 int x,
43 int y,
44 int width,
45 int height,
46 float dpr,
47 SubWindowRepaintCallback repaint_callback,
48 void* repaint_callback_param,
49 int hideWindow) {
50 auto x11 = getX11Api();
51 // The call to this function is protected by a lock
52 // in FrameBuffer so it is safe to check and initialize s_display here
53 if (!s_display) {
54 s_display = x11->XOpenDisplay(NULL);
55 }
56
57 XSetWindowAttributes wa;
58 wa.event_mask = StructureNotifyMask;
59 wa.override_redirect = True;
60 Window win = x11->XCreateWindow(s_display,
61 p_window,
62 x * dpr,
63 y * dpr,
64 width * dpr,
65 height * dpr,
66 0,
67 CopyFromParent,
68 CopyFromParent,
69 CopyFromParent,
70 CWEventMask,
71 &wa);
72 if (!hideWindow) {
73 x11->XMapWindow(s_display,win);
74 x11->XSetWindowBackground(s_display, win, 0);
75 XEvent e;
76 x11->XIfEvent(s_display, &e, WaitForMapNotify, (char *)win);
77 }
78 return win;
79 }
80
destroySubWindow(EGLNativeWindowType win)81 void destroySubWindow(EGLNativeWindowType win) {
82 if (!s_display) {
83 return;
84 }
85
86 getX11Api()->XDestroyWindow(s_display, win);
87 }
88
moveSubWindow(FBNativeWindowType p_parent_window,EGLNativeWindowType p_sub_window,int x,int y,int width,int height,float dpr)89 int moveSubWindow(FBNativeWindowType p_parent_window,
90 EGLNativeWindowType p_sub_window,
91 int x,
92 int y,
93 int width,
94 int height,
95 float dpr) {
96 // This value is set during create, so if it is still null, simply
97 // return because the global state is corrupted
98 if (!s_display) {
99 return false;
100 }
101
102 x *= dpr;
103 y *= dpr;
104 width *= dpr;
105 height *= dpr;
106
107 auto x11 = getX11Api();
108
109 // Make sure something has changed, otherwise XIfEvent will block and
110 // freeze the emulator.
111 XWindowAttributes attrs;
112 if (!x11->XGetWindowAttributes(s_display, p_sub_window, &attrs)) {
113 return false;
114 }
115 if (x == attrs.x && y == attrs.y &&
116 width == attrs.width && height == attrs.height) {
117 // Technically, resizing was a success because it was unneeded.
118 return true;
119 }
120
121 // This prevents flicker on resize.
122 x11->XSetWindowBackgroundPixmap(s_display, p_sub_window, None);
123
124 int ret = x11->XMoveResizeWindow(
125 s_display,
126 p_sub_window,
127 x,
128 y,
129 width,
130 height);
131
132 XEvent e;
133 x11->XIfEvent(s_display, &e, WaitForConfigureNotify, (char *)p_sub_window);
134
135 return ret;
136 }
137