CtrlCore: Developing Cocoa support

git-svn-id: svn://ultimatepp.org/upp/trunk@12096 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2018-07-24 14:57:38 +00:00
parent 7d17920252
commit c784c30d5c
15 changed files with 284 additions and 139 deletions

View file

@ -2,12 +2,36 @@
#ifdef GUI_COCO
#define LLOG(x)
#define LLOG(x) DLOG(x)
NSAutoreleasePool *main_coco_pool;
int Upp::Ctrl::WndCaretTime;
bool Upp::Ctrl::WndCaretVisible;
static NSAutoreleasePool *main_coco_pool;
static NSEvent *current_event;
static NSEvent *GetNextEvent(NSDate *until)
{
if(!current_event) {
current_event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:until
inMode:NSDefaultRunLoopMode dequeue:YES];
[current_event retain];
}
return current_event;
}
void ReleaseCurrentEvent()
{
if(current_event) {
[current_event release];
current_event = nil;
}
}
void Upp::CocoInit(int argc, const char **argv, const char **envptr)
{
Ctrl::GlobalBackBuffer();
main_coco_pool = [NSAutoreleasePool new];
[NSApplication sharedApplication];
@ -28,16 +52,13 @@ void Upp::CocoInit(int argc, const char **argv, const char **envptr)
void Upp::CocoExit()
{
ReleaseCurrentEvent();
[main_coco_pool release];
}
bool Upp::Ctrl::IsWaitingEvent()
{
Upp::AutoreleasePool __;
bool b = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:[NSDate date]
inMode:NSDefaultRunLoopMode dequeue:NO];
return b;
return GetNextEvent(nil);
}
bool Upp::Ctrl::ProcessEvent(bool *)
@ -50,12 +71,12 @@ bool Upp::Ctrl::ProcessEvent(bool *)
[NSApp finishLaunching];
}
NSEvent *event = [NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:[NSDate distantFuture]
inMode:NSDefaultRunLoopMode
dequeue:YES];
NSEvent *event = GetNextEvent(nil);
if(!event)
return false;
[NSApp sendEvent:event];
ReleaseCurrentEvent();
return true;
}
@ -67,6 +88,7 @@ bool Upp::Ctrl::ProcessEvents(bool *quit)
if(ProcessEvent(quit)) {
while(ProcessEvent(quit) && (!LoopCtrl || LoopCtrl->InLoop())); // LoopCtrl-MF 071008
TimerProc(GetTickCount());
AnimateCaret();
[NSApp updateWindows];
SweepMkImageCache();
return true;
@ -83,7 +105,7 @@ void Upp::Ctrl::EventLoop(Ctrl *ctrl)
ASSERT(IsMainThread());
ASSERT(LoopLevel == 0 || ctrl);
LoopLevel++;
LLOG("Entering event loop at level " << LoopLevel << BeginIndent);
LLOG("Entering event loop at level " << LoopLevel);
Ptr<Ctrl> ploop;
if(ctrl) {
ploop = LoopCtrl;
@ -97,7 +119,9 @@ void Upp::Ctrl::EventLoop(Ctrl *ctrl)
{
// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / GuiSleep");
SyncCaret();
GuiSleep(1000);
AnimateCaret();
GuiSleep(20);
DDUMP(GetTickCount());
// if(EndSession()) break;
// LLOG(GetSysTime() << " % " << (unsigned)msecs() % 10000 << ": EventLoop / ProcessEvents");
ProcessEvents(&quit);
@ -107,17 +131,101 @@ void Upp::Ctrl::EventLoop(Ctrl *ctrl)
if(ctrl)
LoopCtrl = ploop;
LoopLevel--;
LLOG(EndIndent << "Leaving event loop ");
LLOG("Leaving event loop ");
}
void Upp::Ctrl::GuiSleep(int ms)
{
ASSERT(IsMainThread());
GetNextEvent([NSDate dateWithTimeIntervalSinceNow:ms / 1000.0]);
}
void Upp::Ctrl::AnimateCaret()
{
GuiLock __;
Upp::AutoreleasePool ___;
[NSApp nextEventMatchingMask:NSEventMaskAny
untilDate:[NSDate dateWithTimeIntervalSinceNow:ms / 1000.0]
inMode:NSDefaultRunLoopMode dequeue:NO];
int v = !(((GetTickCount() - WndCaretTime) / 500) & 1);
if(v != WndCaretVisible) {
DDUMP(WndCaretVisible);
WndCaretVisible = v;
RefreshCaret();
}
}
void Upp::Ctrl::PaintCaret(SystemDraw& w)
{
GuiLock __;
LLOG("PaintCaret " << Name() << ", caretCtrl: " << caretCtrl << ", WndCaretVisible: " << WndCaretVisible);
if(this == caretCtrl && WndCaretVisible)
w.DrawRect(caretx, carety, caretcx, caretcy, InvertColor);
}
void Upp::Ctrl::SetCaret(int x, int y, int cx, int cy)
{
GuiLock __;
LLOG("SetCaret " << Name());
if(this == caretCtrl)
RefreshCaret();
caretx = x;
carety = y;
caretcx = cx;
caretcy = cy;
if(this == caretCtrl) {
WndCaretTime = GetTickCount();
RefreshCaret();
AnimateCaret();
}
}
void Upp::Ctrl::SyncCaret() {
GuiLock __;
LLOG("SyncCaret");
if(focusCtrl != caretCtrl) {
LLOG("SyncCaret DO " << Upp::Name(caretCtrl) << " -> " << Upp::Name(focusCtrl));
RefreshCaret();
caretCtrl = focusCtrl;
RefreshCaret();
}
}
Upp::Rect Upp::Ctrl::GetWorkArea() const
{
return GetPrimaryWorkArea();
}
void Upp::Ctrl::GetWorkArea(Array<Rect>& rc)
{
GuiLock __;
rc.Add(GetPrimaryWorkArea());
}
Upp::Rect Upp::Ctrl::GetVirtualWorkArea()
{
return GetPrimaryWorkArea();
}
Upp::Rect Upp::Ctrl::GetVirtualScreenArea()
{
return GetPrimaryWorkArea();
}
Upp::Rect Upp::Ctrl::GetPrimaryWorkArea()
{
for (NSScreen *screen in [NSScreen screens]) {
Rect f = MakeRect([screen frame]);
Rect v = MakeRect([screen visibleFrame], f.GetHeight());
// double scale = [screen backingScaleFactor];
return v;
}
return Rect(0, 0, 1024, 768);
}
Upp::Rect Upp::Ctrl::GetPrimaryScreenArea()
{
for (NSScreen *screen in [NSScreen screens]) {
Rect f = MakeRect([screen frame]);
return f;
}
return Rect(0, 0, 1024, 768);
}
#endif

View file

@ -18,25 +18,19 @@
void Upp::MMCtrl::SyncRect(CocoView *view)
{
NSWindow *win = [view window];
view->ctrl->SetWndRect(MakeRect([win contentRectForFrameRect: [win frame]]));
view->ctrl->SetWndRect(MakeRect([win contentRectForFrameRect: [win frame]], 1000));
}
void Upp::Ctrl::Create(const Upp::Rect& r, const char *title, bool popup)
void Upp::Ctrl::Create(dword style)
{
NSRect frame = NSMakeRect(r.left, r.top, r.GetWidth(), r.GetHeight());
Upp::dword style = popup ? NSWindowStyleMaskBorderless :
NSWindowStyleMaskTitled | NSWindowStyleMaskClosable
| NSWindowStyleMaskMiniaturizable
| NSWindowStyleMaskResizable;
Rect r = GetRect();
NSRect frame = NSMakeRect(r.left, GetPrimaryScreenArea().GetHeight() - r.top - r.GetHeight(),
r.GetWidth(), r.GetHeight());
NSWindow *window = [[CocoWindow alloc] initWithContentRect:frame styleMask: style
backing:NSBackingStoreBuffered defer:false];
// TODO: Move title
CFRef<CFStringRef> s = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8);
[window setTitle:(NSString *)~s];
window.backgroundColor = nil;
CocoView *view = [[[CocoView alloc] initWithFrame:frame] autorelease];
@ -69,9 +63,9 @@ void Upp::Ctrl::WndDestroy()
void Upp::Ctrl::WndInvalidateRect(const Rect& r)
{
GuiLock __;
DLOG("InvalidateRect " << r);
[top->coco->view setNeedsDisplay:YES];
// - (BOOL)needsToDrawRect:(NSRect)rect;
[top->coco->view
setNeedsDisplayInRect:(NSRect)CGRectMake(r.left, GetRect().GetHeight() - r.top - r.GetHeight(),
r.GetWidth(), r.GetHeight())];
}
bool Upp::Ctrl::IsWndOpen() const {
@ -79,4 +73,93 @@ bool Upp::Ctrl::IsWndOpen() const {
return top;
}
void Upp::Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, bool topmost)
{
Create(NSWindowStyleMaskBorderless);
}
Upp::dword Upp::TopWindow::GetMMStyle() const
{
Upp::dword style = NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskResizable;
if(minimizebox)
style |= NSWindowStyleMaskMiniaturizable;
// if(maximizebox)
// style |= ;
return style;
}
void Upp::TopWindow::Open(Ctrl *owner_)
{
GuiLock __;
owner = owner_;
SetupRect(owner);
if((owner && center == 1) || center == 2)
SetRect((center == 1 ? owner->GetRect() : owner ? owner->GetWorkArea()
: GetPrimaryWorkArea())
.CenterRect(GetRect().GetSize()));
Create(GetMMStyle());
SyncCaption();
SyncSizeHints();
}
void Upp::TopWindow::Open()
{
Open(NULL);
}
void Upp::TopWindow::OpenMain()
{
Open(NULL);
}
void Upp::TopWindow::SyncTitle()
{
GuiLock __;
if(top) {
DLOG("SyncTitle " << title);
CFRef<CFStringRef> s = CFStringCreateWithCString(NULL, (const char *)~title.ToString(), kCFStringEncodingUTF8);
[top->coco->window setTitle:(NSString *)~s];
}
}
void Upp::TopWindow::SyncCaption()
{
GuiLock __;
if(top) {
SyncTitle();
NSWindow *window = top->coco->window;
[[window standardWindowButton:NSWindowMiniaturizeButton] setHidden:!minimizebox];
[[window standardWindowButton:NSWindowZoomButton] setHidden:!maximizebox];
}
}
CGRect MMFrameRect(const Upp::Rect& r, Upp::dword style)
{// TODO: Revert Y
return [NSWindow frameRectForContentRect:(NSRect)MakeCGRect(r, 1000) styleMask:style];
}
CGSize MMFrameSize(Upp::Size sz, Upp::dword style)
{
return MMFrameRect(Upp::RectC(100, 100, sz.cx, sz.cy), style).size;
}
void Upp::TopWindow::SyncSizeHints()
{
GuiLock __;
if(top) {
NSWindow *window = top->coco->window;
Upp::dword style = GetMMStyle();
Size sz0 = GetRect().GetSize();
Size sz = sz0;
if(sizeable)
sz = GetMinSize();
[window setMinSize:MMFrameSize(sz, style)];
sz = sz0;
if(sizeable)
sz = GetMaxSize();
[window setMaxSize:MMFrameSize(sz, style)];
}
}
#endif

View file

@ -40,10 +40,6 @@ bool Ctrl::GuiPlatformSetFullRefreshSpecial()
return false;
}
void Ctrl::PaintCaret(SystemDraw& w)
{
}
String GuiPlatformGetKeyDesc(dword key)
{
return Null;
@ -75,21 +71,6 @@ void GuiPlatformAfterMenuPopUp()
{
}
void Ctrl::SetCaret(int x, int y, int cx, int cy)
{
GuiLock __;
caretx = x;
carety = y;
caretcx = cx;
caretcy = cy;
SyncCaret();
}
void Ctrl::SyncCaret() {
GuiLock __;
}
String Ctrl::Name() const {
GuiLock __;
#ifdef CPU_64

View file

@ -5,10 +5,16 @@ private:
friend struct MMCtrl;
friend struct MMImp;
public:
// TODO: Temp only, remove!
void Create(const Upp::Rect& r, const char *title, bool popup);
static int WndCaretTime;
static bool WndCaretVisible;
static void AnimateCaret();
protected:
virtual void MMClose() { DLOG("MMClose"); }
void Create(dword style);
public:
static void EndSession() {}
static bool IsEndSession() { return false; }
//$ };

View file

@ -75,6 +75,14 @@ inline Upp::Rect MakeRect(const CGRect& r) {
return Upp::RectC(r.origin.x, r.origin.y, r.size.width, r.size.height);
}
inline Upp::Rect MakeRect(const CGRect& r, int h) {
return Upp::RectC(r.origin.x, h - r.origin.y - r.size.height, r.size.width, r.size.height);
}
inline CGRect MakeCGRect(const Upp::Rect& r, int h) {
return CGRectMake(r.left, h - r.top - r.GetHeight(), r.GetWidth(), r.GetHeight());
}
#endif
#endif

View file

@ -35,11 +35,10 @@ struct MMImp {
static void MouseEvent(CocoView *view, NSEvent *e, int event)
{
NSPoint np = [view convertPoint:[e locationInWindow] fromView:nil];
Upp::Point p(np.x, np.y);
Upp::Point p(np.x, view->ctrl->GetRect().GetHeight() - np.y);
int zd = 0; // TODO: MouseWheel
coco_mouse_pos = p + view->ctrl->GetRect().TopLeft();
view->ctrl->DispatchMouse(event, p, zd);
DLOG("MOUSE " << Upp::Point(p.x, p.y));
}
static void Flags(NSEvent *e)
@ -78,14 +77,22 @@ struct MMImp {
{
ctrl->ActivateWnd();
}
static void DoClose(Upp::Ctrl *ctrl)
{
DLOG("DoClose");
ctrl->MMClose();
}
};
};
@implementation CocoView
-(void)drawRect:(NSRect)rect {
Upp::SystemDraw w([[NSGraphicsContext currentContext] CGContext], [self bounds].size.height);
Upp::MMImp::Paint(ctrl, w, MakeRect(rect));
-(void)drawRect:(NSRect)r {
int h = ctrl->GetRect().GetHeight();
Upp::SystemDraw w([[NSGraphicsContext currentContext] CGContext], h);
Upp::MMImp::Paint(ctrl, w, Upp::RectC(r.origin.x, h - r.origin.y - r.size.height,
r.size.width, r.size.height));
}
- (void)mouseDown:(NSEvent *)e { Upp::MMImp::MouseEvent(self, e, Upp::Ctrl::LEFTDOWN); coco_mouse_left = true; }
@ -95,13 +102,10 @@ struct MMImp {
- (void)rightMouseDown:(NSEvent*)e { Upp::MMImp::MouseEvent(self, e, Upp::Ctrl::RIGHTDOWN); coco_mouse_right = true; }
- (void)rightMouseUp:(NSEvent*)e { Upp::MMImp::MouseEvent(self, e, Upp::Ctrl::RIGHTUP); coco_mouse_right = false; }
- (void)keyDown:(NSEvent *)e {
Upp::MMImp::KeyEvent(ctrl, e, 0);
}
- (void)keyDown:(NSEvent *)e { Upp::MMImp::KeyEvent(ctrl, e, 0); }
- (void)keyUp:(NSEvent *)e { Upp::MMImp::KeyEvent(ctrl, e, Upp::K_KEYUP); }
- (void)keyUp:(NSEvent *)e {
Upp::MMImp::KeyEvent(ctrl, e, Upp::K_KEYUP);
}
- (BOOL)windowShouldClose:(NSWindow *)sender { DLOG("SHOULD CLOSE"); Upp::MMImp::DoClose(ctrl); return NO; }
- (void)windowDidResize:(NSNotification *)notification { Upp::MMCtrl::SyncRect(self); }
- (void)windowDidMove:(NSNotification *)notification { Upp::MMCtrl::SyncRect(self); }

View file

@ -6,31 +6,6 @@ NAMESPACE_UPP
#define LLOG(x) // LOG(x)
void TopWindow::SyncSizeHints() {}
void TopWindow::SyncTitle()
{
GuiLock __;
}
void TopWindow::SyncCaption()
{
GuiLock __;
}
void TopWindow::Open(Ctrl *owner)
{
GuiLock __;
}
void TopWindow::Open()
{
}
void TopWindow::OpenMain()
{
}
void TopWindow::Minimize(bool effect)
{
state = MINIMIZED;

View file

@ -1,3 +1,8 @@
//$ class TopWindow {
protected:
Ptr<Ctrl> owner;
dword GetMMStyle() const;
virtual void MMClose() { DLOG("Top::MMClose"); WhenClose(); }
//$ };

View file

@ -101,44 +101,6 @@ void Ctrl::SetAlpha(byte alpha)
GuiLock __;
}
Rect Ctrl::GetWorkArea() const
{
GuiLock __;
return Rect();
}
void Ctrl::GetWorkArea(Array<Rect>& rc)
{
GuiLock __;
}
Rect Ctrl::GetVirtualWorkArea()
{
Rect out = GetPrimaryWorkArea();
Array<Rect> rc;
GetWorkArea(rc);
for(int i = 0; i < rc.GetCount(); i++)
out |= rc[i];
return out;
}
Rect Ctrl::GetVirtualScreenArea()
{
GuiLock __;
return Rect();
}
Rect Ctrl::GetPrimaryWorkArea()
{
Rect r;
return r;
}
Rect Ctrl::GetPrimaryScreenArea()
{
return Size();
}
int Ctrl::GetKbdDelay()
{
GuiLock __;
@ -215,10 +177,6 @@ void Ctrl::WndScrollView(const Rect& r, int dx, int dy)
GuiLock __;
}
void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, bool topmost)
{
}
Rect Ctrl::GetDefaultWindowRect() {
return Rect(0, 0, 100, 100);
}

View file

@ -133,6 +133,7 @@ file
CocoDrawText.mm,
CocoImage.mm,
CocoCtrl.h,
CocoTop.h,
CocoApp.mm,
CocoCreate.mm,
CocoProc.mm,
@ -140,7 +141,6 @@ file
CocoWnd.cpp,
CocoClip.cpp,
CocoDnD.cpp,
CocoTop.h,
CocoTop.cpp,
CocoChSysInit.cpp,
cocotodo.txt,

View file

@ -2,7 +2,7 @@
namespace Upp {
#define LLOG(x) // DLOG(x)
#define LLOG(x) DLOG(x)
#define LTIMING(x) // TIMING(x)
bool Ctrl::globalbackpaint;

View file

@ -581,7 +581,7 @@ bool Ctrl::ProcessEvents0(bool *quit, bool fetch)
bool r = false;
while(IsWaitingEvent0(fetch) && (!LoopCtrl || LoopCtrl->InLoop()))
r = ProcessEvent0(quit, fetch) || r;
TimerProc(GetTickCount());
TimerProc(GetTickCount());
AnimateCaret();
if(quit)
*quit = IsEndSession();

View file

@ -147,12 +147,15 @@ void TopWindow::RejectBreak(int ID)
void TopWindow::SetupRect(Ctrl *owner)
{
DLOG("SetupRect");
Rect r = GetRect();
DDUMP(r);
if(r.IsEmpty())
SetRect(GetDefaultWindowRect());
else
if(r.left == 0 && r.top == 0 && center == 1) {
Rect area = owner ? owner->GetWorkArea() : Ctrl::GetWorkArea();
DDUMP(area);
SetRect(area.CenterRect(min(area.Size(), r.Size())));
}
}

View file

@ -1,3 +1,12 @@
sooner:
- workarea and window placement
- backspace and delete not working
- implement standard cursors
- minimize, maximaze
- fullscreen
- Open/OpenMain variants
later:
- PrinterJob
- DrawDragRect
- CT_Font caching
@ -17,12 +26,16 @@
- fix link options (joining link options missing space)
- set application icons
- fix resizing arrows
- implement cursor shape
- implement caret
- RenderCharacterSys
- flagCOCOA
- USEMALLOC
- multimonitor support
done:
- window close button
- window maximize / minimize buttons
- window minmax
- caret
- implement caret

View file

@ -357,6 +357,7 @@ LabelBase& LabelBase::SetVAlign(int valign) {
Size LabelBase::PaintLabel(Ctrl *ctrl, Draw& w, const Rect& r, bool disabled, bool push, bool focus, bool vak)
{
DLOG("Paint label!");
DrawLabel lbl1 = lbl;
lbl1.disabled = disabled;
lbl1.push = push;