diff --git a/src/video/x11/SDL_x11messagebox.c b/src/video/x11/SDL_x11messagebox.c index 94d386f50a..b5b3871dbc 100644 --- a/src/video/x11/SDL_x11messagebox.c +++ b/src/video/x11/SDL_x11messagebox.c @@ -96,7 +96,7 @@ static void X11_PositionMessageBox(SDL_MessageBoxControlsX11 *controls, int *wp, controls->message->rect.y = X11Toolkit_GetIconControlCharY(controls->icon); } else { controls->message->rect.x = 0; - controls->message->rect.y = -2; + controls->message->rect.y = -2 * controls->window->iscale; controls->icon = &controls->fake_icon; controls->icon->rect.w = 0; controls->icon->rect.h = 0; @@ -168,6 +168,114 @@ static void X11_PositionMessageBox(SDL_MessageBoxControlsX11 *controls, int *wp, *hp = h; } +static void X11_PositionMessageBoxFlipped(SDL_MessageBoxControlsX11 *controls, int *wp, int *hp) +{ + int max_button_w; + int max_button_h; + int total_button_w; + int total_text_and_icon_w; + int w; + int h; + int i; + int t; + + /* Init vars */ + max_button_w = 50; + max_button_h = 0; + w = h = 2; + i = t = total_button_w = total_text_and_icon_w = 0; + max_button_w *= controls->window->iscale; + + /* Positioning and sizing */ + for (i = 0; i < controls->messageboxdata->numbuttons; i++) { + max_button_w = SDL_max(max_button_w, controls->buttons[i]->rect.w); + max_button_h = SDL_max(max_button_h, controls->buttons[i]->rect.h); + controls->buttons[i]->rect.x = 0; + } + + if (controls->icon) { + controls->icon->rect.y = 0; + } + + if (controls->icon) { + controls->message->rect.x = 0; + controls->message->rect.y = X11Toolkit_GetIconControlCharY(controls->icon); + controls->icon->rect.x = (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale) + controls->message->rect.w + controls->message->rect.x; + } else { + controls->message->rect.x = 0; + controls->message->rect.y = -2 * controls->window->iscale; + controls->icon = &controls->fake_icon; + controls->icon->rect.w = 0; + controls->icon->rect.h = 0; + controls->icon->rect.x = 0; + controls->icon->rect.y = 0; + } + if (controls->messageboxdata->flags & SDL_MESSAGEBOX_BUTTONS_RIGHT_TO_LEFT) { + for (i = controls->messageboxdata->numbuttons; i != -1; i--) { + controls->buttons[i]->rect.w = max_button_w; + controls->buttons[i]->rect.h = max_button_h; + X11Toolkit_NotifyControlOfSizeChange(controls->buttons[i]); + + if (controls->icon->rect.h > controls->message->rect.h) { + controls->buttons[i]->rect.y = controls->icon->rect.h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 *controls-> window->iscale); + } else { + controls->buttons[i]->rect.y = controls->message->rect.h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale); + } + + if (i) { + controls->buttons[i]->rect.x = controls->buttons[i-1]->rect.x + controls->buttons[i-1]->rect.w + (SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * controls->window->iscale); + } + } + } else { + for (i = 0; i < controls->messageboxdata->numbuttons; i++) { + controls->buttons[i]->rect.w = max_button_w; + controls->buttons[i]->rect.h = max_button_h; + X11Toolkit_NotifyControlOfSizeChange(controls->buttons[i]); + + if (controls->icon->rect.h > controls->message->rect.h) { + controls->buttons[i]->rect.y = controls->icon->rect.h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale); + } else { + controls->buttons[i]->rect.y = controls->message->rect.h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale); + } + + if (i) { + controls->buttons[i]->rect.x = controls->buttons[i-1]->rect.x + controls->buttons[i-1]->rect.w + (SDL_TOOLKIT_X11_ELEMENT_PADDING_3 * controls->window->iscale); + } + } + } + total_button_w = controls->buttons[controls->messageboxdata->numbuttons-1]->rect.x + controls->buttons[controls->messageboxdata->numbuttons-1]->rect.w; + total_text_and_icon_w = controls->message->rect.w + controls->icon->rect.w + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale); + if (total_button_w > total_text_and_icon_w) { + w = total_button_w; + } else { + w = total_text_and_icon_w; + } + w += (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale) * 2; + if (controls->message->rect.h > controls->icon->rect.h) { + h = controls->message->rect.h; + } else { + h = controls->icon->rect.h; + } + h += max_button_h + (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale) * 3; + t = (w - total_text_and_icon_w) / 2; + controls->icon->rect.x += t; + controls->message->rect.x += t; + controls->icon->rect.y += (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale); + controls->message->rect.y += (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale); + t = (w - total_button_w) / 2; + for (i = 0; i < controls->messageboxdata->numbuttons; i++) { + controls->buttons[i]->rect.x += t; + controls->buttons[i]->rect.y += (SDL_TOOLKIT_X11_ELEMENT_PADDING_2 * controls->window->iscale); + } + if (!controls->messageboxdata->message) { + controls->icon->rect.x = (w - controls->icon->rect.w)/2; + } + + *wp = w; + *hp = h; +} + + static void X11_OnMessageBoxScaleChange(SDL_ToolkitWindowX11 *window, void *data) { SDL_MessageBoxControlsX11 *controls; int w; @@ -220,7 +328,11 @@ static bool X11_ShowMessageBoxImpl(const SDL_MessageBoxData *messageboxdata, int } /* Positioning */ - X11_PositionMessageBox(&controls, &w, &h); + if (data.window->flip_interface) { + X11_PositionMessageBoxFlipped(&controls, &w, &h); + } else { + X11_PositionMessageBox(&controls, &w, &h); + } /* Actually create window, do event loop, cleanup */ X11Toolkit_CreateWindowRes(controls.window, w, h, 0, 0, (char *)messageboxdata->title); diff --git a/src/video/x11/SDL_x11toolkit.c b/src/video/x11/SDL_x11toolkit.c index 14aba12a3a..3790d2894a 100644 --- a/src/video/x11/SDL_x11toolkit.c +++ b/src/video/x11/SDL_x11toolkit.c @@ -603,6 +603,42 @@ static void X11Toolkit_GetTextWidthHeight(SDL_ToolkitWindowX11 *data, const char } } +static bool X11Toolkit_ShouldFlipUI(void) +{ + SDL_Locale **current_locales; + static const SDL_Locale rtl_locales[] = { + { "ar", NULL, }, + { "fa", "AF", }, + { "fa", "IR", }, + { "he", NULL, }, + { "iw", NULL, }, + { "yi", NULL, }, + { "ur", NULL, }, + { "ug", NULL, }, + { "kd", NULL, }, + { "pk", "PK", }, + { "ps", NULL, } + }; + int current_locales_sz; + int i; + + current_locales = SDL_GetPreferredLocales(¤t_locales_sz); + if (current_locales_sz <= 0) { + return false; + } + for (i = 0; i < SDL_arraysize(rtl_locales); ++i) { + if (SDL_startswith(current_locales[0]->language, rtl_locales[i].language)) { + if (!rtl_locales[i].country) { + return true; + } else { + return SDL_startswith(current_locales[0]->country, rtl_locales[i].country); + } + } + } + + return false; +} + SDL_ToolkitWindowX11 *X11Toolkit_CreateWindowStruct(SDL_Window *parent, SDL_ToolkitWindowX11 *tkparent, SDL_ToolkitWindowModeX11 mode, const SDL_MessageBoxColor *colorhints, bool create_new_display) { SDL_ToolkitWindowX11 *window; @@ -809,9 +845,14 @@ SDL_ToolkitWindowX11 *X11Toolkit_CreateWindowStruct(SDL_Window *parent, SDL_Tool /* Menu windows */ window->popup_windows = NULL; + /* BIDI engine */ #ifdef HAVE_FRIBIDI_H window->fribidi = SDL_FriBidi_Create(); #endif + + /* Interface direction */ + window->flip_interface = X11Toolkit_ShouldFlipUI(); + return window; } diff --git a/src/video/x11/SDL_x11toolkit.h b/src/video/x11/SDL_x11toolkit.h index 69ec8dcb97..0e882b32a9 100644 --- a/src/video/x11/SDL_x11toolkit.h +++ b/src/video/x11/SDL_x11toolkit.h @@ -72,9 +72,9 @@ typedef struct SDL_ToolkitWindowX11 Window window; Drawable drawable; #ifndef NO_SHARED_MEMORY - XImage *image; - XShmSegmentInfo shm_info; - int shm_bytes_per_line; + XImage *image; + XShmSegmentInfo shm_info; + int shm_bytes_per_line; #endif /* Visuals and drawing */ @@ -94,8 +94,8 @@ typedef struct SDL_ToolkitWindowX11 bool xrandr; // Whether Xrandr is present or not #endif #ifndef NO_SHARED_MEMORY - bool shm; - Bool shm_pixmap; + bool shm; + Bool shm_pixmap; #endif bool utf8; /* Atoms */ @@ -160,9 +160,11 @@ typedef struct SDL_ToolkitWindowX11 #ifdef HAVE_FRIBIDI_H /* BIDI engine */ - SDL_FriBidi *fribidi; - bool do_shaping; + SDL_FriBidi *fribidi; + bool do_shaping; #endif + + bool flip_interface; } SDL_ToolkitWindowX11; typedef enum SDL_ToolkitControlStateX11 @@ -183,7 +185,7 @@ typedef struct SDL_ToolkitControlX11 bool dynamic; bool is_default_enter; bool is_default_esc; - bool do_size; + bool do_size; /* User data */ void *data;