mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-02-13 23:33:13 +00:00
X11TK: Flip the positioning of the UI if the locale is RTL (#14183)
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user