mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -06:00
Custom Title Bar refactored / gtk support (#345)
This commit is contained in:
parent
68dbd76e01
commit
241cc4ea9d
48 changed files with 1606 additions and 538 deletions
|
|
@ -12,5 +12,6 @@ file
|
||||||
|
|
||||||
mainconfig
|
mainconfig
|
||||||
"" = "GUI",
|
"" = "GUI",
|
||||||
|
"" = "GUI FORCE_CSD",
|
||||||
"" = "GUI X11";
|
"" = "GUI X11";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,22 +3,15 @@
|
||||||
using namespace Upp;
|
using namespace Upp;
|
||||||
|
|
||||||
struct MyApp : TopWindow {
|
struct MyApp : TopWindow {
|
||||||
FrameTop<StaticRect> bararea; // we represent whole TitleBar area as frame
|
|
||||||
ParentCtrl barrect; // to do custom caption clipping
|
|
||||||
MenuBar menubar;
|
MenuBar menubar;
|
||||||
LineEdit editor;
|
LineEdit editor;
|
||||||
Label title;
|
Label title;
|
||||||
|
|
||||||
void MainMenu(Bar& bar)
|
|
||||||
{
|
|
||||||
bar.Sub("File", [=](Bar& bar) {
|
|
||||||
bar.Add("Exit", [=] { Break(); });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetMenuBar() {
|
void SetMenuBar() {
|
||||||
menubar.Set([=](Bar& bar) {
|
menubar.Set([=](Bar& bar) {
|
||||||
MainMenu(bar);
|
bar.Sub("File", [=](Bar& bar) {
|
||||||
|
bar.Add("Exit", [=] { Break(); });
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,23 +27,16 @@ struct MyApp : TopWindow {
|
||||||
Icon(CtrlImg::new_doc());
|
Icon(CtrlImg::new_doc());
|
||||||
|
|
||||||
int h = menubar.GetStdHeight();
|
int h = menubar.GetStdHeight();
|
||||||
CustomTitleBar(h); // h is suggested minimum height
|
Ctrl *custom_bar = CustomTitleBar(SColorFace());
|
||||||
|
|
||||||
if(IsCustomTitleBar()) {
|
if(custom_bar) {
|
||||||
menubar.Transparent();
|
menubar.Transparent();
|
||||||
auto cm = GetCustomTitleBarMetrics();
|
auto cm = GetCustomTitleBarMetrics();
|
||||||
bararea.Height(cm.height);
|
*custom_bar << menubar;
|
||||||
AddFrame(bararea);
|
|
||||||
bararea << barrect.VSizePos().HSizePos(cm.lm, cm.rm);
|
|
||||||
ImageBuffer m(1, 2);
|
|
||||||
m[0][0] = Blend(SWhite(), SLtCyan());
|
|
||||||
m[0][1] = Blend(SWhite(), SLtMagenta());
|
|
||||||
bararea.Background(Image(m)); // simple gradient
|
|
||||||
barrect << menubar;
|
|
||||||
SetMenuBar(); // run it here to get GetWidth
|
SetMenuBar(); // run it here to get GetWidth
|
||||||
menubar.LeftPos(0, menubar.GetWidth()).TopPos((cm.height - h) / 2, h);
|
menubar.LeftPos(0, menubar.GetWidth()).TopPos((cm.height - h) / 2, h);
|
||||||
barrect << title.HSizePos(menubar.GetWidth(), cm.rm).VSizePos();
|
*custom_bar << title.HSizePos(menubar.GetWidth(), cm.rm).VSizePos();
|
||||||
title.SetLabel("This is CustomTitleBar example");
|
title.SetLabel("\1[g This is [* CustomTitleBar] [/ example]");
|
||||||
title.AlignCenter();
|
title.AlignCenter();
|
||||||
title.AlignVCenter();
|
title.AlignVCenter();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
28
s
Normal file
28
s
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
DarkModeContent[m
|
||||||
|
* [32mDisplayPopup3[m
|
||||||
|
NewDisplayPopup[m
|
||||||
|
_t[m
|
||||||
|
animations[m
|
||||||
|
bad_alloc[m
|
||||||
|
blocksel[m
|
||||||
|
custom_caption[m
|
||||||
|
custom_titlebar[m
|
||||||
|
diagram_dev[m
|
||||||
|
display_popup[m
|
||||||
|
ext2[m
|
||||||
|
gui_sizeof[m
|
||||||
|
ide_ext[m
|
||||||
|
ide_external[m
|
||||||
|
ime[m
|
||||||
|
layzoom[m
|
||||||
|
+ [36mllbm_ide[m
|
||||||
|
logs[m
|
||||||
|
master[m
|
||||||
|
mt_painter[m
|
||||||
|
newmouse[m
|
||||||
|
next2025_1[m
|
||||||
|
pixelmode[m
|
||||||
|
skin[m
|
||||||
|
stable[m
|
||||||
|
wchar[m
|
||||||
|
|
||||||
|
|
@ -675,6 +675,8 @@ private:
|
||||||
static Point dndpos;
|
static Point dndpos;
|
||||||
static bool dndframe;
|
static bool dndframe;
|
||||||
static PasteClip dndclip;
|
static PasteClip dndclip;
|
||||||
|
|
||||||
|
static int last_mouse_action;
|
||||||
|
|
||||||
void DnD(Point p, PasteClip& clip);
|
void DnD(Point p, PasteClip& clip);
|
||||||
static void DnDRepeat();
|
static void DnDRepeat();
|
||||||
|
|
@ -700,8 +702,11 @@ private:
|
||||||
Rect GetPreeditScreenRect();
|
Rect GetPreeditScreenRect();
|
||||||
void SyncPreedit();
|
void SyncPreedit();
|
||||||
void ShowPreedit(const WString& text, int cursor = INT_MAX);
|
void ShowPreedit(const WString& text, int cursor = INT_MAX);
|
||||||
static void HidePreedit();
|
|
||||||
static void PreeditSync(void (*enable_preedit)(Ctrl *top, bool enable));
|
static void HidePreedit();
|
||||||
|
static void PreeditSync(void (*enable_preedit)(Ctrl *top, bool enable));
|
||||||
|
|
||||||
|
static bool MouseActiveCtrl(Ctrl *w, Point p);
|
||||||
|
|
||||||
// System window interface...
|
// System window interface...
|
||||||
void WndShow(bool b);
|
void WndShow(bool b);
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,22 @@ IMAGE_ID(DndNone98)
|
||||||
IMAGE_ID(DndCopy)
|
IMAGE_ID(DndCopy)
|
||||||
IMAGE_ID(DndCopy98)
|
IMAGE_ID(DndCopy98)
|
||||||
IMAGE_ID(DndData)
|
IMAGE_ID(DndData)
|
||||||
|
IMAGE_ID(GtkBarButton__UHD)
|
||||||
|
IMAGE_ID(GtkBarButtonH__UHD)
|
||||||
|
IMAGE_ID(GtkBarClose__UHD)
|
||||||
|
IMAGE_ID(GtkBarMaximize__UHD)
|
||||||
|
IMAGE_ID(GtkBarMinimize__UHD)
|
||||||
|
IMAGE_ID(GtkBarOverlap__UHD)
|
||||||
IMAGE_ID(WinClose)
|
IMAGE_ID(WinClose)
|
||||||
IMAGE_ID(WinMinimize)
|
IMAGE_ID(WinMinimize)
|
||||||
IMAGE_ID(WinMaximize)
|
IMAGE_ID(WinMaximize)
|
||||||
IMAGE_ID(WinMaximized)
|
IMAGE_ID(WinMaximized)
|
||||||
|
IMAGE_ID(GtkBarButton)
|
||||||
|
IMAGE_ID(GtkBarButtonH)
|
||||||
|
IMAGE_ID(GtkBarClose)
|
||||||
|
IMAGE_ID(GtkBarMaximize)
|
||||||
|
IMAGE_ID(GtkBarMinimize)
|
||||||
|
IMAGE_ID(GtkBarOverlap)
|
||||||
|
|
||||||
IMAGE_BEGIN_DATA
|
IMAGE_BEGIN_DATA
|
||||||
IMAGE_DATA(120,156,237,150,91,10,194,64,16,4,61,142,231,240,254,119,138,136,54,129,128,178,143,217,157,238,118,10,242,23,72,117)
|
IMAGE_DATA(120,156,237,150,91,10,194,64,16,4,61,142,231,240,254,119,138,136,54,129,128,178,143,217,157,238,118,10,242,23,72,117)
|
||||||
|
|
@ -97,23 +109,111 @@ IMAGE_DATA(32,123,164,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
|
||||||
IMAGE_END_DATA(1152, 4)
|
IMAGE_END_DATA(1152, 4)
|
||||||
|
|
||||||
IMAGE_BEGIN_DATA
|
IMAGE_BEGIN_DATA
|
||||||
IMAGE_DATA(120,156,237,152,191,106,21,65,20,198,207,35,88,228,1,182,201,35,216,164,178,21,83,104,149,194,62,24,31,32,77,64)
|
IMAGE_DATA(120,156,237,154,63,107,20,81,20,197,223,71,176,240,3,108,99,99,111,147,202,86,180,208,202,194,94,140,31,32,8,130)
|
||||||
IMAGE_DATA(236,82,72,192,20,86,193,34,104,103,170,96,99,33,232,3,8,130,88,104,17,66,2,17,3,33,66,98,140,70,248,220)
|
IMAGE_DATA(164,179,16,65,11,43,177,16,237,180,10,54,22,130,126,0,65,16,11,45,68,12,81,20,130,130,241,191,112,221,231,204)
|
||||||
IMAGE_DATA(147,153,235,157,204,206,236,206,122,119,206,68,114,62,248,184,115,103,151,249,125,103,118,119,246,15,85,84,145,35,80,89)
|
IMAGE_DATA(184,147,217,55,51,111,118,222,223,51,231,192,33,147,201,50,231,222,251,219,59,187,217,68,205,212,76,213,36,42,174,164)
|
||||||
IMAGE_DATA(193,122,218,250,154,52,159,101,51,204,215,158,17,206,128,145,108,134,69,225,12,112,85,32,3,124,9,103,104,240,133,51)
|
IMAGE_DATA(244,161,210,7,66,231,107,149,53,156,157,123,45,112,13,82,169,172,97,35,112,13,82,87,132,26,164,169,192,53,44,229)
|
||||||
IMAGE_DATA(4,249,130,25,162,124,161,12,173,124,129,12,157,252,204,25,186,152,35,111,214,126,92,251,78,237,169,92,124,106,174,71)
|
IMAGE_DATA(7,174,193,152,31,176,134,214,252,64,53,116,230,7,168,161,55,223,115,13,125,153,149,183,230,190,54,247,169,185,15,250)
|
||||||
IMAGE_DATA(204,93,175,253,136,242,172,143,141,122,3,124,102,223,165,60,247,7,159,181,25,200,192,252,91,25,216,68,227,227,187,68)
|
IMAGE_DATA(202,87,203,247,35,157,123,123,238,43,202,207,253,113,169,95,67,190,206,62,163,252,188,62,52,179,182,12,53,232,252,227)
|
||||||
IMAGE_DATA(102,158,23,3,124,238,231,185,159,206,196,191,94,251,62,141,207,239,42,144,193,157,3,255,220,12,249,166,29,39,69,92)
|
IMAGE_DATA(30,178,149,90,240,189,168,138,57,111,24,242,245,121,61,251,67,158,242,143,204,125,94,45,158,223,51,67,13,245,25,52)
|
||||||
IMAGE_DATA(215,13,186,120,110,181,205,1,86,55,128,123,43,192,220,67,224,246,146,49,183,185,207,238,63,107,51,164,136,153,83,212)
|
IMAGE_DATA(159,155,38,31,43,175,99,35,221,215,81,181,255,185,213,53,3,185,126,95,228,220,85,145,211,155,34,39,47,22,214,199)
|
||||||
IMAGE_DATA(60,190,177,57,192,219,247,192,218,75,96,249,185,217,246,224,169,105,115,159,221,247,73,237,133,68,126,76,177,57,192,167)
|
IMAGE_DATA(250,92,249,248,19,101,13,54,210,153,7,213,50,223,182,25,200,147,103,34,55,31,136,92,190,91,252,236,210,173,226,88)
|
||||||
IMAGE_DATA(29,224,245,59,224,197,27,179,237,217,43,211,230,190,1,249,68,227,227,185,238,242,191,28,52,214,167,115,127,216,26,156)
|
IMAGE_DATA(159,43,31,123,99,238,117,203,252,54,181,205,64,94,190,21,121,244,84,228,222,227,226,103,119,30,22,199,250,156,195,124)
|
||||||
IMAGE_DATA(207,199,100,198,114,71,235,15,190,29,3,187,251,192,231,93,195,251,184,109,218,220,55,48,127,148,193,125,62,197,201,79)
|
IMAGE_DATA(165,22,60,111,215,243,223,239,46,221,159,254,249,249,107,231,249,154,201,90,153,91,221,127,228,243,158,200,246,71,145,87)
|
||||||
IMAGE_DATA(224,240,8,248,122,104,120,123,7,166,205,125,25,248,190,112,246,27,56,253,5,124,63,5,142,127,24,115,155,251,36,248)
|
IMAGE_DATA(219,69,222,139,55,197,177,62,231,56,191,170,161,254,254,84,190,253,20,249,244,69,228,195,167,34,239,221,110,113,172,207)
|
||||||
IMAGE_DATA(9,206,201,231,235,122,214,50,98,238,115,253,247,85,101,199,94,104,113,159,245,79,165,42,163,75,250,49,160,24,223,185)
|
IMAGE_DATA(121,200,111,74,126,255,17,249,241,75,228,235,15,145,189,239,133,245,177,62,23,34,223,194,62,243,245,94,159,40,51,218)
|
||||||
IMAGE_DATA(217,22,227,23,204,16,122,1,41,198,47,144,161,193,23,206,16,228,11,102,136,242,133,50,180,242,5,50,116,242,51,103)
|
IMAGE_DATA(60,100,255,135,106,86,94,123,189,195,67,238,127,20,21,71,137,126,24,16,45,191,246,98,27,45,63,98,13,166,95,64)
|
||||||
IMAGE_DATA(232,98,138,214,79,242,235,81,163,222,18,124,143,37,153,33,196,144,230,7,251,91,50,164,188,12,76,156,171,141,159,241)
|
IMAGE_DATA(162,229,71,168,97,41,63,112,13,198,252,128,53,180,230,7,170,161,51,63,64,13,189,249,158,107,232,203,12,218,191,10)
|
||||||
IMAGE_DATA(90,141,158,139,161,126,255,154,241,247,233,155,197,103,197,198,236,226,123,191,255,82,255,223,255,129,26,46,100,114,237,214)
|
IMAGE_DATA(127,63,90,234,55,70,126,35,43,100,13,166,140,208,249,198,243,29,53,216,252,50,48,186,174,174,124,143,187,218,250,92)
|
||||||
IMAGE_DATA(60,73,253,41,25,59,230,63,84,75,106,132,65,248,82,245,251,34,129,250,19,156,179,254,62,195,229,168,63,121,32,250)
|
IMAGE_DATA(52,157,111,238,76,243,49,67,107,105,102,181,93,179,47,191,241,117,149,254,255,127,111,232,97,95,77,117,215,123,30,211)
|
||||||
IMAGE_DATA(127,235,31,236,183,47,60,67,6,85,76,149,126,176,82,169,84,42,149,74,165,114,117,213,31,134,7,123,128,158,164,254)
|
IMAGE_DATA(191,77,141,61,243,55,245,98,91,130,147,252,80,253,55,165,2,244,111,97,159,253,15,185,156,143,254,173,47,164,242,237)
|
||||||
IMAGE_DATA(33,248,164,245,107,253,90,191,126,12,80,69,245,7,245,218,88,188,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
|
IMAGE_DATA(223,217,215,161,225,30,106,160,218,52,227,7,86,20,69,81,20,69,81,117,77,253,205,176,179,55,208,99,250,119,145,175)
|
||||||
IMAGE_END_DATA(608, 3)
|
IMAGE_DATA(216,63,251,103,255,252,48,128,106,213,225,11,234,66,236,26,188,105,115,115,83,198,56,118,253,212,66,99,89,146,121,90)
|
||||||
|
IMAGE_DATA(10,197,147,188,195,105,232,236,119,118,118,70,153,172,253,43,20,75,215,204,99,207,45,117,165,194,115,44,239,216,115,76)
|
||||||
|
IMAGE_DATA(77,57,48,93,133,117,236,185,198,86,206,92,201,185,93,72,92,201,121,191,80,185,218,114,142,61,127,95,154,10,215,41)
|
||||||
|
IMAGE_DATA(114,158,34,87,27,206,177,185,140,21,185,226,114,38,91,92,198,100,139,203,152,92,199,113,142,205,175,75,100,139,203,152)
|
||||||
|
IMAGE_DATA(108,113,25,147,45,46,99,178,197,101,76,182,184,140,201,22,151,49,217,226,50,38,91,108,198,100,27,151,113,40,182,228)
|
||||||
|
IMAGE_DATA(27,135,175,47,198,100,139,205,152,108,227,219,23,95,178,77,199,174,25,243,190,156,150,93,223,167,201,54,61,187,226,203)
|
||||||
|
IMAGE_DATA(221,77,211,174,118,152,108,211,245,88,190,220,221,180,61,118,135,201,54,125,175,202,151,187,155,135,87,221,97,178,205,199)
|
||||||
|
IMAGE_DATA(67,249,114,119,243,242,208,29,38,219,252,76,190,216,182,229,75,182,249,218,134,49,249,230,107,242,197,118,31,95,178,205)
|
||||||
|
IMAGE_DATA(223,93,140,201,55,127,147,47,182,201,23,219,109,124,201,22,199,38,198,228,139,99,242,197,54,249,98,155,124,177,221,228)
|
||||||
|
IMAGE_DATA(75,182,120,110,254,205,144,124,177,76,190,216,38,95,108,147,47,182,201,23,219,228,139,109,242,197,54,249,98,155,124,177)
|
||||||
|
IMAGE_DATA(77,190,216,38,95,108,147,47,182,201,23,219,228,139,109,242,197,54,255,6,140,107,254,255,6,182,201,23,219,228,139,109)
|
||||||
|
IMAGE_DATA(242,197,182,137,47,25,99,184,141,45,249,98,152,124,177,77,190,216,238,226,75,198,121,187,143,45,249,230,109,242,197,182)
|
||||||
|
IMAGE_DATA(13,95,50,206,211,182,108,201,55,79,175,202,151,140,211,119,147,87,31,95,238,112,94,30,202,150,59,156,143,87,217,93)
|
||||||
|
IMAGE_DATA(238,112,62,94,149,45,119,56,125,143,217,93,238,112,250,30,203,150,59,156,174,93,236,46,119,56,93,187,98,203,29,78)
|
||||||
|
IMAGE_DATA(207,46,119,151,59,156,158,93,179,37,227,116,236,139,109,147,47,25,199,101,235,131,47,25,99,179,53,49,142,221,247,84)
|
||||||
|
IMAGE_DATA(28,138,109,147,47,25,135,101,27,130,47,25,99,179,37,99,124,182,100,140,207,150,140,241,217,86,34,99,92,182,149,200)
|
||||||
|
IMAGE_DATA(24,151,109,37,50,198,101,91,137,140,113,217,86,106,214,76,206,253,92,115,97,91,137,140,113,217,86,34,99,92,182,117)
|
||||||
|
IMAGE_DATA(145,51,38,215,186,76,253,77,129,115,91,223,177,121,248,210,84,56,79,141,107,93,109,189,35,112,238,234,45,246,220,67)
|
||||||
|
IMAGE_DATA(11,137,51,185,182,43,103,206,228,106,175,174,89,165,196,186,175,206,216,115,76,93,125,243,11,205,219,182,158,216,115,203)
|
||||||
|
IMAGE_DATA(81,182,179,117,197,124,104,94,236,249,32,105,232,236,125,57,246,28,166,34,242,156,158,200,114,191,254,2,145,219,214,121)
|
||||||
|
IMAGE_END_DATA(1248, 4)
|
||||||
|
|
||||||
|
IMAGE_BEGIN_DATA
|
||||||
|
IMAGE_DATA(120,156,237,218,65,78,195,64,16,5,81,206,195,9,89,230,138,57,17,172,44,18,43,182,199,158,177,187,187,92,95,170)
|
||||||
|
IMAGE_DATA(53,201,60,53,27,248,254,249,250,249,162,238,241,120,252,246,20,253,249,221,255,122,45,53,207,181,171,60,245,190,110,123)
|
||||||
|
IMAGE_DATA(223,254,249,124,118,165,245,249,187,202,114,180,121,244,187,101,95,22,207,94,239,232,119,204,182,10,166,71,172,163,223,53)
|
||||||
|
IMAGE_DATA(122,149,93,117,94,30,201,85,231,247,81,93,91,157,163,223,255,172,221,197,245,142,206,119,116,109,113,142,118,233,157,174)
|
||||||
|
IMAGE_DATA(92,103,109,185,198,218,114,141,117,237,115,142,246,91,155,182,92,99,109,185,198,218,114,141,181,229,26,107,203,53,214,150)
|
||||||
|
IMAGE_DATA(107,172,45,215,88,91,182,177,182,177,198,87,217,234,27,227,123,150,177,182,108,99,109,227,59,203,87,219,60,141,54,246)
|
||||||
|
IMAGE_DATA(247,114,174,70,255,158,214,54,95,163,124,189,221,156,141,186,97,109,243,214,235,235,237,230,174,247,134,181,205,223,81,95)
|
||||||
|
IMAGE_DATA(111,183,70,71,111,88,219,58,237,245,245,118,107,181,247,134,181,173,151,190,236,90,125,181,173,91,139,177,190,117,211,151)
|
||||||
|
IMAGE_DATA(221,150,175,182,245,91,51,214,183,126,250,178,211,151,221,146,175,182,156,62,25,235,203,73,95,118,250,178,211,151,221,220)
|
||||||
|
IMAGE_DATA(87,91,94,243,191,25,234,203,74,95,118,250,178,211,151,157,190,236,244,101,167,47,59,125,217,233,203,78,95,118,250,178)
|
||||||
|
IMAGE_DATA(211,151,157,190,236,244,101,167,47,59,255,6,204,205,255,223,96,167,47,59,125,217,233,203,238,147,175,198,140,150,108,245)
|
||||||
|
IMAGE_DATA(101,164,47,59,125,217,173,249,106,92,187,45,91,125,107,167,47,187,22,95,141,107,214,106,171,111,205,142,250,106,156,191)
|
||||||
|
IMAGE_DATA(185,215,150,175,55,92,171,189,182,222,112,157,142,220,174,55,92,167,163,182,222,112,254,122,110,215,27,206,95,175,173,55)
|
||||||
|
IMAGE_DATA(156,183,17,183,235,13,231,109,148,173,55,156,175,145,183,235,13,231,107,180,173,198,121,58,203,118,238,171,113,172,237,25)
|
||||||
|
IMAGE_DATA(190,26,179,109,63,25,71,127,239,187,116,149,237,220,87,227,107,109,175,240,213,152,109,171,49,223,86,99,190,173,198,124)
|
||||||
|
IMAGE_DATA(219,105,26,115,109,167,105,204,181,157,166,49,215,118,154,198,92,219,105,243,207,172,243,182,107,21,219,105,26,115,109,167)
|
||||||
|
IMAGE_DATA(105,204,181,125,157,206,76,215,215,125,250,126,119,112,94,250,222,209,30,103,237,46,206,119,115,125,221,210,119,39,56,175)
|
||||||
|
IMAGE_DATA(125,183,232,119,191,122,36,103,93,151,87,217,89,215,246,173,189,85,38,235,173,207,25,253,142,217,183,245,126,87,123,183)
|
||||||
|
IMAGE_DATA(126,158,232,119,171,184,214,183,29,101,190,247,231,69,191,15,105,123,223,254,172,162,223,225,46,211,243,126,211,242,125,127)
|
||||||
|
IMAGE_DATA(247,87,34,215,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
|
||||||
|
IMAGE_END_DATA(640, 1)
|
||||||
|
|
||||||
|
IMAGE_BEGIN_DATA
|
||||||
|
IMAGE_DATA(120,156,237,216,75,10,194,80,16,68,81,215,227,10,221,125,156,58,8,226,39,239,117,117,115,14,100,222,212,133,16,189)
|
||||||
|
IMAGE_DATA(63,110,143,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,176,220,81,125,192,137,196,155,58,58,94)
|
||||||
|
IMAGE_DATA(158,20,137,55,117,116,156,60,213,18,111,234,232,108,199,234,61,19,111,234,44,105,207,164,91,38,73,216,53,225,134,201)
|
||||||
|
IMAGE_DATA(42,247,213,118,143,138,157,181,221,107,231,222,218,214,216,177,187,182,181,86,238,175,109,134,21,29,180,205,114,101,15,109)
|
||||||
|
IMAGE_DATA(51,93,209,69,219,108,255,244,209,182,135,95,58,105,219,203,55,189,180,237,233,147,110,218,246,246,174,159,182,51,104,59)
|
||||||
|
IMAGE_DATA(159,182,243,105,59,155,190,115,121,63,207,229,251,106,46,191,143,230,242,255,198,92,223,116,211,184,151,95,122,105,220,195)
|
||||||
|
IMAGE_DATA(63,157,52,206,118,69,31,141,51,93,217,69,227,44,43,122,104,156,97,101,7,141,107,237,216,95,227,26,59,119,215,120)
|
||||||
|
IMAGE_DATA(175,138,189,53,222,163,114,103,141,215,74,216,55,225,134,137,146,118,77,186,101,130,196,61,19,111,234,44,113,199,196,155)
|
||||||
|
IMAGE_DATA(58,75,220,49,241,166,206,18,119,76,188,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,70,120,2)
|
||||||
|
IMAGE_DATA(156,202,31,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
|
||||||
|
IMAGE_END_DATA(320, 1)
|
||||||
|
|
||||||
|
IMAGE_BEGIN_DATA
|
||||||
|
IMAGE_DATA(120,156,237,209,193,9,2,64,16,4,65,227,49,66,179,215,8,244,119,220,180,84,193,254,135,222,231,235,241,122,0,0)
|
||||||
|
IMAGE_DATA(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,147,222,241,227,183,219,255,241,223,179,110,255,199,127,207,186,253)
|
||||||
|
IMAGE_DATA(31,255,61,235,246,127,252,247,172,219,255,241,223,179,42,221,42,59,215,84,186,85,118,174,169,116,171,236,92,83,233,86)
|
||||||
|
IMAGE_DATA(217,185,166,210,173,178,115,77,165,91,101,231,154,74,183,202,206,53,149,110,149,157,107,42,221,42,59,215,84,186,85,118)
|
||||||
|
IMAGE_DATA(174,169,116,171,236,92,83,233,86,217,185,166,210,173,178,115,77,165,91,101,231,154,74,183,202,206,53,149,110,149,157,107)
|
||||||
|
IMAGE_DATA(42,221,42,59,215,84,186,85,118,174,169,116,171,236,92,83,233,86,217,185,166,210,173,178,115,77,165,91,101,231,154,74)
|
||||||
|
IMAGE_DATA(183,202,206,53,149,110,149,157,107,42,221,42,59,215,84,186,85,118,174,169,116,171,236,92,83,233,86,217,185,166,210,173)
|
||||||
|
IMAGE_DATA(178,115,77,165,91,101,231,154,74,183,202,206,53,149,110,149,157,107,42,221,42,59,215,84,186,85,118,174,169,116,171,236)
|
||||||
|
IMAGE_DATA(92,83,233,86,217,185,230,91,183,202,241,219,237,255,248,239,89,183,255,227,191,103,221,254,143,255,158,117,251,63,254,123)
|
||||||
|
IMAGE_DATA(214,237,255,248,47,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,252,137,15,205,212,237,88,0,0,0,0)
|
||||||
|
IMAGE_END_DATA(320, 1)
|
||||||
|
|
||||||
|
IMAGE_BEGIN_DATA
|
||||||
|
IMAGE_DATA(120,156,237,209,65,13,0,32,12,4,65,244,160,176,238,193,1,191,230,82,50,147,172,130,221,181,106,1,0,0,0,0)
|
||||||
|
IMAGE_DATA(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48)
|
||||||
|
IMAGE_DATA(214,25,30,111,233,63,254,246,74,255,241,183,87,250,143,191,189,210,127,252,237,149,254,227,47,0,0,0,0,0,0,0)
|
||||||
|
IMAGE_DATA(0,0,0,0,0,0,0,0,0,124,226,2,64,145,32,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
|
||||||
|
IMAGE_END_DATA(128, 1)
|
||||||
|
|
||||||
|
IMAGE_BEGIN_DATA
|
||||||
|
IMAGE_DATA(120,156,237,209,193,9,2,81,16,68,193,141,199,8,61,110,230,107,2,202,162,48,244,255,109,21,204,125,232,247,120,30)
|
||||||
|
IMAGE_DATA(207,3,0,0,0,0,0,0,0,0,0,0,0,0,0,32,237,60,207,107,183,75,111,182,147,116,43,125,103,165,91,233)
|
||||||
|
IMAGE_DATA(59,43,221,74,223,89,233,86,250,206,74,183,210,247,127,233,219,77,223,110,250,118,211,183,155,190,221,244,189,117,109,114)
|
||||||
|
IMAGE_DATA(111,233,123,43,221,77,223,89,233,110,250,206,74,119,211,119,86,186,155,190,179,210,221,244,157,245,213,158,171,253,163,239)
|
||||||
|
IMAGE_DATA(45,125,187,233,219,77,223,110,250,118,211,183,155,190,221,244,237,166,111,55,125,187,233,219,77,223,110,250,118,211,183,155)
|
||||||
|
IMAGE_DATA(190,221,244,237,166,111,55,125,187,233,219,77,223,110,250,118,211,183,155,190,221,244,237,166,111,55,125,187,233,219,109,235)
|
||||||
|
IMAGE_DATA(190,220,90,109,207,213,254,217,221,106,123,174,246,207,238,62,237,185,218,241,155,116,55,125,103,165,187,233,59,43,221,77)
|
||||||
|
IMAGE_DATA(223,89,233,110,250,206,74,119,211,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,189,0,154,158,72)
|
||||||
|
IMAGE_DATA(59,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)
|
||||||
|
IMAGE_END_DATA(288, 1)
|
||||||
|
|
|
||||||
|
|
@ -97,12 +97,12 @@ file
|
||||||
GtkCtrl.h,
|
GtkCtrl.h,
|
||||||
GtkCtrl.cpp,
|
GtkCtrl.cpp,
|
||||||
GtkCapture.cpp,
|
GtkCapture.cpp,
|
||||||
GtkCSD.cpp,
|
|
||||||
GtkWnd.cpp,
|
GtkWnd.cpp,
|
||||||
GtkCreate.cpp,
|
GtkCreate.cpp,
|
||||||
GtkEvent.cpp,
|
GtkEvent.cpp,
|
||||||
GtkTop.h,
|
GtkTop.h,
|
||||||
GtkTop.cpp,
|
GtkTop.cpp,
|
||||||
|
GtkCustomBar.cpp,
|
||||||
GtkClip.cpp,
|
GtkClip.cpp,
|
||||||
GtkDnD.cpp,
|
GtkDnD.cpp,
|
||||||
GtkApp.cpp,
|
GtkApp.cpp,
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ Point Ctrl::middlemousepos = Null;
|
||||||
PenInfo Ctrl::pen;
|
PenInfo Ctrl::pen;
|
||||||
bool Ctrl::is_pen_event;
|
bool Ctrl::is_pen_event;
|
||||||
|
|
||||||
|
int Ctrl::last_mouse_action;
|
||||||
|
|
||||||
dword GetMouseFlags() {
|
dword GetMouseFlags() {
|
||||||
dword style = 0;
|
dword style = 0;
|
||||||
if(GetAlt()) style |= K_ALT;
|
if(GetAlt()) style |= K_ALT;
|
||||||
|
|
@ -67,6 +69,7 @@ void Ctrl::LogMouseEvent(const char *f, const Ctrl *ctrl, int event, Point p, in
|
||||||
Image Ctrl::FrameMouseEventH(int event, Point p, int zdelta, dword keyflags)
|
Image Ctrl::FrameMouseEventH(int event, Point p, int zdelta, dword keyflags)
|
||||||
{
|
{
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
|
last_mouse_action = event;
|
||||||
Ptr<Ctrl> this_ = this;
|
Ptr<Ctrl> this_ = this;
|
||||||
for(int i = 0; i < mousehook().GetCount(); i++)
|
for(int i = 0; i < mousehook().GetCount(); i++)
|
||||||
if(this_ && (*mousehook()[i])(this, true, event, p, zdelta, keyflags))
|
if(this_ && (*mousehook()[i])(this, true, event, p, zdelta, keyflags))
|
||||||
|
|
@ -104,6 +107,7 @@ Image Ctrl::MouseEvent0(int event, Point p, int zdelta, dword keyflags)
|
||||||
Image Ctrl::MouseEventH(int event, Point p, int zdelta, dword keyflags)
|
Image Ctrl::MouseEventH(int event, Point p, int zdelta, dword keyflags)
|
||||||
{
|
{
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
|
last_mouse_action = event;
|
||||||
Ptr<Ctrl> this_ = this;
|
Ptr<Ctrl> this_ = this;
|
||||||
for(int i = 0; i < mousehook().GetCount(); i++)
|
for(int i = 0; i < mousehook().GetCount(); i++)
|
||||||
if(this_ && (*mousehook()[i])(this, false, event, p, zdelta, keyflags))
|
if(this_ && (*mousehook()[i])(this, false, event, p, zdelta, keyflags))
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ void Ctrl::SyncLayout(int force)
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
if(destroying)
|
if(destroying)
|
||||||
return;
|
return;
|
||||||
LLOG("SyncLayout " << Name() << " size: " << GetSize());
|
LLOG("SyncLayout " << Name() << " size: " << GetSize() << " force: " << force);
|
||||||
fullrefresh = false;
|
fullrefresh = false;
|
||||||
bool refresh = false;
|
bool refresh = false;
|
||||||
Rect oview = GetView();
|
Rect oview = GetView();
|
||||||
|
|
@ -174,7 +174,6 @@ void Ctrl::SyncLayout(int force)
|
||||||
if(oview.Size() != view.Size() || force > 1) {
|
if(oview.Size() != view.Size() || force > 1) {
|
||||||
for(Ctrl& q : *this) {
|
for(Ctrl& q : *this) {
|
||||||
q.rect = q.CalcRect(rect, view);
|
q.rect = q.CalcRect(rect, view);
|
||||||
LLOG("Layout set rect " << q.Name() << " " << q.rect);
|
|
||||||
q.SyncLayout(force > 1 ? force : 0);
|
q.SyncLayout(force > 1 ? force : 0);
|
||||||
}
|
}
|
||||||
Refresh();
|
Refresh();
|
||||||
|
|
@ -264,10 +263,11 @@ void Ctrl::UpdateRect0(bool sync)
|
||||||
Rect pwa = GetPrimaryWorkArea();
|
Rect pwa = GetPrimaryWorkArea();
|
||||||
rect = OffsetMegaRect(CalcRect(pwa, pwa));
|
rect = OffsetMegaRect(CalcRect(pwa, pwa));
|
||||||
}
|
}
|
||||||
LLOG("UpdateRect0 " << Name() << " to " << rect);
|
|
||||||
|
LLOG("UpdateRect0 " << Name() << " to " << rect << ", sync: " << sync);
|
||||||
LTIMING("UpdateRect0 SyncLayout");
|
LTIMING("UpdateRect0 SyncLayout");
|
||||||
if(sync)
|
if(sync)
|
||||||
SyncLayout();
|
SyncLayout(sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ private:
|
||||||
void PutTxt(const RichTxt& txt, int nesting, int dot_width);
|
void PutTxt(const RichTxt& txt, int nesting, int dot_width);
|
||||||
void PutTable(const RichTable& table, int nesting, int dot_width);
|
void PutTable(const RichTable& table, int nesting, int dot_width);
|
||||||
void PutParts(const Array<RichPara::Part>& parts,
|
void PutParts(const Array<RichPara::Part>& parts,
|
||||||
RichPara::CharFormat& base, int bpart, int boff, int epart, int eoff);
|
RichPara::CharFormat& base, int bpart, int boff, int epart, int eoff);
|
||||||
|
|
||||||
void Begin() { stream.Put('{'); }
|
void Begin() { stream.Put('{'); }
|
||||||
void Begin(const char *cmd) { Begin(); Command(cmd); }
|
void Begin(const char *cmd) { Begin(); Command(cmd); }
|
||||||
|
|
|
||||||
|
|
@ -163,25 +163,6 @@ public:
|
||||||
~ImageGdk();
|
~ImageGdk();
|
||||||
};
|
};
|
||||||
|
|
||||||
class GtkCSD final : Rect { // wayland client side decoration handling
|
|
||||||
bool enabled = false;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static bool IsSSDSupported();
|
|
||||||
|
|
||||||
void Create(GdkWindowTypeHint hint);
|
|
||||||
|
|
||||||
bool IsEnabled() const { return enabled; }
|
|
||||||
|
|
||||||
int ExtraWidth() const { return left + right; }
|
|
||||||
int ExtraHeight() const { return top + bottom; }
|
|
||||||
|
|
||||||
int LeftMargin() const { return left; }
|
|
||||||
int RightMargin() const { return right; }
|
|
||||||
int TopMargin() const { return top; }
|
|
||||||
int BottomMargin() const { return bottom; }
|
|
||||||
};
|
|
||||||
|
|
||||||
String FilesClipFromUrisFree(gchar **uris);
|
String FilesClipFromUrisFree(gchar **uris);
|
||||||
String ImageClipFromPixbufUnref(GdkPixbuf *pixbuf);
|
String ImageClipFromPixbufUnref(GdkPixbuf *pixbuf);
|
||||||
|
|
||||||
|
|
@ -200,13 +181,23 @@ Vector<int> GetPropertyInts(GdkWindow *w, const char *property);
|
||||||
#define GUIPLATFORM_CTRL_TOP_DECLS \
|
#define GUIPLATFORM_CTRL_TOP_DECLS \
|
||||||
GtkWidget *window; \
|
GtkWidget *window; \
|
||||||
GtkWidget *header = nullptr; \
|
GtkWidget *header = nullptr; \
|
||||||
GtkWidget *drawing_area = nullptr; \
|
GtkWidget *client = nullptr; \
|
||||||
|
GtkWidget *header_area = nullptr; \
|
||||||
|
Ptr<Ctrl> hdr_screen[2]; \
|
||||||
GtkIMContext *im_context = nullptr; \
|
GtkIMContext *im_context = nullptr; \
|
||||||
GtkIMContext *im_context_simple; \
|
GtkIMContext *im_context_simple; \
|
||||||
GtkIMContext *im_context_multi; \
|
GtkIMContext *im_context_multi; \
|
||||||
GtkCSD csd; \
|
|
||||||
int64 cursor_id; \
|
int64 cursor_id; \
|
||||||
int id; \
|
int id; \
|
||||||
|
bool csd = false; \
|
||||||
|
bool sync_rect = true; \
|
||||||
|
Rect client_rect; \
|
||||||
|
Rect header_rect; \
|
||||||
|
Rect screen_rect; \
|
||||||
|
String bar_css_class; \
|
||||||
|
Color bar_color; \
|
||||||
|
int bar_cy; \
|
||||||
|
bool draw_after_configure = false; \
|
||||||
|
|
||||||
#define GUIPLATFORM_CTRL_DECLS_INCLUDE <CtrlCore/GtkCtrl.h>
|
#define GUIPLATFORM_CTRL_DECLS_INCLUDE <CtrlCore/GtkCtrl.h>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,10 @@ void Ctrl::UseWayland()
|
||||||
sUseWayland = true;
|
sUseWayland = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern Event<const TopWindow *, TopWindow::CustomTitleBarMetrics&> custom_titlebar_metrics__;
|
||||||
|
extern Function<bool (const TopWindow *)> is_custom_titlebar__;
|
||||||
|
extern Function<Ctrl *(TopWindow *, Color, int)> custom_titlebar_make__;
|
||||||
|
|
||||||
bool InitGtkApp(int argc, char **argv, const char **envptr)
|
bool InitGtkApp(int argc, char **argv, const char **envptr)
|
||||||
{
|
{
|
||||||
LLOG(rmsecs() << " InitGtkApp");
|
LLOG(rmsecs() << " InitGtkApp");
|
||||||
|
|
@ -154,6 +158,8 @@ bool InitGtkApp(int argc, char **argv, const char **envptr)
|
||||||
g_signal_connect_swapped(settings, "notify::gtk-application-prefer-dark-theme", G_CALLBACK(Ctrl::ThemeChanged), NULL);
|
g_signal_connect_swapped(settings, "notify::gtk-application-prefer-dark-theme", G_CALLBACK(Ctrl::ThemeChanged), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TopWindow::Init();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
#include <CtrlCore/CtrlCore.h>
|
|
||||||
|
|
||||||
#ifdef GUI_GTK
|
|
||||||
|
|
||||||
namespace Upp {
|
|
||||||
|
|
||||||
bool GtkCSD::IsSSDSupported()
|
|
||||||
{
|
|
||||||
if (Ctrl::IsX11()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Rewrite to negotiate with window manager once XDG decoration protocol will be
|
|
||||||
// stable. (https://wayland.app/protocols/xdg-decoration-unstable-v1)
|
|
||||||
|
|
||||||
// NOTE: Server side decoration are optional. It might be supported by Window manager or
|
|
||||||
// not. Let's have a list of desktop environments on which we tested it works correctly.
|
|
||||||
auto desktop = GetEnv("XDG_SESSION_DESKTOP");
|
|
||||||
if (desktop == "KDE") {
|
|
||||||
return true;
|
|
||||||
//return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GtkCSD::Create(GdkWindowTypeHint hint)
|
|
||||||
{
|
|
||||||
enabled = false;
|
|
||||||
left = right = top = bottom = 0;
|
|
||||||
if(!Ctrl::IsWayland())
|
|
||||||
return;
|
|
||||||
if(IsSSDSupported() && hint != GDK_WINDOW_TYPE_HINT_POPUP_MENU ||
|
|
||||||
hint == GDK_WINDOW_TYPE_HINT_COMBO)
|
|
||||||
return;
|
|
||||||
|
|
||||||
enabled = true;
|
|
||||||
GtkWidget* win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
|
||||||
GtkWidget* header;
|
|
||||||
if (findarg(hint, GDK_WINDOW_TYPE_HINT_POPUP_MENU) >= 0) {
|
|
||||||
header = gtk_drawing_area_new();
|
|
||||||
gtk_widget_set_size_request(header, 1, 1);
|
|
||||||
gtk_window_set_titlebar((GtkWindow *)win, header);
|
|
||||||
} else {
|
|
||||||
header = gtk_header_bar_new();
|
|
||||||
gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(header), TRUE);
|
|
||||||
gtk_window_set_titlebar((GtkWindow *)win, header);
|
|
||||||
}
|
|
||||||
GtkWidget* drawing_area = gtk_drawing_area_new();
|
|
||||||
gtk_container_add(GTK_CONTAINER(win), drawing_area);
|
|
||||||
gtk_widget_show_all(win);
|
|
||||||
|
|
||||||
gdk_window_get_origin(gtk_widget_get_window(drawing_area), &left, &top);
|
|
||||||
|
|
||||||
gint drawing_area_width = gtk_widget_get_allocated_width(drawing_area);
|
|
||||||
gint drawing_area_height = gtk_widget_get_allocated_height(drawing_area);
|
|
||||||
|
|
||||||
gint win_width = gtk_widget_get_allocated_width(win);
|
|
||||||
gint win_height = gtk_widget_get_allocated_height(win);
|
|
||||||
|
|
||||||
right = win_width - left - drawing_area_width;
|
|
||||||
bottom = win_height - top - drawing_area_height;
|
|
||||||
|
|
||||||
left = Ctrl::SCL(left);
|
|
||||||
right = Ctrl::SCL(right);
|
|
||||||
bottom = Ctrl::SCL(bottom);
|
|
||||||
top = Ctrl::SCL(top);
|
|
||||||
|
|
||||||
gtk_widget_destroy(drawing_area);
|
|
||||||
gtk_widget_destroy(header);
|
|
||||||
gtk_widget_destroy(win);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -25,13 +25,20 @@ GdkDevice *Ctrl::GetMouseDevice()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// (*) it is not really possible to do system-wide grab as there is conflict with csd
|
||||||
|
// so we depend on gtk doing automatic grab when mouse is down
|
||||||
|
|
||||||
bool Ctrl::MouseIsGrabbed()
|
bool Ctrl::MouseIsGrabbed()
|
||||||
{
|
{
|
||||||
|
if(grabwindow && grabwindow->top && grabwindow->utop->csd) // (*)
|
||||||
|
return true;
|
||||||
return gdk_display_device_is_grabbed(gdk_display_get_default(), GetMouseDevice());
|
return gdk_display_device_is_grabbed(gdk_display_get_default(), GetMouseDevice());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ctrl::GrabMouse()
|
bool Ctrl::GrabMouse()
|
||||||
{
|
{
|
||||||
|
if(top && utop->csd) // (*)
|
||||||
|
return true;
|
||||||
return
|
return
|
||||||
#if GTK_CHECK_VERSION(3, 20, 0)
|
#if GTK_CHECK_VERSION(3, 20, 0)
|
||||||
gdk_seat_grab(GetSeat(), gdk(), GDK_SEAT_CAPABILITY_ALL_POINTING, true, NULL, NULL, NULL, 0)
|
gdk_seat_grab(GetSeat(), gdk(), GDK_SEAT_CAPABILITY_ALL_POINTING, true, NULL, NULL, NULL, 0)
|
||||||
|
|
@ -43,10 +50,12 @@ bool Ctrl::GrabMouse()
|
||||||
|
|
||||||
void Ctrl::UngrabMouse()
|
void Ctrl::UngrabMouse()
|
||||||
{
|
{
|
||||||
|
if(grabwindow && grabwindow->top && grabwindow->utop->csd) // (*)
|
||||||
|
return;
|
||||||
#if GTK_CHECK_VERSION(3, 20, 0)
|
#if GTK_CHECK_VERSION(3, 20, 0)
|
||||||
gdk_seat_ungrab(GetSeat());
|
gdk_seat_ungrab(GetSeat());
|
||||||
#else
|
#else
|
||||||
gdk_device_ungrab(GetMouseDevice(), GDK_CURRENT_TIME);
|
gdk_device_ungrab(GetMouseDevice(), GDK_CURRENT_TIME);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,7 +101,6 @@ bool Ctrl::ReleaseWndCapture0()
|
||||||
{
|
{
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
ASSERT(IsMainThread());
|
ASSERT(IsMainThread());
|
||||||
LLOG("ReleaseWndCapture");
|
|
||||||
if(grabwindow) {
|
if(grabwindow) {
|
||||||
UngrabMouse();
|
UngrabMouse();
|
||||||
grabwindow = NULL;
|
grabwindow = NULL;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,46 @@ namespace Upp {
|
||||||
|
|
||||||
#define LLOG(x) // DLOG(x)
|
#define LLOG(x) // DLOG(x)
|
||||||
|
|
||||||
|
void Ctrl::SetCustomBarColor(Color c)
|
||||||
|
{
|
||||||
|
GuiLock __;
|
||||||
|
|
||||||
|
Top *top = GetTop();
|
||||||
|
if(!top || !top->header)
|
||||||
|
return;
|
||||||
|
|
||||||
|
String new_css_class;
|
||||||
|
|
||||||
|
static VectorMap<Color, GtkCssProvider *> providers;
|
||||||
|
|
||||||
|
int q = providers.Find(c);
|
||||||
|
auto ClassName = [&] { return "upp_custom_titlebar_" + AsString(q); };
|
||||||
|
if(q < 0) {
|
||||||
|
if(providers.GetCount() > 64)
|
||||||
|
Panic("Too many custom bar colors !");
|
||||||
|
q = providers.GetCount();
|
||||||
|
String css;
|
||||||
|
css << "." << ClassName() << " { background-image: none; background-color: "
|
||||||
|
<< Format("#%02x%02x%02x;", c.GetR(), c.GetG(), c.GetB()) << "; }";
|
||||||
|
GtkCssProvider *provider = gtk_css_provider_new();
|
||||||
|
gtk_css_provider_load_from_data (provider, css, -1, NULL);
|
||||||
|
gtk_style_context_add_provider_for_screen(gtk_widget_get_screen(top->window),
|
||||||
|
GTK_STYLE_PROVIDER (provider),
|
||||||
|
GTK_STYLE_PROVIDER_PRIORITY_USER);
|
||||||
|
providers.Add(c, provider);
|
||||||
|
}
|
||||||
|
new_css_class = ClassName();
|
||||||
|
|
||||||
|
if(top->bar_css_class == new_css_class)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(top->bar_css_class.GetCount())
|
||||||
|
gtk_style_context_remove_class (gtk_widget_get_style_context (top->header), ~top->bar_css_class);
|
||||||
|
|
||||||
|
top->bar_css_class = new_css_class;
|
||||||
|
gtk_style_context_add_class (gtk_widget_get_style_context (top->header), new_css_class);
|
||||||
|
}
|
||||||
|
|
||||||
void Ctrl::Create(Ctrl *owner, bool popup)
|
void Ctrl::Create(Ctrl *owner, bool popup)
|
||||||
{
|
{
|
||||||
MemoryIgnoreLeaksBlock ___;
|
MemoryIgnoreLeaksBlock ___;
|
||||||
|
|
@ -14,7 +54,7 @@ void Ctrl::Create(Ctrl *owner, bool popup)
|
||||||
LLOG("Create " << Name() << " " << GetRect());
|
LLOG("Create " << Name() << " " << GetRect());
|
||||||
ASSERT(!IsChild() && !IsOpen());
|
ASSERT(!IsChild() && !IsOpen());
|
||||||
LLOG("Ungrab1");
|
LLOG("Ungrab1");
|
||||||
|
|
||||||
Top *top = new Top;
|
Top *top = new Top;
|
||||||
SetTop(top);
|
SetTop(top);
|
||||||
top->window = gtk_window_new(popup && owner ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
|
top->window = gtk_window_new(popup && owner ? GTK_WINDOW_POPUP : GTK_WINDOW_TOPLEVEL);
|
||||||
|
|
@ -28,7 +68,6 @@ void Ctrl::Create(Ctrl *owner, bool popup)
|
||||||
w.ctrl = this;
|
w.ctrl = this;
|
||||||
w.gtk = top->window;
|
w.gtk = top->window;
|
||||||
w.gdk = nullptr;
|
w.gdk = nullptr;
|
||||||
w.drawing_area = nullptr;
|
|
||||||
|
|
||||||
TopWindow *tw = dynamic_cast<TopWindow *>(this);
|
TopWindow *tw = dynamic_cast<TopWindow *>(this);
|
||||||
GdkWindowTypeHint type_hint;
|
GdkWindowTypeHint type_hint;
|
||||||
|
|
@ -45,58 +84,79 @@ void Ctrl::Create(Ctrl *owner, bool popup)
|
||||||
gtk_window_set_type_hint(gtk(), type_hint);
|
gtk_window_set_type_hint(gtk(), type_hint);
|
||||||
|
|
||||||
Rect r = GetRect();
|
Rect r = GetRect();
|
||||||
|
bool custom_bar = tw && tw->custom_bar;
|
||||||
top->csd.Create(type_hint);
|
static bool need_csd = IsWayland() && GetEnv("XDG_SESSION_DESKTOP") != "KDE";
|
||||||
if(top->csd.IsEnabled()) {
|
top->csd = !popup && (need_csd || custom_bar);
|
||||||
top->header = gtk_header_bar_new();
|
#ifndef flagFORCE_CSD // Force using client side decorations even when server side is available
|
||||||
if (findarg(type_hint, GDK_WINDOW_TYPE_HINT_POPUP_MENU) >= 0)
|
if(tw && tw->force_csd)
|
||||||
gtk_widget_set_size_request(top->header, 1, 1);
|
#endif
|
||||||
else
|
top->csd = !popup;
|
||||||
gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(top->header), TRUE);
|
if(top->csd) {
|
||||||
|
ONCELOCK {
|
||||||
|
UpdateWindowDecorationsGeometry();
|
||||||
|
}
|
||||||
|
top->client = gtk_drawing_area_new();
|
||||||
|
if(custom_bar) {
|
||||||
|
top->header = gtk_event_box_new ();
|
||||||
|
top->header_area = gtk_drawing_area_new();
|
||||||
|
gtk_widget_set_size_request(top->header_area, -1, LSCH(tw->GetCustomTitleBarMetrics().height));
|
||||||
|
gtk_container_add (GTK_CONTAINER (top->header), top->header_area);
|
||||||
|
gtk_widget_show_all(top->header);
|
||||||
|
|
||||||
|
SetCustomBarColor(tw->custom_titlebar_bk);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
top->header = gtk_header_bar_new();
|
||||||
|
if(findarg(type_hint, GDK_WINDOW_TYPE_HINT_POPUP_MENU) >= 0)
|
||||||
|
gtk_widget_set_size_request(top->header, 1, 1);
|
||||||
|
else
|
||||||
|
gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(top->header), TRUE);
|
||||||
|
|
||||||
|
gtk_header_bar_set_has_subtitle(GTK_HEADER_BAR(top->header), false);
|
||||||
|
}
|
||||||
|
|
||||||
gtk_window_set_titlebar(gtk(), top->header);
|
gtk_window_set_titlebar(gtk(), top->header);
|
||||||
gtk_header_bar_set_has_subtitle(GTK_HEADER_BAR(top->header), false);
|
|
||||||
|
|
||||||
top->drawing_area = gtk_drawing_area_new();
|
|
||||||
gtk_widget_set_can_focus(top->drawing_area, TRUE);
|
|
||||||
|
|
||||||
r.left -= top->csd.LeftMargin();
|
gtk_widget_set_can_focus(top->client, TRUE);
|
||||||
r.right += top->csd.RightMargin();
|
|
||||||
r.top -= top->csd.TopMargin();
|
gtk_container_add(GTK_CONTAINER(top->window), top->client);
|
||||||
r.bottom += top->csd.BottomMargin();
|
|
||||||
|
|
||||||
g_signal_connect(top->window, "delete-event", G_CALLBACK(GtkEvent), (gpointer)(uintptr_t)top->id);
|
g_signal_connect(top->window, "delete-event", G_CALLBACK(GtkEvent), (gpointer)(uintptr_t)top->id);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
top->drawing_area = top->window;
|
ONCELOCK {
|
||||||
|
UpdateWindowFrameMargins();
|
||||||
|
}
|
||||||
|
top->client = top->window;
|
||||||
}
|
}
|
||||||
|
|
||||||
w.drawing_area = top->drawing_area;
|
|
||||||
|
|
||||||
top->cursor_id = -1;
|
top->cursor_id = -1;
|
||||||
|
|
||||||
gtk_widget_set_events(top->drawing_area, GDK_ALL_EVENTS_MASK & ~GDK_POINTER_MOTION_HINT_MASK & ~GDK_SMOOTH_SCROLL_MASK);
|
auto SetupEvents = [&](GtkWidget *w) {
|
||||||
g_signal_connect(top->drawing_area, "event", G_CALLBACK(GtkEvent), (gpointer)(uintptr_t)top->id);
|
gtk_widget_set_events(w, GDK_ALL_EVENTS_MASK & ~GDK_POINTER_MOTION_HINT_MASK & ~GDK_SMOOTH_SCROLL_MASK);
|
||||||
g_signal_connect(top->drawing_area, "draw", G_CALLBACK(GtkDraw), (gpointer)(uintptr_t)top->id);
|
};
|
||||||
|
SetupEvents(GTK_WIDGET(gtk()));
|
||||||
GdkWindowTypeHint hint = gtk_window_get_type_hint(gtk());
|
g_signal_connect(gtk(), "event", G_CALLBACK(TopGtkEvent), (gpointer)(uintptr_t)top->id);
|
||||||
if(tw && findarg(hint, GDK_WINDOW_TYPE_HINT_NORMAL, GDK_WINDOW_TYPE_HINT_DIALOG, GDK_WINDOW_TYPE_HINT_UTILITY) >= 0)
|
|
||||||
tw->SyncSizeHints();
|
|
||||||
|
|
||||||
gtk_window_set_default_size(gtk(), LSC(r.GetWidth()), LSC(r.GetHeight()));
|
|
||||||
gtk_window_move(gtk(), LSC(r.left), LSC(r.top));
|
|
||||||
gtk_window_resize(gtk(), LSC(r.GetWidth()) - top->csd.ExtraWidth(),
|
|
||||||
LSC(r.GetHeight()) - top->csd.ExtraHeight());
|
|
||||||
|
|
||||||
if (top->header) {
|
|
||||||
gtk_container_add(GTK_CONTAINER(top->window), top->drawing_area);
|
|
||||||
gtk_widget_show_all(top->window);
|
|
||||||
} else {
|
|
||||||
gtk_widget_realize(top->window);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
auto SetupEvents2 = [&](GtkWidget *w) {
|
||||||
|
SetupEvents(w);
|
||||||
|
g_signal_connect(w, "event", G_CALLBACK(GtkEvent), (gpointer)(uintptr_t)top->id);
|
||||||
|
g_signal_connect(w, "draw", G_CALLBACK(GtkDraw), (gpointer)(uintptr_t)top->id);
|
||||||
|
};
|
||||||
|
|
||||||
|
SetupEvents2(top->client);
|
||||||
|
|
||||||
|
if(top->header_area)
|
||||||
|
SetupEvents2(top->header_area);
|
||||||
|
|
||||||
|
if(tw)
|
||||||
|
if(findarg(gtk_window_get_type_hint(gtk()), GDK_WINDOW_TYPE_HINT_NORMAL, GDK_WINDOW_TYPE_HINT_DIALOG, GDK_WINDOW_TYPE_HINT_UTILITY) >= 0)
|
||||||
|
tw->SyncSizeHints();
|
||||||
|
|
||||||
|
gtk_widget_show_all(top->window);
|
||||||
|
|
||||||
w.gdk = gtk_widget_get_window(top->window);
|
w.gdk = gtk_widget_get_window(top->window);
|
||||||
|
|
||||||
if(owner && owner->top)
|
if(owner && owner->top)
|
||||||
gtk_window_set_transient_for(gtk(), owner->gtk());
|
gtk_window_set_transient_for(gtk(), owner->gtk());
|
||||||
gtk_widget_set_app_paintable(top->window, TRUE);
|
gtk_widget_set_app_paintable(top->window, TRUE);
|
||||||
|
|
@ -111,6 +171,7 @@ void Ctrl::Create(Ctrl *owner, bool popup)
|
||||||
g_signal_connect(top->im_context, "preedit-end", G_CALLBACK(IMPreeditEnd), (gpointer)(uintptr_t)top->id);
|
g_signal_connect(top->im_context, "preedit-end", G_CALLBACK(IMPreeditEnd), (gpointer)(uintptr_t)top->id);
|
||||||
g_signal_connect(top->im_context, "commit", G_CALLBACK(IMCommit), (gpointer)(uintptr_t)top->id);
|
g_signal_connect(top->im_context, "commit", G_CALLBACK(IMCommit), (gpointer)(uintptr_t)top->id);
|
||||||
|
|
||||||
|
WndSetPos(r);
|
||||||
WndShow(IsShown());
|
WndShow(IsShown());
|
||||||
|
|
||||||
SweepConfigure(true);
|
SweepConfigure(true);
|
||||||
|
|
@ -124,12 +185,13 @@ void Ctrl::Create(Ctrl *owner, bool popup)
|
||||||
|
|
||||||
StateH(OPEN);
|
StateH(OPEN);
|
||||||
|
|
||||||
GdkModifierType mod;
|
Point m = prev_mouse_pos;
|
||||||
Point m = GetMouseInfo(gdk(), mod);
|
|
||||||
r = GetWndScreenRect();
|
r = GetWndScreenRect();
|
||||||
if(r.Contains(m))
|
if(r.Contains(m))
|
||||||
DispatchMouse(MOUSEMOVE, m);
|
DispatchMouse(MOUSEMOVE, m);
|
||||||
|
|
||||||
|
top->sync_rect = true;
|
||||||
|
WndRectsSync();
|
||||||
RefreshLayoutDeep();
|
RefreshLayoutDeep();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,10 +225,10 @@ void Ctrl::WndDestroy()
|
||||||
if(q >= 0)
|
if(q >= 0)
|
||||||
wins.Remove(q);
|
wins.Remove(q);
|
||||||
if(owner) {
|
if(owner) {
|
||||||
if(owner->top && owner->utop && owner->utop->csd.IsEnabled()) {
|
if(owner->top && owner->utop && owner->utop->csd) {
|
||||||
// TODO: This fix the problem with keyboard when going back to original window, but
|
// TODO: This fix the problem with keyboard when going back to original window, but
|
||||||
// the previous control is not being focused like it should be.
|
// the previous control is not being focused like it should be.
|
||||||
gtk_window_set_focus(owner->gtk(), owner->utop->drawing_area);
|
gtk_window_set_focus(owner->gtk(), owner->utop->client);
|
||||||
}
|
}
|
||||||
owner->WndUpdate();
|
owner->WndUpdate();
|
||||||
}
|
}
|
||||||
|
|
@ -219,3 +281,4 @@ void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,12 +12,6 @@
|
||||||
|
|
||||||
static void ThemeChanged(void *);
|
static void ThemeChanged(void *);
|
||||||
|
|
||||||
/*
|
|
||||||
_DBG_
|
|
||||||
static void AddEvent(gpointer user_data, int type, const Value& value);
|
|
||||||
static void DoMouseEvent(int state, Point pos);
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool DispatchMouseIn(int act, int zd);
|
bool DispatchMouseIn(int act, int zd);
|
||||||
Image GtkMouseEvent(int action, int act, int zd);
|
Image GtkMouseEvent(int action, int act, int zd);
|
||||||
void GtkButtonEvent(int action);
|
void GtkButtonEvent(int action);
|
||||||
|
|
@ -31,6 +25,8 @@ _DBG_
|
||||||
static gboolean GtkEvent(GtkWidget *widget, GdkEvent *key, gpointer user_data);
|
static gboolean GtkEvent(GtkWidget *widget, GdkEvent *key, gpointer user_data);
|
||||||
static gboolean GtkDraw(GtkWidget *widget, cairo_t *cr, gpointer data);
|
static gboolean GtkDraw(GtkWidget *widget, cairo_t *cr, gpointer data);
|
||||||
|
|
||||||
|
static gboolean TopGtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data);
|
||||||
|
|
||||||
static Point GetMouseInfo(GdkWindow *win, GdkModifierType& mod);
|
static Point GetMouseInfo(GdkWindow *win, GdkModifierType& mod);
|
||||||
static GdkDevice *GetMouseDevice();
|
static GdkDevice *GetMouseDevice();
|
||||||
#if GTK_CHECK_VERSION(3, 20, 0)
|
#if GTK_CHECK_VERSION(3, 20, 0)
|
||||||
|
|
@ -39,7 +35,7 @@ _DBG_
|
||||||
static bool MouseIsGrabbed();
|
static bool MouseIsGrabbed();
|
||||||
bool GrabMouse();
|
bool GrabMouse();
|
||||||
static void UngrabMouse();
|
static void UngrabMouse();
|
||||||
|
|
||||||
static int scale; // in case GUI is scaling (e.g. in UHD mode)
|
static int scale; // in case GUI is scaling (e.g. in UHD mode)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
|
@ -47,7 +43,7 @@ _DBG_
|
||||||
EVENT_TEXT,
|
EVENT_TEXT,
|
||||||
EVENT_FOCUS_CHANGE,
|
EVENT_FOCUS_CHANGE,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GEvent0 {
|
struct GEvent0 {
|
||||||
int time;
|
int time;
|
||||||
int windowid;
|
int windowid;
|
||||||
|
|
@ -56,6 +52,9 @@ _DBG_
|
||||||
Point mousepos;
|
Point mousepos;
|
||||||
guint state;
|
guint state;
|
||||||
int count;
|
int count;
|
||||||
|
GdkDevice *device;
|
||||||
|
double x_root;
|
||||||
|
double y_root;
|
||||||
|
|
||||||
bool pen;
|
bool pen;
|
||||||
bool pen_barrel;
|
bool pen_barrel;
|
||||||
|
|
@ -65,7 +64,7 @@ _DBG_
|
||||||
double pen_rotation;
|
double pen_rotation;
|
||||||
Pointf pen_tilt;
|
Pointf pen_tilt;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GEvent : Moveable<GEvent>, GEvent0 {
|
struct GEvent : Moveable<GEvent>, GEvent0 {
|
||||||
GdkEvent *event;
|
GdkEvent *event;
|
||||||
|
|
||||||
|
|
@ -77,12 +76,11 @@ _DBG_
|
||||||
GEvent();
|
GEvent();
|
||||||
~GEvent();
|
~GEvent();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Win : Moveable<Win> {
|
struct Win : Moveable<Win> {
|
||||||
int id;
|
int id;
|
||||||
GtkWidget *gtk;
|
GtkWidget *gtk;
|
||||||
GdkWindow *gdk;
|
GdkWindow *gdk;
|
||||||
GtkWidget *drawing_area;
|
|
||||||
Ptr<Ctrl> ctrl;
|
Ptr<Ctrl> ctrl;
|
||||||
Vector<Rect> invalid; // areas invalidated to be processed at next opportunity
|
Vector<Rect> invalid; // areas invalidated to be processed at next opportunity
|
||||||
};
|
};
|
||||||
|
|
@ -90,7 +88,12 @@ _DBG_
|
||||||
void Proc();
|
void Proc();
|
||||||
bool SweepConfigure(bool wait);
|
bool SweepConfigure(bool wait);
|
||||||
bool SweepFocus(bool wait);
|
bool SweepFocus(bool wait);
|
||||||
void SyncWndRect(const Rect& rect);
|
void SyncWndRect();
|
||||||
|
void InvalidateScreenRect();
|
||||||
|
|
||||||
|
void SetCustomBarColor(Color c);
|
||||||
|
void WndRectsSync() const;
|
||||||
|
|
||||||
|
|
||||||
static BiVector<GEvent> Events;
|
static BiVector<GEvent> Events;
|
||||||
static Vector<Ptr<Ctrl>> activePopup; // created with 'activate' flag - usually menu
|
static Vector<Ptr<Ctrl>> activePopup; // created with 'activate' flag - usually menu
|
||||||
|
|
@ -106,13 +109,13 @@ _DBG_
|
||||||
static int FindCtrl(Ctrl *ctrl);
|
static int FindCtrl(Ctrl *ctrl);
|
||||||
static int FindGtkWindow(GtkWidget *gtk);
|
static int FindGtkWindow(GtkWidget *gtk);
|
||||||
static int FindGdkWindow(GdkWindow *gdk);
|
static int FindGdkWindow(GdkWindow *gdk);
|
||||||
|
|
||||||
static Ctrl *GetTopCtrlFromId(int id);
|
static Ctrl *GetTopCtrlFromId(int id);
|
||||||
static Ctrl *GetTopCtrlFromId(gpointer user_data) { return GetTopCtrlFromId((uint32)(uintptr_t)user_data); }
|
static Ctrl *GetTopCtrlFromId(gpointer user_data) { return GetTopCtrlFromId((uint32)(uintptr_t)user_data); }
|
||||||
|
|
||||||
static void SyncPopupCapture();
|
static void SyncPopupCapture();
|
||||||
void ReleasePopupCapture();
|
void ReleasePopupCapture();
|
||||||
|
|
||||||
static void FocusSync();
|
static void FocusSync();
|
||||||
static gboolean TimeHandler(GtkWidget *);
|
static gboolean TimeHandler(GtkWidget *);
|
||||||
static void InvalidateMousePos();
|
static void InvalidateMousePos();
|
||||||
|
|
@ -120,9 +123,6 @@ _DBG_
|
||||||
static void StartGrabPopup();
|
static void StartGrabPopup();
|
||||||
static bool ReleaseWndCapture0();
|
static bool ReleaseWndCapture0();
|
||||||
static void DoCancelPreedit();
|
static void DoCancelPreedit();
|
||||||
|
|
||||||
static Rect frameMargins;
|
|
||||||
static Rect GetFrameMargins();
|
|
||||||
|
|
||||||
static Index<String> dnd_targets;
|
static Index<String> dnd_targets;
|
||||||
static String dnd_text_target;
|
static String dnd_text_target;
|
||||||
|
|
@ -141,7 +141,7 @@ _DBG_
|
||||||
static Vector<String> dnd_fmts;
|
static Vector<String> dnd_fmts;
|
||||||
static int dnd_result;
|
static int dnd_result;
|
||||||
static Image dnd_icon;
|
static Image dnd_icon;
|
||||||
|
|
||||||
static void GtkSelectionDataSet(GtkSelectionData *selection_data, const String& fmt, const String& data);
|
static void GtkSelectionDataSet(GtkSelectionData *selection_data, const String& fmt, const String& data);
|
||||||
static void GtkGetClipData(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer user_data);
|
static void GtkGetClipData(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer user_data);
|
||||||
static void AddFmt(GtkTargetList *list, const String& fmt, int info);
|
static void AddFmt(GtkTargetList *list, const String& fmt, int info);
|
||||||
|
|
@ -169,6 +169,22 @@ _DBG_
|
||||||
guint time, gpointer user_data, bool paste);
|
guint time, gpointer user_data, bool paste);
|
||||||
static bool ProcessInvalids();
|
static bool ProcessInvalids();
|
||||||
|
|
||||||
|
static Rect csd_border;
|
||||||
|
static int csd_std_header_cy;
|
||||||
|
static Rect frameMargins;
|
||||||
|
|
||||||
|
static void UpdateWindowDecorationsGeometry();
|
||||||
|
static void UpdateWindowFrameMargins();
|
||||||
|
|
||||||
|
|
||||||
|
static bool prevent_custombar_drag;
|
||||||
|
static bool custom_titlebar_drag_click;
|
||||||
|
|
||||||
|
static int GetGtkTitleBarHeight(const TopWindow *tw);
|
||||||
|
static int GetGtkTitleBarButtonWidth();
|
||||||
|
static void SetCustomBarDragPrevention();
|
||||||
|
void SyncPreventCustomBarDragPrevention();
|
||||||
|
|
||||||
friend bool InitGtkApp(int argc, char **argv, const char **envptr);
|
friend bool InitGtkApp(int argc, char **argv, const char **envptr);
|
||||||
friend void GuiPlatformGripResize(TopWindow *q);
|
friend void GuiPlatformGripResize(TopWindow *q);
|
||||||
|
|
||||||
|
|
@ -188,30 +204,35 @@ public: // really private:
|
||||||
static Gclipboard& gclipboard();
|
static Gclipboard& gclipboard();
|
||||||
static Gclipboard& gselection();
|
static Gclipboard& gselection();
|
||||||
static String RenderPrimarySelection(const Value& fmt);
|
static String RenderPrimarySelection(const Value& fmt);
|
||||||
|
|
||||||
static Vector<Event<>> hotkey;
|
static Vector<Event<>> hotkey;
|
||||||
static Vector<dword> keyhot;
|
static Vector<dword> keyhot;
|
||||||
static Vector<dword> modhot;
|
static Vector<dword> modhot;
|
||||||
static guint MouseState;
|
static guint prev_state;
|
||||||
|
static Point prev_mouse_pos;
|
||||||
|
|
||||||
static int SCL(int x) { return scale * x; }
|
static int SCL(int x) { return scale * x; }
|
||||||
|
static int SCL(double x) { return scale * x; }
|
||||||
static Rect SCL(int x, int y, int cx, int cy) { return RectC(SCL(x), SCL(y), SCL(cx), SCL(cy)); }
|
static Rect SCL(int x, int y, int cx, int cy) { return RectC(SCL(x), SCL(y), SCL(cx), SCL(cy)); }
|
||||||
static double LSC(int x) { return (double)x / scale; }
|
static double LSC(int x) { return (double)x / scale; }
|
||||||
|
static int LSCH(int x) { return (x + scale - 1) / scale; }
|
||||||
|
static Rect LSCH(int x, int y, int cx, int cy){ return Rect(LSC(x), LSC(y), LSCH(x + cx), LSCH(y + cy)); }
|
||||||
|
static Rect LSCH(const Rect& r) { return LSCH(r.left, r.top, r.GetWidth(), r.GetHeight()); }
|
||||||
|
|
||||||
static int GetCaretBlinkTime() { return 500; }
|
static int GetCaretBlinkTime() { return 500; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static void EndSession() {}
|
static void EndSession() {}
|
||||||
static bool IsEndSession() { return false; }
|
static bool IsEndSession() { return false; }
|
||||||
static void PanicMsgBox(const char *title, const char *text);
|
static void PanicMsgBox(const char *title, const char *text);
|
||||||
|
|
||||||
static bool IsX11();
|
static bool IsX11();
|
||||||
static bool IsWayland();
|
static bool IsWayland();
|
||||||
static bool IsRunningOnWayland();
|
static bool IsRunningOnWayland();
|
||||||
static bool IsXWayland() { return IsX11() && IsRunningOnWayland(); }
|
static bool IsXWayland() { return IsX11() && IsRunningOnWayland(); }
|
||||||
|
|
||||||
static void UseWayland();
|
static void UseWayland();
|
||||||
|
|
||||||
static Point CurrentMousePos;
|
static Point CurrentMousePos;
|
||||||
static guint CurrentState;
|
static guint CurrentState;
|
||||||
static guint32 CurrentTime;
|
static guint32 CurrentTime;
|
||||||
|
|
|
||||||
207
uppsrc/CtrlCore/GtkCustomBar.cpp
Normal file
207
uppsrc/CtrlCore/GtkCustomBar.cpp
Normal file
|
|
@ -0,0 +1,207 @@
|
||||||
|
#include <CtrlCore/CtrlCore.h>
|
||||||
|
|
||||||
|
#ifdef GUI_GTK
|
||||||
|
|
||||||
|
namespace Upp {
|
||||||
|
|
||||||
|
extern Event<const TopWindow *, TopWindow::CustomTitleBarMetrics&> custom_titlebar_metrics__;
|
||||||
|
extern Function<bool (const TopWindow *)> is_custom_titlebar__;
|
||||||
|
extern Function<Ctrl *(TopWindow *, Color, int)> custom_titlebar_make__;
|
||||||
|
|
||||||
|
void TopWindow::CustomBarIcon::Paint(Draw& w)
|
||||||
|
{
|
||||||
|
w.DrawImage(0, 0, HasMouse() ? CtrlCoreImg::GtkBarButtonH() : CtrlCoreImg::GtkBarButton());
|
||||||
|
w.DrawImage(0, 0, img);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TopWindow::CustomBarIcon::MouseMove(Point p, dword keyflags)
|
||||||
|
{
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TopWindow::CustomBarIcon::LeftDown(Point p, dword keyflags)
|
||||||
|
{
|
||||||
|
SetCapture();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TopWindow::CustomBarIcon::LeftUp(Point, dword keyflags)
|
||||||
|
{
|
||||||
|
if(HasMouse())
|
||||||
|
Action();
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TopWindow::CustomBarIcon::MouseLeave()
|
||||||
|
{
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TopWindow::BarCtrl::LeftDouble(Point p, dword keyflags)
|
||||||
|
{
|
||||||
|
WhenAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TopWindow::Init()
|
||||||
|
{
|
||||||
|
custom_titlebar_metrics__ = [](const TopWindow *tw, TopWindow::CustomTitleBarMetrics& m) {
|
||||||
|
if(!tw->custom_bar)
|
||||||
|
return;
|
||||||
|
m.height = GetGtkTitleBarHeight(tw);
|
||||||
|
m.lm = 0;
|
||||||
|
m.rm = 0;
|
||||||
|
/*
|
||||||
|
Image icon = tw->GetIcon();
|
||||||
|
if(!IsNull(icon))
|
||||||
|
m.lm = DPI(4) + min(icon.GetWidth(), 32);
|
||||||
|
m.rm = (tw->IsZoomable() ? 3 : 1) * GetGtkTitleBarButtonWidth();
|
||||||
|
*/
|
||||||
|
};
|
||||||
|
|
||||||
|
is_custom_titlebar__ = [](const TopWindow *win) {
|
||||||
|
return win->IsCustomTitleBar__();
|
||||||
|
};
|
||||||
|
|
||||||
|
custom_titlebar_make__ = [=](TopWindow *win, Color bk, int mincy) -> Ctrl * {
|
||||||
|
return win->MakeCustomTitleBar__(bk, mincy);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
int Ctrl::GetGtkTitleBarHeight(const TopWindow *tw)
|
||||||
|
{
|
||||||
|
return max(tw->custom_titlebar_cy, IsUHDMode() ? 60 : 31);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Ctrl::GetGtkTitleBarButtonWidth()
|
||||||
|
{
|
||||||
|
return IsUHDMode() ? 94 : 47;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TopWindow::SyncIcons()
|
||||||
|
{
|
||||||
|
minicon.Set(CtrlCoreImg::GtkBarMinimize());
|
||||||
|
GtkWindow *w = gtk();
|
||||||
|
maxicon.Set(w && gtk_window_is_maximized(w) ? CtrlCoreImg::GtkBarOverlap()
|
||||||
|
: CtrlCoreImg::GtkBarMaximize());
|
||||||
|
closeicon.Set(CtrlCoreImg::GtkBarClose());
|
||||||
|
}
|
||||||
|
|
||||||
|
void TopWindow::SyncCustomBar()
|
||||||
|
{
|
||||||
|
if(custom_bar_frame) {
|
||||||
|
// custom_bar_frame->Height(GetCustomTitleBarMetrics().height);
|
||||||
|
SetCustomBarColor(Nvl(custom_titlebar_bk, SColorFace()));
|
||||||
|
auto cm = GetCustomTitleBarMetrics();
|
||||||
|
custom_bar->VSizePos().HSizePos(DPI(10), DPI(6));
|
||||||
|
RefreshFrame(0, 0, GetRect().Width(), cm.height);
|
||||||
|
Size isz = CtrlCoreImg::GtkBarButton().GetSize();
|
||||||
|
int y = (cm.height - isz.cy) / 2;
|
||||||
|
custom_bar_icons->Width((isz.cx + DPI(8)) * (IsZoomable() ? 3 : 1));
|
||||||
|
*custom_bar_icons << closeicon.RightPos(DPI(8), isz.cx).TopPos(y, isz.cy);
|
||||||
|
if(IsZoomable()) {
|
||||||
|
*custom_bar_icons << minicon.LeftPos(0, isz.cx).TopPos(y, isz.cy);
|
||||||
|
*custom_bar_icons << maxicon.LeftPos(isz.cx + DPI(8), isz.cx).TopPos(y, isz.cy);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
minicon.Remove();
|
||||||
|
maxicon.Remove();
|
||||||
|
}
|
||||||
|
SyncIcons();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Ctrl::prevent_custombar_drag;
|
||||||
|
|
||||||
|
void Ctrl::SetCustomBarDragPrevention()
|
||||||
|
{ // ugly as hell, but seems to be the only simple way how to prevent window drag in custom titlebar
|
||||||
|
static gint p1, p2;
|
||||||
|
GtkSettings *gs = gtk_settings_get_default();
|
||||||
|
ONCELOCK {
|
||||||
|
g_object_get(gs, "gtk-double-click-distance", &p1, "gtk-dnd-drag-threshold", &p2, NULL);
|
||||||
|
};
|
||||||
|
gint s1 = p1;
|
||||||
|
gint s2 = p2;
|
||||||
|
if(prevent_custombar_drag)
|
||||||
|
s1 = s2 = 1000000; // no drags for you, GtkWindow...
|
||||||
|
g_object_set (gs, "gtk-double-click-distance", s1, "gtk-dnd-drag-threshold", s2, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ctrl::SyncPreventCustomBarDragPrevention()
|
||||||
|
{
|
||||||
|
TopWindow *tw = dynamic_cast<TopWindow *>(this);
|
||||||
|
prevent_custombar_drag = !(tw && !tw->custom_bar_frame); // prevent for popup too to avoid problems with menu
|
||||||
|
SetCustomBarDragPrevention();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TopWindow::IsCustomTitleBar__() const
|
||||||
|
{
|
||||||
|
return custom_bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TopWindow::DoZoom()
|
||||||
|
{
|
||||||
|
GtkWindow *w = gtk();
|
||||||
|
if(w) {
|
||||||
|
if(gtk_window_is_maximized(w))
|
||||||
|
gtk_window_unmaximize(w);
|
||||||
|
else
|
||||||
|
gtk_window_maximize(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TopWindow::DoMoveWindow()
|
||||||
|
{
|
||||||
|
DLOG(">>>>> MoveWindow");
|
||||||
|
#if GTK_CHECK_VERSION(3, 22, 0)
|
||||||
|
if(CurrentEvent.device)
|
||||||
|
gdk_window_begin_move_drag_for_device(gdk(), CurrentEvent.device,
|
||||||
|
1, CurrentEvent.x_root, CurrentEvent.y_root, CurrentEvent.time);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
gdk_window_begin_move_drag(gdk(), 1, CurrentEvent.x_root, CurrentEvent.y_root, CurrentEvent.time);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ctrl *TopWindow::MakeCustomTitleBar__(Color bk, int mincy)
|
||||||
|
{
|
||||||
|
if(!custom_bar) {
|
||||||
|
custom_bar_frame.Create();
|
||||||
|
custom_bar_frame->Transparent();
|
||||||
|
custom_bar_icons.Create();
|
||||||
|
custom_bar_icons->Transparent();
|
||||||
|
custom_bar_frame->AddFrame(*custom_bar_icons);
|
||||||
|
custom_bar.Create();
|
||||||
|
|
||||||
|
minicon << [=] {
|
||||||
|
GtkWindow *w = gtk();
|
||||||
|
if(w)
|
||||||
|
gtk_window_iconify(w);
|
||||||
|
};
|
||||||
|
maxicon << [=] {
|
||||||
|
DoZoom();
|
||||||
|
};
|
||||||
|
closeicon << [=] {
|
||||||
|
if(IsEnabled()) {
|
||||||
|
IgnoreMouseUp();
|
||||||
|
WhenClose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if(custom_bar) {
|
||||||
|
if(&GetFrame(0) != ~custom_bar_frame) {
|
||||||
|
RemoveFrame(*custom_bar_frame);
|
||||||
|
if(&GetFrame(0) == &NullFrame())
|
||||||
|
SetFrame(0, *custom_bar_frame);
|
||||||
|
else
|
||||||
|
InsertFrame(0, *custom_bar_frame);
|
||||||
|
}
|
||||||
|
custom_bar_frame->Add(*custom_bar);
|
||||||
|
}
|
||||||
|
custom_titlebar_bk = bk;
|
||||||
|
if(custom_titlebar_cy < 0)
|
||||||
|
custom_titlebar_cy = mincy;
|
||||||
|
SyncCustomBar();
|
||||||
|
return ~custom_bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -288,7 +288,10 @@ PasteClip Ctrl::GtkDnd(GtkWidget *widget, GdkDragContext *context, gint x, gint
|
||||||
if(w) {
|
if(w) {
|
||||||
GetMouseInfo(gdk_get_default_root_window(), mod);
|
GetMouseInfo(gdk_get_default_root_window(), mod);
|
||||||
CurrentState = mod;
|
CurrentState = mod;
|
||||||
CurrentMousePos = Point(SCL(x), SCL(y)) + w->GetScreenRect().TopLeft();
|
CurrentMousePos = Point(SCL(x), SCL(y));
|
||||||
|
int x1, y1;
|
||||||
|
gdk_window_get_position(w->gdk(), &x1, &y1);
|
||||||
|
CurrentMousePos += Point(SCL(x1), SCL(y1));
|
||||||
w->DnD(CurrentMousePos, clip);
|
w->DnD(CurrentMousePos, clip);
|
||||||
}
|
}
|
||||||
gdk_drag_status(context, clip.IsAccepted() ? clip.GetAction() == DND_MOVE ? GDK_ACTION_MOVE
|
gdk_drag_status(context, clip.IsAccepted() ? clip.GetAction() == DND_MOVE ? GDK_ACTION_MOVE
|
||||||
|
|
@ -358,3 +361,4 @@ void Ctrl::DndExit()
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
namespace Upp {
|
namespace Upp {
|
||||||
|
|
||||||
#define LLOG(x) // DLOG(x)
|
#define LLOG(x) // DLOG(x)
|
||||||
// #define LOG_EVENTS _DBG_
|
// #define LOG_EVENTS _DBG_
|
||||||
|
|
||||||
BiVector<Ctrl::GEvent> Ctrl::Events;
|
BiVector<Ctrl::GEvent> Ctrl::Events;
|
||||||
|
|
||||||
|
|
@ -17,7 +17,6 @@ Point Ctrl::CurrentMousePos;
|
||||||
guint Ctrl::CurrentState;
|
guint Ctrl::CurrentState;
|
||||||
guint32 Ctrl::CurrentTime;
|
guint32 Ctrl::CurrentTime;
|
||||||
Ctrl::GEvent Ctrl::CurrentEvent;
|
Ctrl::GEvent Ctrl::CurrentEvent;
|
||||||
guint Ctrl::MouseState;
|
|
||||||
|
|
||||||
bool GetShift() { return Ctrl::CurrentState & GDK_SHIFT_MASK; }
|
bool GetShift() { return Ctrl::CurrentState & GDK_SHIFT_MASK; }
|
||||||
bool GetCtrl() { return Ctrl::CurrentState & GDK_CONTROL_MASK; }
|
bool GetCtrl() { return Ctrl::CurrentState & GDK_CONTROL_MASK; }
|
||||||
|
|
@ -87,10 +86,26 @@ bool Ctrl::ProcessInvalids()
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
if(invalids) {
|
if(invalids) {
|
||||||
for(Win& win : wins) {
|
for(Win& win : wins) {
|
||||||
for(const Rect& r : win.invalid)
|
Top *top = win.ctrl->GetTop();
|
||||||
if(win.drawing_area && win.ctrl)
|
TopWindow *tw = dynamic_cast<TopWindow *>(~win.ctrl);
|
||||||
gdk_window_invalidate_rect(gtk_widget_get_window(win.drawing_area),
|
if(top)
|
||||||
GdkRect(Nvl(r, win.ctrl->GetRect().GetSize())), TRUE);
|
for(const Rect& r : win.invalid)
|
||||||
|
if(top->client && win.ctrl) {
|
||||||
|
win.ctrl->WndRectsSync();
|
||||||
|
Rect rr = Nvl(r, win.ctrl->GetRect().GetSize());
|
||||||
|
auto Invalidate = [](GtkWidget *w, Rect r) {
|
||||||
|
if(r.IsEmpty())
|
||||||
|
return;
|
||||||
|
r = LSCH(r);
|
||||||
|
gtk_widget_queue_draw_area(w, r.left, r.top, r.GetWidth(), r.GetHeight());
|
||||||
|
};
|
||||||
|
if(top && tw && top->header_area) {
|
||||||
|
int h = tw->custom_bar_frame->GetHeight();
|
||||||
|
Invalidate(top->header_area, rr & Rect(0, 0, INT_MAX, h));
|
||||||
|
rr.Offset(0, -h);
|
||||||
|
}
|
||||||
|
Invalidate(top->client, rr);
|
||||||
|
}
|
||||||
win.invalid.Clear();
|
win.invalid.Clear();
|
||||||
}
|
}
|
||||||
invalids = false;
|
invalids = false;
|
||||||
|
|
@ -104,8 +119,15 @@ gboolean Ctrl::GtkDraw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
|
||||||
Ctrl *p = GetTopCtrlFromId(user_data);
|
Ctrl *p = GetTopCtrlFromId(user_data);
|
||||||
if(p) {
|
if(p) {
|
||||||
p->fullrefresh = false;
|
p->fullrefresh = false;
|
||||||
|
|
||||||
cairo_scale(cr, 1.0 / scale, 1.0 / scale); // cancel scaling to be pixel perfect
|
cairo_scale(cr, 1.0 / scale, 1.0 / scale); // cancel scaling to be pixel perfect
|
||||||
p->SyncWndRect(p->GetWndScreenRect()); // avoid black areas when resizing
|
|
||||||
|
Top *top = p->GetTop();
|
||||||
|
if(top && top->draw_after_configure) {
|
||||||
|
p->InvalidateScreenRect();
|
||||||
|
top->draw_after_configure = false;
|
||||||
|
}
|
||||||
|
p->SyncWndRect();
|
||||||
|
|
||||||
SystemDraw w(cr);
|
SystemDraw w(cr);
|
||||||
painting = true;
|
painting = true;
|
||||||
|
|
@ -113,7 +135,6 @@ gboolean Ctrl::GtkDraw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
|
||||||
double x1, y1, x2, y2;
|
double x1, y1, x2, y2;
|
||||||
cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
|
cairo_clip_extents (cr, &x1, &y1, &x2, &y2);
|
||||||
Rect r = RectC((int)x1, (int)y1, (int)ceil(x2 - x1), (int)ceil(y2 - y1));
|
Rect r = RectC((int)x1, (int)y1, (int)ceil(x2 - x1), (int)ceil(y2 - y1));
|
||||||
w.Clip(r); // Because of IsPainting
|
|
||||||
|
|
||||||
cairo_rectangle_list_t *list = cairo_copy_clip_rectangle_list(cr);
|
cairo_rectangle_list_t *list = cairo_copy_clip_rectangle_list(cr);
|
||||||
if(list->status == CAIRO_STATUS_SUCCESS && list->num_rectangles < 10) {
|
if(list->status == CAIRO_STATUS_SUCCESS && list->num_rectangles < 10) {
|
||||||
|
|
@ -126,13 +147,62 @@ gboolean Ctrl::GtkDraw(GtkWidget *widget, cairo_t *cr, gpointer user_data)
|
||||||
}
|
}
|
||||||
cairo_rectangle_list_destroy(list);
|
cairo_rectangle_list_destroy(list);
|
||||||
|
|
||||||
|
TopWindow *tw = dynamic_cast<TopWindow *>(p);
|
||||||
|
if(top && tw && top->header_area && widget != top->header_area) {
|
||||||
|
int h = tw->GetCustomTitleBarMetrics().height;
|
||||||
|
w.Offset(0, -h);
|
||||||
|
r.OffsetVert(h);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
w.Begin();
|
||||||
|
|
||||||
|
w.Clip(r);
|
||||||
p->UpdateArea(w, r);
|
p->UpdateArea(w, r);
|
||||||
w.End();
|
w.End();
|
||||||
|
w.End();
|
||||||
painting = false;
|
painting = false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Ctrl::InvalidateScreenRect()
|
||||||
|
{
|
||||||
|
LLOG("InvalidateScreenRect");
|
||||||
|
Top *top = GetTop();
|
||||||
|
if(top)
|
||||||
|
top->sync_rect = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean Ctrl::TopGtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
|
||||||
|
{
|
||||||
|
#ifdef LOG_EVENTS
|
||||||
|
String ev = "? " + AsString((int)event->type);
|
||||||
|
Tuple2<int, const char *> *f = FindTuple(xEvent, __countof(xEvent), event->type);
|
||||||
|
if(f)
|
||||||
|
ev = f->b;
|
||||||
|
LOG(rmsecs() << " TOP FETCH EVENT " << ev);
|
||||||
|
#endif
|
||||||
|
Ctrl *p = GetTopCtrlFromId(user_data);
|
||||||
|
Top *top = p ? p->GetTop() : nullptr;
|
||||||
|
TopWindow *tw = dynamic_cast<TopWindow *>(p);
|
||||||
|
switch(event->type) {
|
||||||
|
case GDK_SETTING:
|
||||||
|
if(tw)
|
||||||
|
tw->SetCustomBarDragPrevention();
|
||||||
|
break;
|
||||||
|
case GDK_CONFIGURE:
|
||||||
|
AddEvent(user_data, GDK_CONFIGURE, Value(), event);
|
||||||
|
// case GDK_EXPOSE:
|
||||||
|
if(p)
|
||||||
|
p->InvalidateScreenRect();
|
||||||
|
if(top)
|
||||||
|
top->draw_after_configure = true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
|
gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
|
||||||
{
|
{
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
|
|
@ -141,6 +211,7 @@ gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
|
||||||
bool retval = true;
|
bool retval = true;
|
||||||
Value value;
|
Value value;
|
||||||
Ctrl *p = GetTopCtrlFromId(user_data);
|
Ctrl *p = GetTopCtrlFromId(user_data);
|
||||||
|
Top *top = p ? p->GetTop() : nullptr;
|
||||||
#ifdef LOG_EVENTS
|
#ifdef LOG_EVENTS
|
||||||
String ev = "? " + AsString((int)event->type);
|
String ev = "? " + AsString((int)event->type);
|
||||||
Tuple2<int, const char *> *f = FindTuple(xEvent, __countof(xEvent), event->type);
|
Tuple2<int, const char *> *f = FindTuple(xEvent, __countof(xEvent), event->type);
|
||||||
|
|
@ -149,6 +220,8 @@ gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
|
||||||
LOG(rmsecs() << " FETCH EVENT " << ev << " ctrl: " << Name(p));
|
LOG(rmsecs() << " FETCH EVENT " << ev << " ctrl: " << Name(p));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if(!p)
|
||||||
|
return false;
|
||||||
switch(event->type) {
|
switch(event->type) {
|
||||||
case GDK_DELETE:
|
case GDK_DELETE:
|
||||||
p->CancelPreedit();
|
p->CancelPreedit();
|
||||||
|
|
@ -175,12 +248,13 @@ gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
|
||||||
if(IsNull(value))
|
if(IsNull(value))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
/* this only adds issues
|
||||||
case GDK_2BUTTON_PRESS:
|
case GDK_2BUTTON_PRESS:
|
||||||
p->CancelPreedit();
|
p->CancelPreedit();
|
||||||
value = DoButtonEvent(event, true);
|
value = DoButtonEvent(event, true);
|
||||||
if(IsNull(value))
|
if(IsNull(value))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;*/
|
||||||
case GDK_BUTTON_RELEASE:
|
case GDK_BUTTON_RELEASE:
|
||||||
p->CancelPreedit();
|
p->CancelPreedit();
|
||||||
value = DoButtonEvent(event, false);
|
value = DoButtonEvent(event, false);
|
||||||
|
|
@ -212,19 +286,16 @@ gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
|
||||||
case GDK_KEY_RELEASE:
|
case GDK_KEY_RELEASE:
|
||||||
key = (GdkEventKey *)event;
|
key = (GdkEventKey *)event;
|
||||||
value << (int) key->keyval << (int) key->hardware_keycode;
|
value << (int) key->keyval << (int) key->hardware_keycode;
|
||||||
if(pressed) {
|
if(pressed && top && gtk_im_context_filter_keypress(top->im_context, key))
|
||||||
p = GetTopCtrlFromId(user_data);
|
return true;
|
||||||
if(p) {
|
|
||||||
Top *top = p->GetTop();
|
|
||||||
if(top && gtk_im_context_filter_keypress(top->im_context, key))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
// case GDK_EXPOSE:
|
||||||
case GDK_CONFIGURE: {
|
case GDK_CONFIGURE: {
|
||||||
retval = false;
|
retval = false;
|
||||||
GdkEventConfigure *e = (GdkEventConfigure *)event;
|
if(p)
|
||||||
value = SCL(e->x, e->y, e->width, e->height);
|
p->InvalidateScreenRect();
|
||||||
|
if(top)
|
||||||
|
top->draw_after_configure = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|
@ -237,7 +308,7 @@ gboolean Ctrl::GtkEvent(GtkWidget *widget, GdkEvent *event, gpointer user_data)
|
||||||
int Ctrl::DoButtonEvent(GdkEvent *event, bool press)
|
int Ctrl::DoButtonEvent(GdkEvent *event, bool press)
|
||||||
{
|
{
|
||||||
GdkEventButton *e = (GdkEventButton *)event;
|
GdkEventButton *e = (GdkEventButton *)event;
|
||||||
static int mask[] = { GDK_BUTTON1_MASK, GDK_BUTTON2_MASK, GDK_BUTTON3_MASK };
|
/* static int mask[] = { GDK_BUTTON1_MASK, GDK_BUTTON2_MASK, GDK_BUTTON3_MASK };
|
||||||
if(e->button >= 1 && e->button <= 3) {
|
if(e->button >= 1 && e->button <= 3) {
|
||||||
int m = mask[e->button - 1];
|
int m = mask[e->button - 1];
|
||||||
if(press)
|
if(press)
|
||||||
|
|
@ -246,7 +317,10 @@ int Ctrl::DoButtonEvent(GdkEvent *event, bool press)
|
||||||
MouseState &= ~m;
|
MouseState &= ~m;
|
||||||
return e->button;
|
return e->button;
|
||||||
}
|
}
|
||||||
return findarg(e->button, 8, 9) >= 0 ? (int)e->button : (int)Null;
|
*/
|
||||||
|
// 1 2 3 left middle right
|
||||||
|
// 8 9 FW / BK
|
||||||
|
return findarg(e->button, 1, 2, 3, 8, 9) >= 0 ? (int)e->button : (int)Null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ctrl::GEvent::GEvent()
|
Ctrl::GEvent::GEvent()
|
||||||
|
|
@ -294,7 +368,8 @@ void Ctrl::GEvent::operator=(const GEvent& e)
|
||||||
Set(e);
|
Set(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Point s_mousepos;
|
Point Ctrl::prev_mouse_pos = Null;
|
||||||
|
guint Ctrl::prev_state = 0;
|
||||||
|
|
||||||
Point Ctrl::GetMouseInfo(GdkWindow *win, GdkModifierType& mod)
|
Point Ctrl::GetMouseInfo(GdkWindow *win, GdkModifierType& mod)
|
||||||
{
|
{
|
||||||
|
|
@ -303,7 +378,7 @@ Point Ctrl::GetMouseInfo(GdkWindow *win, GdkModifierType& mod)
|
||||||
GdkDevice *pointer = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
|
GdkDevice *pointer = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
|
||||||
double x, y;
|
double x, y;
|
||||||
gdk_window_get_device_position_double (win, pointer, &x, &y, &mod);
|
gdk_window_get_device_position_double (win, pointer, &x, &y, &mod);
|
||||||
return s_mousepos; //return Point((int)SCL(x), (int)SCL(y));
|
return prev_mouse_pos; //return Point((int)SCL(x), (int)SCL(y));
|
||||||
#else
|
#else
|
||||||
gint x, y;
|
gint x, y;
|
||||||
gdk_window_get_pointer(win, &x, &y, &mod);
|
gdk_window_get_pointer(win, &x, &y, &mod);
|
||||||
|
|
@ -319,24 +394,77 @@ void Ctrl::AddEvent(gpointer user_data, int type, const Value& value, GdkEvent *
|
||||||
e.windowid = (uint32)(uintptr_t)user_data;
|
e.windowid = (uint32)(uintptr_t)user_data;
|
||||||
e.type = type;
|
e.type = type;
|
||||||
e.value = value;
|
e.value = value;
|
||||||
GdkModifierType mod;
|
e.state = prev_state;
|
||||||
e.mousepos = GetMouseInfo(gdk_get_default_root_window(), mod);
|
bool press = false;
|
||||||
if(event && event->type == GDK_MOTION_NOTIFY){
|
if(event)
|
||||||
GdkEventMotion *mevent = (GdkEventMotion *)event;
|
switch(event->type) {
|
||||||
e.mousepos = s_mousepos = Point(SCL(mevent->x_root), SCL(mevent->y_root));
|
case GDK_MOTION_NOTIFY: {
|
||||||
}
|
GdkEventMotion *mevent = (GdkEventMotion *)event;
|
||||||
if(event && event->type == GDK_LEAVE_NOTIFY){
|
prev_mouse_pos = Point(SCL(mevent->x_root), SCL(mevent->y_root));
|
||||||
GdkEventCrossing *mevent = (GdkEventCrossing *)event;
|
prev_state = e.state = mevent->state;
|
||||||
e.mousepos = s_mousepos = Point(SCL(mevent->x_root), SCL(mevent->y_root));
|
e.x_root = mevent->x_root;
|
||||||
}
|
e.y_root = mevent->y_root;
|
||||||
e.state = (mod & ~(GDK_BUTTON1_MASK|GDK_BUTTON2_MASK|GDK_BUTTON3_MASK)) | MouseState;
|
break;
|
||||||
|
}
|
||||||
|
case GDK_LEAVE_NOTIFY: {
|
||||||
|
GdkEventCrossing *mevent = (GdkEventCrossing *)event;
|
||||||
|
prev_mouse_pos = Point(SCL(mevent->x_root), SCL(mevent->y_root));
|
||||||
|
prev_state = e.state = mevent->state;
|
||||||
|
e.x_root = mevent->x_root;
|
||||||
|
e.y_root = mevent->y_root;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GDK_BUTTON_PRESS:
|
||||||
|
press = true;
|
||||||
|
case GDK_BUTTON_RELEASE: {
|
||||||
|
GdkEventButton *mevent = (GdkEventButton *)event;
|
||||||
|
prev_mouse_pos = Point(SCL(mevent->x_root), SCL(mevent->y_root));
|
||||||
|
prev_state = mevent->state;
|
||||||
|
int n = mevent->button;
|
||||||
|
if(n >= 1 && n <= 5) { // gdk reports one state back, without current event
|
||||||
|
dword mask = get_i(n - 1, GDK_BUTTON1_MASK, GDK_BUTTON2_MASK, GDK_BUTTON3_MASK, GDK_BUTTON4_MASK, GDK_BUTTON5_MASK);
|
||||||
|
if(press)
|
||||||
|
prev_state |= mask;
|
||||||
|
else
|
||||||
|
prev_state &= ~mask;
|
||||||
|
}
|
||||||
|
e.state = prev_state;
|
||||||
|
e.x_root = mevent->x_root;
|
||||||
|
e.y_root = mevent->y_root;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GDK_KEY_PRESS:
|
||||||
|
press = true;
|
||||||
|
case GDK_KEY_RELEASE: {
|
||||||
|
auto *kev = (GdkEventKey *)event;
|
||||||
|
prev_state = kev->state;
|
||||||
|
dword mask = decode(kev->keyval,
|
||||||
|
GDKEY(Control_L), GDK_CONTROL_MASK,
|
||||||
|
GDKEY(Control_R), GDK_CONTROL_MASK,
|
||||||
|
GDKEY(Shift_L), GDK_SHIFT_MASK,
|
||||||
|
GDKEY(Shift_R), GDK_SHIFT_MASK,
|
||||||
|
GDKEY(Alt_L), GDK_MOD1_MASK,
|
||||||
|
GDKEY(Alt_R), GDK_MOD1_MASK, 0);
|
||||||
|
if(mask) {
|
||||||
|
if(press)
|
||||||
|
prev_state |= mask;
|
||||||
|
else
|
||||||
|
prev_state &= ~mask;
|
||||||
|
}
|
||||||
|
e.state = prev_state;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
e.mousepos = prev_mouse_pos;
|
||||||
e.count = 1;
|
e.count = 1;
|
||||||
e.event = NULL;
|
e.event = nullptr;
|
||||||
|
e.device = nullptr;
|
||||||
#if GTK_CHECK_VERSION(3, 22, 0)
|
#if GTK_CHECK_VERSION(3, 22, 0)
|
||||||
GdkDevice *d = event ? gdk_event_get_source_device(event) : NULL;
|
e.device = event ? gdk_event_get_source_device(event) : NULL;
|
||||||
if(d && findarg(gdk_device_get_source(d), GDK_SOURCE_PEN, GDK_SOURCE_TOUCHSCREEN) >= 0) {
|
if(e.device && findarg(gdk_device_get_source(e.device), GDK_SOURCE_PEN, GDK_SOURCE_TOUCHSCREEN) >= 0) {
|
||||||
e.pen = true;
|
e.pen = true;
|
||||||
e.pen_barrel = MouseState & GDK_BUTTON3_MASK;
|
e.pen_barrel = e.state & GDK_BUTTON3_MASK;
|
||||||
double *axes = NULL;
|
double *axes = NULL;
|
||||||
switch(event->type){
|
switch(event->type){
|
||||||
case GDK_BUTTON_PRESS:
|
case GDK_BUTTON_PRESS:
|
||||||
|
|
@ -350,18 +478,16 @@ void Ctrl::AddEvent(gpointer user_data, int type, const Value& value, GdkEvent *
|
||||||
axes = ((GdkEventButton *)event)->axes;
|
axes = ((GdkEventButton *)event)->axes;
|
||||||
break;
|
break;
|
||||||
case GDK_MOTION_NOTIFY:{
|
case GDK_MOTION_NOTIFY:{
|
||||||
GdkEventMotion *mevent = (GdkEventMotion *)event;
|
|
||||||
e.mousepos = s_mousepos = Point(SCL(mevent->x_root), SCL(mevent->y_root));
|
|
||||||
axes = ((GdkEventMotion *)event)->axes;
|
axes = ((GdkEventMotion *)event)->axes;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
if(axes) {
|
if(axes) {
|
||||||
if(!gdk_device_get_axis(d, axes, GDK_AXIS_PRESSURE, &e.pen_pressure)) e.pen_pressure=Null;
|
if(!gdk_device_get_axis(e.device, axes, GDK_AXIS_PRESSURE, &e.pen_pressure)) e.pen_pressure=Null;
|
||||||
if(!gdk_device_get_axis(d, axes, GDK_AXIS_ROTATION, &e.pen_rotation)) e.pen_rotation=Null;
|
if(!gdk_device_get_axis(e.device, axes, GDK_AXIS_ROTATION, &e.pen_rotation)) e.pen_rotation=Null;
|
||||||
if(!gdk_device_get_axis(d, axes, GDK_AXIS_XTILT, &e.pen_tilt.x)) e.pen_tilt.x=Null;
|
if(!gdk_device_get_axis(e.device, axes, GDK_AXIS_XTILT, &e.pen_tilt.x)) e.pen_tilt.x=Null;
|
||||||
if(!gdk_device_get_axis(d, axes, GDK_AXIS_YTILT, &e.pen_tilt.y)) e.pen_tilt.y=Null;
|
if(!gdk_device_get_axis(e.device, axes, GDK_AXIS_YTILT, &e.pen_tilt.y)) e.pen_tilt.y=Null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -488,10 +614,12 @@ void Ctrl::GtkButtonEvent(int action)
|
||||||
GtkMouseEvent(action, act, 0);
|
GtkMouseEvent(action, act, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Ctrl::custom_titlebar_drag_click;
|
||||||
|
|
||||||
void Ctrl::Proc()
|
void Ctrl::Proc()
|
||||||
{
|
{
|
||||||
#ifdef LOG_EVENTS
|
#ifdef LOG_EVENTS
|
||||||
String ev = "?";
|
String ev = "?" + AsString(CurrentEvent.type);
|
||||||
Tuple2<int, const char *> *f = FindTuple(xEvent, __countof(xEvent), CurrentEvent.type);
|
Tuple2<int, const char *> *f = FindTuple(xEvent, __countof(xEvent), CurrentEvent.type);
|
||||||
if(f)
|
if(f)
|
||||||
ev = f->b;
|
ev = f->b;
|
||||||
|
|
@ -543,9 +671,22 @@ void Ctrl::Proc()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
for(Ctrl *q : GetTopCtrls())
|
||||||
|
q->SyncWndRect();
|
||||||
|
|
||||||
|
TopWindow *tw = dynamic_cast<TopWindow *>(this);
|
||||||
|
|
||||||
|
auto IsCustomBarAction = [&] {
|
||||||
|
return tw && tw->custom_bar_frame && tw->custom_bar_frame->GetScreenRect().Contains(GetMousePos())
|
||||||
|
&& tw->IsCustomTitleBarDragArea(GetMousePos() - GetScreenRect().TopLeft());
|
||||||
|
};
|
||||||
|
|
||||||
switch(CurrentEvent.type) {
|
switch(CurrentEvent.type) {
|
||||||
case GDK_MOTION_NOTIFY:
|
case GDK_MOTION_NOTIFY:
|
||||||
GtkMouseEvent(MOUSEMOVE, MOUSEMOVE, 0);
|
GtkMouseEvent(MOUSEMOVE, MOUSEMOVE, 0);
|
||||||
|
SyncPreventCustomBarDragPrevention();
|
||||||
|
if(GetMouseLeft() && custom_titlebar_drag_click && IsCustomBarAction())
|
||||||
|
tw->DoMoveWindow();
|
||||||
break;
|
break;
|
||||||
case GDK_BUTTON_PRESS:
|
case GDK_BUTTON_PRESS:
|
||||||
if(CurrentEvent.value == 8) {
|
if(CurrentEvent.value == 8) {
|
||||||
|
|
@ -565,17 +706,18 @@ void Ctrl::Proc()
|
||||||
ignoremouseup = false;
|
ignoremouseup = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
custom_titlebar_drag_click = CurrentEvent.value == 1 && IsCustomBarAction();
|
||||||
|
|
||||||
if(!ignoreclick) {
|
if(!ignoreclick) {
|
||||||
bool dbl = msecs(clicktime) < 250;
|
bool dbl = msecs(clicktime) < 250;
|
||||||
clicktime = dbl ? clicktime - 1000 : msecs();
|
clicktime = dbl ? clicktime - 1000 : msecs();
|
||||||
GtkButtonEvent(dbl ? DOUBLE : DOWN);
|
if(dbl && IsCustomBarAction())
|
||||||
|
tw->DoZoom();
|
||||||
|
else
|
||||||
|
GtkButtonEvent(dbl ? DOUBLE : DOWN);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
/* case GDK_2BUTTON_PRESS:
|
case GDK_BUTTON_RELEASE:
|
||||||
if(!ignoreclick)
|
|
||||||
GtkButtonEvent(DOUBLE);
|
|
||||||
break;
|
|
||||||
*/ case GDK_BUTTON_RELEASE:
|
|
||||||
if(CurrentEvent.value == 8) {
|
if(CurrentEvent.value == 8) {
|
||||||
DispatchKey(K_MOUSE_BACKWARD|K_KEYUP, 1);
|
DispatchKey(K_MOUSE_BACKWARD|K_KEYUP, 1);
|
||||||
break;
|
break;
|
||||||
|
|
@ -589,11 +731,17 @@ void Ctrl::Proc()
|
||||||
else
|
else
|
||||||
if(!dnd_events)
|
if(!dnd_events)
|
||||||
GtkButtonEvent(UP);
|
GtkButtonEvent(UP);
|
||||||
|
if(!GetMouseRight() && !GetMouseMiddle() && !GetMouseLeft()) {
|
||||||
|
StopGrabPopup();
|
||||||
|
ReleaseWndCapture0();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case GDK_SCROLL: {
|
case GDK_SCROLL: {
|
||||||
Point delta = CurrentEvent.value;
|
Point delta = CurrentEvent.value;
|
||||||
if(delta.y!=0.0) GtkMouseEvent(MOUSEWHEEL, MOUSEWHEEL, delta.y);
|
if(delta.y)
|
||||||
if(delta.x!=0.0) GtkMouseEvent(MOUSEHWHEEL, MOUSEHWHEEL, delta.x);
|
GtkMouseEvent(MOUSEWHEEL, MOUSEWHEEL, delta.y);
|
||||||
|
if(delta.x)
|
||||||
|
GtkMouseEvent(MOUSEHWHEEL, MOUSEHWHEEL, delta.x);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case GDK_KEY_PRESS:
|
case GDK_KEY_PRESS:
|
||||||
|
|
@ -680,7 +828,6 @@ void Ctrl::Proc()
|
||||||
}
|
}
|
||||||
kv += K_DELTA;
|
kv += K_DELTA;
|
||||||
}
|
}
|
||||||
GetKeyDesc(kv);
|
|
||||||
if(GetShift() && kv != K_SHIFT_KEY)
|
if(GetShift() && kv != K_SHIFT_KEY)
|
||||||
kv |= K_SHIFT;
|
kv |= K_SHIFT;
|
||||||
if(GetCtrl() && kv != K_CTRL_KEY)
|
if(GetCtrl() && kv != K_CTRL_KEY)
|
||||||
|
|
@ -710,18 +857,18 @@ void Ctrl::Proc()
|
||||||
activeCtrl = NULL;
|
activeCtrl = NULL;
|
||||||
break;
|
break;
|
||||||
case GDK_DELETE: {
|
case GDK_DELETE: {
|
||||||
TopWindow *w = dynamic_cast<TopWindow *>(this);
|
if(tw) {
|
||||||
if(w) {
|
|
||||||
if(IsEnabled()) {
|
if(IsEnabled()) {
|
||||||
IgnoreMouseUp();
|
IgnoreMouseUp();
|
||||||
w->WhenClose();
|
tw->WhenClose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case GDK_CONFIGURE:
|
case GDK_CONFIGURE:
|
||||||
SyncWndRect(CurrentEvent.value);
|
InvalidateScreenRect();
|
||||||
break;
|
SyncWndRect();
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -729,13 +876,23 @@ void Ctrl::Proc()
|
||||||
_this->PostInput();
|
_this->PostInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ctrl::SyncWndRect(const Rect& rect)
|
void Ctrl::SyncWndRect()
|
||||||
{
|
{
|
||||||
|
WndRectsSync();
|
||||||
|
Rect rect = GetWndScreenRect();
|
||||||
|
TopWindow *tw = dynamic_cast<TopWindow *>(this);
|
||||||
|
if(tw) {
|
||||||
|
tw->SyncIcons();
|
||||||
|
if(tw->state == TopWindow::OVERLAPPED)
|
||||||
|
tw->overlapped = rect;
|
||||||
|
|
||||||
|
Top *top = GetTop();
|
||||||
|
int cy = utop->header_rect.GetHeight();
|
||||||
|
if(top && tw->custom_bar_frame && tw->custom_bar_frame->GetHeight() != cy)
|
||||||
|
tw->custom_bar_frame->Height(cy);
|
||||||
|
}
|
||||||
if(GetRect() != rect)
|
if(GetRect() != rect)
|
||||||
SetWndRect(rect);
|
SetWndRect(rect);
|
||||||
TopWindow *w = dynamic_cast<TopWindow *>(this);
|
|
||||||
if(w && w->state == TopWindow::OVERLAPPED)
|
|
||||||
w->overlapped = rect;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ctrl::ProcessEvent0(bool *quit, bool fetch)
|
bool Ctrl::ProcessEvent0(bool *quit, bool fetch)
|
||||||
|
|
@ -769,6 +926,7 @@ bool Ctrl::ProcessEvent0(bool *quit, bool fetch)
|
||||||
Value val = e.value;
|
Value val = e.value;
|
||||||
Events.DropHead();
|
Events.DropHead();
|
||||||
Ctrl *w = GetTopCtrlFromId(e.windowid);
|
Ctrl *w = GetTopCtrlFromId(e.windowid);
|
||||||
|
SetCustomBarDragPrevention();
|
||||||
FocusSync();
|
FocusSync();
|
||||||
CaptureSync();
|
CaptureSync();
|
||||||
if(w) {
|
if(w) {
|
||||||
|
|
@ -839,8 +997,6 @@ void Ctrl::EventLoop(Ctrl *ctrl)
|
||||||
ASSERT(LoopLevel == 0 || ctrl);
|
ASSERT(LoopLevel == 0 || ctrl);
|
||||||
LoopLevel++;
|
LoopLevel++;
|
||||||
LLOG("Entering event loop at level " << LoopLevel << LOG_BEGIN);
|
LLOG("Entering event loop at level " << LoopLevel << LOG_BEGIN);
|
||||||
if(!GetMouseRight() && !GetMouseMiddle() && !GetMouseLeft())
|
|
||||||
ReleaseCtrlCapture();
|
|
||||||
Ptr<Ctrl> ploop;
|
Ptr<Ctrl> ploop;
|
||||||
if(ctrl) {
|
if(ctrl) {
|
||||||
ploop = LoopCtrl;
|
ploop = LoopCtrl;
|
||||||
|
|
|
||||||
|
|
@ -6,39 +6,47 @@ namespace Upp {
|
||||||
|
|
||||||
#define LLOG(x) // DLOG(x)
|
#define LLOG(x) // DLOG(x)
|
||||||
|
|
||||||
Rect Ctrl::frameMargins;
|
|
||||||
|
|
||||||
Rect Ctrl::GetFrameMargins()
|
|
||||||
{
|
|
||||||
GuiLock __;
|
|
||||||
return frameMargins != Rect(0, 0, 0, 0) ? frameMargins : Rect(8, 32, 8, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TopWindow::SyncSizeHints()
|
void TopWindow::SyncSizeHints()
|
||||||
{
|
{
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
if(!top)
|
if(!top)
|
||||||
return;
|
return;
|
||||||
GdkGeometry m;
|
|
||||||
Size sz0 = GetRect().GetSize();
|
Size sz0 = GetRect().GetSize();
|
||||||
LLOG("SyncSizeHints sz0: " << sz0 << ", sizeable: " << sizeable << ", min: " << GetMinSize() << ", max: " << GetMaxSize());
|
LLOG("SyncSizeHints sz0: " << sz0 << ", sizeable: " << sizeable << ", min: " << GetMinSize() << ", max: " << GetMaxSize());
|
||||||
Size sz = sz0;
|
|
||||||
if(sizeable)
|
|
||||||
sz = GetMinSize();
|
|
||||||
m.min_width = LSC(sz.cx + utop->csd.ExtraWidth());
|
|
||||||
m.min_height = LSC(sz.cy + utop->csd.ExtraHeight());
|
|
||||||
sz = sz0;
|
|
||||||
if(sizeable)
|
|
||||||
sz = GetMaxSize();
|
|
||||||
m.max_width = LSC(sz.cx + utop->csd.ExtraWidth());
|
|
||||||
m.max_height = LSC(sz.cy + utop->csd.ExtraHeight());
|
|
||||||
gtk_window_set_resizable(gtk(), sizeable);
|
|
||||||
Top *top = GetTop();
|
Top *top = GetTop();
|
||||||
if(top) {
|
if(top) {
|
||||||
gtk_window_set_geometry_hints(gtk(), top->window, &m,
|
int mcx = 0;
|
||||||
GdkWindowHints(GDK_HINT_MIN_SIZE|GDK_HINT_MAX_SIZE));
|
int mcy = 0;
|
||||||
|
|
||||||
|
if(top->csd) {
|
||||||
|
mcx += csd_border.left + csd_border.right;
|
||||||
|
mcy += csd_border.top + csd_border.bottom;
|
||||||
|
if(custom_bar_frame)
|
||||||
|
mcy += GetCustomTitleBarMetrics().height;
|
||||||
|
else
|
||||||
|
mcy += csd_std_header_cy;
|
||||||
|
}
|
||||||
|
|
||||||
|
GdkGeometry m;
|
||||||
|
|
||||||
|
m.base_width = sz0.cx;
|
||||||
|
m.base_height = sz0.cy;
|
||||||
|
|
||||||
|
Size minsz = sizeable ? GetMinSize() : sz0;
|
||||||
|
m.min_width = LSCH(minsz.cx + mcx);
|
||||||
|
m.min_height = LSCH(minsz.cy + mcy);
|
||||||
|
|
||||||
|
Size maxsz = sizeable ? GetMaxSize() : sz0;
|
||||||
|
m.max_width = LSCH(maxsz.cx + mcx);
|
||||||
|
m.max_height = LSCH(maxsz.cy + mcy);
|
||||||
|
|
||||||
|
gtk_window_set_resizable(gtk(), sizeable);
|
||||||
|
gtk_window_set_geometry_hints(gtk(), NULL, &m,
|
||||||
|
GdkWindowHints(GDK_HINT_MIN_SIZE|GDK_HINT_MAX_SIZE|GDK_HINT_BASE_SIZE));
|
||||||
gtk_widget_set_size_request(top->window, m.min_width, m.min_height);
|
gtk_widget_set_size_request(top->window, m.min_width, m.min_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SyncCustomBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopWindow::SyncTitle()
|
void TopWindow::SyncTitle()
|
||||||
|
|
@ -73,8 +81,8 @@ void TopWindow::CenterRect(Ctrl *owner)
|
||||||
SetupRect(owner);
|
SetupRect(owner);
|
||||||
if(owner && center == 1 || center == 2) {
|
if(owner && center == 1 || center == 2) {
|
||||||
Size sz = GetRect().Size();
|
Size sz = GetRect().Size();
|
||||||
Rect wr = owner? owner->GetWorkArea() : Ctrl::GetPrimaryWorkArea();
|
Rect wr = owner ? owner->GetWorkArea() : Ctrl::GetPrimaryWorkArea();
|
||||||
Rect fm = GetFrameMargins();
|
Rect fm = frameMargins;
|
||||||
Rect r = (center == 1 && owner ? owner->GetRect() : wr)
|
Rect r = (center == 1 && owner ? owner->GetRect() : wr)
|
||||||
.CenterRect(sz);
|
.CenterRect(sz);
|
||||||
wr.left += fm.left;
|
wr.left += fm.left;
|
||||||
|
|
@ -107,6 +115,7 @@ gboolean TopWindow::StateEvent(GtkWidget *widget, GdkEventWindowState *event, gp
|
||||||
{
|
{
|
||||||
TopWindow *w = (TopWindow *)user_data;
|
TopWindow *w = (TopWindow *)user_data;
|
||||||
dword h = event->new_window_state;
|
dword h = event->new_window_state;
|
||||||
|
int prev = w->state;
|
||||||
if(h & GDK_WINDOW_STATE_FULLSCREEN)
|
if(h & GDK_WINDOW_STATE_FULLSCREEN)
|
||||||
w->state = FULLSCREEN;
|
w->state = FULLSCREEN;
|
||||||
else
|
else
|
||||||
|
|
@ -119,7 +128,14 @@ gboolean TopWindow::StateEvent(GtkWidget *widget, GdkEventWindowState *event, gp
|
||||||
w->state = OVERLAPPED;
|
w->state = OVERLAPPED;
|
||||||
w->overlapped = w->GetRect();
|
w->overlapped = w->GetRect();
|
||||||
}
|
}
|
||||||
|
LLOG("StateEvent " << prev << " -> " << (int)w->state);
|
||||||
w->topmost = h & GDK_WINDOW_STATE_ABOVE;
|
w->topmost = h & GDK_WINDOW_STATE_ABOVE;
|
||||||
|
w->Layout();
|
||||||
|
if(prev == MINIMIZED && w->state != MINIMIZED) {
|
||||||
|
prev_mouse_pos = CurrentMousePos = Null; // we lost the track of mouse, otherwise "minimize" button would render highlighted
|
||||||
|
if(w->custom_bar_icons)
|
||||||
|
w->custom_bar_icons->RefreshFrame();
|
||||||
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -145,13 +161,6 @@ void TopWindow::Open(Ctrl *owner)
|
||||||
state = OVERLAPPED;
|
state = OVERLAPPED;
|
||||||
SetMode(q);
|
SetMode(q);
|
||||||
SyncTopMost();
|
SyncTopMost();
|
||||||
GdkRectangle fr;
|
|
||||||
gdk_window_get_frame_extents(gdk(), &fr);
|
|
||||||
Rect r = GetRect();
|
|
||||||
frameMargins.left = max(frameMargins.left, minmax(r.left - SCL(fr.x), 0, 32));
|
|
||||||
frameMargins.right = max(frameMargins.right, minmax(SCL(fr.x + fr.width) - r.right, 0, 32));
|
|
||||||
frameMargins.top = max(frameMargins.top, minmax(r.top - SCL(fr.y), 0, 64));
|
|
||||||
frameMargins.bottom = max(frameMargins.bottom, minmax(SCL(fr.y + fr.height) - r.bottom, 0, 48));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopWindow::Open()
|
void TopWindow::Open()
|
||||||
|
|
@ -178,29 +187,24 @@ void TopWindow::SetMode(int mode)
|
||||||
if(w)
|
if(w)
|
||||||
switch(state) {
|
switch(state) {
|
||||||
case MINIMIZED:
|
case MINIMIZED:
|
||||||
gtk_window_deiconify(w);
|
fullscreen = false;
|
||||||
break;
|
|
||||||
case MAXIMIZED:
|
|
||||||
gtk_window_unmaximize(w);
|
|
||||||
break;
|
|
||||||
case FULLSCREEN:
|
|
||||||
gtk_window_unfullscreen(w);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
state = mode;
|
|
||||||
if(w)
|
|
||||||
switch(state) {
|
|
||||||
case MINIMIZED:
|
|
||||||
gtk_window_iconify(w);
|
gtk_window_iconify(w);
|
||||||
break;
|
break;
|
||||||
case MAXIMIZED:
|
case MAXIMIZED:
|
||||||
|
fullscreen = false;
|
||||||
|
gtk_window_deiconify(w);
|
||||||
gtk_window_maximize(w);
|
gtk_window_maximize(w);
|
||||||
break;
|
break;
|
||||||
|
case OVERLAPPED:
|
||||||
|
fullscreen = false;
|
||||||
|
gtk_window_deiconify(w);
|
||||||
|
gtk_window_unmaximize(w);
|
||||||
|
break;
|
||||||
case FULLSCREEN:
|
case FULLSCREEN:
|
||||||
gtk_window_fullscreen(w);
|
gtk_window_fullscreen(w);
|
||||||
|
fullscreen = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fullscreen = state == FULLSCREEN;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopWindow::Minimize(bool effect)
|
void TopWindow::Minimize(bool effect)
|
||||||
|
|
@ -263,7 +267,7 @@ void TopWindow::SerializePlacement(Stream& s, bool reminimize)
|
||||||
if(s.IsLoading()) {
|
if(s.IsLoading()) {
|
||||||
if(mn) rect = overlapped;
|
if(mn) rect = overlapped;
|
||||||
Rect limit = GetVirtualWorkArea();
|
Rect limit = GetVirtualWorkArea();
|
||||||
Rect fm = GetFrameMargins();
|
Rect fm = frameMargins;
|
||||||
limit.left += fm.left;
|
limit.left += fm.left;
|
||||||
limit.right -= fm.right;
|
limit.right -= fm.right;
|
||||||
limit.top += fm.top;
|
limit.top += fm.top;
|
||||||
|
|
@ -291,4 +295,4 @@ void TopWindow::SerializePlacement(Stream& s, bool reminimize)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1,13 +1,51 @@
|
||||||
ImageGdk gdk_icon;
|
ImageGdk gdk_icon;
|
||||||
ImageGdk gdk_largeicon;
|
ImageGdk gdk_largeicon;
|
||||||
bool topmost;
|
bool topmost;
|
||||||
|
|
||||||
|
struct CustomBarIcon : public Ctrl {
|
||||||
|
void Paint(Draw& w) override;
|
||||||
|
void MouseMove(Point p, dword keyflags) override;
|
||||||
|
void LeftDown(Point p, dword keyflags) override;
|
||||||
|
void LeftUp(Point, dword keyflags) override;
|
||||||
|
void MouseLeave() override;
|
||||||
|
|
||||||
|
Image img;
|
||||||
|
|
||||||
|
void Set(const Image& m) { if(!m.IsSame(img)) { img = m; Refresh(); }}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BarCtrl : public Ctrl {
|
||||||
|
void LeftDouble(Point p, dword keyflags) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
One<FrameTop<Ctrl>> custom_bar_frame;
|
||||||
|
One<FrameRight<Ctrl>> custom_bar_icons;
|
||||||
|
One<BarCtrl> custom_bar;
|
||||||
|
CustomBarIcon minicon, maxicon, closeicon;
|
||||||
|
Color custom_titlebar_bk = SColorFace();
|
||||||
|
int custom_titlebar_cy = -1;
|
||||||
|
bool force_csd = false;
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Force_csd_() { force_csd = true; } // this is for testing...
|
||||||
|
|
||||||
|
private:
|
||||||
enum { FULLSCREEN = 99 };
|
enum { FULLSCREEN = 99 };
|
||||||
|
|
||||||
void CenterRect(Ctrl *owner);
|
void CenterRect(Ctrl *owner);
|
||||||
void SetMode(int mode);
|
void SetMode(int mode);
|
||||||
void SyncTopMost();
|
void SyncTopMost();
|
||||||
|
|
||||||
|
void SyncCustomBar();
|
||||||
|
void SyncIcons();
|
||||||
|
bool IsCustomTitleBar__() const;
|
||||||
|
Ctrl *MakeCustomTitleBar__(Color bk, int mincy);
|
||||||
|
void DoZoom();
|
||||||
|
void DoMoveWindow();
|
||||||
|
static void Init();
|
||||||
|
|
||||||
static gboolean StateEvent(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data);
|
static gboolean StateEvent(GtkWidget *widget, GdkEventWindowState *event, gpointer user_data);
|
||||||
|
|
||||||
friend class Ctrl;
|
friend class Ctrl;
|
||||||
|
friend bool InitGtkApp(int argc, char **argv, const char **envptr);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -152,32 +152,107 @@ void Ctrl::UnregisterSystemHotKey(int id)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Rect Ctrl::csd_border;
|
||||||
|
int Ctrl::csd_std_header_cy;
|
||||||
|
Rect Ctrl::frameMargins;
|
||||||
|
|
||||||
|
void Ctrl::UpdateWindowDecorationsGeometry()
|
||||||
|
{
|
||||||
|
GtkWidget* win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||||
|
|
||||||
|
GtkWidget* header = gtk_header_bar_new();
|
||||||
|
|
||||||
|
gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(header), TRUE);
|
||||||
|
gtk_window_set_titlebar((GtkWindow *)win, header);
|
||||||
|
|
||||||
|
GtkWidget* client = gtk_drawing_area_new();
|
||||||
|
gtk_container_add(GTK_CONTAINER(win), client);
|
||||||
|
gtk_widget_show_all(win);
|
||||||
|
|
||||||
|
gint left, top;
|
||||||
|
|
||||||
|
gdk_window_get_origin(gtk_widget_get_window(client), &left, &top);
|
||||||
|
|
||||||
|
int win_cx = gtk_widget_get_allocated_width(win);
|
||||||
|
int win_cy = gtk_widget_get_allocated_height(win);
|
||||||
|
|
||||||
|
csd_std_header_cy = gtk_widget_get_allocated_height(header);
|
||||||
|
|
||||||
|
int client_cx = gtk_widget_get_allocated_width(client);
|
||||||
|
int client_cy = gtk_widget_get_allocated_height(client);
|
||||||
|
|
||||||
|
csd_border.left = SCL(left);
|
||||||
|
csd_border.right = SCL(win_cx - client_cx - left);
|
||||||
|
csd_border.top = SCL(top - csd_std_header_cy);
|
||||||
|
|
||||||
|
csd_border.bottom = SCL(win_cy - client_cy - top);
|
||||||
|
csd_std_header_cy = SCL(csd_std_header_cy);
|
||||||
|
|
||||||
|
gtk_widget_destroy(win);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ctrl::UpdateWindowFrameMargins()
|
||||||
|
{
|
||||||
|
#ifdef GDK_WINDOWING_X11
|
||||||
|
// No realiable way how to do this in wayland, but there the window pos is ignored anyway
|
||||||
|
GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
|
||||||
|
gtk_widget_show_all(win);
|
||||||
|
gdk_display_sync(gdk_display_get_default());
|
||||||
|
Vector<int> fe = GetPropertyInts(gtk_widget_get_window(win), "_NET_FRAME_EXTENTS");
|
||||||
|
if(fe.GetCount() >= 4) {
|
||||||
|
frameMargins.left = clamp(fe[0], 0, DPI(32));
|
||||||
|
frameMargins.right = clamp(fe[1], 0, DPI(32));
|
||||||
|
frameMargins.top = clamp(fe[2], 0, DPI(96));
|
||||||
|
frameMargins.bottom = clamp(fe[3], 0, DPI(32));
|
||||||
|
}
|
||||||
|
gtk_widget_destroy(win);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ctrl::WndRectsSync() const
|
||||||
|
{
|
||||||
|
if(utop && utop->sync_rect) {
|
||||||
|
auto GetScreenRect = [&](GtkWidget *w) {
|
||||||
|
gint x, y;
|
||||||
|
gint width, height;
|
||||||
|
|
||||||
|
width = gtk_widget_get_allocated_width(w);
|
||||||
|
height = gtk_widget_get_allocated_height(w);
|
||||||
|
|
||||||
|
if(top && utop->csd) {
|
||||||
|
gdk_window_get_root_origin(gdk(), &x, &y);
|
||||||
|
int x1, y1;
|
||||||
|
gtk_widget_translate_coordinates(w, GTK_WIDGET(gtk()), 0, 0, &x1, &y1);
|
||||||
|
x += x1;
|
||||||
|
y += y1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gdk_window_get_position(gdk(), &x, &y);
|
||||||
|
|
||||||
|
return SCL(x, y, width, height);
|
||||||
|
};
|
||||||
|
|
||||||
|
utop->client_rect = GetScreenRect(utop->client);
|
||||||
|
utop->screen_rect = utop->client_rect;
|
||||||
|
const TopWindow *tw = dynamic_cast<const TopWindow *>(this);
|
||||||
|
if(tw && tw->custom_bar_frame) {
|
||||||
|
utop->header_rect = GetScreenRect(utop->header_area);
|
||||||
|
utop->screen_rect.Union(utop->header_rect);
|
||||||
|
}
|
||||||
|
utop->sync_rect = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Rect Ctrl::GetWndScreenRect() const
|
Rect Ctrl::GetWndScreenRect() const
|
||||||
{
|
{
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
|
|
||||||
if(!IsOpen())
|
if(!IsOpen() || !top)
|
||||||
return Null;
|
return Null;
|
||||||
|
|
||||||
|
WndRectsSync();
|
||||||
|
|
||||||
gint x, y;
|
return utop->screen_rect;
|
||||||
gint width, height;
|
|
||||||
|
|
||||||
if(IsWayland()) {
|
|
||||||
if(top && utop->csd.IsEnabled()) {
|
|
||||||
gdk_window_get_origin(gtk_widget_get_window(utop->drawing_area), &x, &y);
|
|
||||||
width = gtk_widget_get_allocated_width(utop->drawing_area);
|
|
||||||
height = gtk_widget_get_allocated_height(utop->drawing_area);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
gdk_window_get_geometry(gdk(), &x, &y, &width, &height);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
gdk_window_get_position(gdk(), &x, &y);
|
|
||||||
width = gdk_window_get_width(gdk());
|
|
||||||
height = gdk_window_get_height(gdk());
|
|
||||||
}
|
|
||||||
|
|
||||||
return SCL(x, y, width, height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ctrl::WndShow(bool b)
|
void Ctrl::WndShow(bool b)
|
||||||
|
|
@ -431,27 +506,24 @@ void Ctrl::WndInvalidateRect(const Rect& r)
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
|
|
||||||
Rect rr = r;
|
Rect rr = r;
|
||||||
if(scale > 1) {
|
|
||||||
rr.left = r.left / 2;
|
|
||||||
rr.top = r.top / 2;
|
|
||||||
rr.right = (r.right + 1) / 2;
|
|
||||||
rr.bottom = (r.bottom + 1) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(IsWayland())
|
if(IsWayland())
|
||||||
rr.Inflate(2, 2); // TODO: This is temporary fix
|
rr.Inflate(DPI(2), DPI(2)); // TODO: This is temporary fix
|
||||||
|
|
||||||
// as gtk3 dropped thread locking, we need to push invalid rectangles onto main loop
|
// as gtk3 dropped thread locking, we need to push invalid rectangles onto main loop
|
||||||
for(Win& win : wins) {
|
for(Win& win : wins) {
|
||||||
if(win.ctrl == this) {
|
if(win.ctrl == this) {
|
||||||
if(win.invalid.GetCount() && IsNull(win.invalid[0]))
|
if(win.invalid.GetCount() && IsNull(win.invalid[0]))
|
||||||
return;
|
return;
|
||||||
|
for(const Rect& ir : win.invalid)
|
||||||
|
if(ir.Contains(r)) // ignore repeated invalidates
|
||||||
|
return;
|
||||||
if(win.invalid.GetCount() > 40) { // keep things sane
|
if(win.invalid.GetCount() > 40) { // keep things sane
|
||||||
win.invalid.Clear();
|
win.invalid.Clear();
|
||||||
win.invalid.Add(Null);
|
win.invalid.Add(Null);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
win.invalid.Add(rr);
|
win.invalid.Add(rr);
|
||||||
|
}
|
||||||
if(!invalids) {
|
if(!invalids) {
|
||||||
invalids = true;
|
invalids = true;
|
||||||
WakeUpGuiThread();
|
WakeUpGuiThread();
|
||||||
|
|
@ -476,10 +548,12 @@ bool Ctrl::SweepConfigure(bool wait)
|
||||||
GEvent& e = Events[i];
|
GEvent& e = Events[i];
|
||||||
Top *top = GetTop();
|
Top *top = GetTop();
|
||||||
if(e.type == GDK_CONFIGURE && this_ && top && top->id == e.windowid) {
|
if(e.type == GDK_CONFIGURE && this_ && top && top->id == e.windowid) {
|
||||||
Rect rect = e.value;
|
LLOG("SweepConfigure " << e.value);
|
||||||
LLOG("SweepConfigure " << rect);
|
if(top) {
|
||||||
if(GetRect() != rect)
|
utop->sync_rect = true;
|
||||||
SetWndRect(rect);
|
LLOG("Sweep");
|
||||||
|
SetWndRect(GetWndScreenRect());
|
||||||
|
}
|
||||||
r = true;
|
r = true;
|
||||||
e.type = EVENT_NONE;
|
e.type = EVENT_NONE;
|
||||||
}
|
}
|
||||||
|
|
@ -489,22 +563,38 @@ bool Ctrl::SweepConfigure(bool wait)
|
||||||
|
|
||||||
void Ctrl::WndSetPos(const Rect& rect)
|
void Ctrl::WndSetPos(const Rect& rect)
|
||||||
{
|
{
|
||||||
|
LLOG("========================== WNDSETPOS");
|
||||||
LLOG("WndSetPos " << UPP::Name(this) << " " << rect);
|
LLOG("WndSetPos " << UPP::Name(this) << " " << rect);
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
if(!IsOpen())
|
if(!IsOpen())
|
||||||
return;
|
return;
|
||||||
Ptr<Ctrl> this_ = this;
|
|
||||||
SweepConfigure(false); // Remove any previous GDK_CONFIGURE for this window
|
|
||||||
if(!this_ || !IsOpen())
|
|
||||||
return;
|
|
||||||
|
|
||||||
Rect m(0, 0, 0, 0);
|
TopWindow *tw = dynamic_cast<TopWindow *>(this);
|
||||||
if(dynamic_cast<TopWindow *>(this))
|
if(tw)
|
||||||
m = GetFrameMargins();
|
|
||||||
SetWndRect(rect);
|
|
||||||
if(TopWindow *tw = dynamic_cast<TopWindow *>(this))
|
|
||||||
tw->SyncSizeHints();
|
tw->SyncSizeHints();
|
||||||
gdk_window_move_resize(gdk(), LSC(rect.left - m.left), LSC(rect.top - m.top), LSC(rect.GetWidth()), LSC(rect.GetHeight()));
|
|
||||||
|
if(top && utop->csd) {
|
||||||
|
int top = csd_border.top;
|
||||||
|
if(tw) {
|
||||||
|
if(tw->custom_bar_frame)
|
||||||
|
top += tw->GetCustomTitleBarMetrics().height;
|
||||||
|
else
|
||||||
|
top += csd_std_header_cy;
|
||||||
|
}
|
||||||
|
gdk_window_move_resize(gdk(), LSC(rect.left - csd_border.left), LSC(rect.top - top),
|
||||||
|
LSCH(rect.GetWidth() + csd_border.left + csd_border.right),
|
||||||
|
LSCH(rect.GetHeight() + top + csd_border.bottom));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Rect m(0, 0, 0, 0);
|
||||||
|
if(tw)
|
||||||
|
m = frameMargins;
|
||||||
|
|
||||||
|
gdk_window_move_resize(gdk(), LSC(rect.left - m.left), LSC(rect.top - m.top),
|
||||||
|
LSCH(rect.GetWidth()), LSCH(rect.GetHeight()));
|
||||||
|
}
|
||||||
|
InvalidateScreenRect();
|
||||||
|
SyncWndRect();
|
||||||
LLOG("-- WndSetPos0 " << rect);
|
LLOG("-- WndSetPos0 " << rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -557,8 +647,8 @@ TopFrameDraw::TopFrameDraw(Ctrl *ctrl, const Rect& r)
|
||||||
cairo_rectangle_int_t rr;
|
cairo_rectangle_int_t rr;
|
||||||
rr.x = Ctrl::LSC(r.left);
|
rr.x = Ctrl::LSC(r.left);
|
||||||
rr.y = Ctrl::LSC(r.top);
|
rr.y = Ctrl::LSC(r.top);
|
||||||
rr.width = Ctrl::LSC(r.GetWidth());
|
rr.width = Ctrl::LSCH(r.GetWidth());
|
||||||
rr.height = Ctrl::LSC(r.GetHeight());
|
rr.height = Ctrl::LSCH(r.GetHeight());
|
||||||
cairo_region_t *rg = cairo_region_create_rectangle(&rr);
|
cairo_region_t *rg = cairo_region_create_rectangle(&rr);
|
||||||
ctx = gdk_window_begin_draw_frame(top->gdk(), rg);
|
ctx = gdk_window_begin_draw_frame(top->gdk(), rg);
|
||||||
cairo_region_destroy(rg);
|
cairo_region_destroy(rg);
|
||||||
|
|
@ -606,4 +696,3 @@ Vector<WString> SplitCmdLine__(const char *cmd)
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -184,9 +184,50 @@ void TopWindow::SyncCaption()
|
||||||
|
|
||||||
SetIco();
|
SetIco();
|
||||||
Ptr<TopWindow> ptr = this;
|
Ptr<TopWindow> ptr = this;
|
||||||
PostCallback([=] { // windows 11 ignores icon if Window does not start processing messages within ~200ms
|
PostCallback([=] { // windows 11 seems to ignore icon if Window does not start processing messages within ~200ms
|
||||||
if(ptr) ptr->SetIco(); // set it again when we are processing events
|
if(ptr) ptr->SetIco(); // set it again when we are processing events
|
||||||
});
|
});
|
||||||
|
|
||||||
|
SyncCustomBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TopWindow::SyncCustomBar()
|
||||||
|
{
|
||||||
|
if(custom_bar_frame)
|
||||||
|
custom_bar_frame->Height(GetCustomTitleBarMetrics().height);
|
||||||
|
if(custom_bar) {
|
||||||
|
auto cm = GetCustomTitleBarMetrics();
|
||||||
|
custom_bar->VSizePos().HSizePos(cm.lm, cm.rm);
|
||||||
|
RefreshFrame(0, 0, GetRect().Width(), cm.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TopWindow::IsCustomTitleBar__() const
|
||||||
|
{
|
||||||
|
return custom_bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ctrl *TopWindow::MakeCustomTitleBar__(Color bk, int mincy)
|
||||||
|
{
|
||||||
|
if(!custom_bar && IsWin11()) {
|
||||||
|
custom_bar_frame.Create();
|
||||||
|
custom_bar_frame->Transparent();
|
||||||
|
custom_bar.Create();
|
||||||
|
}
|
||||||
|
if(custom_bar) {
|
||||||
|
if(&GetFrame(0) != ~custom_bar_frame) {
|
||||||
|
RemoveFrame(*custom_bar_frame);
|
||||||
|
if(&GetFrame(0) == &NullFrame())
|
||||||
|
SetFrame(0, *custom_bar_frame);
|
||||||
|
else
|
||||||
|
InsertFrame(0, *custom_bar_frame);
|
||||||
|
}
|
||||||
|
custom_bar_frame->Add(*custom_bar);
|
||||||
|
}
|
||||||
|
custom_titlebar_bk = bk;
|
||||||
|
custom_titlebar_cy = mincy;
|
||||||
|
SyncCustomBar();
|
||||||
|
return ~custom_bar;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TopWindow::SetIco()
|
void TopWindow::SetIco()
|
||||||
|
|
@ -203,7 +244,7 @@ void TopWindow::SetIco()
|
||||||
ico = new_ico;
|
ico = new_ico;
|
||||||
lico = new_lico;
|
lico = new_lico;
|
||||||
|
|
||||||
if(custom_titlebar) {
|
if(custom_bar) {
|
||||||
Rect r = GetTitleBarRect(this);
|
Rect r = GetTitleBarRect(this);
|
||||||
|
|
||||||
bool maximized = IsMaximized();
|
bool maximized = IsMaximized();
|
||||||
|
|
|
||||||
|
|
@ -421,26 +421,29 @@ TopWindow& TopWindow::Icon(const Image& smallicon, const Image& _largeicon)
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_custom_titlebar_available__;
|
// avoid the need to implement custom titlebar in all platforms:
|
||||||
|
|
||||||
bool TopWindow::IsCustomTitleBar() const
|
|
||||||
{
|
|
||||||
return custom_titlebar && is_custom_titlebar_available__;
|
|
||||||
}
|
|
||||||
|
|
||||||
TopWindow& TopWindow::CustomTitleBar(int cy)
|
|
||||||
{
|
|
||||||
custom_titlebar = is_custom_titlebar_available__;
|
|
||||||
custom_titlebar_cy = cy;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Function<bool (const TopWindow *)> is_custom_titlebar__;
|
||||||
|
Function<Ctrl *(TopWindow *, Color bk, int)> custom_titlebar_make__;
|
||||||
Event<const TopWindow *, TopWindow::CustomTitleBarMetrics&> custom_titlebar_metrics__ =
|
Event<const TopWindow *, TopWindow::CustomTitleBarMetrics&> custom_titlebar_metrics__ =
|
||||||
[](const TopWindow *, TopWindow::CustomTitleBarMetrics& m) {
|
[](const TopWindow *, TopWindow::CustomTitleBarMetrics& m) {
|
||||||
m.lm = m.rm = m.height = 0;
|
m.lm = m.rm = m.height = 0;
|
||||||
m.background = SColorPaper();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool TopWindow::IsCustomTitleBar() const
|
||||||
|
{
|
||||||
|
return is_custom_titlebar__(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ctrl * TopWindow::CustomTitleBar(Color bk, int min_cy)
|
||||||
|
{
|
||||||
|
#ifdef flagNOCUSTOMBAR // suppress custom title bar for testing
|
||||||
|
return nullptr;
|
||||||
|
#else
|
||||||
|
return custom_titlebar_make__(this, bk, min_cy);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
TopWindow::CustomTitleBarMetrics TopWindow::GetCustomTitleBarMetrics() const
|
TopWindow::CustomTitleBarMetrics TopWindow::GetCustomTitleBarMetrics() const
|
||||||
{
|
{
|
||||||
CustomTitleBarMetrics m;
|
CustomTitleBarMetrics m;
|
||||||
|
|
@ -448,17 +451,18 @@ TopWindow::CustomTitleBarMetrics TopWindow::GetCustomTitleBarMetrics() const
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool sIsDragArea(Ctrl& w, Point p)
|
bool Ctrl::MouseActiveCtrl(Ctrl *w, Point p)
|
||||||
{
|
{
|
||||||
for(Ctrl& q : w)
|
for(Ctrl *q = w->GetLastChild(); q; q = q->GetPrev())
|
||||||
if(q.GetScreenRect().Contains(p))
|
if(q->GetScreenRect().Contains(p))
|
||||||
return q.IsIgnoreMouse() || sIsDragArea(q, p);
|
return MouseActiveCtrl(q, p);
|
||||||
return false;
|
|
||||||
|
return w->IsMouseActive();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TopWindow::IsCustomTitleBarDragArea(Point p)
|
bool TopWindow::IsCustomTitleBarDragArea(Point p)
|
||||||
{
|
{
|
||||||
return sIsDragArea(*this, p + GetScreenRect().TopLeft());
|
return !MouseActiveCtrl(this, p + GetScreenRect().TopLeft());
|
||||||
}
|
}
|
||||||
|
|
||||||
TopWindow& TopWindow::ToolWindow(bool b)
|
TopWindow& TopWindow::ToolWindow(bool b)
|
||||||
|
|
@ -545,8 +549,6 @@ TopWindow::TopWindow()
|
||||||
dokeys = true;
|
dokeys = true;
|
||||||
fullscreen = frameless = urgent = false;
|
fullscreen = frameless = urgent = false;
|
||||||
close_rejects = false;
|
close_rejects = false;
|
||||||
custom_titlebar = false;
|
|
||||||
custom_titlebar_cy = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TopWindow::~TopWindow()
|
TopWindow::~TopWindow()
|
||||||
|
|
|
||||||
|
|
@ -80,14 +80,9 @@ private:
|
||||||
bool frameless:1;
|
bool frameless:1;
|
||||||
bool urgent:1;
|
bool urgent:1;
|
||||||
bool close_rejects:1;
|
bool close_rejects:1;
|
||||||
bool custom_titlebar:1;
|
|
||||||
byte state;
|
byte state;
|
||||||
Image icon, largeicon;
|
Image icon, largeicon;
|
||||||
|
|
||||||
int custom_titlebar_cy = 0;
|
|
||||||
int active_titlebar_button = -1;
|
|
||||||
bool active_titlebar_active = false;
|
|
||||||
|
|
||||||
const TopStyle *st;
|
const TopStyle *st;
|
||||||
|
|
||||||
void GuiPlatformConstruct();
|
void GuiPlatformConstruct();
|
||||||
|
|
@ -181,14 +176,14 @@ public:
|
||||||
TopWindow& LargeIcon(const Image& m);
|
TopWindow& LargeIcon(const Image& m);
|
||||||
TopWindow& Icon(const Image& smallicon, const Image& largeicon);
|
TopWindow& Icon(const Image& smallicon, const Image& largeicon);
|
||||||
|
|
||||||
TopWindow& CustomTitleBar(int min_cy = 0);
|
Ctrl *CustomTitleBar(Color bk = Null, int min_cy = 0);
|
||||||
|
|
||||||
bool IsCustomTitleBar() const;
|
bool IsCustomTitleBar() const;
|
||||||
|
|
||||||
struct CustomTitleBarMetrics {
|
struct CustomTitleBarMetrics {
|
||||||
int lm;
|
int lm;
|
||||||
int rm;
|
int rm;
|
||||||
int height;
|
int height;
|
||||||
Color background;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CustomTitleBarMetrics GetCustomTitleBarMetrics() const;
|
CustomTitleBarMetrics GetCustomTitleBarMetrics() const;
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,9 @@ protected:
|
||||||
void Create(HWND parent, DWORD style, DWORD exstyle, bool savebits, int show, bool dropshadow);
|
void Create(HWND parent, DWORD style, DWORD exstyle, bool savebits, int show, bool dropshadow);
|
||||||
Image DoMouse(int e, Point p, int zd = 0);
|
Image DoMouse(int e, Point p, int zd = 0);
|
||||||
|
|
||||||
|
Rect AdjustWindowRect(const Rect& client, dword style, dword exstyle);
|
||||||
|
Rect AdjustWindowRect(const Rect& client);
|
||||||
|
|
||||||
void PaintWinBarBackground(SystemDraw& w, const Rect& clip);
|
void PaintWinBarBackground(SystemDraw& w, const Rect& clip);
|
||||||
void PaintWinBar(SystemDraw& w, const Rect& clip);
|
void PaintWinBar(SystemDraw& w, const Rect& clip);
|
||||||
int GetActiveTitleBarButton();
|
int GetActiveTitleBarButton();
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ void Ctrl::PaintWinBarBackground(SystemDraw& w, const Rect& clip)
|
||||||
HWND hwnd = GetHWND();
|
HWND hwnd = GetHWND();
|
||||||
if(topwin && topwin->IsCustomTitleBar() && hwnd) {
|
if(topwin && topwin->IsCustomTitleBar() && hwnd) {
|
||||||
Rect r = GetTitleBarRect(topwin);
|
Rect r = GetTitleBarRect(topwin);
|
||||||
w.DrawRect(r, IsDarkTheme() ? Color(26, 34, 39) : Color(238, 244, 249));
|
w.DrawRect(r, Nvl(topwin->custom_titlebar_bk, IsDarkTheme() ? Color(26, 34, 39) : Color(238, 244, 249)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -471,7 +471,7 @@ LRESULT Ctrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||||
int padding = GetSystemMetricsForDpi(92 /*SM_CXPADDEDBORDER*/, dpi);
|
int padding = GetSystemMetricsForDpi(92 /*SM_CXPADDEDBORDER*/, dpi);
|
||||||
Point p((LONG)lParam);
|
Point p((LONG)lParam);
|
||||||
ScreenToClient(hwnd, p);
|
ScreenToClient(hwnd, p);
|
||||||
// We should not return HTTOP when hit-testing a maximized window
|
// We should not return HTTOP when hit-testing a maximized window
|
||||||
if(!IsMaximized(hwnd) && p.y > 0 && p.y < frame_y + padding && topwin->IsSizeable())
|
if(!IsMaximized(hwnd) && p.y > 0 && p.y < frame_y + padding && topwin->IsSizeable())
|
||||||
return HTTOP;
|
return HTTOP;
|
||||||
|
|
||||||
|
|
@ -896,16 +896,8 @@ LRESULT Ctrl::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||||
MINMAXINFO *mmi = (MINMAXINFO *)lParam;
|
MINMAXINFO *mmi = (MINMAXINFO *)lParam;
|
||||||
Rect frmrc = Size(200, 200);
|
Rect frmrc = Size(200, 200);
|
||||||
::AdjustWindowRect(frmrc, WS_OVERLAPPEDWINDOW, FALSE);
|
::AdjustWindowRect(frmrc, WS_OVERLAPPEDWINDOW, FALSE);
|
||||||
// Size msz = Ctrl::GetWorkArea().Deflated(-frmrc.left, -frmrc.top,
|
Rect minr = AdjustWindowRect(Rect(Point(50, 50), GetMinSize()));
|
||||||
// frmrc.right - 200, frmrc.bottom - 200).GetSize();
|
Rect maxr = AdjustWindowRect(Rect(Point(50, 50), GetMaxSize()));
|
||||||
// Rect minr(Point(50, 50), min(msz, GetMinSize()));
|
|
||||||
// Rect maxr(Point(50, 50), min(msz, GetMaxSize())); // Removed cxl&nixnixnix 2012-6-12
|
|
||||||
Rect minr(Point(50, 50), GetMinSize());
|
|
||||||
Rect maxr(Point(50, 50), GetMaxSize());
|
|
||||||
dword style = ::GetWindowLong(hwnd, GWL_STYLE);
|
|
||||||
dword exstyle = ::GetWindowLong(hwnd, GWL_EXSTYLE);
|
|
||||||
AdjustWindowRectEx(minr, style, FALSE, exstyle);
|
|
||||||
AdjustWindowRectEx(maxr, style, FALSE, exstyle);
|
|
||||||
mmi->ptMinTrackSize = Point(minr.Size());
|
mmi->ptMinTrackSize = Point(minr.Size());
|
||||||
mmi->ptMaxTrackSize = Point(maxr.Size());
|
mmi->ptMaxTrackSize = Point(maxr.Size());
|
||||||
LLOG("WM_GETMINMAXINFO: MinTrackSize = " << Point(mmi->ptMinTrackSize) << ", MaxTrackSize = " << Point(mmi->ptMaxTrackSize));
|
LLOG("WM_GETMINMAXINFO: MinTrackSize = " << Point(mmi->ptMinTrackSize) << ", MaxTrackSize = " << Point(mmi->ptMaxTrackSize));
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,17 @@ private:
|
||||||
void SetIco();
|
void SetIco();
|
||||||
void CenterRect(HWND owner, int center);
|
void CenterRect(HWND owner, int center);
|
||||||
|
|
||||||
|
One<FrameTop<Ctrl>> custom_bar_frame;
|
||||||
|
One<Ctrl> custom_bar;
|
||||||
|
Color custom_titlebar_bk = Null;
|
||||||
|
int custom_titlebar_cy = 0;
|
||||||
|
int active_titlebar_button = -1;
|
||||||
|
bool active_titlebar_active = false;
|
||||||
|
|
||||||
|
bool IsCustomTitleBar__() const;
|
||||||
|
Ctrl *MakeCustomTitleBar__(Color bk, int mincy);
|
||||||
|
void SyncCustomBar();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Open(HWND ownerhwnd);
|
void Open(HWND ownerhwnd);
|
||||||
TopWindow& Style(dword _style);
|
TopWindow& Style(dword _style);
|
||||||
|
|
|
||||||
|
|
@ -220,8 +220,9 @@ void Ctrl::InstallPanicBox()
|
||||||
InstallPanicMessageBox(&Win32PanicMessageBox);
|
InstallPanicMessageBox(&Win32PanicMessageBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern bool is_custom_titlebar_available__;
|
|
||||||
extern Event<const TopWindow *, TopWindow::CustomTitleBarMetrics&> custom_titlebar_metrics__;
|
extern Event<const TopWindow *, TopWindow::CustomTitleBarMetrics&> custom_titlebar_metrics__;
|
||||||
|
extern Function<bool (const TopWindow *)> is_custom_titlebar__;
|
||||||
|
extern Function<Ctrl *(TopWindow *, Color, int)> custom_titlebar_make__;
|
||||||
|
|
||||||
void Ctrl::InitWin32(HINSTANCE hInstance)
|
void Ctrl::InitWin32(HINSTANCE hInstance)
|
||||||
{
|
{
|
||||||
|
|
@ -284,10 +285,8 @@ void Ctrl::InitWin32(HINSTANCE hInstance)
|
||||||
|
|
||||||
GlobalBackPaint();
|
GlobalBackPaint();
|
||||||
|
|
||||||
is_custom_titlebar_available__ = IsWin11();
|
custom_titlebar_metrics__ = [](const TopWindow *tw, TopWindow::CustomTitleBarMetrics& m) {
|
||||||
|
if(!tw->custom_bar)
|
||||||
custom_titlebar_metrics__ = [=](const TopWindow *tw, TopWindow::CustomTitleBarMetrics& m) {
|
|
||||||
if(!tw->custom_titlebar)
|
|
||||||
return;
|
return;
|
||||||
m.height = GetWin32TitleBarHeight(tw);
|
m.height = GetWin32TitleBarHeight(tw);
|
||||||
m.lm = 0;
|
m.lm = 0;
|
||||||
|
|
@ -296,7 +295,15 @@ void Ctrl::InitWin32(HINSTANCE hInstance)
|
||||||
m.lm = DPI(4) + min(icon.GetWidth(), 32);
|
m.lm = DPI(4) + min(icon.GetWidth(), 32);
|
||||||
m.rm = (tw->IsZoomable() ? 3 : 1) * GetWin32TitleBarButtonWidth();
|
m.rm = (tw->IsZoomable() ? 3 : 1) * GetWin32TitleBarButtonWidth();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
is_custom_titlebar__ = [](const TopWindow *win) {
|
||||||
|
return win->IsCustomTitleBar__();
|
||||||
|
};
|
||||||
|
|
||||||
|
custom_titlebar_make__ = [=](TopWindow *win, Color bk, int mincy) -> Ctrl * {
|
||||||
|
return win->MakeCustomTitleBar__(bk, mincy);
|
||||||
|
};
|
||||||
|
|
||||||
EnterGuiMutex();
|
EnterGuiMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -465,14 +472,40 @@ void Ctrl::UseImmersiveDarkModeForWindowBorder()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Rect Ctrl::AdjustWindowRect(const Rect& client, dword style, dword exstyle)
|
||||||
|
{
|
||||||
|
Rect r = client;
|
||||||
|
TopWindow *tw = dynamic_cast<TopWindow *>(this);
|
||||||
|
if(tw && tw->custom_bar_frame) {
|
||||||
|
Rect mr(100, 100, 200, 200);
|
||||||
|
AdjustWindowRectEx(mr, style, FALSE, exstyle);
|
||||||
|
|
||||||
|
r.left -= (100 - mr.left);
|
||||||
|
r.right += (mr.right - 200);
|
||||||
|
r.bottom += (mr.bottom - 200);
|
||||||
|
|
||||||
|
r.top -= tw->GetCustomTitleBarMetrics().height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
AdjustWindowRectEx(r, style, FALSE, exstyle);
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect Ctrl::AdjustWindowRect(const Rect& client)
|
||||||
|
{
|
||||||
|
HWND hwnd = GetHWND();
|
||||||
|
return hwnd ? AdjustWindowRect(client, ::GetWindowLong(hwnd, GWL_STYLE), ::GetWindowLong(hwnd, GWL_EXSTYLE))
|
||||||
|
: client;
|
||||||
|
}
|
||||||
|
|
||||||
void Ctrl::Create(HWND parent, DWORD style, DWORD exstyle, bool savebits, int show, bool dropshadow)
|
void Ctrl::Create(HWND parent, DWORD style, DWORD exstyle, bool savebits, int show, bool dropshadow)
|
||||||
{
|
{
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
ASSERT_(IsMainThread(), "Window creation can only happen in the main thread");
|
ASSERT_(IsMainThread(), "Window creation can only happen in the main thread");
|
||||||
LLOG("Ctrl::Create(parent = " << (void *)parent << ") in " <<UPP::Name(this) << LOG_BEGIN);
|
LLOG("Ctrl::Create(parent = " << (void *)parent << ") in " <<UPP::Name(this) << LOG_BEGIN);
|
||||||
ASSERT(!IsChild() && !IsOpen());
|
ASSERT(!IsChild() && !IsOpen());
|
||||||
Rect r = GetRect();
|
Rect r = AdjustWindowRect(GetRect(), style, exstyle);
|
||||||
AdjustWindowRectEx(r, style, FALSE, exstyle);
|
|
||||||
isopen = true;
|
isopen = true;
|
||||||
Top *top = new Top;
|
Top *top = new Top;
|
||||||
SetTop(top);
|
SetTop(top);
|
||||||
|
|
@ -1093,9 +1126,7 @@ void Ctrl::WndSetPos(const Rect& rect)
|
||||||
LLOG("WndSetPos " << UPP::Name(this) << " " << rect);
|
LLOG("WndSetPos " << UPP::Name(this) << " " << rect);
|
||||||
HWND hwnd = GetHWND();
|
HWND hwnd = GetHWND();
|
||||||
if(hwnd) {
|
if(hwnd) {
|
||||||
Rect r = rect;
|
Rect r = AdjustWindowRect(rect);
|
||||||
AdjustWindowRectEx(r, ::GetWindowLong(hwnd, GWL_STYLE), FALSE,
|
|
||||||
::GetWindowLong(hwnd, GWL_EXSTYLE));
|
|
||||||
SetWindowPos(hwnd, NULL, r.left, r.top, r.Width(), r.Height(),
|
SetWindowPos(hwnd, NULL, r.left, r.top, r.Width(), r.Height(),
|
||||||
SWP_NOACTIVATE|SWP_NOZORDER);
|
SWP_NOACTIVATE|SWP_NOZORDER);
|
||||||
if(HasFocusDeep()) {
|
if(HasFocusDeep()) {
|
||||||
|
|
|
||||||
|
|
@ -54,7 +54,7 @@ void Ctrl::DoPaint(const Vector<Rect>& invalid)
|
||||||
{
|
{
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
Window xwin = GetWindow();
|
Window xwin = GetWindow();
|
||||||
if(utop && IsVisible()) {
|
if(top && IsVisible()) {
|
||||||
LTIMING("DoPaint");
|
LTIMING("DoPaint");
|
||||||
fullrefresh = false;
|
fullrefresh = false;
|
||||||
// if(GLX) return;
|
// if(GLX) return;
|
||||||
|
|
@ -647,7 +647,7 @@ void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool, bool)
|
||||||
WndShow(visible);
|
WndShow(visible);
|
||||||
if(activate && IsEnabled())
|
if(activate && IsEnabled())
|
||||||
SetFocus();
|
SetFocus();
|
||||||
if(utop) utop->owner = owner;
|
if(top) utop->owner = owner;
|
||||||
StateH(OPEN);
|
StateH(OPEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -539,6 +539,14 @@ windows decoration on the left / right side of area, [@(0.0.255) height
|
||||||
would use to draw the background of title bar area.&]
|
would use to draw the background of title bar area.&]
|
||||||
[s3; &]
|
[s3; &]
|
||||||
[s4; &]
|
[s4; &]
|
||||||
|
[s5;:Upp`:`:TopWindow`:`:IsCustomTitleBarDragArea`(Point`): [@(0.0.255) virtual
|
||||||
|
bool] [* IsCustomTitleBarDragArea](Point [*@3 p])&]
|
||||||
|
[s2;%% This method can be overriden to determine whether mouse at
|
||||||
|
[%-*@3 p] should possibly drag the window. Default implementation
|
||||||
|
allows that in mouse inactive areas and is probably fine for
|
||||||
|
most use cases.&]
|
||||||
|
[s3; &]
|
||||||
|
[s4; &]
|
||||||
[s5;:TopWindow`:`:SerializePlacement`(Stream`&`,bool`): [@(0.0.255) void]_[* SerializePla
|
[s5;:TopWindow`:`:SerializePlacement`(Stream`&`,bool`): [@(0.0.255) void]_[* SerializePla
|
||||||
cement]([_^Stream^ Stream][@(0.0.255) `&]_[*@3 s], [@(0.0.255) bool]_[*@3 reminimize]_`=_[@(0.0.255) f
|
cement]([_^Stream^ Stream][@(0.0.255) `&]_[*@3 s], [@(0.0.255) bool]_[*@3 reminimize]_`=_[@(0.0.255) f
|
||||||
alse])&]
|
alse])&]
|
||||||
|
|
|
||||||
|
|
@ -512,7 +512,8 @@ public:
|
||||||
virtual ~ToolButton();
|
virtual ~ToolButton();
|
||||||
};
|
};
|
||||||
|
|
||||||
void PaintBarArea(Draw& w, Ctrl *x, const Value& look, int bottom = Null);
|
void PaintBarArea(Draw& w, Ctrl *x, const Value& look, int bottom = Null);
|
||||||
|
Color GetBarAreaAvgColor();
|
||||||
|
|
||||||
class ToolBar : public BarCtrl {
|
class ToolBar : public BarCtrl {
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,17 @@
|
||||||
|
|
||||||
namespace Upp {
|
namespace Upp {
|
||||||
|
|
||||||
Rect DisplayPopup::screen_rect;
|
Rect DisplayPopup::screen_rect;
|
||||||
Ptr<Ctrl> DisplayPopup::ctrl;
|
Ptr<Ctrl> DisplayPopup::ctrl;
|
||||||
Rect DisplayPopup::item;
|
Ptr<DisplayPopup> DisplayPopup::owner;
|
||||||
Value DisplayPopup::value;
|
Rect DisplayPopup::item;
|
||||||
Color DisplayPopup::paper;
|
Value DisplayPopup::value;
|
||||||
Color DisplayPopup::ink;
|
Color DisplayPopup::paper;
|
||||||
dword DisplayPopup::style;
|
Color DisplayPopup::ink;
|
||||||
const Display *DisplayPopup::display;
|
dword DisplayPopup::style;
|
||||||
int DisplayPopup::margin;
|
const Display *DisplayPopup::display;
|
||||||
bool DisplayPopup::usedisplaystdsize_s;
|
int DisplayPopup::margin;
|
||||||
|
bool DisplayPopup::usedisplaystdsize_s;
|
||||||
|
|
||||||
DisplayPopup::DisplayPopup()
|
DisplayPopup::DisplayPopup()
|
||||||
{
|
{
|
||||||
|
|
@ -38,6 +39,7 @@ void DisplayPopup::PaintHook(Ctrl *tw, Draw& w, const Rect& clip)
|
||||||
r.top += (r.Height() - display->GetStdSize(value).cy) / 2;
|
r.top += (r.Height() - display->GetStdSize(value).cy) / 2;
|
||||||
display->Paint(w, r, value, ink, paper, style);
|
display->Paint(w, r, value, ink, paper, style);
|
||||||
}
|
}
|
||||||
|
w.End();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -102,15 +104,15 @@ bool DisplayPopup::StateHook(Ctrl *, int reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DisplayPopup::MouseHook(Ctrl *, bool, int, Point, int, dword)
|
bool DisplayPopup::MouseHook(Ctrl *, bool, int event, Point, int, dword)
|
||||||
{
|
{
|
||||||
Sync();
|
Sync();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayPopup::Set(Ctrl *_ctrl, const Rect& _item,
|
void DisplayPopup::Set(Ctrl *_ctrl, const Rect& _item,
|
||||||
const Value& _value, const Display *_display,
|
const Value& _value, const Display *_display,
|
||||||
Color _ink, Color _paper, dword _style, int _margin)
|
Color _ink, Color _paper, dword _style, int _margin)
|
||||||
{
|
{
|
||||||
if(!GUI_ToolTips())
|
if(!GUI_ToolTips())
|
||||||
return;
|
return;
|
||||||
|
|
@ -120,6 +122,7 @@ void DisplayPopup::Set(Ctrl *_ctrl, const Rect& _item,
|
||||||
RefreshRect();
|
RefreshRect();
|
||||||
item = _item;
|
item = _item;
|
||||||
ctrl = _ctrl;
|
ctrl = _ctrl;
|
||||||
|
owner = this;
|
||||||
value = _value;
|
value = _value;
|
||||||
display = _display;
|
display = _display;
|
||||||
ink = _ink;
|
ink = _ink;
|
||||||
|
|
@ -133,8 +136,10 @@ void DisplayPopup::Set(Ctrl *_ctrl, const Rect& _item,
|
||||||
|
|
||||||
void DisplayPopup::Cancel()
|
void DisplayPopup::Cancel()
|
||||||
{
|
{
|
||||||
screen_rect = Null;
|
if(owner == this) {
|
||||||
Sync();
|
screen_rect = Null;
|
||||||
|
Sync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DisplayPopup::IsOpen()
|
bool DisplayPopup::IsOpen()
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,16 @@
|
||||||
class DisplayPopup : public Pte<DisplayPopup> {
|
class DisplayPopup : public Pte<DisplayPopup> {
|
||||||
bool usedisplaystdsize = false;
|
bool usedisplaystdsize = false;
|
||||||
|
|
||||||
static Rect screen_rect;
|
static Rect screen_rect;
|
||||||
static Ptr<Ctrl> ctrl;
|
static Ptr<Ctrl> ctrl;
|
||||||
static Rect item;
|
static Ptr<DisplayPopup> owner;
|
||||||
static Value value;
|
static Rect item;
|
||||||
static Color paper, ink;
|
static Value value;
|
||||||
static dword style;
|
static Color paper, ink;
|
||||||
static const Display *display;
|
static dword style;
|
||||||
static int margin;
|
static const Display *display;
|
||||||
static bool usedisplaystdsize_s;
|
static int margin;
|
||||||
|
static bool usedisplaystdsize_s;
|
||||||
|
|
||||||
static bool StateHook(Ctrl *, int reason);
|
static bool StateHook(Ctrl *, int reason);
|
||||||
static bool MouseHook(Ctrl *, bool, int, Point, int, dword);
|
static bool MouseHook(Ctrl *, bool, int, Point, int, dword);
|
||||||
|
|
|
||||||
|
|
@ -280,14 +280,11 @@ void PopUpList::PopUp(Ctrl *owner, int x, int top, int bottom, int width) {
|
||||||
rt.top = top - h;
|
rt.top = top - h;
|
||||||
rt.bottom = rt.top + h;
|
rt.bottom = rt.top + h;
|
||||||
}
|
}
|
||||||
if(up) {
|
if(up)
|
||||||
popup->SetRect(Rect(rt.left, rt.bottom - 1, rt.right, rt.bottom));
|
popup->SetRect(Rect(rt.left, rt.bottom - 1, rt.right, rt.bottom));
|
||||||
popup->Add(popup->ac.TopPos(0, rt.Height()).LeftPos(0, rt.Width()));
|
else
|
||||||
}
|
|
||||||
else {
|
|
||||||
popup->SetRect(Rect(rt.left, rt.top, rt.right, rt.top + 1));
|
popup->SetRect(Rect(rt.left, rt.top, rt.right, rt.top + 1));
|
||||||
popup->Add(popup->ac.BottomPos(0, rt.Height()).LeftPos(0, rt.Width()));
|
popup->Add(popup->ac.SizePos());
|
||||||
}
|
|
||||||
if(GUI_PopUpEffect()) {
|
if(GUI_PopUpEffect()) {
|
||||||
popup->ac.CenterCursor();
|
popup->ac.CenterCursor();
|
||||||
popup->PopUp(owner, true, true, GUI_DropShadows());
|
popup->PopUp(owner, true, true, GUI_DropShadows());
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Upp {
|
namespace Upp {
|
||||||
|
|
||||||
#define LLOG(x) // LOG(x)
|
#define LLOG(x) LOG(x)
|
||||||
|
|
||||||
void Sb(Button::Style& bs, const Image& img)
|
void Sb(Button::Style& bs, const Image& img)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -132,4 +132,12 @@ void StaticBarArea::Paint(Draw& w)
|
||||||
upperframe ? Null : GetScreenRect().bottom);
|
upperframe ? Null : GetScreenRect().bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Color GetBarAreaAvgColor()
|
||||||
|
{
|
||||||
|
Size sz(8, 8);
|
||||||
|
ImageDraw w(sz);
|
||||||
|
ChPaint(w, sz, Nvl(ToolBar().StyleDefault().arealook, ToolBar().StyleDefault().look));
|
||||||
|
return AvgColor(w);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -389,7 +389,6 @@ public:
|
||||||
virtual void Activate();
|
virtual void Activate();
|
||||||
virtual void Layout();
|
virtual void Layout();
|
||||||
virtual void Skin();
|
virtual void Skin();
|
||||||
virtual bool IsCustomTitleBarDragArea(Point p);
|
|
||||||
|
|
||||||
virtual bool IsVerbose() const;
|
virtual bool IsVerbose() const;
|
||||||
virtual void PutConsole(const char *s);
|
virtual void PutConsole(const char *s);
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,15 @@ void Ide::Skin()
|
||||||
SyncUsc();
|
SyncUsc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ide::ToggleVerboseBuild() {
|
void Ide::ToggleVerboseBuild()
|
||||||
|
{
|
||||||
console.verbosebuild = !console.verbosebuild;
|
console.verbosebuild = !console.verbosebuild;
|
||||||
|
|
||||||
SetToolBar();
|
SetToolBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Ide::ToggleStopOnErrors() {
|
void Ide::ToggleStopOnErrors()
|
||||||
|
{
|
||||||
stoponerrors = !stoponerrors;
|
stoponerrors = !stoponerrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -306,18 +308,25 @@ void Ide::SetupBars()
|
||||||
menubar.Transparent();
|
menubar.Transparent();
|
||||||
display.IgnoreMouse();
|
display.IgnoreMouse();
|
||||||
bararea.Add(barrect.SizePos());
|
bararea.Add(barrect.SizePos());
|
||||||
AddFrame(bararea);
|
Ctrl *custom_bar = nullptr;
|
||||||
|
if(!disable_custom_caption)
|
||||||
|
custom_bar = CustomTitleBar(GetBarAreaAvgColor());
|
||||||
|
if(custom_bar)
|
||||||
|
*custom_bar << bararea.SizePos();
|
||||||
|
else
|
||||||
|
AddFrame(bararea);
|
||||||
|
menubar.LeftPos(0, l).VCenterPos(menubar.GetStdHeight());
|
||||||
if(toolbar_in_row) {
|
if(toolbar_in_row) {
|
||||||
toolbar.SetFrame(NullFrame());
|
toolbar.SetFrame(NullFrame());
|
||||||
int tcy = max(mainconfiglist.GetStdSize().cy + DPI(2), toolbar.GetStdHeight());
|
int tcy = max(mainconfiglist.GetStdSize().cy + DPI(2), toolbar.GetStdHeight());
|
||||||
barrect.Add(menubar.LeftPos(0, l).VCenterPos(menubar.GetStdHeight()));
|
barrect.Add(menubar);
|
||||||
barrect.Add(toolbar.HSizePos(l, r).VCenterPos(tcy));
|
barrect.Add(toolbar.HSizePos(l, r).VCenterPos(tcy));
|
||||||
barrect.Add(display.RightPos(4, r).VSizePos(2, 3));
|
barrect.Add(display.RightPos(4, r).VSizePos(2, 3));
|
||||||
bararea.Height(max(menubar.GetStdHeight(), tcy));
|
bararea.Height(max(menubar.GetStdHeight(), tcy));
|
||||||
toolbar.Transparent();
|
toolbar.Transparent();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
barrect.Add(menubar.LeftPos(0, l).VCenterPos(menubar.GetStdHeight()));
|
barrect.Add(menubar);
|
||||||
barrect.Add(display.RightPos(4, r).VSizePos(2, 3));
|
barrect.Add(display.RightPos(4, r).VSizePos(2, 3));
|
||||||
bararea.Height(menubar.GetStdHeight());
|
bararea.Height(menubar.GetStdHeight());
|
||||||
AddFrame(TopSeparatorFrame());
|
AddFrame(TopSeparatorFrame());
|
||||||
|
|
@ -345,14 +354,13 @@ void Ide::Layout()
|
||||||
int tcy = max(mainconfiglist.GetStdSize().cy + DPI(2), toolbar.GetStdHeight());
|
int tcy = max(mainconfiglist.GetStdSize().cy + DPI(2), toolbar.GetStdHeight());
|
||||||
|
|
||||||
auto cm = GetCustomTitleBarMetrics();
|
auto cm = GetCustomTitleBarMetrics();
|
||||||
barrect.HSizePos(cm.lm, cm.rm);
|
|
||||||
|
|
||||||
int x = 0;
|
int x = 0;
|
||||||
|
|
||||||
int mh = menubar.GetStdHeight();
|
int mh = menubar.GetStdHeight();
|
||||||
menubar.LeftPos(0, mw).TopPos((cm.height - mh) / 2, mh);
|
menubar.LeftPos(0, mw).TopPos((cm.height - mh) / 2, mh);
|
||||||
x += mw;
|
x += mw;
|
||||||
|
|
||||||
if(toolbar_in_row) {
|
if(toolbar_in_row) {
|
||||||
int tw = toolbar.GetWidth();
|
int tw = toolbar.GetWidth();
|
||||||
int bah = 0;
|
int bah = 0;
|
||||||
|
|
@ -382,12 +390,6 @@ void Ide::Layout()
|
||||||
display.Show(!designer && (menubar.GetSize().cx + display.GetSize().cx < GetSize().cx));
|
display.Show(!designer && (menubar.GetSize().cx + display.GetSize().cx < GetSize().cx));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Ide::IsCustomTitleBarDragArea(Point p)
|
|
||||||
{
|
|
||||||
p += GetScreenRect().TopLeft();
|
|
||||||
return !menubar.GetScreenRect().Contains(p) && !toolbar.GetScreenRect().Contains(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Ide::DoDisplay()
|
void Ide::DoDisplay()
|
||||||
{
|
{
|
||||||
if(replace_in_files)
|
if(replace_in_files)
|
||||||
|
|
@ -400,7 +402,11 @@ void Ide::DoDisplay()
|
||||||
s << "[g [";
|
s << "[g [";
|
||||||
if(editfile_isreadonly)
|
if(editfile_isreadonly)
|
||||||
s << "@B";
|
s << "@B";
|
||||||
s << " \1" << editfile << "\1]";
|
int q = max(editfile.ReverseFind('/'), editfile.ReverseFind('\\'));
|
||||||
|
if(q >= 0)
|
||||||
|
s << " [1 \1" << editfile.Mid(0, q + 1) << "\1]\1" << editfile.Mid(q + 1) << "\1]";
|
||||||
|
else
|
||||||
|
s << " \1" << editfile << "\1]";
|
||||||
if(!designer) {
|
if(!designer) {
|
||||||
s << ": [* " << p.y + 1 << "]:" << p.x + 1;
|
s << ": [* " << p.y + 1 << "]:" << p.x + 1;
|
||||||
int64 l, h;
|
int64 l, h;
|
||||||
|
|
|
||||||
|
|
@ -408,9 +408,6 @@ void AppMain___()
|
||||||
Ctrl::SetAlwaysUseBundledIcon();
|
Ctrl::SetAlwaysUseBundledIcon();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!ide.disable_custom_caption)
|
|
||||||
ide.CustomTitleBar();
|
|
||||||
|
|
||||||
if(arg.GetCount() == 1) {
|
if(arg.GetCount() == 1) {
|
||||||
if(arg[0].EndsWith(".upp")) {
|
if(arg[0].EndsWith(".upp")) {
|
||||||
Vector<String> names = Split(arg[0], DIR_SEP);
|
Vector<String> names = Split(arg[0], DIR_SEP);
|
||||||
|
|
|
||||||
12
upptst/CustomTitleBar2/CustomTitleBar2.upp
Normal file
12
upptst/CustomTitleBar2/CustomTitleBar2.upp
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
uses
|
||||||
|
CtrlLib;
|
||||||
|
|
||||||
|
file
|
||||||
|
main.cpp;
|
||||||
|
|
||||||
|
mainconfig
|
||||||
|
"" = "GUI",
|
||||||
|
"" = "GUI FORCE_CSD",
|
||||||
|
"" = "GUI FORCE_CSD NOCUSTOMBAR",
|
||||||
|
"" = "GUI WAYLAND";
|
||||||
|
|
||||||
112
upptst/CustomTitleBar2/main.cpp
Normal file
112
upptst/CustomTitleBar2/main.cpp
Normal file
|
|
@ -0,0 +1,112 @@
|
||||||
|
#include <CtrlLib/CtrlLib.h>
|
||||||
|
|
||||||
|
using namespace Upp;
|
||||||
|
|
||||||
|
struct TestRect : Ctrl {
|
||||||
|
void Paint(Draw& w) override {
|
||||||
|
Size sz = GetSize();
|
||||||
|
return;
|
||||||
|
w.DrawRect(sz, Yellow());
|
||||||
|
DrawFatFrame(w, sz, LtGreen(), 8);
|
||||||
|
DrawFatFrame(w, sz, Red(), 2);
|
||||||
|
for(int i = 0; i < 100; i++)
|
||||||
|
w.DrawText(i * 100, 2, AsString(i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MyApp : TopWindow {
|
||||||
|
FrameTop<StaticRect> bararea; // we represent whole TitleBar area as frame
|
||||||
|
ParentCtrl barrect; // to do custom caption clipping
|
||||||
|
MenuBar menubar, menu2;
|
||||||
|
LineEdit editor;
|
||||||
|
Label title;
|
||||||
|
Label label;
|
||||||
|
TestRect rect;
|
||||||
|
Button button, button2;
|
||||||
|
bool zooming = true;
|
||||||
|
WithDropChoice<EditString> ed;
|
||||||
|
|
||||||
|
void MainMenu(Bar& bar)
|
||||||
|
{
|
||||||
|
bar.Sub("File", [=](Bar& bar) {
|
||||||
|
bar.Add("Zooming", [=] {
|
||||||
|
zooming = !zooming;
|
||||||
|
Zoomable(zooming);
|
||||||
|
});
|
||||||
|
bar.Add("Yellow", [=] { CustomTitleBar(Yellow()); });
|
||||||
|
bar.Add("Cyan", [=] { CustomTitleBar(Cyan()); });
|
||||||
|
bar.Add("LtCyan", [=] { CustomTitleBar(LtCyan()); });
|
||||||
|
bar.Add("Blue", [=] { CustomTitleBar(Blue()); });
|
||||||
|
bar.Add("Gray", [=] { CustomTitleBar(Gray()); });
|
||||||
|
bar.Separator();
|
||||||
|
bar.Add("GTK dialog", [=] {
|
||||||
|
FileSelNative sel;
|
||||||
|
sel.ActiveDir(GetHomeDirectory());
|
||||||
|
sel.ExecuteSelectDir("Just a test");
|
||||||
|
});
|
||||||
|
bar.Add("U++ dialog", [=] {
|
||||||
|
SelectFileOpen("Text files\t*.txt\nAll files\t*.*");
|
||||||
|
});
|
||||||
|
bar.Separator();
|
||||||
|
|
||||||
|
bar.Add("Exit", [=] { Break(); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetMenuBar() {
|
||||||
|
menubar.Set([=](Bar& bar) {
|
||||||
|
MainMenu(bar);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Layout() override
|
||||||
|
{
|
||||||
|
String s = IsMinimized() ? "Minimized" : IsMaximized() ? "Maximized" : "Overlapped";
|
||||||
|
Title(s);
|
||||||
|
// LOG("Layout " << s << ", rect: " << GetScreenRect() << ", mousepos: " << GetMousePos());
|
||||||
|
}
|
||||||
|
|
||||||
|
MyApp() {
|
||||||
|
Sizeable().Zoomable();
|
||||||
|
Icon(CtrlImg::new_doc());
|
||||||
|
AddFrame(menubar);
|
||||||
|
SetMenuBar();
|
||||||
|
Title("This is CustomTitleBar example - CustomTitleBar not active");
|
||||||
|
Add(editor.SizePos());
|
||||||
|
|
||||||
|
Ctrl *tb = CustomTitleBar(LtCyan(), GetStdFontCy() + DPI(4));
|
||||||
|
if(tb) {
|
||||||
|
// *tb << label.SizePos();
|
||||||
|
*tb << rect.SizePos();
|
||||||
|
rect.IgnoreMouse();
|
||||||
|
rect.SetFrame(BlackFrame());
|
||||||
|
rect << label.SizePos();
|
||||||
|
label.SetLabel("\1[g= This is test");
|
||||||
|
button.SetLabel("Close");
|
||||||
|
*tb << button.RightPos(DPI(2), DPI(100)).VSizePos(2, 2);
|
||||||
|
button << [=] {
|
||||||
|
Break();
|
||||||
|
};
|
||||||
|
*tb << ed.RightPos(DPI(110), DPI(100)).VSizePos(2, 2);
|
||||||
|
button2.SetLabel("RefreshF");
|
||||||
|
*tb << button2.RightPos(DPI(222), DPI(100)).VSizePos(2, 2);
|
||||||
|
button2 << [=] {
|
||||||
|
RefreshFrame();
|
||||||
|
};
|
||||||
|
for(int i = 0; i < 200; i++)
|
||||||
|
ed.AddList(AsString(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
String txt;
|
||||||
|
for(int i = 0; i < 200; i++)
|
||||||
|
txt << i << '\n';
|
||||||
|
editor <<= txt;
|
||||||
|
|
||||||
|
DDUMP(rect.IsIgnoreMouse());
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
GUI_APP_MAIN
|
||||||
|
{
|
||||||
|
MyApp().Run();
|
||||||
|
}
|
||||||
|
|
@ -1,55 +0,0 @@
|
||||||
#include <CtrlLib/CtrlLib.h>
|
|
||||||
|
|
||||||
using namespace Upp;
|
|
||||||
|
|
||||||
struct MyApp : TopWindow {
|
|
||||||
void Paint(Draw& w) override {
|
|
||||||
Size sz = GetSize();
|
|
||||||
// w.DrawRect(sz, WhiteGray()); return;
|
|
||||||
|
|
||||||
auto h = GetCustomTitleBarMetrics().height;
|
|
||||||
Color c2 = SLtCyan();
|
|
||||||
for(int i = 0; i < h; i++)
|
|
||||||
w.DrawRect(0, i, sz.cx, 1, Blend(WhiteGray(), c2, i * 255 / h));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Layout() override {
|
|
||||||
auto m = GetCustomTitleBarMetrics();
|
|
||||||
int h = bar.GetHeight();
|
|
||||||
bar.LeftPos(m.lm, bar.GetWidth()).TopPos((m.height - h) / 2, h);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainMenu(Bar& bar)
|
|
||||||
{
|
|
||||||
bar.Sub("File", [=](Bar& bar) {
|
|
||||||
bar.Add("Exit", [=] { Break(); });
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
MenuBar bar;
|
|
||||||
LineEdit editor;
|
|
||||||
|
|
||||||
MyApp() {
|
|
||||||
Icon(CtrlImg::select_all());
|
|
||||||
|
|
||||||
CustomTitleBar(200);
|
|
||||||
|
|
||||||
Add(bar);
|
|
||||||
bar.Transparent();
|
|
||||||
bar.Set([=](Bar& bar) {
|
|
||||||
MainMenu(bar);
|
|
||||||
});
|
|
||||||
|
|
||||||
DDUMP(bar.GetWidth());
|
|
||||||
DDUMP(bar.GetHeight());
|
|
||||||
|
|
||||||
DDUMP(GetCustomTitleBarMetrics().height);
|
|
||||||
|
|
||||||
Add(editor.VSizePos(GetCustomTitleBarMetrics().height).HSizePos());
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
GUI_APP_MAIN
|
|
||||||
{
|
|
||||||
MyApp().Sizeable().Zoomable().Run();
|
|
||||||
}
|
|
||||||
53
upptst/CustomTitlebar1/main.cpp
Normal file
53
upptst/CustomTitlebar1/main.cpp
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
#include <CtrlLib/CtrlLib.h>
|
||||||
|
|
||||||
|
using namespace Upp;
|
||||||
|
|
||||||
|
struct MyApp : TopWindow {
|
||||||
|
MenuBar bar;
|
||||||
|
LineEdit editor;
|
||||||
|
Label title;
|
||||||
|
|
||||||
|
void Layout() override {
|
||||||
|
if(IsCustomTitleBar()) {
|
||||||
|
int ch = GetCustomTitleBarMetrics().height;
|
||||||
|
int h = bar.GetHeight();
|
||||||
|
int w = bar.GetWidth();
|
||||||
|
bar.LeftPos(0, w).TopPos((ch - h) / 2, h);
|
||||||
|
|
||||||
|
title.HSizePos(w, 0).VSizePos();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MyApp() {
|
||||||
|
Sizeable().Zoomable();
|
||||||
|
|
||||||
|
Icon(CtrlImg::select_all());
|
||||||
|
|
||||||
|
Ctrl *tb = CustomTitleBar(Blend(SWhiteGray(), SLtMagenta(), 50), 50);
|
||||||
|
|
||||||
|
if(tb) {
|
||||||
|
tb->Add(bar);
|
||||||
|
tb->Add(title);
|
||||||
|
bar.Transparent();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
AddFrame(bar);
|
||||||
|
bar.Set([=](Bar& bar) {
|
||||||
|
bar.Sub("File", [=](Bar& bar) {
|
||||||
|
bar.Add("Yellow", [=] { CustomTitleBar(Yellow(), 20); });
|
||||||
|
bar.Add("Red", [=] { CustomTitleBar(LtRed(), 20); });
|
||||||
|
bar.Add("Exit", [=] { Break(); });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
title = "\1[g This is [* title";
|
||||||
|
title.AlignCenter();
|
||||||
|
|
||||||
|
Add(editor.SizePos());
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
GUI_APP_MAIN
|
||||||
|
{
|
||||||
|
MyApp().Sizeable().Zoomable().Run();
|
||||||
|
}
|
||||||
12
upptst/GUI/GUI.upp
Normal file
12
upptst/GUI/GUI.upp
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
uses
|
||||||
|
CtrlLib;
|
||||||
|
|
||||||
|
file
|
||||||
|
main.cpp;
|
||||||
|
|
||||||
|
mainconfig
|
||||||
|
"" = "GUI",
|
||||||
|
"" = "GUI FORCE_CSD",
|
||||||
|
"" = "GUI FORCE_CSD NOCUSTOMBAR",
|
||||||
|
"" = "GUI WAYLAND";
|
||||||
|
|
||||||
100
upptst/GUI/main.cpp
Normal file
100
upptst/GUI/main.cpp
Normal file
|
|
@ -0,0 +1,100 @@
|
||||||
|
#include <CtrlLib/CtrlLib.h>
|
||||||
|
|
||||||
|
using namespace Upp;
|
||||||
|
|
||||||
|
struct TestRect : Ctrl {
|
||||||
|
void Paint(Draw& w) override {
|
||||||
|
Size sz = GetSize();
|
||||||
|
return;
|
||||||
|
w.DrawRect(sz, Yellow());
|
||||||
|
DrawFatFrame(w, sz, LtGreen(), 8);
|
||||||
|
DrawFatFrame(w, sz, Red(), 2);
|
||||||
|
for(int i = 0; i < 100; i++)
|
||||||
|
w.DrawText(i * 100, 2, AsString(i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MyApp : TopWindow {
|
||||||
|
FrameTop<StaticRect> bararea; // we represent whole TitleBar area as frame
|
||||||
|
ParentCtrl barrect; // to do custom caption clipping
|
||||||
|
MenuBar menubar, menu2;
|
||||||
|
LineEdit editor;
|
||||||
|
Label title;
|
||||||
|
Label label;
|
||||||
|
TestRect rect;
|
||||||
|
Button button;
|
||||||
|
bool zooming = true;
|
||||||
|
WithDropChoice<EditString> ed;
|
||||||
|
|
||||||
|
void MainMenu(Bar& bar)
|
||||||
|
{
|
||||||
|
bar.Sub("File", [=](Bar& bar) {
|
||||||
|
bar.Add("Zooming", [=] {
|
||||||
|
zooming = !zooming;
|
||||||
|
Zoomable(zooming);
|
||||||
|
});
|
||||||
|
bar.Add("Yellow", [=] { CustomTitleBar(Yellow()); });
|
||||||
|
bar.Add("Cyan", [=] { CustomTitleBar(Cyan()); });
|
||||||
|
bar.Add("LtCyan", [=] { CustomTitleBar(LtCyan()); });
|
||||||
|
bar.Add("Blue", [=] { CustomTitleBar(Blue()); });
|
||||||
|
bar.Add("Gray", [=] { CustomTitleBar(Gray()); });
|
||||||
|
bar.Separator();
|
||||||
|
bar.Add("Exit", [=] { Break(); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetMenuBar() {
|
||||||
|
menubar.Set([=](Bar& bar) {
|
||||||
|
MainMenu(bar);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCustomTitleBarDragArea(Point p) override
|
||||||
|
{ // identifies which titlebar areas can be clicked for dragging the window
|
||||||
|
p += GetScreenRect().TopLeft();
|
||||||
|
return !menubar.GetScreenRect().Contains(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void Layout() override
|
||||||
|
{
|
||||||
|
String s = IsMinimized() ? "Minimized" : IsMaximized() ? "Maximized" : "Overlapped";
|
||||||
|
Title(s);
|
||||||
|
DLOG("Layout " << s << ", rect: " << GetScreenRect() << ", mousepos: " << GetMousePos());
|
||||||
|
}
|
||||||
|
|
||||||
|
MyApp() {
|
||||||
|
Sizeable().Zoomable();
|
||||||
|
Icon(CtrlImg::new_doc());
|
||||||
|
AddFrame(menubar);
|
||||||
|
SetMenuBar();
|
||||||
|
Title("This is CustomTitleBar example - CustomTitleBar not active");
|
||||||
|
Add(editor.SizePos());
|
||||||
|
|
||||||
|
Ctrl *tb = CustomTitleBar(LtCyan(), GetStdFontCy() + DPI(4));
|
||||||
|
if(tb) {
|
||||||
|
// *tb << label.SizePos();
|
||||||
|
*tb << rect.SizePos();
|
||||||
|
rect.SetFrame(BlackFrame());
|
||||||
|
rect << label.SizePos();
|
||||||
|
label.SetLabel("\1[g= This is test");
|
||||||
|
button.SetLabel("Close");
|
||||||
|
rect << button.RightPos(DPI(2), DPI(100)).VSizePos(2, 2);
|
||||||
|
button << [=] {
|
||||||
|
Break();
|
||||||
|
};
|
||||||
|
rect << ed.RightPos(DPI(110), DPI(100)).VSizePos(2, 2);
|
||||||
|
for(int i = 0; i < 200; i++)
|
||||||
|
ed.AddList(AsString(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
String txt;
|
||||||
|
for(int i = 0; i < 200; i++)
|
||||||
|
txt << i << '\n';
|
||||||
|
editor <<= txt;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
GUI_APP_MAIN
|
||||||
|
{
|
||||||
|
MyApp().Run();
|
||||||
|
}
|
||||||
10
upptst/MinMaxSize/MinMaxSize.upp
Normal file
10
upptst/MinMaxSize/MinMaxSize.upp
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
uses
|
||||||
|
CtrlLib;
|
||||||
|
|
||||||
|
file
|
||||||
|
main.cpp;
|
||||||
|
|
||||||
|
mainconfig
|
||||||
|
"" = "GUI",
|
||||||
|
"" = "GUI FORCE_CSD";
|
||||||
|
|
||||||
92
upptst/MinMaxSize/main.cpp
Normal file
92
upptst/MinMaxSize/main.cpp
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
#include <CtrlLib/CtrlLib.h>
|
||||||
|
|
||||||
|
using namespace Upp;
|
||||||
|
|
||||||
|
struct App : public TopWindow
|
||||||
|
{
|
||||||
|
DropList dl;
|
||||||
|
Button move;
|
||||||
|
|
||||||
|
void Paint(Draw& w) override {
|
||||||
|
w.DrawRect(GetSize(), LtCyan());
|
||||||
|
DrawFrame(w, 0, 0, 500, 500, Black());
|
||||||
|
DrawFrame(w, 0, 0, 400, 400, Black());
|
||||||
|
DrawFrame(w, 0, 0, 600, 600, Black());
|
||||||
|
w.DrawText(10, 10, AsString(GetScreenView()));
|
||||||
|
w.DrawText(10, 50, AsString(GetScreenRect()));
|
||||||
|
w.DrawText(10, 90, AsString(GetRect()));
|
||||||
|
w.DrawText(10, 130, AsString(GetMousePos()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseMove(Point p, dword keyflags) override {
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Layout() override {
|
||||||
|
Refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
Size GetMinSize() const override {
|
||||||
|
return Size(400, 400);
|
||||||
|
}
|
||||||
|
|
||||||
|
Size GetMaxSize() const override {
|
||||||
|
return Size(600, 600);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef App CLASSNAME;
|
||||||
|
|
||||||
|
App()
|
||||||
|
{
|
||||||
|
SetRect(100, 200, 500, 500);
|
||||||
|
Sizeable().Zoomable();
|
||||||
|
|
||||||
|
Add(dl.LeftPos(10, 101).BottomPos(0));
|
||||||
|
for(int i = 0; i < 20; i++)
|
||||||
|
dl.Add(i);
|
||||||
|
|
||||||
|
Add(move.HSizePos(120, 0).BottomPosZ(0, 24));
|
||||||
|
move.SetLabel("Move to 320, 420, 400");
|
||||||
|
move << [=] {
|
||||||
|
DLOG("================ MOVE");
|
||||||
|
SetRect(320, 420, 400, 400);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct App2 : App {
|
||||||
|
Label title;
|
||||||
|
|
||||||
|
App2(int h = GetStdFontCy() + DPI(4)) {
|
||||||
|
SetRect(700, 200, 500, 500);
|
||||||
|
Ctrl *tb = CustomTitleBar(SYellow(), h);
|
||||||
|
if(tb)
|
||||||
|
*tb << title.SizePos();
|
||||||
|
|
||||||
|
title = "\1[g= [* custom [/_ titlebar";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
GUI_APP_MAIN
|
||||||
|
{
|
||||||
|
App app, app_csd;
|
||||||
|
App2 app2, app3(DPI(128));
|
||||||
|
|
||||||
|
app.Title("SSD");
|
||||||
|
app.OpenMain();
|
||||||
|
|
||||||
|
#ifdef PLATFORM_POSIX
|
||||||
|
app_csd.Title("CSD");
|
||||||
|
app_csd.Force_csd_();
|
||||||
|
app_csd.SetRect(1300, 200, 500, 500);
|
||||||
|
app_csd.OpenMain();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
app2.OpenMain();
|
||||||
|
|
||||||
|
app3.SetRect(1900, 200, 500, 500);
|
||||||
|
app3.OpenMain();
|
||||||
|
|
||||||
|
app.Run();
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue