~ubuntu-branches/ubuntu/karmic/fltk1.1/karmic

« back to all changes in this revision

Viewing changes to src/Fl_mac.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Aaron M. Ucko
  • Date: 2005-05-22 13:57:06 UTC
  • mfrom: (2.1.1 hoary)
  • Revision ID: james.westby@ubuntu.com-20050522135706-mchag24yf42lu7bu
Tags: 1.1.6-5
* Revert previous change, which seems to have been ineffective for some
  reason, in favor of commenting out the problematic Makefile rule
  altogether.  (Closes: #310151.)
* debian/control: Go back to specifying the URL as part of the
  description rather than via a non-standard field that doesn't seem to
  have caught on.  (Closes: #310240.)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
//
2
 
// "$Id: Fl_mac.cxx,v 1.1.2.54 2004/04/11 04:38:59 easysw Exp $"
 
2
// "$Id: Fl_mac.cxx,v 1.1.2.65 2004/11/23 00:28:35 matthiaswm Exp $"
3
3
//
4
4
// MacOS specific code for the Fast Light Tool Kit (FLTK).
5
5
//
36
36
// One Compile to copy them all and in the bundle bind them,
37
37
// in the Land of MacOS X where the Drop-Shadows lie.
38
38
 
 
39
// warning: the Apple Quartz version still uses some Quickdraw calls,
 
40
//          mostly to get around the single active context in QD and 
 
41
//          to implement clipping. This should be changed into pure
 
42
//          Quartz calls in the near future.
39
43
 
40
44
// we don't need the following definition because we deliver only
41
45
// true mouse moves.  On very slow systems however, this flag may
45
49
#include <pthread.h>
46
50
}
47
51
 
 
52
#include <config.h>
48
53
#include <FL/Fl.H>
49
54
#include <FL/x.H>
50
55
#include <FL/Fl_Tooltip.H>
78
83
 
79
84
// public variables
80
85
int fl_screen;
 
86
CGContextRef fl_gc = 0;
81
87
Handle fl_system_menu;
82
88
Fl_Sys_Menu_Bar *fl_sys_menu_bar = 0;
83
89
CursHandle fl_default_cursor;
131
137
    FL_KP+'6', FL_KP+'7', 0, FL_KP+'8', FL_KP+'9', 0, 0, 0,
132
138
 
133
139
    FL_F+5, FL_F+6, FL_F+7, FL_F+3, FL_F+8, FL_F+9, 0, FL_F+11,
134
 
    0, 0, FL_Print, FL_Scroll_Lock, 0, FL_F+10, 0, FL_F+12,
 
140
    0, 0, FL_Print, FL_Scroll_Lock, 0, FL_F+10, FL_Menu, FL_F+12,
135
141
 
136
142
    0, FL_Pause, FL_Help, FL_Home, FL_Page_Up, FL_Delete, FL_F+4, FL_End,
137
143
    FL_F+2, FL_Page_Down, FL_F+1, FL_Left, FL_Right, FL_Down, FL_Up, 0,
936
942
  else if ( mods & rightShiftKey ) Fl::e_keysym = FL_Shift_R;
937
943
  else if ( mods & alphaLock ) Fl::e_keysym = FL_Caps_Lock;
938
944
  else Fl::e_keysym = 0;
 
945
  //printf( "to sym 0x%08x (%04x)\n", Fl::e_keysym, mods );
939
946
}
940
947
 
941
948
/**
960
967
/**
961
968
 * handle carbon keyboard events
962
969
 */
963
 
pascal OSStatus carbonKeyboardHandler( EventHandlerCallRef nextHandler, EventRef event, void *userData )
 
970
pascal OSStatus carbonKeyboardHandler( 
 
971
  EventHandlerCallRef nextHandler, EventRef event, void *userData )
964
972
{
965
973
  static char buffer[5];
966
974
  int sendEvent = 0;
970
978
 
971
979
  fl_lock_function();
972
980
  
973
 
  GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &mods );
 
981
  int kind = GetEventKind(event);
 
982
  
 
983
  // get the modifiers for any of the events
 
984
  GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, 
 
985
                     NULL, sizeof(UInt32), NULL, &mods );
974
986
  if ( prevMods == 0xffffffff ) prevMods = mods;
975
 
  UInt32 keyCode;
976
 
  GetEventParameter( event, kEventParamKeyCode, typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode );
977
 
  unsigned char key;
978
 
  GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, NULL, sizeof(char), NULL, &key );
