📄 fl_mac.cxx
字号:
else if ( mods & rightControlKey ) Fl::e_keysym = FL_Control_R;
else if ( mods & shiftKey ) Fl::e_keysym = FL_Shift_L;
else if ( mods & rightShiftKey ) Fl::e_keysym = FL_Shift_R;
else if ( mods & alphaLock ) Fl::e_keysym = FL_Caps_Lock;
else Fl::e_keysym = 0;
}
/**
* convert the keyboard return code into the symbol on the keycaps
*/
static unsigned short keycode_to_sym( UInt32 keyCode, UInt32 mods, unsigned short deflt )
{
static Ptr map = 0;
UInt32 state = 0;
if (!map) {
map = (Ptr)GetScriptManagerVariable(smKCHRCache);
if (!map) {
long kbID = GetScriptManagerVariable(smKeyScript);
map = *GetResource('KCHR', kbID);
}
}
if (map)
return KeyTranslate(map, keyCode|mods, &state );
return deflt;
}
/**
* handle carbon keyboard events
*/
pascal OSStatus carbonKeyboardHandler( EventHandlerCallRef nextHandler, EventRef event, void *userData )
{
static char buffer[5];
int sendEvent = 0;
Fl_Window *window = (Fl_Window*)userData;
UInt32 mods;
static UInt32 prevMods = 0xffffffff;
fl_lock_function();
GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &mods );
if ( prevMods == 0xffffffff ) prevMods = mods;
UInt32 keyCode;
GetEventParameter( event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
unsigned char key;
GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &key );
unsigned short sym;
switch ( GetEventKind( event ) )
{
case kEventRawKeyDown:
case kEventRawKeyRepeat:
sendEvent = FL_KEYBOARD;
// fall through
case kEventRawKeyUp:
if ( !sendEvent ) sendEvent = FL_KEYUP;
// if the user pressed alt/option, event_key should have the keycap, but event_text should generate the international symbol
if ( isalpha(key) )
sym = tolower(key);
else if ( Fl::e_state&FL_CTRL && key<32 )
sym = key+96;
else if ( Fl::e_state&FL_ALT )
sym = keycode_to_sym( keyCode & 0x7f, 0, macKeyLookUp[ keyCode & 0x7f ] ); // find the keycap of this key
else
sym = macKeyLookUp[ keyCode & 0x7f ];
Fl::e_keysym = sym;
if ( keyCode==0x4c ) key=0x0d;
if ( ( (sym>=FL_KP) && (sym<=FL_KP_Last) ) || ((sym&0xff00)==0) || (sym==FL_Tab) ) {
buffer[0] = key;
Fl::e_length = 1;
} else {
buffer[0] = 0;
Fl::e_length = 0;
}
Fl::e_text = buffer;
// insert UnicodeHandling here!
break;
case kEventRawKeyModifiersChanged: {
UInt32 tMods = prevMods ^ mods;
if ( tMods )
{
mods_to_e_keysym( tMods );
if ( Fl::e_keysym )
sendEvent = ( prevMods<mods ) ? FL_KEYBOARD : FL_KEYUP;
Fl::e_length = 0;
buffer[0] = 0;
prevMods = mods;
}
mods_to_e_state( mods );
break; }
}
while (window->parent()) window = window->window();
if (sendEvent && Fl::handle(sendEvent,window)) {
fl_unlock_function();
return noErr; // return noErr if FLTK handled the event
} else {
fl_unlock_function();
return CallNextEventHandler( nextHandler, event );;
}
}
/**
* initialize the Mac toolboxes and set the default menubar
*/
void fl_open_display() {
static char beenHereDoneThat = 0;
if ( !beenHereDoneThat ) {
beenHereDoneThat = 1;
FlushEvents(everyEvent,0);
MoreMasters(); // \todo Carbon suggests MoreMasterPointers()
AEInstallEventHandler( kCoreEventClass, kAEQuitApplication, NewAEEventHandlerUPP((AEEventHandlerProcPtr)QuitAppleEventHandler), 0, false );
// create the Mac Handle for the default cursor (a pointer to a pointer)
GetQDGlobalsArrow(&default_cursor);
default_cursor_ptr = &default_cursor;
fl_default_cursor = &default_cursor_ptr;
ClearMenuBar();
AppendResMenu( GetMenuHandle( 1 ), 'DRVR' );
DrawMenuBar();
}
}
/**
* get rid of allocated resources
*/
void fl_close_display() {
}
/**
* smallest x ccordinate in screen space
*/
int Fl::x() {
BitMap r;
GetQDGlobalsScreenBits(&r);
return r.bounds.left;
}
/**
* smallest y ccordinate in screen space
*/
int Fl::y() {
BitMap r;
GetQDGlobalsScreenBits(&r);
return r.bounds.top + 20; // \todo 20 pixel menu bar?
}
/**
* screen width (single monitor!?)
*/
int Fl::w() {
BitMap r;
GetQDGlobalsScreenBits(&r);
return r.bounds.right - r.bounds.left;
}
/**
* screen height (single monitor!?)
*/
int Fl::h() {
BitMap r;
GetQDGlobalsScreenBits(&r);
return r.bounds.bottom - r.bounds.top - 20;
}
/**
* get the current mouse pointer world coordinates
*/
void Fl::get_mouse(int &x, int &y)
{
fl_open_display();
Point loc;
GetMouse( &loc );
LocalToGlobal( &loc );
x = loc.h;
y = loc.v;
}
/**
* convert Mac keystrokes to FLTK
*/
unsigned short mac2fltk(ulong macKey)
{
unsigned short cc = macKeyLookUp[(macKey>>8)&0x7f];
if (cc) return cc;
return macKey&0xff;
}
/**
* Initialize the given port for redraw and call the windw's flush() to actually draw the content
*/
void Fl_X::flush()
{
w->flush();
SetOrigin( 0, 0 );
//QDFlushPortBuffer( GetWindowPort(xid), 0 ); // \todo do we need this?
}
/**
* Handle all clipping and redraw for the given port
* There are two different callers for this event:
* 1: the OS can request a redraw and provides all clipping itself
* 2: Fl::flush() wants all redraws now
*/
void handleUpdateEvent( WindowPtr xid )
{
Fl_Window *window = fl_find( xid );
if ( !window ) return;
GrafPtr oldPort;
GetPort( &oldPort );
SetPort( GetWindowPort(xid) );
Fl_X *i = Fl_X::i( window );
i->wait_for_expose = 0;
if ( window->damage() ) {
if ( i->region ) {
InvalWindowRgn( xid, i->region );
}
}
if ( i->region ) { // no region, so the sytem will take the update region from the OS
DisposeRgn( i->region );
i->region = 0;
}
for ( Fl_X *cx = i->xidChildren; cx; cx = cx->xidNext )
{
cx->w->clear_damage(window->damage()|FL_DAMAGE_EXPOSE);
cx->flush();
cx->w->clear_damage();
}
window->clear_damage(window->damage()|FL_DAMAGE_EXPOSE);
i->flush();
window->clear_damage();
SetPort( oldPort );
}
/**
* \todo this is a leftover from OS9 times. Please check how much applies to Carbon!
*/
int Fl_X::fake_X_wm(const Fl_Window* w,int &X,int &Y, int &bt,int &bx, int &by) {
int W, H, xoff, yoff, dx, dy;
int ret = bx = by = bt = 0;
if (w->border() && !w->parent()) {
if (w->maxw != w->minw || w->maxh != w->minh) {
ret = 2;
bx = 6; // \todo Mac : GetSystemMetrics(SM_CXSIZEFRAME);
by = 6; // \todo Mac : get Mac window frame size GetSystemMetrics(SM_CYSIZEFRAME);
} else {
ret = 1;
bx = 6; // \todo Mac : GetSystemMetrics(SM_CXFIXEDFRAME);
by = 6; // \todo Mac : GetSystemMetrics(SM_CYFIXEDFRAME);
}
bt = 22; // \todo Mac : GetSystemMetrics(SM_CYCAPTION);
}
//The coordinates of the whole window, including non-client area
xoff = bx;
yoff = by + bt;
dx = 2*bx;
dy = 2*by + bt;
X = w->x()-xoff;
Y = w->y()-yoff;
W = w->w()+dx;
H = w->h()+dy;
//Proceed to positioning the window fully inside the screen, if possible
//Make border's lower right corner visible
if (Fl::w() < X+W) X = Fl::w() - W;
if (Fl::h() < Y+H) Y = Fl::h() - H;
//Make border's upper left corner visible
if (X<0) X = 0;
if (Y<0) Y = 0;
//Make client area's lower right corner visible
if (Fl::w() < X+dx+ w->w()) X = Fl::w() - w->w() - dx;
if (Fl::h() < Y+dy+ w->h()) Y = Fl::h() - w->h() - dy;
//Make client area's upper left corner visible
if (X+xoff < 0) X = -xoff;
if (Y+yoff < 0) Y = -yoff;
//Return the client area's top left corner in (X,Y)
X+=xoff;
Y+=yoff;
return ret;
}
/**
* convert a Mac FSSpec structure into a Unix filename
*/
static int FSSpec2UnixPath( FSSpec *fs, char *dst )
{
FSRef fsRef;
FSpMakeFSRef( fs, &fsRef );
FSRefMakePath( &fsRef, (UInt8*)dst, 1024 );
return strlen(dst);
/* keep the code below. The above function is only implemented in OS X, so we might need the other code for OS 9 and friends
short offset = 0;
if ( fs->parID != fsRtParID )
{
FSSpec parent;
OSErr ret = FSMakeFSSpec( fs->vRefNum, fs->parID, 0, &parent );
if ( ret != noErr ) return 0;
offset = FSSpec2UnixPath( &parent, dst );
}
if ( fs->parID == fsRtParID && fs->vRefNum == -100 ) //+ bad hack: we assume that volume -100 is mounted as root
{
memcpy( dst, "/", 2 );
return 1; // don't add anything to the filename - we are fine already
}
short len = fs->name[0];
if ( fs->parID == fsRtParID ) { // assume tat all other volumes are in this directory (international name WILL vary!)
memcpy( dst, "/Volumes", 8 );
offset = 8;
}
if ( offset!=1 ) dst[ offset++ ] = '/'; // avoid double '/'
memcpy( dst+offset, fs->name+1, len );
dst[ len+offset ] = 0;
return len+offset;
*/
}
Fl_Window *fl_dnd_target_window = 0;
#include <FL/fl_draw.H>
/**
* Drag'n'drop tracking handler
*/
static pascal OSErr dndTrackingHandler( DragTrackingMessage msg, WindowPtr w, void *userData, DragReference dragRef )
{
Fl_Window *target = (Fl_Window*)userData;
Point mp;
static int px, py;
switch ( msg )
{
case kDragTrackingEnterWindow:
// check if 'TEXT' is available
GetDragMouse( dragRef, &mp, 0 );
Fl::e_x_root = px = mp.h;
Fl::e_y_root = py = mp.v;
Fl::e_x = px - target->x();
Fl::e_y = py - target->y();
fl_dnd_target_window = target;
if ( Fl::handle( FL_DND_ENTER, target ) )
fl_cursor( FL_CURSOR_HAND ); //ShowDragHilite( ); // modify the mouse cursor?!
else
fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef );
breakMacEventLoop();
return noErr;
case kDragTrackingInWindow:
GetDragMouse( dragRef, &mp, 0 );
if ( mp.h==px && mp.v==py )
break; //+ return previous condition for dnd hiliting
Fl::e_x_root = px = mp.h;
Fl::e_y_root = py = mp.v;
Fl::e_x = px - target->x();
Fl::e_y = py - target->y();
fl_dnd_target_window = target;
if ( Fl::handle( FL_DND_DRAG, target ) )
fl_cursor( FL_CURSOR_HAND ); //ShowDragHilite( ); // modify the mouse cursor?!
else
fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef );
breakMacEventLoop();
return noErr;
break;
case kDragTrackingLeaveWindow:
// HideDragHilite()
fl_cursor( FL_CURSOR_DEFAULT ); //HideDragHilite( dragRef );
if ( fl_dnd_target_window )
{
Fl::handle( FL_DND_LEAVE, fl_dnd_target_window );
fl_dnd_target_window = 0;
}
breakMacEventLoop();
return noErr;
}
return noErr;
}
/**
* Drag'n'drop receive handler
*/
static pascal OSErr dndReceiveHandler( WindowPtr w, void *userData, DragReference dragRef )
{
Point mp;
OSErr ret;
Fl_Window *target = fl_dnd_target_window = (Fl_Window*)userData;
GetDragMouse( dragRef, &mp, 0 );
Fl::e_x_root = mp.h;
Fl::e_y_root = mp.v;
Fl::e_x = Fl::e_x_root - target->x();
Fl::e_y = Fl::e_y_root - target->y();
if ( !Fl::handle( FL_DND_RELEASE, target ) )
return userCanceledErr;
// get the ASCII text
UInt16 i, nItem;
ItemReference itemRef;
FlavorFlags flags;
Size itemSize, size = 0;
CountDragItems( dragRef, &nItem );
for ( i = 1; i <= nItem; i++ )
{
GetDragItemReferenceNumber( dragRef, i, &itemRef );
ret = GetFlavorFlags( dragRef, itemRef, 'TEXT', &flags );
if ( ret == noErr )
{
GetFlavorDataSize( dragRef, itemRef, 'TEXT', &itemSize );
size += itemSize;
}
ret = GetFlavorFlags( dragRef, itemRef, 'hfs ', &flags );
if ( ret == noErr )
{
size += 1024; //++ ouch! We should create the full pathname and figure out its length
}
}
if ( !size )
return userCanceledErr;
Fl::e_length = size + nItem - 1;
char *dst = Fl::e_text = (char*)malloc( size+nItem );;
for ( i = 1; i <= nItem; i++ )
{
GetDragItemReferenceNumber( dragRef, i, &itemRef );
ret = GetFlavorFlags( dragRef, itemRef, 'TEXT', &flags );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -