From: Andy Spencer Date: Mon, 23 Feb 2015 05:47:10 +0000 (+0000) Subject: Add new GTK and XDG Shell Interfaces X-Git-Url: http://pileus.org/git/?a=commitdiff_plain;ds=sidebyside;h=762f4752ad00f1759b1809903c25e01e184f322f;p=wmpus Add new GTK and XDG Shell Interfaces - Add protocol XML files and rules to generate the sources - Add section comments to the makefile and add ignores - Flush out some additional interfaces - Add GTK and XDG Shell/Surface/Popup interfaces - Bump version for Seat and Keyboard interfaces --- diff --git a/.gitignore b/.gitignore index 5dac380..8b7115c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,8 @@ *~ *.o *.swp +*-protocol.c +*-protocol.h .vimrc config.mk local diff --git a/gtk-shell.xml b/gtk-shell.xml new file mode 100644 index 0000000..cd66259 --- /dev/null +++ b/gtk-shell.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/makefile b/makefile index 1bb8c93..0393964 100644 --- a/makefile +++ b/makefile @@ -3,6 +3,7 @@ -include config.mk +# Common configuration VERSION ?= 0.1-rc1 WM ?= wmii SYS ?= x11 @@ -10,11 +11,17 @@ CFLAGS ?= -g -Wall PREFIX ?= /usr/local MANPREFIX ?= ${PREFIX}/share/man +# System specific configuration ifeq ($(SYS),xwl) GCC ?= gcc PROG ?= wmpus LDFLAGS += -lwayland-client -lwayland-server +PROTOCOL ?= gtk-shell xdg-shell +HEADERS += $(addsuffix -client-protocol.h,$(PROTOCOL)) +HEADERS += $(addsuffix -server-protocol.h,$(PROTOCOL)) +OBJECTS += $(addsuffix -protocol.o,$(PROTOCOL)) + sys-xwl.o: CFLAGS += $(shell pkg-config --cflags gtk+-3.0) wmpus: LDFLAGS += $(shell pkg-config --libs gtk+-3.0) endif @@ -43,10 +50,11 @@ PROG ?= wmpus.exe LDFLAGS += -lgdi32 endif -all: $(PROG) +# Targets +all: $(HEADERS) $(PROG) clean: - rm -f wmpus *.exe *.o + rm -f wmpus *.exe *.o *-protocol.[ch] dist: tar -czf wmpus-$(VERSION).tar.gz --transform s::wmpus-$(VERSION)/: \ @@ -63,10 +71,21 @@ uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/$(PROG) rm -f $(DESTDIR)$(MANPREFIX)/man1/wmpus.1 -$(PROG): main.o conf.o util.o sys-$(SYS).o wm-$(WM).o +# Common Rules +$(PROG): main.o conf.o util.o sys-$(SYS).o wm-$(WM).o $(OBJECTS) $(GCC) $(CFLAGS) -o $@ $+ $(LDFLAGS) %.o: %.c $(wildcard *.h) makefile $(GCC) $(CFLAGS) --std=gnu99 -c -o $@ $< +# Wayland Rules +%-protocol.c: %.xml + wayland-scanner code < $+ > $@ + +%-server-protocol.h: %.xml + wayland-scanner server-header < $+ > $@ + +%-client-protocol.h: %.xml + wayland-scanner client-header < $+ > $@ + .PHONY: all clean dist install uninstall diff --git a/sys-xwl.c b/sys-xwl.c index 01d43b4..67a4e98 100644 --- a/sys-xwl.c +++ b/sys-xwl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Andy Spencer + * Copyright (c) 2014-2015 Andy Spencer * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -32,6 +32,11 @@ #include "sys.h" #include "wm.h" +#include "xdg-shell-client-protocol.h" +#include "xdg-shell-server-protocol.h" +#include "gtk-shell-client-protocol.h" +#include "gtk-shell-server-protocol.h" + /* Internal structures */ struct win_sys { win_t *win; @@ -156,8 +161,13 @@ static void new_screen(void) /**************************** * Wayland Buffer Interface * ****************************/ +static void buffer_destroy(struct wl_client *cli, struct wl_resource *reso) +{ + printf("buffer_destroy\n"); +} + static struct wl_buffer_interface buffer_iface = { - .destroy = NULL, + .destroy = buffer_destroy, }; /*********************************** @@ -250,19 +260,43 @@ static struct wl_shm_interface shm_iface = { **************************/ /* Pointer */ +static void pointer_set_cursor(struct wl_client *cli, struct wl_resource *ptr, + uint32_t serial, + struct wl_resource *surface, + int32_t hotspot_x, + int32_t hotspot_y) +{ + printf("pointer_set_cursor\n"); +} + +static void pointer_release(struct wl_client *cli, struct wl_resource *ptr) +{ + printf("pointer_release\n"); +} + static struct wl_pointer_interface pointer_iface = { - .set_cursor = NULL, - .release = NULL, + .set_cursor = pointer_set_cursor, + .release = pointer_release, }; /* Keyboard */ +static void keyboard_release(struct wl_client *cli, struct wl_resource *kbd) +{ + printf("keyboard_release\n"); +} + static struct wl_keyboard_interface keyboard_iface = { - .release = NULL, + .release = keyboard_release, }; /* Touch */ +static void touch_release(struct wl_client *cli, struct wl_resource *tch) +{ + printf("touch_release\n"); +} + static struct wl_touch_interface touch_iface = { - .release = NULL, + .release = touch_release, }; /* Seat */ @@ -276,7 +310,7 @@ static void seat_get_pointer(struct wl_client *cli, struct wl_resource *seat, static void seat_get_keyboard(struct wl_client *cli, struct wl_resource *seat, uint32_t id) { printf("seat_get_keyboard\n"); - struct wl_resource *res = wl_resource_create(cli, &wl_keyboard_interface, 3, id); + struct wl_resource *res = wl_resource_create(cli, &wl_keyboard_interface, 4, id); wl_resource_set_implementation(res, &keyboard_iface, NULL, NULL); } @@ -298,22 +332,64 @@ static struct wl_seat_interface seat_iface = { *****************************************/ /* Data Offer */ +static void doff_accept(struct wl_client *cli, struct wl_resource *res, + uint32_t serial, const char *mime_type) +{ + printf("doff_accept\n"); +} + +static void doff_receive(struct wl_client *cli, struct wl_resource *res, + const char *mime_type, int32_t fd) +{ + printf("doff_receive\n"); +} + +static void doff_destroy(struct wl_client *cli, struct wl_resource *res) +{ + printf("doff_destroy\n"); +} + static struct wl_data_offer_interface doff_iface = { - .accept = NULL, - .receive = NULL, - .destroy = NULL, + .accept = doff_accept, + .receive = doff_receive, + .destroy = doff_destroy, }; /* Data Source */ +static void dsrc_offer(struct wl_client *cli, struct wl_resource *res, + const char *mime_type) +{ + (void)doff_iface; + printf("dsrc_offer\n"); +} + +static void dsrc_destroy(struct wl_client *cli, struct wl_resource *res) +{ + printf("dsrc_destroy\n"); +} + static struct wl_data_source_interface dsrc_iface = { - .offer = NULL, - .destroy = NULL, + .offer = dsrc_offer, + .destroy = dsrc_destroy, }; /* Data Device */ +static void ddev_start_drag(struct wl_client *cli, struct wl_resource *res, + struct wl_resource *source, struct wl_resource *origin, + struct wl_resource *icon, uint32_t serial) +{ + printf("start_drag\n"); +} + +static void ddev_set_selection(struct wl_client *cli, struct wl_resource *res, + struct wl_resource *source, uint32_t serial) +{ + printf("set_selection\n"); +} + static struct wl_data_device_interface ddev_iface = { - .start_drag = NULL, - .set_selection = NULL, + .start_drag = ddev_start_drag, + .set_selection = ddev_set_selection, }; /* Data Device Manager */ @@ -552,6 +628,176 @@ static struct wl_shell_interface shell_iface = { .get_shell_surface = shell_get_shell_surface, }; +/* XDG Popup */ +static void xpopup_destroy(struct wl_client *cli, struct wl_resource *xpopup) +{ + printf("xpopup_destroy\n"); +} + +static struct xdg_popup_interface xpopup_iface = { + .destroy = xpopup_destroy, +}; + +/* XDG Surface */ +static void xsurface_destroy(struct wl_client *cli, struct wl_resource *xsfc) +{ + printf("xsurface_destroy\n"); +} + +static void xsurface_set_parent(struct wl_client *cli, struct wl_resource *xsfc, + struct wl_resource *parent) +{ + printf("xsurface_set_parent\n"); +} + +static void xsurface_set_title(struct wl_client *cli, struct wl_resource *xsfc, + const char *title) +{ + printf("xsurface_set_title\n"); +} + +static void xsurface_set_app_id(struct wl_client *cli, struct wl_resource *xsfc, + const char *app_id) +{ + printf("xsurface_set_app_id\n"); +} + +static void xsurface_show_window_menu(struct wl_client *cli, struct wl_resource *xsfc, + struct wl_resource *seat, uint32_t serial, int32_t x, int32_t y) +{ + printf("xsurface_show_window_menu\n"); +} + +static void xsurface_move(struct wl_client *cli, struct wl_resource *xsfc, + struct wl_resource *seat, uint32_t serial) +{ + printf("xsurface_move\n"); +} + +static void xsurface_resize(struct wl_client *cli, struct wl_resource *xsfc, + struct wl_resource *seat, uint32_t serial, uint32_t edges) +{ + printf("xsurface_resize\n"); +} + +static void xsurface_ack_configure(struct wl_client *cli, struct wl_resource *xsfc, + uint32_t serial) +{ + printf("xsurface_ack_configure\n"); +} + +static void xsurface_set_window_geometry(struct wl_client *cli, struct wl_resource *xsfc, + int32_t x, int32_t y, int32_t width, int32_t height) +{ + printf("xsurface_set_window_geometry\n"); +} + +static void xsurface_set_maximized(struct wl_client *cli, struct wl_resource *xsfc) +{ + printf("xsurface_set_maximized\n"); +} + +static void xsurface_unset_maximized(struct wl_client *cli, struct wl_resource *xsfc) +{ + printf("xsurface_unset_maximized\n"); +} + +static void xsurface_set_fullscreen(struct wl_client *cli, struct wl_resource *xsfc, + struct wl_resource *output) +{ + printf("xsurface_set_fullscreen\n"); +} + +static void xsurface_unset_fullscreen(struct wl_client *cli, struct wl_resource *xsfc) +{ + printf("xsurface_unset_fullscreen\n"); +} + +static void xsurface_set_minimized(struct wl_client *cli, struct wl_resource *xsfc) +{ + printf("xsurface_set_minimized\n"); +} + +static struct xdg_surface_interface xsurface_iface = { + .destroy = xsurface_destroy, + .set_parent = xsurface_set_parent, + .set_title = xsurface_set_title, + .set_app_id = xsurface_set_app_id, + .show_window_menu = xsurface_show_window_menu, + .move = xsurface_move, + .resize = xsurface_resize, + .ack_configure = xsurface_ack_configure, + .set_window_geometry = xsurface_set_window_geometry, + .set_maximized = xsurface_set_maximized, + .unset_maximized = xsurface_unset_maximized, + .set_fullscreen = xsurface_set_fullscreen, + .unset_fullscreen = xsurface_unset_fullscreen, + .set_minimized = xsurface_set_minimized, +}; + +/* XDG Shell */ +static void xshell_use_unstable_version(struct wl_client *cli, struct wl_resource *gshell, + int32_t version) +{ + printf("xshell_use_unstable_version\n"); +} + +static void xshell_get_xdg_surface(struct wl_client *cli, struct wl_resource *gshell, + uint32_t id, struct wl_resource *surface) +{ + printf("xshell_get_xdg_surface\n"); + struct wl_resource *res = wl_resource_create(cli, &xdg_surface_interface, 1, id); + wl_resource_set_implementation(res, &xsurface_iface, NULL, NULL); +} + +static void xshell_get_xdg_popup(struct wl_client *cli, struct wl_resource *gshell, + uint32_t id, struct wl_resource *surface, struct wl_resource *parent, + struct wl_resource *seat, uint32_t serial, int32_t x, int32_t y, uint32_t flags) +{ + printf("xshell_get_xdg_popup\n"); + struct wl_resource *res = wl_resource_create(cli, &xdg_popup_interface, 1, id); + wl_resource_set_implementation(res, &xpopup_iface, NULL, NULL); +} + +static void xshell_pong(struct wl_client *cli, struct wl_resource *gshell, + uint32_t serial) +{ + printf("xshell_pong\n"); +} + +static struct xdg_shell_interface xshell_iface = { + .use_unstable_version = xshell_use_unstable_version, + .get_xdg_surface = xshell_get_xdg_surface, + .get_xdg_popup = xshell_get_xdg_popup, + .pong = xshell_pong, +}; + +/* GTK Surface */ +static void gsurface_set_dbus_properties(struct wl_client *cli, struct wl_resource *gsfc, + const char *application_id, const char *app_menu_path, + const char *menubar_path, const char *window_object_path, + const char *application_object_path, const char *unique_bus_name) +{ + printf("gsurface_set_dbus_properties\n"); +} + +static struct gtk_surface_interface gsurface_iface = { + .set_dbus_properties = gsurface_set_dbus_properties, +}; + +/* GTK Shell */ +static void gshell_get_gtk_surface(struct wl_client *cli, struct wl_resource *gshell, + uint32_t id, struct wl_resource *sfc) +{ + printf("gshell_get_gtk_surface\n"); + struct wl_resource *res = wl_resource_create(cli, >k_surface_interface, 1, id); + wl_resource_set_implementation(res, &gsurface_iface, NULL, NULL); +} + +static struct gtk_shell_interface gshell_iface = { + .get_gtk_surface = gshell_get_gtk_surface, +}; + /******************* * Wayland Globals * *******************/ @@ -563,6 +809,8 @@ static struct wl_global *ref_seat; static struct wl_global *ref_ddm; static struct wl_global *ref_comp; static struct wl_global *ref_shell; +static struct wl_global *ref_xshell; +static struct wl_global *ref_gshell; /* Bind functions */ static void bind_shm(struct wl_client *cli, void *data, uint32_t version, uint32_t id) @@ -631,6 +879,20 @@ static void bind_shell(struct wl_client *cli, void *data, uint32_t version, uint wl_resource_set_implementation(res, &shell_iface, NULL, NULL); } +static void bind_xshell(struct wl_client *cli, void *data, uint32_t version, uint32_t id) +{ + printf("bind_xshell\n"); + struct wl_resource *res = wl_resource_create(cli, &xdg_shell_interface, version, id); + wl_resource_set_implementation(res, &xshell_iface, NULL, NULL); +} + +static void bind_gshell(struct wl_client *cli, void *data, uint32_t version, uint32_t id) +{ + printf("bind_gshell\n"); + struct wl_resource *res = wl_resource_create(cli, >k_shell_interface, version, id); + wl_resource_set_implementation(res, &gshell_iface, NULL, NULL); +} + /******************** * System functions * ********************/ @@ -694,7 +956,9 @@ win_t *sys_init(void) ref_ddm = wl_global_create(display, &wl_data_device_manager_interface, 1, NULL, &bind_ddm); ref_shell = wl_global_create(display, &wl_shell_interface, 1, NULL, &bind_shell); ref_comp = wl_global_create(display, &wl_compositor_interface, 3, NULL, &bind_comp); - ref_seat = wl_global_create(display, &wl_seat_interface, 3, NULL, &bind_seat); + ref_seat = wl_global_create(display, &wl_seat_interface, 4, NULL, &bind_seat); + ref_xshell = wl_global_create(display, &xdg_shell_interface, 1, NULL, &bind_xshell); + ref_gshell = wl_global_create(display, >k_shell_interface, 1, NULL, &bind_gshell); /* Setup GTK display */ gtk_init(&conf_argc, &conf_argv); diff --git a/xdg-shell.xml b/xdg-shell.xml new file mode 100644 index 0000000..275837f --- /dev/null +++ b/xdg-shell.xml @@ -0,0 +1,413 @@ + + + + + Copyright © 2008-2013 Kristian Høgsberg + Copyright © 2013 Rafael Antognolli + Copyright © 2013 Jasper St. Pierre + Copyright © 2010-2013 Intel Corporation + + Permission to use, copy, modify, distribute, and sell this + software and its documentation for any purpose is hereby granted + without fee, provided that the above copyright notice appear in + all copies and that both that copyright notice and this permission + notice appear in supporting documentation, and that the name of + the copyright holders not be used in advertising or publicity + pertaining to distribution of the software without specific, + written prior permission. The copyright holders make no + representations about the suitability of this software for any + purpose. It is provided "as is" without express or implied + warranty. + + THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS + SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND + FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN + AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + THIS SOFTWARE. + + + + + This interface is implemented by servers that provide + desktop-style user interfaces. + + It allows clients to associate a xdg_surface with + a basic surface. + + + + + The 'current' member of this enum gives the version of the + protocol. Implementations can compare this to the version + they implement using static_assert to ensure the protocol and + implementation versions match. + + + + + + + + Negotiate the unstable version of the interface. This + mechanism is in place to ensure client and server agree on the + unstable versions of the protocol that they speak or exit + cleanly if they don't agree. This request will go away once + the xdg-shell protocol is stable. + + + + + + + Create a shell surface for an existing surface. + + Only one shell or popup surface can be associated with a given + surface. + + + + + + + + Create a popup surface for an existing surface. + + Only one shell or popup surface can be associated with a given + surface. + + + + + + + + + + + + + + The ping event asks the client if it's still alive. Pass the + serial specified in the event back to the compositor by sending + a "pong" request back with the specified serial. + + Compositors can use this to determine if the client is still + alive. It's unspecified what will happen if the client doesn't + respond to the ping request, or in what timeframe. Clients should + try to respond in a reasonable amount of time. + + + + + + + A client must respond to a ping event with a pong request or + the client may be deemed unresponsive. + + + + + + + + + An interface that may be implemented by a wl_surface, for + implementations that provide a desktop-style user interface. + + It provides requests to treat surfaces like windows, allowing to set + properties like maximized, fullscreen, minimized, and to move and resize + them, and associate metadata like title and app id. + + On the server side the object is automatically destroyed when + the related wl_surface is destroyed. On client side, + xdg_surface.destroy() must be called before destroying + the wl_surface object. + + + + + The xdg_surface interface is removed from the wl_surface object + that was turned into a xdg_surface with + xdg_shell.get_xdg_surface request. The xdg_surface properties, + like maximized and fullscreen, are lost. The wl_surface loses + its role as a xdg_surface. The wl_surface is unmapped. + + + + + + Child surfaces are stacked above their parents, and will be + unmapped if the parent is unmapped too. They should not appear + on task bars and alt+tab. + + + + + + + Set a short title for the surface. + + This string may be used to identify the surface in a task bar, + window list, or other user interface elements provided by the + compositor. + + The string must be encoded in UTF-8. + + + + + + + Set an id for the surface. + + The app id identifies the general class of applications to which + the surface belongs. + + It should be the ID that appears in the new desktop entry + specification, the interface name. + + + + + + + Clients implementing client-side decorations might want to show + a context menu when right-clicking on the decorations, giving the + user a menu that they can use to maximize or minimize the window. + + This request asks the compositor to pop up such a window menu at + the given position, relative to the parent surface. There are + no guarantees as to what the window menu contains. + + Your surface must have focus on the seat passed in to pop up the + window menu. + + + + + + + + + + + Start a pointer-driven move of the surface. + + This request must be used in response to a button press event. + The server may ignore move requests depending on the state of + the surface (e.g. fullscreen or maximized). + + + + + + + + These values are used to indicate which edge of a surface + is being dragged in a resize operation. The server may + use this information to adapt its behavior, e.g. choose + an appropriate cursor image. + + + + + + + + + + + + + + + Start a pointer-driven resizing of the surface. + + This request must be used in response to a button press event. + The server may ignore resize requests depending on the state of + the surface (e.g. fullscreen or maximized). + + + + + + + + + The different state values used on the surface. This is designed for + state values like maximized, fullscreen. It is paired with the + configure event to ensure that both the client and the compositor + setting the state can be synchronized. + + States set in this way are double-buffered. They will get applied on + the next commit. + + Desktop environments may extend this enum by taking up a range of + values and documenting the range they chose in this description. + They are not required to document the values for the range that they + chose. Ideally, any good extensions from a desktop environment should + make its way into standardization into this enum. + + The current reserved ranges are: + + 0x0000 - 0x0FFF: xdg-shell core values, documented below. + 0x1000 - 0x1FFF: GNOME + + + The surface is maximized. The window geometry specified in the configure + event must be obeyed by the client. + + + The surface is fullscreen. The window geometry specified in the configure + event must be obeyed by the client. + + + The surface is being resized. The window geometry specified in the + configure event is a maximum; the client cannot resize beyond it. + Clients that have aspect ratio or cell sizing configuration can use + a smaller size, however. + + + Client window decorations should be painted as if the window is + active. Do not assume this means that the window actually has + keyboard or pointer focus. + + + + + + The configure event asks the client to resize its surface. + + The width and height arguments specify a hint to the window + about how its surface should be resized in window geometry + coordinates. The states listed in the event specify how the + width/height arguments should be interpreted. + + A client should arrange a new surface, and then send a + ack_configure request with the serial sent in this configure + event before attaching a new surface. + + If the client receives multiple configure events before it + can respond to one, it is free to discard all but the last + event it received. + + + + + + + + + + + When a configure event is received, a client should then ack it + using the ack_configure request to ensure that the compositor + knows the client has seen the event. + + By this point, the state is confirmed, and the next attach should + contain the buffer drawn for the configure event you are acking. + + + + + + + The window geometry of a window is its "visible bounds" from the + user's perspective. Client-side decorations often have invisible + portions like drop-shadows which should be ignored for the + purposes of aligning, placing and constraining windows. + + The default value is the full bounds of the surface, including any + subsurfaces. Once the window geometry of the surface is set once, + it is not possible to unset it, and it will remain the same until + set_window_geometry is called again, even if a new subsurface or + buffer is attached. + + If responding to a configure event, the window geometry in here + must respect the sizing negotiations specified by the states in + the configure event. + + + + + + + + + + + + + Make the surface fullscreen. + + You can specify an output that you would prefer to be fullscreen. + If this value is NULL, it's up to the compositor to choose which + display will be used to map this surface. + + + + + + + + + + The close event is sent by the compositor when the user + wants the surface to be closed. This should be equivalent to + the user clicking the close button in client-side decorations, + if your application has any... + + This is only a request that the user intends to close your + window. The client may choose to ignore this request, or show + a dialog to ask the user to save their data... + + + + + + + An interface that may be implemented by a wl_surface, for + implementations that provide a desktop-style popups/menus. A popup + surface is a transient surface with an added pointer grab. + + An existing implicit grab will be changed to owner-events mode, + and the popup grab will continue after the implicit grab ends + (i.e. releasing the mouse button does not cause the popup to be + unmapped). + + The popup grab continues until the window is destroyed or a mouse + button is pressed in any other clients window. A click in any of + the clients surfaces is reported as normal, however, clicks in + other clients surfaces will be discarded and trigger the callback. + + The x and y arguments specify the locations of the upper left + corner of the surface relative to the upper left corner of the + parent surface, in surface local coordinates. + + xdg_popup surfaces are always transient for another surface. + + + + + The xdg_surface interface is removed from the wl_surface object + that was turned into a xdg_surface with + xdg_shell.get_xdg_surface request. The xdg_surface properties, + like maximized and fullscreen, are lost. The wl_surface loses + its role as a xdg_surface. The wl_surface is unmapped. + + + + + + The popup_done event is sent out when a popup grab is broken, + that is, when the users clicks a surface that doesn't belong + to the client owning the popup surface. + + + + + +