979
 
  unsigned short sym;
980
 
 
981
 
  switch ( GetEventKind( event ) )
 
987
  
 
988
  // get the key code only for key events
 
989
  UInt32 keyCode = 0;
 
990
  unsigned char key = 0;
 
991
  unsigned short sym = 0;
 
992
  if (kind!=kEventRawKeyModifiersChanged) {
 
993
    GetEventParameter( event, kEventParamKeyCode, typeUInt32, 
 
994
                       NULL, sizeof(UInt32), NULL, &keyCode );
 
995
    GetEventParameter( event, kEventParamKeyMacCharCodes, typeChar, 
 
996
                       NULL, sizeof(char), NULL, &key );
 
997
  }
 
998
  /* output a human readbale event identifier for debugging
 
999
  const char *ev = "";
 
1000
  switch (kind) {
 
1001
    case kEventRawKeyDown: ev = "kEventRawKeyDown"; break;
 
1002
    case kEventRawKeyRepeat: ev = "kEventRawKeyRepeat"; break;
 
1003
    case kEventRawKeyUp: ev = "kEventRawKeyUp"; break;
 
1004
    case kEventRawKeyModifiersChanged: ev = "kEventRawKeyModifiersChanged"; break;
 
1005
    default: ev = "unknown";
 
1006
  }
 
1007
  printf("%08x %08x %08x '%c' %s \n", mods, keyCode, key, key, ev);
 
1008
  */
 
1009
  switch (kind)
982
1010
  {
983
1011
  case kEventRawKeyDown:
984
1012
  case kEventRawKeyRepeat:
986
1014
    // fall through
987
1015
  case kEventRawKeyUp:
988
1016
    if ( !sendEvent ) sendEvent = FL_KEYUP;
989
 
    // if the user pressed alt/option, event_key should have the keycap, but event_text should generate the international symbol
 
1017
    // if the user pressed alt/option, event_key should have the keycap, 
 
1018
    // but event_text should generate the international symbol
990
1019
    if ( isalpha(key) )
991
1020
      sym = tolower(key);
992
1021
    else if ( Fl::e_state&FL_CTRL && key<32 )
993
1022
      sym = key+96;
994
 
    else if ( Fl::e_state&FL_ALT )
995
 
      sym = keycode_to_sym( keyCode & 0x7f, 0, macKeyLookUp[ keyCode & 0x7f ] ); // find the keycap of this key
 
1023
    else if ( Fl::e_state&FL_ALT ) // find the keycap of this key
 
1024
      sym = keycode_to_sym( keyCode & 0x7f, 0, macKeyLookUp[ keyCode & 0x7f ] );
996
1025
    else
997
1026
      sym = macKeyLookUp[ keyCode & 0x7f ];
998
1027
    Fl::e_keysym = sym;
999
1028
    if ( keyCode==0x4c ) key=0x0d;
1000
 
    if ( ( (sym>=FL_KP) && (sym<=FL_KP_Last) ) || ((sym&0xff00)==0) || (sym==FL_Tab) || (sym==FL_Enter) ) {
 
1029
    // Matt: the Mac has no concept of a NumLock key, or at least not visible
 
1030
    // Matt: to Carbon. The kEventKeyModifierNumLockMask is only set when
 
1031
    // Matt: a numeric keypad key is pressed and does not correspond with
 
1032
    // Matt: the NumLock light in PowerBook keyboards.
 
1033
    if ( (sym >= FL_KP && sym <= FL_KP_Last) || !(sym & 0xff00) ||
 
1034
            sym == FL_Tab || sym == FL_Enter) {
1001
1035
      buffer[0] = key;
1002
1036
      Fl::e_length = 1;
1003
1037
    } else {
1023
1057
  }
1024
1058
  while (window->parent()) window = window->window();
1025
1059
  if (sendEvent && Fl::handle(sendEvent,window)) {
1026
 
    fl_unlock_function();
1027
 
  
 
1060
    fl_unlock_function();  
1028
1061
    return noErr; // return noErr if FLTK handled the event
1029
1062
  } else {
1030
1063
    fl_unlock_function();
1031
 
  
1032
 
    return CallNextEventHandler( nextHandler, event );;
 
1064
    //return CallNextEventHandler( nextHandler, event );;
 
1065
    // Matt: I had better results (no duplicate events) always returning
 
1066
    // Matt: 'noErr'. System keyboard events still seem to work just fine.
 
1067
    return noErr;
1033
1068
  }
1034
1069
}
1035
1070
 
1221
1256
void Fl_X::flush()
1222
1257
{
1223
1258
  w->flush();
 
1259
#ifdef __APPLE_QD__
 
1260
  GrafPtr port; 
 
1261
  GetPort( &port );
 
1262
  if ( port )
 
1263
    QDFlushPortBuffer( port, 0 );
 
1264
#elif defined (__APPLE_QUARTZ__)
 
1265
  if (fl_gc) 
 
1266
    CGContextFlush(fl_gc);
 
1267
#endif          
1224
1268
  SetOrigin( 0, 0 );
1225
 
  //QDFlushPortBuffer( GetWindowPort(xid), 0 ); // \todo do we need this?
1226
1269
}
1227
1270
 
1228
1271
 
1292
1335
  H = w->h()+dy;
1293
1336
 
1294
1337
  //Proceed to positioning the window fully inside the screen, if possible
1295
 
  //Make border's lower right corner visible
1296
 
  if (Fl::w() < X+W) X = Fl::w() - W;
1297
 
  if (Fl::h() < Y+H) Y = Fl::h() - H;
1298
 
  //Make border's upper left corner visible
1299
 
  if (X<0) X = 0;
1300
 
  if (Y<0) Y = 0;
1301
 
  //Make client area's lower right corner visible
1302
 
  if (Fl::w() < X+dx+ w->w()) X = Fl::w() - w->w() - dx;
1303
 
  if (Fl::h() < Y+dy+ w->h()) Y = Fl::h() - w->h() - dy;
1304
 
  //Make client area's upper left corner visible
1305
 
  if (X+xoff < 0) X = -xoff;
1306
 
  if (Y+yoff < 0) Y = -yoff;
 
1338
 
 
1339
  // let's get a little elaborate here. Mac OS X puts a lot of stuff on the desk
 
1340
  // that we want to avoid when positioning our window, namely the Dock and the
 
1341
  // top menu bar (and even more stuff in 10.4 Tiger). So we will go through the
 
1342
  // list of all available screens and find the one that this window is most
 
1343
  // likely to go to, and then reposition it to fit withing the 'good' area.
 
1344
  Rect r;
 
1345
  // find the screen, that the center of this window will fall into
 
1346
  int R = X+W, B = Y+H; // right and bottom
 
1347
  int cx = (X+R)/2, cy = (Y+B)/2; // center of window;
 
1348
  GDHandle gd = 0L;
 
1349
  for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) {
 
1350
  GDPtr gp = *gd;
 
1351
  if (    cx >= gp->gdRect.left && cx <= gp->gdRect.right
 
1352
       && cy >= gp->gdRect.top  && cy <= gp->gdRect.bottom)
 
1353
    break;
 
1354
  }
 
