diff -u wine-cvs/include/user.h wine/include/user.h
--- wine-cvs/include/user.h	2002-12-03 18:34:53.000000000 -0500
+++ wine/include/user.h	2003-02-13 05:25:59.000000000 -0500
@@ -73,6 +73,8 @@
     INT    (*pGetKeyNameText)(LONG,LPSTR,INT);
     INT    (*pToUnicode)(UINT, UINT, LPBYTE, LPWSTR, int, UINT);
     void   (*pBeep)(void);
+    BOOL   (*pRegisterHotKey)(HWND, INT, UINT, UINT);
+    BOOL   (*pUnregisterHotKey)(HWND, INT);
     /* mouse functions */
     void   (*pInitMouse)(LPBYTE);
     void   (*pSetCursor)(struct tagCURSORICONINFO *);
diff -u wine-cvs/include/winbase.h wine/include/winbase.h
--- wine-cvs/include/winbase.h	2003-01-13 15:44:13.000000000 -0500
+++ wine/include/winbase.h	2003-02-13 05:27:35.000000000 -0500
@@ -1446,6 +1446,7 @@
 HANDLE      WINAPI RegisterEventSourceA(LPCSTR,LPCSTR);
 HANDLE      WINAPI RegisterEventSourceW(LPCWSTR,LPCWSTR);
 #define     RegisterEventSource WINELIB_NAME_AW(RegisterEventSource)
+BOOL        WINAPI RegisterHotKey(HWND,INT,UINT,UINT);
 BOOL        WINAPI ReleaseMutex(HANDLE);
 BOOL        WINAPI ReleaseSemaphore(HANDLE,LONG,LPLONG);
 BOOL        WINAPI ReportEventA(HANDLE,WORD,WORD,DWORD,PSID,WORD,DWORD,LPCSTR *,LPVOID);
@@ -1522,6 +1523,7 @@
 BOOL        WINAPI UnlockFile(HANDLE,DWORD,DWORD,DWORD,DWORD);
 BOOL        WINAPI UnlockFileEx(HANDLE,DWORD,DWORD,DWORD,LPOVERLAPPED);
 BOOL        WINAPI UnmapViewOfFile(LPVOID);
+BOOL        WINAPI UnregisterHotKey(HWND,INT);
 BOOL        WINAPI VerifyVersionInfoA(LPOSVERSIONINFOEXA,DWORD,DWORDLONG);
 BOOL        WINAPI VerifyVersionInfoW(LPOSVERSIONINFOEXW,DWORD,DWORDLONG);
 #define     VerifyVersionInfo WINELIB_NAME_AW(VerifyVersionInfo)
diff -u wine-cvs/dlls/user/user_main.c wine/dlls/user/user_main.c
--- wine-cvs/dlls/user/user_main.c	2002-12-03 18:34:54.000000000 -0500
+++ wine/dlls/user/user_main.c	2003-02-13 04:52:14.000000000 -0500
@@ -82,6 +82,8 @@
     GET_USER_FUNC(GetKeyNameText);
     GET_USER_FUNC(ToUnicode);
     GET_USER_FUNC(Beep);
+    GET_USER_FUNC(RegisterHotKey);
+    GET_USER_FUNC(UnregisterHotKey);
     GET_USER_FUNC(InitMouse);
     GET_USER_FUNC(SetCursor);
     GET_USER_FUNC(GetCursorPos);
diff -u wine-cvs/windows/input.c wine/windows/input.c
--- wine-cvs/windows/input.c	2003-01-07 19:27:58.000000000 -0500
+++ wine/windows/input.c	2003-02-13 11:47:51.000000000 -0500
@@ -876,16 +876,20 @@
  *		RegisterHotKey (USER32.@)
  */
 BOOL WINAPI RegisterHotKey(HWND hwnd,INT id,UINT modifiers,UINT vk) {
-	FIXME_(keyboard)("(%p,%d,0x%08x,%d): stub\n",hwnd,id,modifiers,vk);
-	return TRUE;
+    TRACE_(keyboard)("(%p,0x%x,0x%08x,0x%08x)\n",hwnd,id,modifiers,vk);
+    if (USER_Driver.pRegisterHotKey) 
+	return USER_Driver.pRegisterHotKey( hwnd, id, modifiers, vk );
+    return FALSE;
 }
 
 /***********************************************************************
  *		UnregisterHotKey (USER32.@)
  */
 BOOL WINAPI UnregisterHotKey(HWND hwnd,INT id) {
-	FIXME_(keyboard)("(%p,%d): stub\n",hwnd,id);
-	return TRUE;
+    TRACE_(keyboard)("(%p,%d)\n",hwnd,id);
+    if (USER_Driver.pUnregisterHotKey) 
+	return USER_Driver.pUnregisterHotKey( hwnd, id );
+    return FALSE;
 }
 
 /***********************************************************************
diff -u wine-cvs/dlls/x11drv/keyboard.c wine/dlls/x11drv/keyboard.c
--- wine-cvs/dlls/x11drv/keyboard.c	2003-01-07 15:36:22.000000000 -0500
+++ wine/dlls/x11drv/keyboard.c	2003-02-18 17:13:45.000000000 -0500
@@ -837,6 +837,88 @@
     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x153              /* FFF8 */
 };
 
