diff --git a/desmume/src/frontend/posix/gtk/main.cpp b/desmume/src/frontend/posix/gtk/main.cpp index f3e4c96d6..06861431e 100644 --- a/desmume/src/frontend/posix/gtk/main.cpp +++ b/desmume/src/frontend/posix/gtk/main.cpp @@ -313,6 +313,8 @@ enum orientation_enum { ORIENT_VERTICAL = 0, ORIENT_HORIZONTAL = 1, ORIENT_SINGLE = 2, + ORIENT_HYBRID_EQUAL = 3, + ORIENT_HYBRID_VERTICAL = 4, ORIENT_N }; @@ -322,9 +324,11 @@ struct screen_size_t { }; const struct screen_size_t screen_size[ORIENT_N] = { - {256, 384}, - {512, 192}, - {256, 192} + {GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT*2}, + {GPU_FRAMEBUFFER_NATIVE_WIDTH*2, GPU_FRAMEBUFFER_NATIVE_HEIGHT}, + {GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT}, + {GPU_FRAMEBUFFER_NATIVE_WIDTH*3, GPU_FRAMEBUFFER_NATIVE_HEIGHT*2}, + {GPU_FRAMEBUFFER_NATIVE_WIDTH*3, GPU_FRAMEBUFFER_NATIVE_HEIGHT*2} }; enum spumode_enum { @@ -539,7 +543,9 @@ struct nds_screen_t { gint rotation_angle; orientation_enum orientation; cairo_matrix_t touch_matrix; + cairo_matrix_t touch_matrix_hybrid; cairo_matrix_t topscreen_matrix; + cairo_matrix_t topscreen_matrix_hybrid; gboolean swap; }; @@ -1213,6 +1219,33 @@ static void Reset(GSimpleAction *action, GVariant *parameter, gpointer user_data /////////////////////////////// DRAWING SCREEN ////////////////////////////////// + +struct DrawParams { + bool valid; + + //Drawing area size + gint daW; + gint daH; + + //Image size + gint imgW; + gint imgH; + + //Buffer size + gint dstW; + gint dstH; + gint dstScale; + + gint gap; + gint gapOffset; + + gfloat ratio; + + gdouble hybridBigScreenScale; +}; + +static DrawParams draw_params = {false, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1.0, 0.0}; + static void UpdateDrawingAreaAspect() { gint H, W; @@ -1226,11 +1259,16 @@ static void UpdateDrawingAreaAspect() } if (nds_screen.orientation != ORIENT_SINGLE) { - if (nds_screen.orientation == ORIENT_VERTICAL) { + if ((nds_screen.orientation == ORIENT_VERTICAL) || (nds_screen.orientation == ORIENT_HYBRID_EQUAL) || + (nds_screen.orientation == ORIENT_HYBRID_VERTICAL)) { if ((nds_screen.rotation_angle == 0 || nds_screen.rotation_angle == 180)) { - H += nds_screen.gap_size; + if((nds_screen.orientation == ORIENT_HYBRID_EQUAL) || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL)) + W = (W * 2.0/3.0) * (double)(H + nds_screen.gap_size) / (double)H + W / 3.0; + H += nds_screen.gap_size; } else { - W += nds_screen.gap_size; + if((nds_screen.orientation == ORIENT_HYBRID_EQUAL) || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL)) + H = (H * 2.0/3.0) * (double)(W + nds_screen.gap_size) / (double)W + H / 3.0; + W += nds_screen.gap_size; } } } @@ -1243,6 +1281,8 @@ static void UpdateDrawingAreaAspect() gtk_window_set_resizable(GTK_WINDOW(pWindow), FALSE); gtk_widget_set_size_request(GTK_WIDGET(pDrawingArea), W * winsize_current / 2, H * winsize_current / 2); } + + draw_params.valid = false; } static void ToggleGap(GSimpleAction *action, GVariant *parameter, gpointer user_data) @@ -1306,9 +1346,15 @@ static void SetOrientation(GSimpleAction *action, GVariant *parameter, gpointer orient = ORIENT_HORIZONTAL; else if(strcmp(string, "single") == 0) orient = ORIENT_SINGLE; + else if(strcmp(string, "hybrid_equal") == 0) + orient = ORIENT_HYBRID_EQUAL; + else if(strcmp(string, "hybrid_vertical") == 0) + orient = ORIENT_HYBRID_VERTICAL; nds_screen.orientation = orient; #ifdef HAVE_LIBAGG osd->singleScreen = nds_screen.orientation == ORIENT_SINGLE; + bool hybrid = (nds_screen.orientation == ORIENT_HYBRID_EQUAL) || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL); + osd->swapScreens = nds_screen.swap && !hybrid; #endif config.view_orient = nds_screen.orientation; UpdateDrawingAreaAspect(); @@ -1320,7 +1366,8 @@ static void ToggleSwapScreens(GSimpleAction *action, GVariant *parameter, gpoint gboolean value = !g_variant_get_boolean(variant); nds_screen.swap = value; #ifdef HAVE_LIBAGG - osd->swapScreens = nds_screen.swap; + bool hybrid = (nds_screen.orientation == ORIENT_HYBRID_EQUAL) || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL); + osd->swapScreens = nds_screen.swap && !hybrid; #endif config.view_swap = nds_screen.swap; RedrawScreen(); @@ -1364,6 +1411,17 @@ static inline void drawTopScreen(cairo_t* cr, u32* buf, gint w, gint h, gint gap cairo_translate(cr, w, 0); } break; + case ORIENT_HYBRID_EQUAL: + case ORIENT_HYBRID_VERTICAL: + if (!swap && (draw_params.hybridBigScreenScale > 0.0)) { + cairo_save(cr); + cairo_scale(cr, draw_params.hybridBigScreenScale, draw_params.hybridBigScreenScale); + cairo_get_matrix(cr, &nds_screen.topscreen_matrix_hybrid); + drawScreen(cr, buf, w, h); + cairo_restore(cr); + } + cairo_translate(cr, w * draw_params.hybridBigScreenScale, 0); + break; } // Used for HUD editor mode cairo_get_matrix(cr, &nds_screen.topscreen_matrix); @@ -1387,6 +1445,19 @@ static inline void drawBottomScreen(cairo_t* cr, u32* buf, gint w, gint h, gint cairo_translate(cr, w, 0); } break; + case ORIENT_HYBRID_EQUAL: + case ORIENT_HYBRID_VERTICAL: + if (swap && (draw_params.hybridBigScreenScale > 0.0)) { + cairo_save(cr); + if(orientation == ORIENT_HYBRID_VERTICAL) + cairo_translate(cr, 0, h * (2.0 - draw_params.hybridBigScreenScale) + gap); + cairo_scale(cr, draw_params.hybridBigScreenScale, draw_params.hybridBigScreenScale); + cairo_get_matrix(cr, &nds_screen.touch_matrix_hybrid); + drawScreen(cr, buf, w, h); + cairo_restore(cr); + } + cairo_translate(cr, w * draw_params.hybridBigScreenScale, h + gap); + break; } // Store the matrix for converting touchscreen coordinates cairo_get_matrix(cr, &nds_screen.touch_matrix); @@ -1394,6 +1465,21 @@ static inline void drawBottomScreen(cairo_t* cr, u32* buf, gint w, gint h, gint cairo_restore(cr); } +static void calc_hybrid_vertical_params(gint daW, gint daH, gint gap, gint dstScale, gint & imgW, gint & imgH) +{ + gdouble hyb_hratio1, hyb_hratio2, hyb_vratio1, hyb_vratio2, hyb_ratio1, hyb_ratio2; + hyb_hratio1 = (gdouble)daW / (gdouble)(GPU_FRAMEBUFFER_NATIVE_WIDTH * dstScale / 2); + hyb_vratio1 = (gdouble)daH / (gdouble)(GPU_FRAMEBUFFER_NATIVE_HEIGHT * dstScale + gap); + hyb_ratio1 = MIN(hyb_hratio1, hyb_vratio1); + gint w_rem = daW - GPU_FRAMEBUFFER_NATIVE_WIDTH * dstScale / 2.0 * hyb_ratio1; + hyb_hratio2 = (gdouble)w_rem / (gdouble)(GPU_FRAMEBUFFER_NATIVE_WIDTH * dstScale / 2); + hyb_vratio2 = (gdouble)daH / (gdouble)(GPU_FRAMEBUFFER_NATIVE_HEIGHT * dstScale / 2); + hyb_ratio2 = MIN(hyb_hratio2, hyb_vratio2); + imgW = GPU_FRAMEBUFFER_NATIVE_WIDTH * dstScale / 2 * (1.0 + hyb_ratio2 / hyb_ratio1); + imgH = GPU_FRAMEBUFFER_NATIVE_HEIGHT * dstScale + gap; + draw_params.hybridBigScreenScale = hyb_ratio2 / hyb_ratio1; +} + /* Drawing callback */ static gboolean ExposeDrawingArea (GtkWidget *widget, GdkEventExpose *event, gpointer data) { @@ -1408,51 +1494,96 @@ static gboolean ExposeDrawingArea (GtkWidget *widget, GdkEventExpose *event, gpo u32* fbuf = video->GetDstBufferPtr(); gint dstW = video->GetDstWidth(); gint dstH = video->GetDstHeight(); - - gint dstScale = dstW * 2 / GPU_FRAMEBUFFER_NATIVE_WIDTH; // Actual scale * 2 to handle 1.5x filters - gint gap = nds_screen.orientation == ORIENT_VERTICAL ? nds_screen.gap_size * dstScale / 2 : 0; - gint imgW, imgH; - if (nds_screen.rotation_angle == 0 || nds_screen.rotation_angle == 180) { - imgW = screen_size[nds_screen.orientation].width * dstScale / 2; - imgH = screen_size[nds_screen.orientation].height * dstScale / 2 + gap; - } else { - imgH = screen_size[nds_screen.orientation].width * dstScale / 2; - imgW = screen_size[nds_screen.orientation].height * dstScale / 2 + gap; + if(draw_params.valid) + if(draw_params.daW != daW || draw_params.daH != daH || draw_params.dstW != dstW || draw_params.dstH != dstH) + draw_params.valid = false; + + if(!draw_params.valid) { + draw_params.daW = daW; + draw_params.daH = daH; + draw_params.dstW = dstW; + draw_params.dstH = dstH; + + draw_params.dstScale = dstW * 2 / GPU_FRAMEBUFFER_NATIVE_WIDTH; // Actual scale * 2 to handle 1.5x filters + + draw_params.gap = ((nds_screen.orientation == ORIENT_VERTICAL) || (nds_screen.orientation == ORIENT_HYBRID_EQUAL) + || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL)) ? nds_screen.gap_size * draw_params.dstScale / 2 : 0; + if(nds_screen.orientation == ORIENT_HYBRID_VERTICAL) { + if (nds_screen.rotation_angle == 0 || nds_screen.rotation_angle == 180) + calc_hybrid_vertical_params(daW, daH, draw_params.gap, draw_params.dstScale, draw_params.imgW, draw_params.imgH); + else + calc_hybrid_vertical_params(daH, daW, draw_params.gap, draw_params.dstScale, draw_params.imgH, draw_params.imgW); + } + else { + if (nds_screen.rotation_angle == 0 || nds_screen.rotation_angle == 180) { + draw_params.imgW = screen_size[nds_screen.orientation].width * draw_params.dstScale / 2; + draw_params.imgH = screen_size[nds_screen.orientation].height * draw_params.dstScale / 2 + draw_params.gap; + if(nds_screen.orientation == ORIENT_HYBRID_EQUAL) + draw_params.imgW = (draw_params.imgW * 2.0/3.0) * (double)draw_params.imgH / + (double)(draw_params.imgH - draw_params.gap) + draw_params.imgW / 3.0; + } else { + draw_params.imgH = screen_size[nds_screen.orientation].width * draw_params.dstScale / 2; + draw_params.imgW = screen_size[nds_screen.orientation].height * draw_params.dstScale / 2 + draw_params.gap; + if(nds_screen.orientation == ORIENT_HYBRID_EQUAL) + draw_params.imgH = (draw_params.imgH * 2.0/3.0) * (double)draw_params.imgW / + (double)(draw_params.imgW - draw_params.gap) + draw_params.imgH / 3.0; + } + if(nds_screen.orientation == ORIENT_HYBRID_EQUAL) + draw_params.hybridBigScreenScale = (double)(dstH + draw_params.gap) / (double)(dstH / 2); + } + + // Calculate scale to fit display area to window + gfloat hratio = (gfloat)daW / (gfloat)draw_params.imgW; + gfloat vratio = (gfloat)daH / (gfloat)draw_params.imgH; + draw_params.ratio = MIN(hratio, vratio); + + draw_params.gapOffset = 0; + switch(nds_screen.orientation) { + case ORIENT_HYBRID_EQUAL: + draw_params.gapOffset = dstW * ((gdouble)(dstH + draw_params.gap) / (dstH / 2.0)); + break; + case ORIENT_HYBRID_VERTICAL: + draw_params.gapOffset = dstW * draw_params.hybridBigScreenScale; + break; + } + + draw_params.valid = true; } - // Calculate scale to fit display area to window - gfloat hratio = (gfloat)daW / (gfloat)imgW; - gfloat vratio = (gfloat)daH / (gfloat)imgH; - hratio = MIN(hratio, vratio); - vratio = hratio; - GdkDrawingContext *context = gdk_window_begin_draw_frame(window, gdk_window_get_clip_region(window)); cairo_t* cr = gdk_drawing_context_get_cairo_context(context); // Scale to window size at center of area cairo_translate(cr, daW / 2, daH / 2); - cairo_scale(cr, hratio, vratio); + cairo_scale(cr, draw_params.ratio, draw_params.ratio); // Rotate area cairo_rotate(cr, M_PI / 180 * nds_screen.rotation_angle); // Translate area to top-left corner if (nds_screen.rotation_angle == 0 || nds_screen.rotation_angle == 180) { - cairo_translate(cr, -imgW / 2, -imgH / 2); + cairo_translate(cr, -draw_params.imgW / 2, -draw_params.imgH / 2); } else { - cairo_translate(cr, -imgH / 2, -imgW / 2); + cairo_translate(cr, -draw_params.imgH / 2, -draw_params.imgW / 2); } // Draw both screens - drawTopScreen(cr, fbuf, dstW, dstH / 2, gap, nds_screen.rotation_angle, nds_screen.swap, nds_screen.orientation); - drawBottomScreen(cr, fbuf + dstW * dstH / 2, dstW, dstH / 2, gap, nds_screen.rotation_angle, nds_screen.swap, nds_screen.orientation); + drawTopScreen(cr, fbuf, dstW, dstH / 2, draw_params.gap, nds_screen.rotation_angle, nds_screen.swap, nds_screen.orientation); + drawBottomScreen(cr, fbuf + dstW * dstH / 2, dstW, dstH / 2, draw_params.gap, nds_screen.rotation_angle, nds_screen.swap, nds_screen.orientation); // Draw gap + cairo_set_source_rgb(cr, 0.3, 0.3, 0.3); - cairo_rectangle(cr, 0, dstH / 2, dstW, gap); + cairo_rectangle(cr, draw_params.gapOffset, dstH / 2, dstW, draw_params.gap); cairo_fill(cr); // Complete the touch transformation matrix - cairo_matrix_scale(&nds_screen.topscreen_matrix, (double)dstScale / 2, (double)dstScale / 2); + cairo_matrix_scale(&nds_screen.topscreen_matrix, (double)draw_params.dstScale / 2, (double)draw_params.dstScale / 2); cairo_matrix_invert(&nds_screen.topscreen_matrix); - cairo_matrix_scale(&nds_screen.touch_matrix, (double)dstScale / 2, (double)dstScale / 2); + cairo_matrix_scale(&nds_screen.touch_matrix, (double)draw_params.dstScale / 2, (double)draw_params.dstScale / 2); cairo_matrix_invert(&nds_screen.touch_matrix); + if((nds_screen.orientation == ORIENT_HYBRID_EQUAL) || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL)) { + cairo_matrix_scale(&nds_screen.topscreen_matrix_hybrid, (double)draw_params.dstScale / 2, (double)draw_params.dstScale / 2); + cairo_matrix_invert(&nds_screen.topscreen_matrix_hybrid); + cairo_matrix_scale(&nds_screen.touch_matrix_hybrid, (double)draw_params.dstScale / 2, (double)draw_params.dstScale / 2); + cairo_matrix_invert(&nds_screen.touch_matrix_hybrid); + } gdk_window_end_draw_frame(window, context); draw_count++; @@ -1476,12 +1607,17 @@ static void RedrawScreen() { /////////////////////////////// KEYS AND STYLUS UPDATE /////////////////////////////////////// +static bool move_started_in_big_screen = false; +static bool hud_move_started_in_big_screen = false; + #ifdef HAVE_LIBAGG static gboolean rotoscaled_hudedit(gint x, gint y, gboolean start) { double devX, devY; - gint X, Y, topX = -1, topY = -1, botX = -1, botY = -1; + gint X, Y, topX = -1, topY = -1, botX = -1, botY = -1, hybTopX = -1, hybTopY = -1, hybBotX = -1, hybBotY = -1; static gint startScreen = 0; + bool hybrid = ((nds_screen.orientation == ORIENT_HYBRID_EQUAL) || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL)) && + (draw_params.hybridBigScreenScale > 0.0); if (nds_screen.orientation != ORIENT_SINGLE || !nds_screen.swap) { devX = x; @@ -1489,6 +1625,14 @@ static gboolean rotoscaled_hudedit(gint x, gint y, gboolean start) cairo_matrix_transform_point(&nds_screen.topscreen_matrix, &devX, &devY); topX = devX * gpu_scale_factor; topY = devY * gpu_scale_factor; + + if(hybrid && !nds_screen.swap) { + devX = x; + devY = y; + cairo_matrix_transform_point(&nds_screen.topscreen_matrix_hybrid, &devX, &devY); + hybTopX = devX * gpu_scale_factor; + hybTopY = devY * gpu_scale_factor; + } } if (nds_screen.orientation != ORIENT_SINGLE || nds_screen.swap) { @@ -1497,23 +1641,57 @@ static gboolean rotoscaled_hudedit(gint x, gint y, gboolean start) cairo_matrix_transform_point(&nds_screen.touch_matrix, &devX, &devY); botX = devX * gpu_scale_factor; botY = devY * gpu_scale_factor; + + if(hybrid && nds_screen.swap) { + devX = x; + devY = y; + cairo_matrix_transform_point(&nds_screen.touch_matrix_hybrid, &devX, &devY); + hybBotX = devX * gpu_scale_factor; + hybBotY = devY * gpu_scale_factor; + } } if (topX >= 0 && topY >= 0 && topX < real_framebuffer_width && topY < real_framebuffer_height) { X = topX; - Y = topY + (nds_screen.swap ? real_framebuffer_height : 0); + Y = topY + (osd->swapScreens ? real_framebuffer_height : 0); + startScreen = 0; + if(start) + hud_move_started_in_big_screen = false; + } else if (hybTopX >= 0 && hybTopY >= 0 && hybTopX < real_framebuffer_width && hybTopY < real_framebuffer_height) { + X = hybTopX; + Y = hybTopY; startScreen = 0; + if(start) + hud_move_started_in_big_screen = true; } else if (botX >= 0 && botY >= 0 && botX < real_framebuffer_width && botY < real_framebuffer_height) { X = botX; - Y = botY + (nds_screen.swap ? 0 : real_framebuffer_height); + Y = botY + (osd->swapScreens ? 0 : real_framebuffer_height); startScreen = 1; + if(start) + hud_move_started_in_big_screen = false; + } else if (hybBotX >= 0 && hybBotY >= 0 && hybBotX < real_framebuffer_width && hybBotY < real_framebuffer_height) { + X = hybBotX; + Y = hybBotY + real_framebuffer_height; + startScreen = 1; + if(start) + hud_move_started_in_big_screen = true; } else if (!start) { if (startScreen == 0) { - X = CLAMP(topX, 0, real_framebuffer_width-1); - Y = CLAMP(topY, 0, real_framebuffer_height-1) + (nds_screen.swap ? real_framebuffer_height : 0); + if(!hud_move_started_in_big_screen || !hybrid) { + X = CLAMP(topX, 0, real_framebuffer_width-1); + Y = CLAMP(topY, 0, real_framebuffer_height-1) + (osd->swapScreens ? real_framebuffer_height : 0); + } else { + X = CLAMP(hybTopX, 0, real_framebuffer_width-1); + Y = CLAMP(hybTopY, 0, real_framebuffer_height-1); + } } else { - X = CLAMP(botX, 0, real_framebuffer_width-1); - Y = CLAMP(botY, 0, real_framebuffer_height-1) + (nds_screen.swap ? 0 : real_framebuffer_height); + if(!hud_move_started_in_big_screen || !hybrid) { + X = CLAMP(botX, 0, real_framebuffer_width-1); + Y = CLAMP(botY, 0, real_framebuffer_height-1) + (osd->swapScreens ? 0 : real_framebuffer_height); + } else { + X = CLAMP(hybBotX, 0, real_framebuffer_width-1); + Y = CLAMP(hybBotY, 0, real_framebuffer_height-1) + real_framebuffer_height; + } } } else { LOG("TopX=%d, TopY=%d, BotX=%d, BotY=%d\n", topX, topY, botX, botY); @@ -1545,13 +1723,33 @@ static gboolean rotoscaled_touchpos(gint x, gint y, gboolean start) LOG("X=%d, Y=%d\n", X, Y); - if (!start || (X >= 0 && Y >= 0 && X < 256 && Y < 192)) { + if ((!start && !move_started_in_big_screen) || (X >= 0 && Y >= 0 && X < 256 && Y < 192)) { + if(start) + move_started_in_big_screen = false; EmuX = CLAMP(X, 0, 255); EmuY = CLAMP(Y, 0, 191); NDS_setTouchPos(EmuX, EmuY); return TRUE; } - + + if((((nds_screen.orientation == ORIENT_HYBRID_EQUAL) || + (nds_screen.orientation == ORIENT_HYBRID_VERTICAL)) && (draw_params.hybridBigScreenScale > 0.0)) && (nds_screen.swap)) { + devX = x; + devY = y; + cairo_matrix_transform_point(&nds_screen.touch_matrix_hybrid, &devX, &devY); + X = devX; + Y = devY; + + if ((!start && move_started_in_big_screen) || (X >= 0 && Y >= 0 && X < 256 && Y < 192)) { + if(start) + move_started_in_big_screen = true; + EmuX = CLAMP(X, 0, 255); + EmuY = CLAMP(Y, 0, 191); + NDS_setTouchPos(EmuX, EmuY); + return TRUE; + } + } + return FALSE; } @@ -3450,7 +3648,7 @@ common_gtk_main(GApplication *app, gpointer user_data) } g_simple_action_set_state(G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "winsize")), g_variant_new_string(string.c_str())); - if (config.view_orient < ORIENT_VERTICAL || config.view_orient > ORIENT_SINGLE) { + if (config.view_orient < ORIENT_VERTICAL || config.view_orient > ORIENT_HYBRID_VERTICAL) { config.view_orient = ORIENT_VERTICAL; } nds_screen.orientation = (orientation_enum)config.view_orient.get(); @@ -3464,6 +3662,12 @@ common_gtk_main(GApplication *app, gpointer user_data) case ORIENT_SINGLE: string = "single"; break; + case ORIENT_HYBRID_EQUAL: + string = "hybrid_equal"; + break; + case ORIENT_HYBRID_VERTICAL: + string = "hybrid_vertical"; + break; } g_simple_action_set_state(G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "orient")), g_variant_new_string(string.c_str())); @@ -3484,6 +3688,10 @@ common_gtk_main(GApplication *app, gpointer user_data) nds_screen.gap_size = config.view_gap ? GAP_SIZE : 0; nds_screen.swap = config.view_swap; + #ifdef HAVE_LIBAGG + bool hybrid = (nds_screen.orientation == ORIENT_HYBRID_EQUAL) || (nds_screen.orientation == ORIENT_HYBRID_VERTICAL); + osd->swapScreens = nds_screen.swap && !hybrid; + #endif g_simple_action_set_state(G_SIMPLE_ACTION(g_action_map_lookup_action(G_ACTION_MAP(app), "swapscreens")), g_variant_new_boolean(config.view_swap)); builder = gtk_builder_new_from_resource("/org/desmume/DeSmuME/menu.ui"); diff --git a/desmume/src/frontend/posix/gtk/menu.ui b/desmume/src/frontend/posix/gtk/menu.ui index 807efa898..c9369d697 100644 --- a/desmume/src/frontend/posix/gtk/menu.ui +++ b/desmume/src/frontend/posix/gtk/menu.ui @@ -254,6 +254,18 @@ app.orient single <Control>0 + + + Hybrid (_equal height) + app.orient + hybrid_equal + <Control>3 + + + Hybrid (e_mphasize vertical) + app.orient + hybrid_vertical + <Control>4