1355
  // if the center doesn't fall on a screen, try the top left
 
1356
  if (!gd) {
 
1357
    for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) {
 
1358
      GDPtr gp = *gd;
 
1359
      if (    X >= gp->gdRect.left && X <= gp->gdRect.right
 
1360
           && Y >= gp->gdRect.top  && Y <= gp->gdRect.bottom)
 
1361
        break;
 
1362
    }
 
1363
  }
 
1364
  // if that doesn't fall on a screen, try the top right
 
1365
  if (!gd) {
 
1366
    for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) {
 
1367
      GDPtr gp = *gd;
 
1368
      if (    R >= gp->gdRect.left && R <= gp->gdRect.right
 
1369
           && Y >= gp->gdRect.top  && Y <= gp->gdRect.bottom)
 
1370
        break;
 
1371
    }
 
1372
  }
 
1373
  // if that doesn't fall on a screen, try the bottom left
 
1374
  if (!gd) {
 
1375
    for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) {
 
1376
      GDPtr gp = *gd;
 
1377
      if (    X >= gp->gdRect.left && X <= gp->gdRect.right
 
1378
           && B >= gp->gdRect.top  && B <= gp->gdRect.bottom)
 
1379
        break;
 
1380
    }
 
1381
  }
 
1382
  // last resort, try the bottom right
 
1383
  if (!gd) {
 
1384
    for (gd = GetDeviceList(); gd; gd = GetNextDevice(gd)) {
 
1385
      GDPtr gp = *gd;
 
1386
      if (    R >= gp->gdRect.left && R <= gp->gdRect.right
 
1387
           && B >= gp->gdRect.top  && B <= gp->gdRect.bottom)
 
1388
        break;
 
1389
    }
 
1390
  }
 