+/***********************************************************************
+ * 				HotKey
+ */
+typedef struct GRABKEY_INFO {
+    HWND hWnd;			/* windows window to receive hot-key notification */
+    INT	id;			/* windows identifier of hot key */
+    UINT fsModifiers;		/* windows key-modifier flag */
+    UINT vk;			/* windows virtual-key code */
+    int x_keycode;		/* X keycode */
+    unsigned int x_modifiers;	/* X modifiers */
+} GRABKEY_INFO;
+
+static GRABKEY_INFO * pKeys = 0;
+static int nKeys = 0;
+static int nKeysMax = 0;
+
+static int add_grab(HWND hwnd, INT id, UINT modifiers, UINT vk, unsigned int x_modifiers, int x_keycode)
+{
+    TRACE("(%p,%x,%x,%x,%x,%x)\n",hwnd,id,modifiers,vk,x_modifiers,x_keycode);
+
+    if ( (pKeys == 0) || (nKeys == nKeysMax) ) {
+	GRABKEY_INFO * temp;
+	temp = (GRABKEY_INFO *)HeapReAlloc(GetProcessHeap(),0, pKeys, (nKeysMax + 10) * sizeof(GRABKEY_INFO));
+	if (temp) {
+	    pKeys = temp;
+	    nKeysMax += 10;
+	} else
+	    return False;
+    }
+
+    pKeys[nKeys].hWnd = hwnd;
+    pKeys[nKeys].id = id;
+    pKeys[nKeys].fsModifiers = modifiers;
+    pKeys[nKeys].vk = vk;
+    pKeys[nKeys].x_keycode = x_keycode;
+    pKeys[nKeys].x_modifiers = x_modifiers;
+    nKeys++;
+    return True;
+}
+
+static GRABKEY_INFO * find_grab(INT id)
+{
+    int i;
+    TRACE("(%x)\n", id);
+    for (i = 0; i < nKeys; i++) {
+	if (pKeys[i].id == id)
+	    return &pKeys[i];
+    }
+    return 0;
+}
+
+static GRABKEY_INFO * has_grab(XKeyEvent *event)
+{
+    int i;
+    TRACE("(%p) event->keycode=%d\n",event,event->keycode);
+    for (i = 0; i < nKeys; i++) {
+	if (pKeys[i].x_keycode == event->keycode) 
+	    return &pKeys[i];
+    }
+    return 0;
+}
+
+static int remove_grab(INT id)
+{
+    int i,j;
+    TRACE("(%x)\n", id);
+    for (i = 0; i < nKeys; i++) {
+	if (pKeys[i].id == id) {
+	    for (j = i; j < (nKeys - 1); j++)
+		pKeys[j] = pKeys[j + 1];
+	    nKeys--;
+	    if (nKeys == 0) {
+		HeapFree(GetProcessHeap(),0, pKeys);
+		pKeys = 0;
+		nKeysMax = 0;
+	    }
+	    return True;
+	}
+    }
+    return False;
+}
+
 
 /* Returns the Windows virtual key code associated with the X event <e> */
 /* x11 lock must be held */
@@ -991,6 +1073,15 @@
 
     DWORD event_time = event->time - X11DRV_server_startticks;
 
+    if (event->type == KeyPress) {
+	GRABKEY_INFO * hotkey = has_grab(event);
+
+	if (hotkey) {
+	    PostMessageA(hotkey->hWnd, WM_HOTKEY, hotkey->id, 0);
+	    return;
+	}
+    }
+
     /* this allows support for dead keys */
     if ((event->keycode >> 8) == 0x10)
 	event->keycode=(event->keycode & 0xff);
