From e53a81a71d0932917fa248beb0d46d5dd25ead64 Mon Sep 17 00:00:00 2001 From: cxl Date: Thu, 27 Sep 2018 13:58:15 +0000 Subject: [PATCH] CtrlCore: Cocoa Drag&Drop git-svn-id: svn://ultimatepp.org/upp/trunk@12315 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/Core/Defs.h | 4 +- uppsrc/Core/Mt.h | 4 +- uppsrc/CtrlCore/Coco.h | 4 +- uppsrc/CtrlCore/CocoApp.mm | 98 +++++++++++++++++++---------------- uppsrc/CtrlCore/CocoClip.mm | 70 ++++++++++++++++++------- uppsrc/CtrlCore/CocoCreate.mm | 79 +++++++++++++++------------- uppsrc/CtrlCore/CocoCtrl.h | 2 + uppsrc/CtrlCore/CocoProc.mm | 47 +++++++++++++++++ uppsrc/CtrlCore/CtrlClip.cpp | 2 +- uppsrc/CtrlCore/CtrlCore.h | 4 +- uppsrc/CtrlCore/cocotodo.txt | 5 +- 11 files changed, 209 insertions(+), 110 deletions(-) diff --git a/uppsrc/Core/Defs.h b/uppsrc/Core/Defs.h index d13bd7a39..f8eeb56cc 100644 --- a/uppsrc/Core/Defs.h +++ b/uppsrc/Core/Defs.h @@ -32,11 +32,11 @@ void AssertFailed(const char *file, int line, const char *cond); void InstallPanicMessageBox(void (*mb)(const char *title, const char *text)); void PanicMessageBox(const char *title, const char *text); -#define VERIFY(x) ((x) ? (void)0 : UPP::AssertFailed(__FILE__, __LINE__, #x)) +#define VERIFY(x) ((x) ? (void)0 : ::Upp::AssertFailed(__FILE__, __LINE__, #x)) #ifdef _DEBUG -#define ASSERT_(x, msg) ((x) ? (void)0 : UPP::AssertFailed(__FILE__, __LINE__, msg)) +#define ASSERT_(x, msg) ((x) ? (void)0 : ::Upp ::AssertFailed(__FILE__, __LINE__, msg)) #define ASSERT(x) ASSERT_(x, #x) #else diff --git a/uppsrc/Core/Mt.h b/uppsrc/Core/Mt.h index f84c32123..161586832 100644 --- a/uppsrc/Core/Mt.h +++ b/uppsrc/Core/Mt.h @@ -276,8 +276,8 @@ public: typedef std::atomic OnceFlag; #define ONCELOCK_(o_b_) \ -for(static UPP::Mutex o_ss_; !o_b_.load(std::memory_order_acquire);) \ - for(UPP::Mutex::Lock o_ss_lock__(o_ss_); !o_b_.load(std::memory_order_acquire); o_b_.store(true, std::memory_order_release)) +for(static ::Upp::Mutex o_ss_; !o_b_.load(std::memory_order_acquire);) \ + for(::Upp::Mutex::Lock o_ss_lock__(o_ss_); !o_b_.load(std::memory_order_acquire); o_b_.store(true, std::memory_order_release)) #define ONCELOCK \ for(static OnceFlag o_b_; !o_b_.load(std::memory_order_acquire);) ONCELOCK_(o_b_) diff --git a/uppsrc/CtrlCore/Coco.h b/uppsrc/CtrlCore/Coco.h index dcfd25827..a1665113d 100644 --- a/uppsrc/CtrlCore/Coco.h +++ b/uppsrc/CtrlCore/Coco.h @@ -163,7 +163,9 @@ struct MMImp; #define GUIPLATFORM_CTRL_DECLS_INCLUDE -#define GUIPLATFORM_PASTECLIP_DECLS +#define GUIPLATFORM_PASTECLIP_DECLS \ +void *nspasteboard; \ +friend struct MMImp; #define GUIPLATFORM_TOPWINDOW_DECLS_INCLUDE diff --git a/uppsrc/CtrlCore/CocoApp.mm b/uppsrc/CtrlCore/CocoApp.mm index ffd67423a..84f019301 100644 --- a/uppsrc/CtrlCore/CocoApp.mm +++ b/uppsrc/CtrlCore/CocoApp.mm @@ -1,11 +1,13 @@ #include "CocoMM.h" -#ifdef PLATFORM_COCOA - #define LLOG(x) // DLOG(x) -int Upp::Ctrl::WndCaretTime; -bool Upp::Ctrl::WndCaretVisible; +#ifdef PLATFORM_COCOA + +namespace Upp { + +int Ctrl::WndCaretTime; +bool Ctrl::WndCaretVisible; static NSAutoreleasePool *main_coco_pool; static NSEvent *current_event; @@ -31,7 +33,7 @@ static void ReleaseCurrentEvent() void SyncPopupFocus(NSWindow *win) { - Upp::Ctrl *q = Upp::Ctrl::GetFocusCtrl(); + Ctrl *q = Ctrl::GetFocusCtrl(); if(q) { q = q->GetTopCtrl(); if(q->IsPopUp() && q->GetNSWindow() != win) { @@ -41,11 +43,9 @@ void SyncPopupFocus(NSWindow *win) } } -namespace Upp { - extern const char *sClipFmtsRTF; -}; +extern const char *sClipFmtsRTF; -void Upp::CocoInit(int argc, const char **argv, const char **envptr) +void CocoInit(int argc, const char **argv, const char **envptr) { Ctrl::GlobalBackBuffer(); main_coco_pool = [NSAutoreleasePool new]; @@ -66,7 +66,7 @@ void Upp::CocoInit(int argc, const char **argv, const char **envptr) [NSApp activateIgnoringOtherApps:YES]; NSFont *sysfont = [NSFont systemFontOfSize:0]; - Font::SetFace(0, Upp::ToString((CFStringRef)[sysfont familyName]), Font::TTF); + Font::SetFace(0, ToString((CFStringRef)[sysfont familyName]), Font::TTF); Ctrl::SetUHDEnabled(true); @@ -90,39 +90,39 @@ void Upp::CocoInit(int argc, const char **argv, const char **envptr) return e; }]; - Upp::sClipFmtsRTF = "rtf"; + sClipFmtsRTF = "rtf"; - Upp::Ctrl::Csizeinit(); + Ctrl::Csizeinit(); } -void Upp::CocoExit() +void CocoExit() { ReleaseCurrentEvent(); [main_coco_pool release]; } -int Upp::Ctrl::GetKbdDelay() +int Ctrl::GetKbdDelay() { GuiLock __; return int(1000 * NSEvent.keyRepeatDelay); } -int Upp::Ctrl::GetKbdSpeed() +int Ctrl::GetKbdSpeed() { GuiLock __; return int(1000 * NSEvent.keyRepeatInterval); } -bool Upp::Ctrl::IsWaitingEvent() +bool Ctrl::IsWaitingEvent() { return GetNextEvent(nil); } -bool Upp::Ctrl::ProcessEvent(bool *) +bool Ctrl::ProcessEvent(bool *) { ASSERT(IsMainThread()); - Upp::AutoreleasePool __; + AutoreleasePool __; ONCELOCK { [NSApp finishLaunching]; @@ -144,7 +144,7 @@ bool Upp::Ctrl::ProcessEvent(bool *) void SweepMkImageCache(); -bool Upp::Ctrl::ProcessEvents(bool *quit) +bool Ctrl::ProcessEvents(bool *quit) { if(ProcessEvent(quit)) { while(ProcessEvent(quit) && (!LoopCtrl || LoopCtrl->InLoop())); @@ -160,7 +160,7 @@ bool Upp::Ctrl::ProcessEvents(bool *quit) } -void Upp::Ctrl::EventLoop(Ctrl *ctrl) +void Ctrl::EventLoop(Ctrl *ctrl) { GuiLock __; ASSERT(IsMainThread()); @@ -196,7 +196,7 @@ void Upp::Ctrl::EventLoop(Ctrl *ctrl) static std::atomic sGuiSleep; -void Upp::Ctrl::GuiSleep(int ms) +void Ctrl::GuiSleep(int ms) { ASSERT(IsMainThread()); sGuiSleep = true; @@ -204,20 +204,24 @@ void Upp::Ctrl::GuiSleep(int ms) sGuiSleep = false; } -namespace Upp { void WakeUpGuiThread(void) { if(sGuiSleep) { sGuiSleep = false; [NSApp postEvent:[NSEvent otherEventWithType:NSEventTypeApplicationDefined - location:NSMakePoint(0, 0) modifierFlags:0 timestamp:0.0 - windowNumber:0 context:nil subtype: 0 data1:0 data2:0] - atStart:YES]; + location:NSMakePoint(0, 0) + modifierFlags:0 + timestamp:0.0 + windowNumber:0 + context:nil + subtype:0 + data1:0 + data2:0] + atStart:YES]; } } -}; -void Upp::Ctrl::AnimateCaret() +void Ctrl::AnimateCaret() { GuiLock __; int v = !(((GetTickCount() - WndCaretTime) / 500) & 1); @@ -227,7 +231,7 @@ void Upp::Ctrl::AnimateCaret() } } -void Upp::Ctrl::PaintCaret(SystemDraw& w) +void Ctrl::PaintCaret(SystemDraw& w) { GuiLock __; LLOG("PaintCaret " << Name() << ", caretCtrl: " << caretCtrl << ", WndCaretVisible: " << WndCaretVisible); @@ -235,7 +239,7 @@ void Upp::Ctrl::PaintCaret(SystemDraw& w) w.DrawRect(caretx, carety, caretcx, caretcy, InvertColor); } -void Upp::Ctrl::SetCaret(int x, int y, int cx, int cy) +void Ctrl::SetCaret(int x, int y, int cx, int cy) { GuiLock __; LLOG("SetCaret " << Name()); @@ -252,64 +256,64 @@ void Upp::Ctrl::SetCaret(int x, int y, int cx, int cy) } } -void Upp::Ctrl::SyncCaret() { +void Ctrl::SyncCaret() { GuiLock __; // LLOG("SyncCaret"); if(focusCtrl != caretCtrl) { - LLOG("SyncCaret DO " << Upp::Name(caretCtrl) << " -> " << Upp::Name(focusCtrl)); + LLOG("SyncCaret DO " << Name(caretCtrl) << " -> " << Name(focusCtrl)); RefreshCaret(); caretCtrl = focusCtrl; RefreshCaret(); } } -Upp::Rect Upp::Ctrl::GetWorkArea() const +Rect Ctrl::GetWorkArea() const { return GetPrimaryWorkArea(); } -void Upp::Ctrl::GetWorkArea(Array& rc) +void Ctrl::GetWorkArea(Array& rc) { GuiLock __; rc.Add(GetPrimaryWorkArea()); } -Upp::Rect Upp::Ctrl::GetVirtualWorkArea() +Rect Ctrl::GetVirtualWorkArea() { return GetPrimaryWorkArea(); } -Upp::Rect Upp::Ctrl::GetVirtualScreenArea() +Rect Ctrl::GetVirtualScreenArea() { return GetPrimaryWorkArea(); } -Upp::Rect MakeScreenRect(NSScreen *screen, CGRect r) +Rect MakeScreenRect(NSScreen *screen, CGRect r) { r.origin.y = [screen frame].size.height - r.origin.y - r.size.height; return MakeRect(r); } -Upp::Rect Upp::Ctrl::GetPrimaryWorkArea() +Rect Ctrl::GetPrimaryWorkArea() { for (NSScreen *screen in [NSScreen screens]) return DPI(1) * MakeScreenRect(screen, [screen visibleFrame]); return Rect(0, 0, 1024, 768); } -Upp::Rect Upp::Ctrl::GetPrimaryScreenArea() +Rect Ctrl::GetPrimaryScreenArea() { for (NSScreen *screen in [NSScreen screens]) return DPI(1) * MakeScreenRect(screen, [screen frame]); return Rect(0, 0, 1024, 768); } -bool Upp::Ctrl::IsCompositedGui() +bool Ctrl::IsCompositedGui() { return true; } -Upp::Rect Upp::Ctrl::GetDefaultWindowRect() +Rect Ctrl::GetDefaultWindowRect() { GuiLock __; Rect r = GetPrimaryWorkArea(); @@ -324,29 +328,29 @@ Upp::Rect Upp::Ctrl::GetDefaultWindowRect() return RectC(r.left + pos + 20, r.top + pos + 20, cx, cy); } -void Upp::Ctrl::GuiPlatformGetTopRect(Rect& r) const +void Ctrl::GuiPlatformGetTopRect(Rect& r) const { } -void Upp::MMCtrl::SyncRect(CocoView *view) +void MMCtrl::SyncRect(CocoView *view) { NSWindow *win = [view window]; view->ctrl->SetWndRect(DPI(1) * MakeScreenRect([win screen], [win contentRectForFrameRect: [win frame]])); } -void Upp::AppendClipboardText(const String& s) +void AppendClipboardText(const String& s) { CFRef cs = CFStringCreateWithCString(NULL, (const char *)~s.ToString(), kCFStringEncodingUTF8); [[NSPasteboard generalPasteboard] setString:(NSString *)~cs forType:NSPasteboardTypeString]; } -void Upp::AppendClipboardUnicodeText(const WString& s) +void AppendClipboardUnicodeText(const WString& s) { AppendClipboardText(s.ToString()); } -Upp::ViewDraw::ViewDraw(Ctrl *ctrl) +ViewDraw::ViewDraw(Ctrl *ctrl) { EnterGuiMutex(); ASSERT(ctrl->top->coco); @@ -361,11 +365,13 @@ Upp::ViewDraw::ViewDraw(Ctrl *ctrl) Clipoff(Rect(r.TopLeft() - tr.TopLeft(), r.GetSize())); } -Upp::ViewDraw::~ViewDraw() +ViewDraw::~ViewDraw() { End(); CGContextFlush(cgHandle); LeaveGuiMutex(); } +}; + #endif diff --git a/uppsrc/CtrlCore/CocoClip.mm b/uppsrc/CtrlCore/CocoClip.mm index 8969d6694..7b215edfc 100644 --- a/uppsrc/CtrlCore/CocoClip.mm +++ b/uppsrc/CtrlCore/CocoClip.mm @@ -93,6 +93,14 @@ void ClearClipboard() ClearClipboard(false); } +NSMutableSet *PasteboardTypes(const Vector& fmt) +{ + NSMutableSet *types = [[[NSMutableSet alloc] init] autorelease]; + for(auto id : fmt) + [types addObject:PasteboardType(id)]; + return types; +} + void AppendClipboard(bool dnd, const char *format, const Value& value, String (*render)(const Value& data)) { GuiLock __; @@ -102,17 +110,31 @@ void AppendClipboard(bool dnd, const char *format, const Value& value, String (* for(String fmt : Split(format, ';')) data.GetAdd(fmt) = ClipData(value, render); - NSAutoreleasePool *pool; - pool = [[NSAutoreleasePool alloc] init]; + AutoreleasePool ___; - NSMutableSet *types = [[NSMutableSet alloc] init]; - for(auto id : data.GetKeys()) - [types addObject:PasteboardType(id)]; + [Pasteboard(dnd) declareTypes:[PasteboardTypes(data.GetKeys()) allObjects] + owner:ClipboardOwner(dnd)]; +} - [Pasteboard(dnd) declareTypes:[types allObjects] owner:ClipboardOwner(dnd)]; +Index drop_formats; - [types release]; - [pool release]; +void Ctrl::RegisterCocoaDropFormats() +{ + AutoreleasePool ___; + NSView *nsview = (NSView *)GetNSView(); + [nsview registerForDraggedTypes:[PasteboardTypes(drop_formats.GetKeys()) allObjects]]; +} + +void RegisterDropFormats(const char *formats) +{ + for(String fmt : Split(formats, ';')) + drop_formats.FindAdd(fmt); + for(Ctrl *q : Ctrl::GetTopCtrls()) + q->RegisterCocoaDropFormats(); +} + +INITBLOCK { + RegisterDropFormats("text;png;image;rtf;files;url"); } void AppendClipboard(const char *format, const Value& value, String (*render)(const Value& data)) @@ -132,35 +154,45 @@ void AppendClipboard(const char *format, const byte *data, int length) AppendClipboard(format, String(data, length)); } +bool IsFormatAvailable(NSPasteboard *pasteboard, const char *fmt) +{ + return [pasteboard availableTypeFromArray:[NSArray arrayWithObjects:PasteboardType(fmt), nil]]; +} + +String ReadFormat(NSPasteboard *pasteboard, const char *fmt) +{ + NSData *data = [pasteboard dataForType:PasteboardType(fmt)]; + return String((const char *)[data bytes], [data length]); +} + bool PasteClip::IsAvailable(const char *fmt) const { - return IsClipboardAvailable(fmt); + return nspasteboard ? IsFormatAvailable((NSPasteboard *)nspasteboard, fmt) + : IsClipboardAvailable(fmt); } String PasteClip::Get(const char *fmt) const { - return ReadClipboard(fmt); + return nspasteboard ? ReadFormat((NSPasteboard *)nspasteboard, fmt) + : ReadClipboard(fmt); } void PasteClip::GuiPlatformConstruct() { + nspasteboard = NULL; } -bool IsClipboardAvailable(const char *id) +bool IsClipboardAvailable(const char *fmt) { - return [[NSPasteboard generalPasteboard] - availableTypeFromArray:[NSArray arrayWithObjects:PasteboardType(id), nil]]; + return IsFormatAvailable([NSPasteboard generalPasteboard], fmt); } -String ReadClipboard(const char *fmt_) +String ReadClipboard(const char *fmt) { - String fmt = fmt_; - if(fmt == "text") - return ToString([[NSPasteboard generalPasteboard] stringForType:NSPasteboardTypeString]); - NSData *data = [[NSPasteboard generalPasteboard] dataForType:PasteboardType(fmt)]; - return String((const char *)[data bytes], [data length]); + return ReadFormat([NSPasteboard generalPasteboard], fmt); } + bool IsClipboardAvailableText() { return IsClipboardAvailable("text"); diff --git a/uppsrc/CtrlCore/CocoCreate.mm b/uppsrc/CtrlCore/CocoCreate.mm index 3a58220ac..1d2572625 100644 --- a/uppsrc/CtrlCore/CocoCreate.mm +++ b/uppsrc/CtrlCore/CocoCreate.mm @@ -15,7 +15,7 @@ @implementation CocoWindow - (void)becomeKeyWindow { - [super becomeKeyWindow]; + [super becomeKeyWindow]; } - (BOOL)canBecomeKeyWindow { @@ -29,15 +29,17 @@ @end -static Upp::Vector> mmtopctrl; // should work without Ptr, but let us be defensive.... +namespace Upp { -Upp::Ctrl *Upp::Ctrl::GetOwner() +static Vector> mmtopctrl; // should work without Ptr, but let us be defensive.... + +Ctrl *Ctrl::GetOwner() { GuiLock __; return top && top->coco ? top->coco->owner : NULL; } -Upp::Ctrl *Upp::Ctrl::GetActiveCtrl() +Ctrl *Ctrl::GetActiveCtrl() { GuiLock __; for(Ctrl *p : mmtopctrl) @@ -46,7 +48,7 @@ Upp::Ctrl *Upp::Ctrl::GetActiveCtrl() return NULL; } -bool Upp::Ctrl::SetWndFocus() +bool Ctrl::SetWndFocus() { GuiLock __; if(top && top->coco) { @@ -59,44 +61,44 @@ bool Upp::Ctrl::SetWndFocus() return true; } -bool Upp::Ctrl::HasWndFocus() const +bool Ctrl::HasWndFocus() const { GuiLock __; return GetActiveCtrl() == this; } -void Upp::Ctrl::SetWndForeground() +void Ctrl::SetWndForeground() { GuiLock __; SetWndFocus(); } -bool Upp::Ctrl::IsWndForeground() const +bool Ctrl::IsWndForeground() const { GuiLock __; return HasWndFocus(); } -NSRect DesktopRect(const Upp::Rect& r) +NSRect DesktopRect(const Rect& r) { - double scalei = 1.0 / Upp::DPI(1); + double scalei = 1.0 / DPI(1); return NSMakeRect(scalei * r.left, - scalei * (Upp::Ctrl::GetPrimaryScreenArea().GetHeight() - r.top - r.GetHeight()), + scalei * (Ctrl::GetPrimaryScreenArea().GetHeight() - r.top - r.GetHeight()), scalei * r.GetWidth(), scalei * r.GetHeight()); } -void *Upp::Ctrl::GetNSWindow() const +void *Ctrl::GetNSWindow() const { return top && top->coco ? top->coco->window : NULL; } -void *Upp::Ctrl::GetNSView() const +void *Ctrl::GetNSView() const { return top && top->coco ? top->coco->view : NULL; } -void Upp::Ctrl::Create(Ctrl *owner, dword style, bool active) +void Ctrl::Create(Ctrl *owner, dword style, bool active) { if(owner) owner = owner->GetTopCtrl(); @@ -128,9 +130,11 @@ void Upp::Ctrl::Create(Ctrl *owner, dword style, bool active) MMCtrl::SyncRect(view); isopen = true; mmtopctrl.Add(this); + + RegisterCocoaDropFormats(); } -void Upp::Ctrl::WndDestroy() +void Ctrl::WndDestroy() { LLOG("WndDestroy " << Name()); if(!top) @@ -148,7 +152,7 @@ void Upp::Ctrl::WndDestroy() owner->SetWndFocus(); } -Upp::Vector Upp::Ctrl::GetTopCtrls() +Vector Ctrl::GetTopCtrls() { Vector h; for(Ctrl *p : mmtopctrl) @@ -156,7 +160,7 @@ Upp::Vector Upp::Ctrl::GetTopCtrls() return h; } -void Upp::Ctrl::WndInvalidateRect(const Rect& r) +void Ctrl::WndInvalidateRect(const Rect& r) { GuiLock __; LLOG("Invalidate Rect " << r); @@ -164,19 +168,19 @@ void Upp::Ctrl::WndInvalidateRect(const Rect& r) [top->coco->view setNeedsDisplayInRect:(NSRect)CGRectDPI(r)]; } -void Upp::Ctrl::WndScrollView(const Rect& r, int dx, int dy) +void Ctrl::WndScrollView(const Rect& r, int dx, int dy) { GuiLock __; LLOG("Scroll View " << r); WndInvalidateRect(r); } -bool Upp::Ctrl::IsWndOpen() const { +bool Ctrl::IsWndOpen() const { GuiLock __; return top; } -void Upp::Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, bool topmost) +void Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow, bool topmost) { Create(owner ? owner->GetTopCtrl() : GetActiveCtrl(), NSWindowStyleMaskBorderless, 0); popup = true; @@ -202,9 +206,9 @@ void Upp::Ctrl::PopUp(Ctrl *owner, bool savebits, bool activate, bool dropshadow #endif } -Upp::dword Upp::TopWindow::GetMMStyle() const +dword TopWindow::GetMMStyle() const { - Upp::dword style = NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskResizable; + dword style = NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskResizable; if(minimizebox) style |= NSWindowStyleMaskMiniaturizable; // if(maximizebox) @@ -212,7 +216,7 @@ Upp::dword Upp::TopWindow::GetMMStyle() const return style; } -void Upp::TopWindow::Open(Ctrl *owner) +void TopWindow::Open(Ctrl *owner) { GuiLock __; SetupRect(owner); @@ -233,17 +237,17 @@ void Upp::TopWindow::Open(Ctrl *owner) // top->placefocus = true; } -void Upp::TopWindow::Open() +void TopWindow::Open() { Open(GetActiveCtrl()); } -void Upp::TopWindow::OpenMain() +void TopWindow::OpenMain() { Open(NULL); } -void Upp::TopWindow::SyncTitle() +void TopWindow::SyncTitle() { GuiLock __; if(top) { @@ -253,7 +257,7 @@ void Upp::TopWindow::SyncTitle() } } -void Upp::TopWindow::SyncCaption() +void TopWindow::SyncCaption() { GuiLock __; if(top) { @@ -264,33 +268,33 @@ void Upp::TopWindow::SyncCaption() } } -CGSize MMFrameSize(Upp::Size sz, Upp::dword style) +CGSize MMFrameSize(Size sz, dword style) { - double scale = 1.0 / Upp::DPI(1); + double scale = 1.0 / DPI(1); return [NSWindow frameRectForContentRect: (NSRect)CGRectMake(100, 100, scale * sz.cx, scale * sz.cy) styleMask:style].size; } -void Upp::TopWindow::SyncSizeHints() +void TopWindow::SyncSizeHints() { GuiLock __; if(top) { NSWindow *window = top->coco->window; - Upp::dword style = GetMMStyle(); + dword style = GetMMStyle(); Size sz = GetRect().GetSize(); [window setMinSize:MMFrameSize(sizeable ? GetMinSize() : sz, style)]; [window setMaxSize:MMFrameSize(sizeable ? GetMaxSize() : sz, style)]; } } -Upp::Rect Upp::Ctrl::GetWndScreenRect() const +Rect Ctrl::GetWndScreenRect() const { // THIS IS NOT NEEDED GuiLock __; Rect r = GetRect(); return r; } -void Upp::Ctrl::WndSetPos(const Upp::Rect& rect) +void Ctrl::WndSetPos(const Rect& rect) { GuiLock __; if(top) @@ -299,7 +303,7 @@ void Upp::Ctrl::WndSetPos(const Upp::Rect& rect) display:YES]; } -void Upp::TopWindow::SerializePlacement(Stream& s, bool reminimize) +void TopWindow::SerializePlacement(Stream& s, bool reminimize) { GuiLock __; int version = 0; @@ -310,7 +314,7 @@ void Upp::TopWindow::SerializePlacement(Stream& s, bool reminimize) SetRect(rect); } -void Upp::TopWindow::Maximize(bool effect) +void TopWindow::Maximize(bool effect) { state = MAXIMIZED; if(top && top->coco && top->coco->window && !top->coco->window.zoomed) { @@ -321,7 +325,7 @@ void Upp::TopWindow::Maximize(bool effect) } } -void Upp::TopWindow::Minimize(bool effect) +void TopWindow::Minimize(bool effect) { state = MINIMIZED; if(top && top->coco && top->coco->window && !top->coco->window.miniaturized) { @@ -332,7 +336,7 @@ void Upp::TopWindow::Minimize(bool effect) } } -void Upp::TopWindow::Overlap(bool effect) +void TopWindow::Overlap(bool effect) { state = OVERLAPPED; if(top && top->coco && top->coco->window && top->coco->window.zoomed) @@ -341,5 +345,6 @@ void Upp::TopWindow::Overlap(bool effect) [top->coco->window deminiaturize:top->coco->window]; } +} #endif diff --git a/uppsrc/CtrlCore/CocoCtrl.h b/uppsrc/CtrlCore/CocoCtrl.h index a0e1d0fd5..b71d60267 100644 --- a/uppsrc/CtrlCore/CocoCtrl.h +++ b/uppsrc/CtrlCore/CocoCtrl.h @@ -24,4 +24,6 @@ public: void *GetNSWindow() const; void *GetNSView() const; + + void RegisterCocoaDropFormats(); //$ }; diff --git a/uppsrc/CtrlCore/CocoProc.mm b/uppsrc/CtrlCore/CocoProc.mm index b45e0ad85..b91d7e2fa 100644 --- a/uppsrc/CtrlCore/CocoProc.mm +++ b/uppsrc/CtrlCore/CocoProc.mm @@ -13,6 +13,7 @@ static int coco_flags; static Upp::Ptr coco_capture; namespace Upp { + bool GetShift() { return coco_flags & NSEventModifierFlagShift; } bool GetCtrl() { return coco_flags & NSEventModifierFlagCommand; } bool GetAlt() { return coco_flags & NSEventModifierFlagControl; } @@ -182,6 +183,27 @@ struct MMImp { { ctrl->MMClose(); } + + static int DnD(Upp::Ctrl *ctrl, id info, bool paste = false) + { + NSView *nsview = (NSView *)ctrl->GetNSView(); + PasteClip clip; + clip.nspasteboard = info.draggingPasteboard; + clip.paste = paste; + clip.accepted = false; + clip.allowed = DND_MOVE|DND_COPY; // TODO: Use draggingSourceOperationMask + NSPoint np = [nsview convertPoint:[info draggingLocation] fromView:nil]; + ctrl->DnD(Upp::Point(DPI(np.x), DPI(np.y)) + ctrl->GetScreenView().TopLeft(), clip); + // TODO: Resolve allowed actions + return clip.IsAccepted() ? clip.GetAction() == DND_MOVE ? NSDragOperationMove + : NSDragOperationCopy + : NSDragOperationNone; + } + + static void DnDLeave(Ctrl *ctrl) + { + ctrl->DnDLeave(); + } }; }; @@ -280,6 +302,31 @@ struct MMImp { return ctrl->IsEnabled(); } +- (NSDragOperation)draggingEntered:(id )sender +{ + return Upp::MMImp::DnD(ctrl, sender); +} + +- (NSDragOperation)draggingUpdated:(id )sender +{ + return Upp::MMImp::DnD(ctrl, sender); +} + +- (void)draggingEnded:(id )sender +{ + return Upp::MMImp::DnDLeave(ctrl); +} + +- (void)draggingExited:(id )sender +{ + return Upp::MMImp::DnDLeave(ctrl); +} + +- (BOOL)performDragOperation:(id )sender +{ + return Upp::MMImp::DnD(ctrl, sender, true); +} + @end #endif \ No newline at end of file diff --git a/uppsrc/CtrlCore/CtrlClip.cpp b/uppsrc/CtrlCore/CtrlClip.cpp index 7d26d7f3c..c79b7a410 100644 --- a/uppsrc/CtrlCore/CtrlClip.cpp +++ b/uppsrc/CtrlCore/CtrlClip.cpp @@ -215,7 +215,7 @@ void Ctrl::DnDRepeat() UPP::KillTimeCallback(&dndpos); } -void Ctrl::DnD(Point p, PasteClip& clip) + void Ctrl::DnD(Point p, PasteClip& clip) { GuiLock __; UPP::KillTimeCallback(&dndpos); diff --git a/uppsrc/CtrlCore/CtrlCore.h b/uppsrc/CtrlCore/CtrlCore.h index 0918763ff..4ce9b4304 100644 --- a/uppsrc/CtrlCore/CtrlCore.h +++ b/uppsrc/CtrlCore/CtrlCore.h @@ -310,7 +310,7 @@ void GuiPlatformAdjustDragImage(ImageBuffer& b); Image MakeDragImage(const Image& arrow, Image sample); const char *ClipFmtsText(); -bool AcceptText(PasteClip& clip); +bool AcceptText (PasteClip& clip); String GetString(PasteClip& clip); WString GetWString(PasteClip& clip); String GetTextClip(const String& text, const String& fmt); @@ -1218,6 +1218,8 @@ public: static PasteClip& Selection(); void SetSelectionSource(const char *fmts); + + static void RegisterDropFormats(const char *fmts); // MacOS requires drop formats to be registered int DoDragAndDrop(const char *fmts, const Image& sample, dword actions, const VectorMap& data); diff --git a/uppsrc/CtrlCore/cocotodo.txt b/uppsrc/CtrlCore/cocotodo.txt index 5256ce318..6f7d4f06a 100644 --- a/uppsrc/CtrlCore/cocotodo.txt +++ b/uppsrc/CtrlCore/cocotodo.txt @@ -1,5 +1,6 @@ sooner: +- fix modifier keys (read before each event) - UHD problem with tabbar - UHD problem with Prompt text size ([g ?) - initial focus in uword @@ -7,7 +8,7 @@ sooner: - fix package organiser link options (joining link options missing space) - perhaps better UTI names - CH improve spinbuttons -- Delete CocoClip.mm -> crash +- Delete CocoDnD.cpp -> crash * cursor trouble osscilation * after mouse up, cursor changes to arrow @@ -31,6 +32,8 @@ later: - ch improve button matching to viewedge in droplist / UHD - ch focus +- improve dnd protocol - allow macstyle images and offsets + - filesel icons - Warning: Terminal '/usr/bin/xterm' not found, executing in background.