1391
  // if we still have not found a screen, we will use the main
 
1392
  // screen, the one that has the application menu bar.
 
1393
  if (!gd) gd = GetMainDevice();
 
1394
  if (gd) {
 
1395
    GetAvailableWindowPositioningBounds(gd, &r);
 
1396
    if ( R > r.right )  X -= R - r.right;
 
1397
    if ( B > r.bottom ) Y -= B - r.bottom;
 
1398
    if ( X < r.left )   X = r.left;
 
1399
    if ( Y < r.top )    Y = r.top;
 
1400
  }
 
1401
 
1307
1402
  //Return the client area's top left corner in (X,Y)
1308
1403
  X+=xoff;
1309
1404
  Y+=yoff;
1320
1415
  FSpMakeFSRef( fs, &fsRef );
1321
1416
  FSRefMakePath( &fsRef, (UInt8*)dst, 1024 );
1322
1417
  return strlen(dst);
1323
 
/* 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
1324
 
  short offset = 0;
1325
 
  if ( fs->parID != fsRtParID )
1326
 
  {
1327
 
    FSSpec parent;
1328
 
    OSErr ret = FSMakeFSSpec( fs->vRefNum, fs->parID, 0, &parent );
1329
 
    if ( ret != noErr ) return 0;
1330
 
    offset = FSSpec2UnixPath( &parent, dst );
1331
 
  }
1332
 
 
1333
 
  if ( fs->parID == fsRtParID && fs->vRefNum == -100 ) //+ bad hack: we assume that volume -100 is mounted as root
1334
 
  {
1335
 
    memcpy( dst, "/", 2 );
1336
 
    return 1; // don't add anything to the filename - we are fine already
1337
 
  }
1338
 
 
1339
 
  short len = fs->name[0];
1340
 
  if ( fs->parID == fsRtParID ) { // assume tat all other volumes are in this directory (international name WILL vary!)
1341
 
    memcpy( dst, "/Volumes", 8 );
1342
 
    offset = 8;
1343
 
  }
1344
 
  
1345
 
  if ( offset!=1 ) dst[ offset++ ] = '/'; // avoid double '/'
1346
 
  memcpy( dst+offset, fs->name+1, len );
1347
 
  dst[ len+offset ] = 0;
1348
 
  return len+offset;
1349
 
*/
1350
1418
}
1351
1419
 
1352
1420
Fl_Window *fl_dnd_target_window = 0;
1495
1563
 */
