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
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,
63 y,
64 width,
65 height,
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)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 // This value is set during create, so if it is still null, simply
96 // return because the global state is corrupted
97 if (!s_display) {
98 return false;
99 }
100
101 auto x11 = getX11Api();
102
103 // Make sure something has changed, otherwise XIfEvent will block and
104 // freeze the emulator.
105 XWindowAttributes attrs;
106 if (!x11->XGetWindowAttributes(s_display, p_sub_window, &attrs)) {
107 return false;
108 }
109 if (x == attrs.x && y == attrs.y &&
110 width == attrs.width && height == attrs.height) {
111 // Technically, resizing was a success because it was unneeded.
112 return true;
113 }
114
115 // This prevents flicker on resize.
116 x11->XSetWindowBackgroundPixmap(s_display, p_sub_window, None);
117
118 int ret = x11->XMoveResizeWindow(
119 s_display,
120 p_sub_window,
121 x,
122 y,
123 width,
124 height);
125
126 XEvent e;
127 x11->XIfEvent(s_display, &e, WaitForConfigureNotify, (char *)p_sub_window);
128
129 return ret;
130 }
131