summaryrefslogtreecommitdiff
path: root/src/ui
diff options
context:
space:
mode:
authorJaakko Keränen <jaakko.keranen@iki.fi>2021-02-13 09:47:41 +0200
committerJaakko Keränen <jaakko.keranen@iki.fi>2021-02-13 09:47:41 +0200
commit5d912fc85519e3d0f387a7183711bb5baf521e8a (patch)
tree1e460a5d735c9b28716ef16a87d174049ede2572 /src/ui
parent51a74dc9c66b76dff795a9da3874602f3f0f0285 (diff)
Windows: Improved custom frame behavior
Windows-key shortcuts and cursor edge snapping. Still missing: window shadow and saving the snap mode.
Diffstat (limited to 'src/ui')
-rw-r--r--src/ui/window.c95
-rw-r--r--src/ui/window.h1
2 files changed, 83 insertions, 13 deletions
diff --git a/src/ui/window.c b/src/ui/window.c
index 37586aab..65386e14 100644
--- a/src/ui/window.c
+++ b/src/ui/window.c
@@ -93,6 +93,10 @@ static iBool handleRootCommands_(iWidget *root, const char *cmd) {
93 setTextColor_LabelWidget(findWidget_App("winbar.title"), uiTextStrong_ColorId); 93 setTextColor_LabelWidget(findWidget_App("winbar.title"), uiTextStrong_ColorId);
94 return iFalse; 94 return iFalse;
95 } 95 }
96 else if (equal_Command(cmd, "window.restore")) {
97 setSnap_Window(get_Window(), none_WindowSnap);
98 return iTrue;
99 }
96 else if (equal_Command(cmd, "window.minimize")) { 100 else if (equal_Command(cmd, "window.minimize")) {
97 SDL_MinimizeWindow(get_Window()->win); 101 SDL_MinimizeWindow(get_Window()->win);
98 return iTrue; 102 return iTrue;
@@ -553,9 +557,8 @@ static void setupUserInterface_Window(iWindow *d) {
553 setFont_LabelWidget(appButton, uiContentBold_FontId); 557 setFont_LabelWidget(appButton, uiContentBold_FontId);
554 setId_Widget(addChildFlags_Widget(winBar, 558 setId_Widget(addChildFlags_Widget(winBar,
555 iClob(appTitle = new_LabelWidget("", NULL)), 559 iClob(appTitle = new_LabelWidget("", NULL)),
556 expand_WidgetFlag | /*alignLeft_WidgetFlag |*/ 560 expand_WidgetFlag | fixedHeight_WidgetFlag |
557 fixedHeight_WidgetFlag | frameless_WidgetFlag | 561 frameless_WidgetFlag | commandOnClick_WidgetFlag),
558 commandOnClick_WidgetFlag),
559 "winbar.title"); 562 "winbar.title");
560 setTextColor_LabelWidget(appTitle, uiTextStrong_ColorId); 563 setTextColor_LabelWidget(appTitle, uiTextStrong_ColorId);
561 iLabelWidget *appMin, *appMax, *appClose; 564 iLabelWidget *appMin, *appMax, *appClose;
@@ -570,6 +573,7 @@ static void setupUserInterface_Window(iWindow *d) {
570 winBar, 573 winBar,
571 iClob(appMax = newLargeIcon_LabelWidget("\u25a1", "window.maximize toggle:1")), 574 iClob(appMax = newLargeIcon_LabelWidget("\u25a1", "window.maximize toggle:1")),
572 frameless_WidgetFlag); 575 frameless_WidgetFlag);
576 setId_Widget(as_Widget(appMax), "winbar.max");
573 addChildFlags_Widget(winBar, 577 addChildFlags_Widget(winBar,
574 iClob(appClose = newLargeIcon_LabelWidget("\u2a2f", "window.close")), 578 iClob(appClose = newLargeIcon_LabelWidget("\u2a2f", "window.close")),
575 frameless_WidgetFlag); 579 frameless_WidgetFlag);
@@ -785,7 +789,7 @@ static void drawBlank_Window_(iWindow *d) {
785static SDL_HitTestResult hitTest_Window_(SDL_Window *win, const SDL_Point *pos, void *data) { 789static SDL_HitTestResult hitTest_Window_(SDL_Window *win, const SDL_Point *pos, void *data) {
786 iWindow *d = data; 790 iWindow *d = data;
787 iAssert(d->win == win); 791 iAssert(d->win == win);
788 if (SDL_GetWindowFlags(d->win) & SDL_WINDOW_MOUSE_CAPTURE) { 792 if (SDL_GetWindowFlags(d->win) & (SDL_WINDOW_MOUSE_CAPTURE | SDL_WINDOW_FULLSCREEN_DESKTOP)) {
789 return SDL_HITTEST_NORMAL; 793 return SDL_HITTEST_NORMAL;
790 } 794 }
791 int w, h; 795 int w, h;
@@ -979,10 +983,21 @@ static iBool isNormalPlacement_Window_(const iWindow *d) {
979static iBool unsnap_Window_(iWindow *d, const iInt2 *newPos) { 983static iBool unsnap_Window_(iWindow *d, const iInt2 *newPos) {
980#if defined (LAGRANGE_CUSTOM_FRAME) 984#if defined (LAGRANGE_CUSTOM_FRAME)
981 const int snap = snap_Window(d); 985 const int snap = snap_Window(d);
982 if (snap == yMaximized_WindowSnap && 986 if (snap == yMaximized_WindowSnap || snap == left_WindowSnap || snap == right_WindowSnap) {
983 (!newPos || (d->place.lastHit == SDL_HITTEST_RESIZE_LEFT || 987 if (!newPos || (d->place.lastHit == SDL_HITTEST_RESIZE_LEFT ||
984 d->place.lastHit == SDL_HITTEST_RESIZE_RIGHT))) { 988 d->place.lastHit == SDL_HITTEST_RESIZE_RIGHT)) {
985 return iFalse; 989 return iFalse;
990 }
991 if (newPos) {
992 SDL_Rect usable;
993 SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->win), &usable);
994 /* Snap to top. */
995 if (snap == yMaximized_WindowSnap &&
996 iAbs(newPos->y - usable.y) < lineHeight_Text(uiContent_FontId) * 2) {
997 setSnap_Window(d, redo_WindowSnap | yMaximized_WindowSnap);
998 return iFalse;
999 }
1000 }
986 } 1001 }
987 if (snap && snap != fullscreen_WindowSnap) { 1002 if (snap && snap != fullscreen_WindowSnap) {
988 if (snap_Window(d) == yMaximized_WindowSnap && newPos) { 1003 if (snap_Window(d) == yMaximized_WindowSnap && newPos) {
@@ -1027,6 +1042,33 @@ static iBool handleWindowEvent_Window_(iWindow *d, const SDL_WindowEvent *ev) {
1027 d->isMinimized = iTrue; 1042 d->isMinimized = iTrue;
1028 return iFalse; 1043 return iFalse;
1029 } 1044 }
1045#if defined (LAGRANGE_CUSTOM_FRAME)
1046 /* Set the snap position depending on where the mouse cursor is. */ {
1047 SDL_Rect usable;
1048 iInt2 mouse = cursor_Win32(); /* SDL is unaware of the current cursor pos */
1049 SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->win), &usable);
1050 const iBool isTop = iAbs(mouse.y - usable.y) < gap_UI * 20;
1051 const iBool isBottom = iAbs(usable.y + usable.h - mouse.y) < gap_UI * 20;
1052 if (iAbs(mouse.x - usable.x) < gap_UI) {
1053 setSnap_Window(d,
1054 redo_WindowSnap | left_WindowSnap |
1055 (isTop ? topBit_WindowSnap : 0) |
1056 (isBottom ? bottomBit_WindowSnap : 0));
1057 return iTrue;
1058 }
1059 if (iAbs(mouse.x - usable.x - usable.w) < gap_UI) {
1060 setSnap_Window(d,
1061 redo_WindowSnap | right_WindowSnap |
1062 (isTop ? topBit_WindowSnap : 0) |
1063 (isBottom ? bottomBit_WindowSnap : 0));
1064 return iTrue;
1065 }
1066 if (iAbs(mouse.y - usable.y) < 2) {
1067 setSnap_Window(d, redo_WindowSnap | maximized_WindowSnap);
1068 return iTrue;
1069 }
1070 }
1071#endif
1030 //printf("MOVED: %d, %d\n", ev->data1, ev->data2); fflush(stdout); 1072 //printf("MOVED: %d, %d\n", ev->data1, ev->data2); fflush(stdout);
1031 if (unsnap_Window_(d, &newPos)) { 1073 if (unsnap_Window_(d, &newPos)) {
1032 return iTrue; 1074 return iTrue;
@@ -1138,6 +1180,21 @@ iBool processEvent_Window(iWindow *d, const SDL_Event *ev) {
1138 As a workaround, ignore these events. */ 1180 As a workaround, ignore these events. */
1139 return iTrue; /* won't go to bindings, either */ 1181 return iTrue; /* won't go to bindings, either */
1140 } 1182 }
1183#if 0 //defined (LAGRANGE_CUSTOM_FRAME)
1184 if (event.type == SDL_KEYDOWN) {
1185 if (keyMods_Sym(event.key.keysym.mod) == KMOD_PRIMARY) {
1186 printf("got! %x\n", event.key.keysym.sym); fflush(stdout);
1187 /* Emulate window snapping keys. */
1188 switch (event.key.keysym.sym) {
1189 default:
1190 break;
1191 case SDLK_LEFT:
1192 setSnap_Window(d, left_WindowSnap);
1193 return iTrue;
1194 }
1195 }
1196 }
1197#endif
1141 /* Map mouse pointer coordinate to our coordinate system. */ 1198 /* Map mouse pointer coordinate to our coordinate system. */
1142 if (event.type == SDL_MOUSEMOTION) { 1199 if (event.type == SDL_MOUSEMOTION) {
1143 setCursor_Window(d, SDL_SYSTEM_CURSOR_ARROW); /* default cursor */ 1200 setCursor_Window(d, SDL_SYSTEM_CURSOR_ARROW); /* default cursor */
@@ -1322,13 +1379,14 @@ void setSnap_Window(iWindow *d, int snapMode) {
1322 if (d->place.snap == snapMode) { 1379 if (d->place.snap == snapMode) {
1323 return; 1380 return;
1324 } 1381 }
1382 const int snapDist = gap_UI * 4;
1325 iRect newRect = zero_Rect(); 1383 iRect newRect = zero_Rect();
1326 SDL_Rect usable; 1384 SDL_Rect usable;
1327 SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->win), &usable); 1385 SDL_GetDisplayUsableBounds(SDL_GetWindowDisplayIndex(d->win), &usable);
1328 if (d->place.snap == fullscreen_WindowSnap) { 1386 if (d->place.snap == fullscreen_WindowSnap) {
1329 SDL_SetWindowFullscreen(d->win, 0); 1387 SDL_SetWindowFullscreen(d->win, 0);
1330 } 1388 }
1331 d->place.snap = snapMode; 1389 d->place.snap = snapMode & ~redo_WindowSnap;
1332 switch (snapMode & mask_WindowSnap) { 1390 switch (snapMode & mask_WindowSnap) {
1333 case none_WindowSnap: 1391 case none_WindowSnap:
1334 newRect = d->place.normalRect; 1392 newRect = d->place.normalRect;
@@ -1337,7 +1395,8 @@ void setSnap_Window(iWindow *d, int snapMode) {
1337 newRect = init_Rect(usable.x, usable.y, usable.w / 2, usable.h); 1395 newRect = init_Rect(usable.x, usable.y, usable.w / 2, usable.h);
1338 break; 1396 break;
1339 case right_WindowSnap: 1397 case right_WindowSnap:
1340 newRect = init_Rect(usable.x, usable.y + usable.w / 2, usable.w / 2, usable.h); 1398 newRect =
1399 init_Rect(usable.x + usable.w / 2, usable.y, usable.w - usable.w / 2, usable.h);
1341 break; 1400 break;
1342 case maximized_WindowSnap: 1401 case maximized_WindowSnap:
1343 newRect = init_Rect(usable.x, usable.y, usable.w, usable.h); 1402 newRect = init_Rect(usable.x, usable.y, usable.w, usable.h);
@@ -1345,8 +1404,15 @@ void setSnap_Window(iWindow *d, int snapMode) {
1345 case yMaximized_WindowSnap: 1404 case yMaximized_WindowSnap:
1346 newRect.pos.y = 0; 1405 newRect.pos.y = 0;
1347 newRect.size.y = usable.h; 1406 newRect.size.y = usable.h;
1348 SDL_GetWindowPosition(d->win, &newRect.pos.x, NULL);
1349 SDL_GetWindowSize(d->win, &newRect.size.x, NULL); 1407 SDL_GetWindowSize(d->win, &newRect.size.x, NULL);
1408 SDL_GetWindowPosition(d->win, &newRect.pos.x, NULL);
1409 /* Snap the window to left/right edges, if close by. */
1410 if (iAbs(right_Rect(newRect) - (usable.x + usable.w)) < snapDist) {
1411 newRect.pos.x = usable.x + usable.w - width_Rect(newRect);
1412 }
1413 if (iAbs(newRect.pos.x - usable.x) < snapDist) {
1414 newRect.pos.x = usable.x;
1415 }
1350 break; 1416 break;
1351 case fullscreen_WindowSnap: 1417 case fullscreen_WindowSnap:
1352 SDL_SetWindowFullscreen(d->win, SDL_WINDOW_FULLSCREEN_DESKTOP); 1418 SDL_SetWindowFullscreen(d->win, SDL_WINDOW_FULLSCREEN_DESKTOP);
@@ -1358,10 +1424,13 @@ void setSnap_Window(iWindow *d, int snapMode) {
1358 if (snapMode & bottomBit_WindowSnap) { 1424 if (snapMode & bottomBit_WindowSnap) {
1359 newRect.pos.y += newRect.size.y; 1425 newRect.pos.y += newRect.size.y;
1360 } 1426 }
1361 /* Show and hide the title bar. */ 1427 /* Update window controls. */
1362 iWidget *winBar = findWidget_App("winbar"); 1428 iWidget *winBar = findWidget_App("winbar");
1429 updateTextCStr_LabelWidget(findChild_Widget(winBar, "winbar.max"),
1430 d->place.snap == maximized_WindowSnap ? "\u25a2" : "\u25a1");
1431 /* Show and hide the title bar. */
1363 const iBool wasVisible = isVisible_Widget(winBar); 1432 const iBool wasVisible = isVisible_Widget(winBar);
1364 setFlags_Widget(winBar, hidden_WidgetFlag, snapMode == fullscreen_WindowSnap); 1433 setFlags_Widget(winBar, hidden_WidgetFlag, d->place.snap == fullscreen_WindowSnap);
1365 if (newRect.size.x) { 1434 if (newRect.size.x) {
1366 SDL_SetWindowPosition(d->win, newRect.pos.x, newRect.pos.y); 1435 SDL_SetWindowPosition(d->win, newRect.pos.x, newRect.pos.y);
1367 SDL_SetWindowSize(d->win, newRect.size.x, newRect.size.y); 1436 SDL_SetWindowSize(d->win, newRect.size.x, newRect.size.y);
diff --git a/src/ui/window.h b/src/ui/window.h
index ddb03847..6063df88 100644
--- a/src/ui/window.h
+++ b/src/ui/window.h
@@ -42,6 +42,7 @@ enum iWindowSnap {
42 mask_WindowSnap = 0xff, 42 mask_WindowSnap = 0xff,
43 topBit_WindowSnap = iBit(9), 43 topBit_WindowSnap = iBit(9),
44 bottomBit_WindowSnap = iBit(10), 44 bottomBit_WindowSnap = iBit(10),
45 redo_WindowSnap = iBit(11),
45}; 46};
46 47
47iDeclareType(WindowPlacement) 48iDeclareType(WindowPlacement)