1496
1564
void Fl_X::make(Fl_Window* w)
1497
1565
{
1498
 
  static int xyPos = 50;
 
1566
  static int xyPos = 100;
1499
1567
  if ( w->parent() ) // create a subwindow
1500
1568
  {
1501
1569
    Fl_Group::current(0);
1510
1578
    x->region = 0;
1511
1579
    x->subRegion = 0;
1512
1580
    x->cursor = fl_default_cursor;
 
1581
    x->gc = 0; // stay 0 for Quickdraw; fill with CGContext for Quartz
1513
1582
    Fl_Window *win = w->window();
1514
1583
    Fl_X *xo = Fl_X::i(win);
1515
1584
    w->set_visible();
1570
1639
      w->x(xyPos+Fl::x());
1571
1640
      w->y(xyPos+Fl::y());
1572
1641
      xyPos += 25;
1573
 
      if (xyPos>200) xyPos = 25;
 
1642
      if (xyPos>200) xyPos = 100;
1574
1643
    } else {
1575
1644
      if (!Fl::grab()) {
1576
1645
        xp = xwm; yp = ywm;
1608
1677
    x->cursor = fl_default_cursor;
1609
1678
    x->xidChildren = 0;
1610
1679
    x->xidNext = 0;
 
1680
    x->gc = 0;
1611
1681
 
1612
1682
    winattr &= GetAvailableWindowAttributes( winclass );        // make sure that the window will open
1613
1683
    CreateNewWindow( winclass, winattr, &wRect, &(x->xid) );
1811
1881
 */
1812
1882
void Fl_Window::make_current() 
1813
1883
{
 
1884
#ifdef __APPLE_QUARTZ__
 
1885
  Fl_X::q_release_context();
 
1886
#endif
1814
1887
  if ( !fl_window_region )
1815
1888
    fl_window_region = NewRgn();
1816
1889
  fl_window = i->xid;
1845
1918
  
1846
1919
  fl_clip_region( 0 );
1847
1920
  SetPortClipRegion( GetWindowPort(i->xid), fl_window_region );
 
1921
#ifdef __APPLE_QUARTZ__
 
1922
  QDBeginCGContext(GetWindowPort(i->xid), &i->gc);
 
1923
  fl_gc = i->gc;
 
1924
  CGContextSaveGState(fl_gc);
 
1925
  Fl_X::q_fill_context();
 
1926
#endif
1848
1927
  return;
1849
1928
}
1850
1929
 
 
1930
// helper function to manage the current CGContext fl_gc
 
1931
#ifdef __APPLE_QUARTZ__
 
1932
extern Fl_Color fl_color_;
 
1933
extern class Fl_FontSize *fl_fontsize;
 
1934
extern void fl_font(class Fl_FontSize*);
 
1935
extern void fl_quartz_restore_line_style_();
 
1936
 
 
1937
// FLTK has only on global graphics state. This function copies the FLTK state into the
 
1938
// current Quartz context
 
1939
void Fl_X::q_fill_context() {
 
1940
  if (!fl_gc) return;
 
1941
  int hgt = 0;
 
1942
  if (fl_window) {
 
1943
    Rect portRect; 
 
1944
    GetPortBounds(GetWindowPort( fl_window ), &portRect);
 
1945
    hgt = portRect.bottom-portRect.top;
 
1946
  } else {
 
1947
    hgt = CGBitmapContextGetHeight(fl_gc);
 
1948
  }
 
1949
  CGContextTranslateCTM(fl_gc, 0.5, hgt-0.5f);
 
1950
  CGContextScaleCTM(fl_gc, 1.0f, -1.0f);
 
1951
  static CGAffineTransform font_mx = { 1, 0, 0, -1, 0, 0 };
 
1952
  CGContextSetTextMatrix(fl_gc, font_mx);
 
1953
  fl_font(fl_fontsize);
 
1954
  fl_color(fl_color_);
 
1955
  fl_quartz_restore_line_style_();
 
1956
}
 
1957
 
 
1958
// The only way to reste clipping to its original state is to pop the current graphics
 
1959
// state and restore the global state.
 
1960
void Fl_X::q_clear_clipping() {
 
1961
  if (!fl_gc) return;
 
1962
  CGContextRestoreGState(fl_gc);
 
1963
  CGContextSaveGState(fl_gc);
 
1964
}
 
1965
 
 
1966
// Give the Quartz context back to the system
 
1967
void Fl_X::q_release_context(Fl_X *x) {
 
1968
  if (x && x->gc!=fl_gc) return;
 
1969
  if (!fl_gc) return;
 
1970
  CGContextRestoreGState(fl_gc);
 
1971
  if (fl_window) QDEndCGContext(GetWindowPort(fl_window), &fl_gc);
 
1972
  fl_gc = 0;
 
1973
}
 
1974
 
 
1975
void Fl_X::q_begin_image(CGRect &rect, int cx, int cy, int w, int h) {
 
1976
  CGContextSaveGState(fl_gc);
 
1977
  CGAffineTransform mx = CGContextGetCTM(fl_gc);
 
1978
  CGRect r2 = rect;
 
1979
  r2.origin.x -= 0.5f;
 
1980
  r2.origin.y -= 0.5f;
 
1981
  CGContextClipToRect(fl_gc, r2);
 
1982
  mx.d = -1.0; mx.tx = -mx.tx;
 
1983
  CGContextConcatCTM(fl_gc, mx);
 
1984
  rect.origin.x = rect.origin.x - cx;
 
1985
  rect.origin.y = (mx.ty+0.5f) - rect.origin.y - h + cy;
 
1986
  rect.size.width = w;
 
1987
  rect.size.height = h;
 
1988
}
 
1989
 
 
1990
void Fl_X::q_end_image() {
 
1991
  CGContextRestoreGState(fl_gc);
 
1992
}
 
1993
 
 
1994
#endif
 
1995
 
1851
1996
////////////////////////////////////////////////////////////////
1852
1997
// Cut & paste.
1853
1998
 
1920
2065
 
1921
2066
 
1922
2067
//
1923
 
// End of "$Id: Fl_mac.cxx,v 1.1.2.54 2004/04/11 04:38:59 easysw Exp $".
 
2068
// End of "$Id: Fl_mac.cxx,v 1.1.2.65 2004/11/23 00:28:35 matthiaswm Exp $".
1924
2069
//
1925
2070