22 #include "../../SDL_internal.h"
24 #if SDL_VIDEO_DRIVER_WAYLAND && SDL_VIDEO_OPENGL_EGL
26 #include "../SDL_sysvideo.h"
27 #include "../../events/SDL_windowevents_c.h"
28 #include "../SDL_egl_c.h"
36 #include "xdg-shell-client-protocol.h"
37 #include "xdg-shell-unstable-v6-client-protocol.h"
38 #include "xdg-decoration-unstable-v1-client-protocol.h"
39 #include "org-kde-kwin-server-decoration-manager-client-protocol.h"
51 handle_ping_wl_shell_surface(
void *
data,
struct wl_shell_surface *shell_surface,
54 wl_shell_surface_pong(shell_surface, serial);
58 handle_configure_wl_shell_surface(
void *
data,
struct wl_shell_surface *shell_surface,
97 handle_popup_done_wl_shell_surface(
void *
data,
struct wl_shell_surface *shell_surface)
101 static const struct wl_shell_surface_listener shell_surface_listener_wl = {
102 handle_ping_wl_shell_surface,
103 handle_configure_wl_shell_surface,
104 handle_popup_done_wl_shell_surface
111 handle_configure_zxdg_shell_surface(
void *
data,
struct zxdg_surface_v6 *zxdg,
uint32_t serial)
115 struct wl_region *region;
124 wl_surface_set_buffer_scale(wind->
surface, get_window_scale_factor(
window));
129 zxdg_surface_v6_ack_configure(zxdg, serial);
133 wl_surface_set_opaque_region(wind->
surface, region);
134 wl_region_destroy(region);
147 static const struct zxdg_surface_v6_listener shell_surface_listener_zxdg = {
148 handle_configure_zxdg_shell_surface
153 handle_configure_zxdg_toplevel(
void *
data,
154 struct zxdg_toplevel_v6 *zxdg_toplevel_v6,
157 struct wl_array *states)
162 enum zxdg_toplevel_v6_state *
state;
164 wl_array_for_each(
state, states) {
165 if (*
state == ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN) {
207 handle_close_zxdg_toplevel(
void *
data,
struct zxdg_toplevel_v6 *zxdg_toplevel_v6)
213 static const struct zxdg_toplevel_v6_listener toplevel_listener_zxdg = {
214 handle_configure_zxdg_toplevel,
215 handle_close_zxdg_toplevel
221 handle_configure_xdg_shell_surface(
void *
data,
struct xdg_surface *xdg,
uint32_t serial)
225 struct wl_region *region;
234 wl_surface_set_buffer_scale(wind->
surface, get_window_scale_factor(
window));
239 xdg_surface_ack_configure(xdg, serial);
243 wl_surface_set_opaque_region(wind->
surface, region);
244 wl_region_destroy(region);
257 static const struct xdg_surface_listener shell_surface_listener_xdg = {
258 handle_configure_xdg_shell_surface
263 handle_configure_xdg_toplevel(
void *
data,
264 struct xdg_toplevel *xdg_toplevel,
267 struct wl_array *states)
272 enum xdg_toplevel_state *
state;
274 wl_array_for_each(
state, states) {
275 if (*
state == XDG_TOPLEVEL_STATE_FULLSCREEN) {
317 handle_close_xdg_toplevel(
void *
data,
struct xdg_toplevel *xdg_toplevel)
323 static const struct xdg_toplevel_listener toplevel_listener_xdg = {
324 handle_configure_xdg_toplevel,
325 handle_close_xdg_toplevel
331 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
333 handle_onscreen_visibility(
void *
data,
334 struct qt_extended_surface *qt_extended_surface,
int32_t visible)
339 handle_set_generic_property(
void *
data,
340 struct qt_extended_surface *qt_extended_surface,
const char *
name,
341 struct wl_array *
value)
346 handle_close(
void *
data,
struct qt_extended_surface *qt_extended_surface)
352 static const struct qt_extended_surface_listener extended_surface_listener = {
353 handle_onscreen_visibility,
354 handle_set_generic_property,
361 float old_factor =
window->scale_factor, new_factor = 0.0;
368 if (!
window->num_outputs) {
369 new_factor = old_factor;
376 for (
i = 0;
i <
window->num_outputs;
i++) {
378 if (factor > new_factor) {
383 if (new_factor != old_factor) {
387 window->resize.scale_factor = new_factor;
396 handle_surface_enter(
void *
data,
struct wl_surface *
surface,
397 struct wl_output *
output) {
402 update_scale_factor(
window);
406 handle_surface_leave(
void *
data,
struct wl_surface *
surface,
407 struct wl_output *
output) {
411 if (
window->num_outputs > 1) {
412 struct wl_output **new_outputs =
SDL_malloc((
window->num_outputs - 1) *
sizeof *
window->outputs), **iter = new_outputs;
413 for (
i=0;
i <
window->num_outputs;
i++) {
420 window->outputs = new_outputs;
428 update_scale_factor(
window);
431 static const struct wl_surface_listener surface_listener = {
432 handle_surface_enter,
454 if (version < 2000006) {
460 info->
info.
wl.display =
data->waylandData->display;
462 info->
info.
wl.shell_surface =
data->shell_surface.wl;
495 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
507 struct wl_output *
output = (
struct wl_output *)
window->fullscreen_mode.driverdata;
511 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
513 QtExtendedSurface_OnHintChanged(
void *userdata,
const char *
name,
514 const char *oldValue,
const char *newValue)
516 struct qt_extended_surface *qt_extended_surface = userdata;
523 int32_t orientation = QT_EXTENDED_SURFACE_ORIENTATION_PRIMARYORIENTATION;
525 if (newValue !=
NULL) {
526 if (strcmp(newValue,
"portrait") == 0) {
527 orientation = QT_EXTENDED_SURFACE_ORIENTATION_PORTRAITORIENTATION;
528 }
else if (strcmp(newValue,
"landscape") == 0) {
529 orientation = QT_EXTENDED_SURFACE_ORIENTATION_LANDSCAPEORIENTATION;
530 }
else if (strcmp(newValue,
"inverted-portrait") == 0) {
531 orientation = QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDPORTRAITORIENTATION;
532 }
else if (strcmp(newValue,
"inverted-landscape") == 0) {
533 orientation = QT_EXTENDED_SURFACE_ORIENTATION_INVERTEDLANDSCAPEORIENTATION;
537 qt_extended_surface_set_content_orientation(qt_extended_surface, orientation);
541 if (newValue !=
NULL) {
542 char *tmp =
strdup(newValue);
543 char *saveptr =
NULL;
545 char *flag = strtok_r(tmp,
" ", &saveptr);
547 if (strcmp(flag,
"OverridesSystemGestures") == 0) {
548 flags |= QT_EXTENDED_SURFACE_WINDOWFLAG_OVERRIDESSYSTEMGESTURES;
549 }
else if (strcmp(flag,
"StaysOnTop") == 0) {
550 flags |= QT_EXTENDED_SURFACE_WINDOWFLAG_STAYSONTOP;
551 }
else if (strcmp(flag,
"BypassWindowManager") == 0) {
556 flag = strtok_r(
NULL,
" ", &saveptr);
562 qt_extended_surface_set_window_flags(qt_extended_surface,
flags);
566 static void QtExtendedSurface_Subscribe(
struct qt_extended_surface *
surface,
const char *
name)
571 static void QtExtendedSurface_Unsubscribe(
struct qt_extended_surface *
surface,
const char *
name)
606 const enum zxdg_toplevel_decoration_v1_mode
mode = bordered ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
609 const enum org_kde_kwin_server_decoration_manager_mode
mode = bordered ? ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER : ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_NONE;
628 WAYLAND_wl_display_flush( viddata->
display );
635 struct wl_region *region;
658 data->waylandData =
c;
661 data->scale_factor = 1.0;
676 data->resize.scale_factor =
data->scale_factor;
679 data->num_outputs = 0;
682 wl_compositor_create_surface(
c->compositor);
683 wl_surface_add_listener(
data->surface, &surface_listener,
data);
686 data->shell_surface.xdg.surface = xdg_wm_base_get_xdg_surface(
c->shell.xdg,
data->surface);
688 data->shell_surface.xdg.roleobj.toplevel = xdg_surface_get_toplevel(
data->shell_surface.xdg.surface);
689 xdg_toplevel_add_listener(
data->shell_surface.xdg.roleobj.toplevel, &toplevel_listener_xdg,
data);
690 xdg_toplevel_set_app_id(
data->shell_surface.xdg.roleobj.toplevel,
c->classname);
691 }
else if (
c->shell.zxdg) {
692 data->shell_surface.zxdg.surface = zxdg_shell_v6_get_xdg_surface(
c->shell.zxdg,
data->surface);
694 data->shell_surface.zxdg.roleobj.toplevel = zxdg_surface_v6_get_toplevel(
data->shell_surface.zxdg.surface);
695 zxdg_toplevel_v6_add_listener(
data->shell_surface.zxdg.roleobj.toplevel, &toplevel_listener_zxdg,
data);
696 zxdg_toplevel_v6_set_app_id(
data->shell_surface.zxdg.roleobj.toplevel,
c->classname);
698 data->shell_surface.wl = wl_shell_get_shell_surface(
c->shell.wl,
data->surface);
699 wl_shell_surface_set_class(
data->shell_surface.wl,
c->classname);
702 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
703 if (
c->surface_extension) {
704 data->extended_surface = qt_surface_extension_get_extended_surface(
705 c->surface_extension,
data->surface);
713 data->egl_window = WAYLAND_wl_egl_window_create(
data->surface,
720 return SDL_SetError(
"failed to create an EGL window surface");
725 if (
data->shell_surface.xdg.surface) {
726 xdg_surface_set_user_data(
data->shell_surface.xdg.surface,
data);
727 xdg_surface_add_listener(
data->shell_surface.xdg.surface, &shell_surface_listener_xdg,
data);
729 }
else if (
c->shell.zxdg) {
730 if (
data->shell_surface.zxdg.surface) {
731 zxdg_surface_v6_set_user_data(
data->shell_surface.zxdg.surface,
data);
732 zxdg_surface_v6_add_listener(
data->shell_surface.zxdg.surface, &shell_surface_listener_zxdg,
data);
735 if (
data->shell_surface.wl) {
736 wl_shell_surface_set_user_data(
data->shell_surface.wl,
data);
737 wl_shell_surface_add_listener(
data->shell_surface.wl, &shell_surface_listener_wl,
data);
741 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
742 if (
data->extended_surface) {
743 qt_extended_surface_set_user_data(
data->extended_surface,
data);
744 qt_extended_surface_add_listener(
data->extended_surface,
745 &extended_surface_listener,
data);
749 if (
c->decoration_manager &&
c->shell.xdg &&
data->shell_surface.xdg.surface) {
750 data->server_decoration = zxdg_decoration_manager_v1_get_toplevel_decoration(
c->decoration_manager,
data->shell_surface.xdg.roleobj.toplevel);
751 if (
data->server_decoration) {
753 const enum zxdg_toplevel_decoration_v1_mode
mode = bordered ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE : ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
754 zxdg_toplevel_decoration_v1_set_mode(
data->server_decoration,
mode);
756 }
else if (
c->kwin_server_decoration_manager) {
757 data->kwin_server_decoration = org_kde_kwin_server_decoration_manager_create(
c->kwin_server_decoration_manager,
data->surface);
758 if (
data->kwin_server_decoration) {
760 const enum org_kde_kwin_server_decoration_manager_mode
mode = bordered ? ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_SERVER : ORG_KDE_KWIN_SERVER_DECORATION_MANAGER_MODE_NONE;
761 org_kde_kwin_server_decoration_request_mode(
data->kwin_server_decoration,
mode);
765 region = wl_compositor_create_region(
c->compositor);
767 wl_surface_set_opaque_region(
data->surface, region);
768 wl_region_destroy(region);
770 if (
c->relative_mouse_mode) {
774 wl_surface_commit(
data->surface);
775 WAYLAND_wl_display_flush(
c->display);
780 if (
data->shell_surface.xdg.surface) {
781 while (!
data->shell_surface.xdg.initial_configure_seen) {
782 WAYLAND_wl_display_flush(
c->display);
783 WAYLAND_wl_display_dispatch(
c->display);
786 }
else if (
c->shell.zxdg) {
787 if (
data->shell_surface.zxdg.surface) {
788 while (!
data->shell_surface.zxdg.initial_configure_seen) {
789 WAYLAND_wl_display_flush(
c->display);
790 WAYLAND_wl_display_dispatch(
c->display);
804 if (
data->resize.pending) {
805 struct wl_region *region;
806 if (
data->scale_factor !=
data->resize.scale_factor) {
813 data->scale_factor =
data->resize.scale_factor;
814 wl_surface_set_buffer_scale(
data->surface,
data->scale_factor);
815 if (
data->egl_window) {
816 WAYLAND_wl_egl_window_resize(
data->egl_window,
window->w *
data->scale_factor,
window->h *
data->scale_factor, 0, 0);
819 if (
data->resize.configure) {
820 if (
data->waylandData->shell.xdg) {
821 xdg_surface_ack_configure(
data->shell_surface.xdg.surface,
data->resize.serial);
822 }
else if (
data->waylandData->shell.zxdg) {
823 zxdg_surface_v6_ack_configure(
data->shell_surface.zxdg.surface,
data->resize.serial);
828 region = wl_compositor_create_region(
data->waylandData->compositor);
830 wl_surface_set_opaque_region(
data->surface, region);
831 wl_region_destroy(region);
841 struct wl_region *region;
843 wl_surface_set_buffer_scale(wind->
surface, get_window_scale_factor(
window));
849 region = wl_compositor_create_region(
data->compositor);
851 wl_surface_set_opaque_region(wind->
surface, region);
852 wl_region_destroy(region);
883 WAYLAND_wl_egl_window_destroy(wind->
egl_window);
894 if (
data->shell.xdg) {
901 }
else if (
data->shell.zxdg) {
914 #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH
921 wl_surface_destroy(wind->
surface);
924 WAYLAND_wl_display_flush(
data->display);