@@ -1903,3 +1994,74 @@
 {
   TSXBell(thread_display(), 0);
 }
+
+/***********************************************************************
+ *		RegisterHotKey (X11DRV.@)
+ */
+BOOL X11DRV_RegisterHotKey(HWND hwnd,INT id,UINT modifiers,UINT vk)
+{
+    Display *display;
+    Window window;
+    unsigned int x_modifiers = 0;
+    int x_keycode = 0;
+    int err;
+    int keyc;
+
+    TRACE("(%p,0x%x,0x%08x,0x%08x)\n",hwnd,id,modifiers,vk);
+    
+    display = thread_display();
+    window = X11DRV_get_client_window(hwnd);
+
+    /* FIXME: finish */
+    if (modifiers & MOD_ALT)
+	x_modifiers |= 0;
+    if (modifiers & MOD_CONTROL)
+	x_modifiers |= ControlMask;
+    if (modifiers & MOD_SHIFT)
+	x_modifiers |= ShiftMask;
+    if (modifiers & MOD_WIN)
+	x_modifiers |= 0;
+
+    for (keyc=min_keycode; keyc<=max_keycode; keyc++) {
+	if ((keyc2vkey[keyc] & 0xFF) == vk) {
+	    TRACE("keycode found\n");
+	    x_keycode = keyc;
+	    break;
+	}
+    }
+
+    if (keyc > max_keycode) {
+	TRACE("keycode not found\n");
+	return FALSE;
+    }
+
+    err = TSXGrabKey(display, x_keycode, x_modifiers, DefaultRootWindow(display), False, GrabModeAsync, GrabModeAsync);
+    if (err == 0) {
+	/* FIXME: set proper error value */
+	SetLastError(ERROR_HOTKEY_ALREADY_REGISTERED);
+    } else {
+	add_grab(hwnd, id, modifiers, vk, x_modifiers, x_keycode);
+	return TRUE;
+    }
+
+    return FALSE;
+}
+
+/***********************************************************************
+ *		UnregisterHotKey (X11DRV.@)
+ */
+BOOL X11DRV_UnregisterHotKey(HWND hwnd,INT id)
+{
+    Display *display = thread_display();
+    Window window = X11DRV_get_client_window(hwnd);
+    GRABKEY_INFO * grab = find_grab(id);
+
+    TRACE("(%lx,%d)\n",(DWORD)hwnd,id);
+
+    if (grab) {
+	TSXUngrabKey(display, grab->x_keycode, grab->x_modifiers, window);
+	remove_grab(id);
+	return TRUE;
+    }
+    return FALSE;
+}
diff -u wine-cvs/dlls/x11drv/X11_calls wine/dlls/x11drv/X11_calls
--- wine-cvs/dlls/x11drv/X11_calls	2002-09-24 23:29:55.000000000 -0400
+++ wine/dlls/x11drv/X11_calls	2003-02-13 12:54:34.000000000 -0500
@@ -41,6 +41,7 @@
 XGetSelectionOwner
 XGetWindowAttributes
 XGetWindowProperty
+XGrabKey
 XGrabPointer
 XGrabServer
 XInternAtom
@@ -74,6 +75,7 @@
 XSync
 XTextExtents16
 XTextWidth16
+XUngrabKey
 XUngrabPointer
 XUngrabServer
 XUninstallColormap
diff -u wine-cvs/dlls/x11drv/x11drv.spec wine/dlls/x11drv/x11drv.spec
--- wine-cvs/dlls/x11drv/x11drv.spec	2002-11-14 17:30:20.000000000 -0500
+++ wine/dlls/x11drv/x11drv.spec	2003-02-13 12:48:31.000000000 -0500
@@ -66,6 +66,8 @@
 @ cdecl GetKeyNameText(long str long) X11DRV_GetKeyNameText
 @ cdecl ToUnicode(long long ptr ptr long long) X11DRV_ToUnicode
 @ cdecl Beep() X11DRV_Beep
+@ cdecl RegisterHotKey(long long long long) X11DRV_RegisterHotKey
+@ cdecl UnregisterHotKey(long long) X11DRV_UnregisterHotKey
 @ cdecl InitMouse(ptr) X11DRV_InitMouse
 @ cdecl SetCursor(ptr) X11DRV_SetCursor
 @ cdecl GetCursorPos(ptr) X11DRV_GetCursorPos
