📄 fl_mac.cxx
字号:
if ( ret == noErr )
{
GetFlavorDataSize( dragRef, itemRef, 'TEXT', &itemSize );
GetFlavorData( dragRef, itemRef, 'TEXT', dst, &itemSize, 0L );
dst += itemSize;
*dst++ = '\n'; // add our element seperator
}
ret = GetFlavorFlags( dragRef, itemRef, 'hfs ', &flags );
if ( ret == noErr )
{
HFSFlavor hfs; itemSize = sizeof( hfs );
GetFlavorData( dragRef, itemRef, 'hfs ', &hfs, &itemSize, 0L );
itemSize = FSSpec2UnixPath( &hfs.fileSpec, dst );
dst += itemSize;
if ( itemSize>1 && ( hfs.fileType=='fold' || hfs.fileType=='disk' ) )
*dst++ = '/';
*dst++ = '\n'; // add our element seperator
}
}
dst[-1] = 0;
// if ( Fl::e_text[Fl::e_length-1]==0 ) Fl::e_length--; // modify, if trailing 0 is part of string
Fl::e_length = dst - Fl::e_text - 1;
target->handle(FL_PASTE);
free( Fl::e_text );
fl_dnd_target_window = 0L;
breakMacEventLoop();
return noErr;
}
/**
* go ahead, create that (sub)window
* \todo we should make menu windows slightly transparent for the new Mac look
*/
void Fl_X::make(Fl_Window* w)
{
static int xyPos = 50;
if ( w->parent() ) // create a subwindow
{
Fl_Group::current(0);
Rect wRect;
wRect.top = w->y();
wRect.left = w->x();
wRect.bottom = w->y() + w->h(); if (wRect.bottom<=wRect.top) wRect.bottom = wRect.top+1;
wRect.right = w->x() + w->w(); if (wRect.right<=wRect.left) wRect.right = wRect.left+1;
// our subwindow needs this structure to know about its clipping.
Fl_X* x = new Fl_X;
x->other_xid = 0;
x->region = 0;
x->subRegion = 0;
x->cursor = fl_default_cursor;
Fl_Window *win = w->window();
Fl_X *xo = Fl_X::i(win);
x->xidNext = xo->xidChildren;
x->xidChildren = 0L;
xo->xidChildren = x;
x->xid = fl_xid(win);
x->w = w; w->i = x;
x->wait_for_expose = 0;
x->next = Fl_X::first; // must be in the list for ::flush()
Fl_X::first = x;
w->set_visible();
w->handle(FL_SHOW);
w->redraw(); // force draw to happen
fl_show_iconic = 0;
}
else // create a desktop window
{
Fl_Group::current(0);
fl_open_display();
int winclass = kDocumentWindowClass;
int winattr = kWindowStandardHandlerAttribute | kWindowCloseBoxAttribute | kWindowCollapseBoxAttribute;
int xp = w->x();
int yp = w->y();
int wp = w->w();
int hp = w->h();
if (w->size_range_set) {
if ( w->minh != w->maxh || w->minw != w->maxw)
winattr |= kWindowFullZoomAttribute | kWindowResizableAttribute | kWindowLiveResizeAttribute;
} else {
if (w->resizable()) {
Fl_Widget *o = w->resizable();
int minw = o->w(); if (minw > 100) minw = 100;
int minh = o->h(); if (minh > 100) minh = 100;
w->size_range(w->w() - o->w() + minw, w->h() - o->h() + minh, 0, 0);
winattr |= kWindowFullZoomAttribute | kWindowResizableAttribute | kWindowLiveResizeAttribute;
} else {
w->size_range(w->w(), w->h(), w->w(), w->h());
}
}
int xwm = xp, ywm = yp, bt, bx, by;
if (!fake_X_wm(w, xwm, ywm, bt, bx, by))
{ winclass = kHelpWindowClass; winattr = 0; } // menu windows and tooltips
else if (w->modal())
winclass = kMovableModalWindowClass;
if (by+bt) {
wp += 2*bx;
hp += 2*by+bt;
}
if (!(w->flags() & Fl_Window::FL_FORCE_POSITION)) {
w->x(xyPos+Fl::x()); w->y(xyPos+Fl::y()); // use the Carbon functions below for default window positioning
xyPos += 25;
if (xyPos>200) xyPos = 25;
} else {
if (!Fl::grab()) {
xp = xwm; yp = ywm;
w->x(xp);w->y(yp);
}
xp -= bx;
yp -= by+bt;
}
if (w->non_modal() && Fl_X::first && !fl_disable_transient_for) {
// find some other window to be "transient for":
Fl_Window* w = Fl_X::first->w;
while (w->parent()) w = w->window(); // todo: this code does not make any sense! (w!=w??)
}
Rect wRect;
wRect.top = w->y();
wRect.left = w->x();
wRect.bottom = w->y() + w->h(); if (wRect.bottom<=wRect.top) wRect.bottom = wRect.top+1;
wRect.right = w->x() + w->w(); if (wRect.right<=wRect.left) wRect.right = wRect.left+1;
const char *name = w->label();
Str255 pTitle;
if (name) { pTitle[0] = strlen(name); memcpy(pTitle+1, name, pTitle[0]); }
else pTitle[0]=0;
Fl_X* x = new Fl_X;
x->other_xid = 0; // room for doublebuffering image map. On OS X this is only used by overlay windows
x->region = 0;
x->subRegion = 0;
x->cursor = fl_default_cursor;
x->xidChildren = 0;
x->xidNext = 0;
winattr &= GetAvailableWindowAttributes( winclass ); // make sure that the window will open
CreateNewWindow( winclass, winattr, &wRect, &(x->xid) );
SetWTitle(x->xid, pTitle);
MoveWindow(x->xid, wRect.left, wRect.top, 1); // avoid Carbon Bug on old OS
if (w->non_modal() && !w->modal())
SetWindowClass(x->xid, kFloatingWindowClass ); // Major kludge: this is to have the regular look, but stay above the document windows
if (!(w->flags() & Fl_Window::FL_FORCE_POSITION))
{
WindowRef pw = Fl_X::first ? Fl_X::first->xid : 0 ;
if ( w->modal() )
RepositionWindow( x->xid, pw, kWindowAlertPositionOnParentWindowScreen );
else if ( w->non_modal() )
RepositionWindow( x->xid, pw, kWindowCenterOnParentWindowScreen );
else
RepositionWindow( x->xid, pw, kWindowCascadeOnParentWindowScreen );
}
x->w = w; w->i = x;
x->wait_for_expose = 1;
x->next = Fl_X::first;
Fl_X::first = x;
if (w->resizable()) DrawGrowIcon(x->xid);
w->set_visible();
{ // Install Carbon Event handlers
OSStatus ret;
EventHandlerUPP mousewheelHandler = NewEventHandlerUPP( carbonMousewheelHandler ); // will not be disposed by Carbon...
static EventTypeSpec mousewheelEvents[] = {
{ kEventClassMouse, kEventMouseWheelMoved } };
ret = InstallWindowEventHandler( x->xid, mousewheelHandler, 1, mousewheelEvents, w, 0L );
EventHandlerUPP mouseHandler = NewEventHandlerUPP( carbonMouseHandler ); // will not be disposed by Carbon...
static EventTypeSpec mouseEvents[] = {
{ kEventClassMouse, kEventMouseDown },
{ kEventClassMouse, kEventMouseUp },
{ kEventClassMouse, kEventMouseMoved },
{ kEventClassMouse, kEventMouseDragged } };
ret = InstallWindowEventHandler( x->xid, mouseHandler, 4, mouseEvents, w, 0L );
EventHandlerUPP keyboardHandler = NewEventHandlerUPP( carbonKeyboardHandler ); // will not be disposed by Carbon...
static EventTypeSpec keyboardEvents[] = {
{ kEventClassKeyboard, kEventRawKeyDown },
{ kEventClassKeyboard, kEventRawKeyRepeat },
{ kEventClassKeyboard, kEventRawKeyUp },
{ kEventClassKeyboard, kEventRawKeyModifiersChanged } };
ret = InstallWindowEventHandler( x->xid, keyboardHandler, 4, keyboardEvents, w, 0L );
EventHandlerUPP windowHandler = NewEventHandlerUPP( carbonWindowHandler ); // will not be disposed by Carbon...
static EventTypeSpec windowEvents[] = {
{ kEventClassWindow, kEventWindowDrawContent },
{ kEventClassWindow, kEventWindowShown },
{ kEventClassWindow, kEventWindowHidden },
{ kEventClassWindow, kEventWindowActivated },
{ kEventClassWindow, kEventWindowDeactivated },
{ kEventClassWindow, kEventWindowClose },
{ kEventClassWindow, kEventWindowBoundsChanged } };
ret = InstallWindowEventHandler( x->xid, windowHandler, 7, windowEvents, w, 0L );
ret = InstallTrackingHandler( dndTrackingHandler, x->xid, w );
ret = InstallReceiveHandler( dndReceiveHandler, x->xid, w );
}
if ( ! Fl_X::first->next ) // if this is the first window, we need to bring the application to the front
{
ProcessSerialNumber psn;
OSErr err = GetCurrentProcess( &psn );
if ( err==noErr ) SetFrontProcess( &psn );
}
if (fl_show_iconic) {
fl_show_iconic = 0;
CollapseWindow( x->xid, true ); // \todo Mac ; untested
} else if (winclass != kHelpWindowClass) {
Fl_Tooltip::enter(0);
}
ShowWindow(x->xid);
w->handle(FL_SHOW);
w->redraw(); // force draw to happen
w->set_visible();
if (w->modal()) { Fl::modal_ = w; fl_fix_focus(); }
}
}
/**
* this is a leftover from X Windows
*/
void Fl_Window::size_range_() {
size_range_set = 1;
}
/**
* returns pointer to the filename, or null if name ends with ':'
*/
const char *fl_filename_name( const char *name )
{
const char *p, *q;
if (!name) return (0);
for ( p = q = name ; *p ; )
{
if ( ( p[0] == ':' ) && ( p[1] == ':' ) )
{
q = p+2;
p++;
}
else if (p[0] == '/')
q = p + 1;
p++;
}
return q;
}
/**
* set the window title bar
* \todo make the titlebar icon work!
*/
void Fl_Window::label(const char *name,const char */*iname*/) {
Fl_Widget::label(name);
Str255 pTitle;
if (name) { pTitle[0] = strlen(name); memcpy(pTitle+1, name, pTitle[0]); }
else pTitle[0] = 0;
if (shown() || i) SetWTitle(fl_xid(this), pTitle);
}
/**
* make a window visible
*/
void Fl_Window::show() {
image(Fl::scheme_bg_);
if (Fl::scheme_bg_) {
labeltype(FL_NORMAL_LABEL);
align(FL_ALIGN_CENTER | FL_ALIGN_INSIDE | FL_ALIGN_CLIP);
} else {
labeltype(FL_NO_LABEL);
}
if (!shown() || !i) {
Fl_X::make(this);
} else {
if ( !parent() )
{
if ( IsWindowCollapsed( i->xid ) ) CollapseWindow( i->xid, false );
if (!fl_capture) {
BringToFront(i->xid);
SelectWindow(i->xid);
}
}
}
}
/**
* resize a window
*/
void Fl_Window::resize(int X,int Y,int W,int H) {
int is_a_resize = (W != w() || H != h());
if (X != x() || Y != y()) set_flag(FL_FORCE_POSITION);
else if (!is_a_resize) return;
if ( (resize_from_system!=this) && (!parent()) && shown()) {
MoveWindow(i->xid, X, Y, 0);
if (is_a_resize) {
SizeWindow(i->xid, W>0 ? W : 1, H>0 ? H : 1, 1);
Rect all; all.top=-32000; all.bottom=32000; all.left=-32000; all.right=32000;
InvalWindowRect( i->xid, &all );
}
} else if (resize_from_system == this && size_range_set && !parent() && shown()) {
if (size_range_set) {
if (W < minw) W = minw;
else if (W > maxw && maxw) W = maxw;
if (H < minh) H = minh;
else if (H > maxh && maxh) H = maxh;
}
SizeWindow(i->xid, W>0 ? W : 1, H>0 ? H : 1, 1);
}
resize_from_system = 0;
if (is_a_resize) {
Fl_Group::resize(X,Y,W,H);
if (shown()) { redraw(); if (!parent()) i->wait_for_expose = 1; }
} else {
x(X); y(Y);
}
}
/**
* make all drawing go into this window (called by subclass flush() impl.)
*/
void Fl_Window::make_current()
{
if ( !fl_window_region )
fl_window_region = NewRgn();
fl_window = i->xid;
current_ = this;
SetPort( GetWindowPort(i->xid) ); // \todo check for the handling of doublebuffered windows
int xp = 0, yp = 0;
Fl_Window *win = this;
while ( win )
{
if ( !win->window() )
break;
xp += win->x();
yp += win->y();
win = (Fl_Window*)win->window();
}
SetOrigin( -xp, -yp );
SetRectRgn( fl_window_region, 0, 0, w(), h() );
// \todo for performance reasons: we don't have to create this unless the child windows moved
for ( Fl_X *cx = i->xidChildren; cx; cx = cx->xidNext )
{
Fl_Region r = NewRgn();
Fl_Window *cw = cx->w;
SetRectRgn( r, cw->x() - xp, cw->y() - yp,
cw->x() + cw->w() - xp, cw->y() + cw->h() - yp );
DiffRgn( fl_window_region, r, fl_window_region );
DisposeRgn( r );
}
fl_clip_region( 0 );
SetPortClipRegion( GetWindowPort(i->xid), fl_window_region );
return;
}
////////////////////////////////////////////////////////////////
// Cut & paste.
Fl_Widget *fl_selection_requestor = 0;
char *fl_selection_buffer[2];
int fl_selection_length[2];
int fl_selection_buffer_length[2];
static ScrapRef myScrap = 0;
/**
* create a selection
* owner: widget that created the selection
* stuff: pointer to selected data
* size of selected data
*/
void Fl::copy(const char *stuff, int len, int clipboard) {
if (!stuff || len<0) return;
if (len+1 > fl_selection_buffer_length[clipboard]) {
delete[] fl_selection_buffer[clipboard];
fl_selection_buffer[clipboard] = new char[len+100];
fl_selection_buffer_length[clipboard] = len+100;
}
memcpy(fl_selection_buffer[clipboard], stuff, len);
fl_selection_buffer[clipboard][len] = 0; // needed for direct paste
fl_selection_length[clipboard] = len;
if (clipboard) {
ClearCurrentScrap();
OSStatus ret = GetCurrentScrap( &myScrap );
if ( ret != noErr ) {
myScrap = 0;
return;
}
// Previous version changed \n to \r before sending the text, but I would
// prefer to leave the local buffer alone, so a copied buffer may be
// needed. Check to see if this is necessary on OS/X.
PutScrapFlavor( myScrap, kScrapFlavorTypeText, 0,
len, fl_selection_buffer[1] );
}
}
// Call this when a "paste" operation happens:
void Fl::paste(Fl_Widget &receiver, int clipboard) {
if (clipboard) {
// see if we own the selection, if not go get it:
ScrapRef scrap = 0;
Size len = 0;
if (GetCurrentScrap(&scrap) == noErr && scrap != myScrap &&
GetScrapFlavorSize(scrap, kScrapFlavorTypeText, &len) == noErr) {
if ( len > fl_selection_buffer_length[1] ) {
fl_selection_buffer_length[1] = len + 32;
delete[] fl_selection_buffer[1];
fl_selection_buffer[1] = new char[len];
}
GetScrapFlavorData( scrap, kScrapFlavorTypeText, &len,
fl_selection_buffer[1] );
fl_selection_length[1] = len;
// turn all \r characters into \n:
for (int x = 0; x < len; x++) {
if (fl_selection_buffer[1][x] == '\r')
fl_selection_buffer[1][x] = '\n';
}
}
}
Fl::e_text = fl_selection_buffer[clipboard];
Fl::e_length = fl_selection_length[clipboard];
receiver.handle(FL_PASTE);
return;
}
//
// End of "$Id: Fl_mac.cxx,v 1.1.1.1 2003/06/03 22:25:45 agno Exp $".
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -