Mercurial > pidgin.yaz
comparison plugins/win32/winprefs/gtkappbar.c @ 10531:940f0d8ce380
[gaim-migrate @ 11858]
This is multi-monitor support for docking. This also should fix the multiple "Show Desktop" request causing the contents of of the docked buddy list to permanently disappear. I also added a handling of a couple Window Manager events that probably aren't really necessary, but the MSDN docs say they are. This is certainly not C89 compliant (variable declaration), but it is win32 API, so it probably doesn't matter.
committer: Tailor Script <tailor@pidgin.im>
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Thu, 20 Jan 2005 03:16:04 +0000 |
parents | 719fc957e9ee |
children | f348b3439ce4 |
comparison
equal
deleted
inserted
replaced
10530:a1eddb973f42 | 10531:940f0d8ce380 |
---|---|
35 #include "gtkappbar.h" | 35 #include "gtkappbar.h" |
36 #include "debug.h" | 36 #include "debug.h" |
37 | 37 |
38 #define APPBAR_CALLBACK WM_USER + 1010 | 38 #define APPBAR_CALLBACK WM_USER + 1010 |
39 | 39 |
40 typedef HMONITOR WINAPI gaim_MonitorFromPoint(POINT, DWORD); | |
41 typedef HMONITOR WINAPI gaim_MonitorFromWindow(HWND, DWORD); | |
42 typedef BOOL WINAPI gaim_GetMonitorInfo(HMONITOR, LPMONITORINFO); | |
43 | |
44 /* Retrieve the rectangular display area from the specified monitor | |
45 * Return TRUE if successful, otherwise FALSE | |
46 */ | |
47 static gboolean | |
48 get_rect_from_monitor(HMODULE hmod, HMONITOR monitor, RECT *rect) { | |
49 gaim_GetMonitorInfo *the_GetMonitorInfo; | |
50 | |
51 if (!(the_GetMonitorInfo = (gaim_GetMonitorInfo*) | |
52 GetProcAddress(hmod, "GetMonitorInfoA"))) { | |
53 return FALSE; | |
54 } | |
55 | |
56 MONITORINFO info; | |
57 info.cbSize = sizeof(info); | |
58 if (!the_GetMonitorInfo(monitor, &info)) { | |
59 return FALSE; | |
60 } | |
61 | |
62 CopyRect(rect, &(info.rcMonitor)); | |
63 | |
64 return TRUE; | |
65 } | |
66 | |
67 /** | |
68 * This will only work on Win98+ and Win2K+ | |
69 * Return TRUE if successful, otherwise FALSE | |
70 */ | |
71 static gboolean | |
72 get_rect_at_point_multimonitor(POINT pt, RECT *rect) { | |
73 HMODULE hmod; | |
74 | |
75 if (!(hmod = GetModuleHandle("user32"))) { | |
76 return FALSE; | |
77 } | |
78 | |
79 gaim_MonitorFromPoint *the_MonitorFromPoint; | |
80 if (!(the_MonitorFromPoint = (gaim_MonitorFromPoint*) | |
81 GetProcAddress(hmod, "MonitorFromPoint"))) { | |
82 return FALSE; | |
83 } | |
84 | |
85 HMONITOR monitor = | |
86 the_MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY); | |
87 | |
88 return get_rect_from_monitor(hmod, monitor, rect); | |
89 } | |
90 | |
91 /** | |
92 * This will only work on Win98+ and Win2K+ | |
93 * Return TRUE if successful, otherwise FALSE | |
94 */ | |
95 static gboolean | |
96 get_rect_of_window_multimonitor(HWND window, RECT *rect) { | |
97 HMODULE hmod; | |
98 | |
99 if (!(hmod = GetModuleHandle("user32"))) { | |
100 return FALSE; | |
101 } | |
102 | |
103 gaim_MonitorFromWindow *the_MonitorFromWindow; | |
104 if (!(the_MonitorFromWindow = (gaim_MonitorFromWindow*) | |
105 GetProcAddress(hmod, "MonitorFromWindow"))) { | |
106 return FALSE; | |
107 } | |
108 | |
109 HMONITOR monitor = | |
110 the_MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY); | |
111 | |
112 return get_rect_from_monitor(hmod, monitor, rect); | |
113 } | |
114 | |
115 /* | |
116 * Fallback if cannot get the RECT from the monitor directly | |
117 */ | |
118 static void get_default_workarea(RECT *rect) { | |
119 if (!SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, FALSE)) { | |
120 /* I don't think this will ever happen */ | |
121 rect->left = 0; | |
122 rect->top = 0; | |
123 rect->bottom = GetSystemMetrics(SM_CYSCREEN); | |
124 rect->right = GetSystemMetrics(SM_CXSCREEN); | |
125 } | |
126 } | |
127 | |
128 /* Retrieve the rectangle of the active work area at a point */ | |
129 static RECT get_rect_at_point(POINT pt) { | |
130 RECT rc; | |
131 if (!get_rect_at_point_multimonitor(pt, &rc)) { | |
132 get_default_workarea(&rc); | |
133 } | |
134 return rc; | |
135 } | |
136 | |
137 /* Retrieve the rectangle of the active work area of a window*/ | |
138 static RECT get_rect_of_window(HWND window) { | |
139 RECT rc; | |
140 if (!get_rect_of_window_multimonitor(window, &rc)) { | |
141 get_default_workarea(&rc); | |
142 } | |
143 return rc; | |
144 } | |
145 | |
40 static void get_window_normal_rc(HWND hwnd, RECT *rc) { | 146 static void get_window_normal_rc(HWND hwnd, RECT *rc) { |
41 WINDOWPLACEMENT wplc; | 147 WINDOWPLACEMENT wplc; |
42 GetWindowPlacement(hwnd, &wplc); | 148 GetWindowPlacement(hwnd, &wplc); |
43 CopyRect(rc, &wplc.rcNormalPosition); | 149 CopyRect(rc, &wplc.rcNormalPosition); |
44 } | 150 } |
45 | 151 #if 0 |
46 static void print_rect(RECT *rc) { | 152 static void print_rect(RECT *rc) { |
47 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "RECT: L:%ld R:%ld T:%ld B:%ld\n", | 153 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "RECT: L:%ld R:%ld T:%ld B:%ld\n", |
48 rc->left, rc->right, rc->top, rc->bottom); | 154 rc->left, rc->right, rc->top, rc->bottom); |
49 } | 155 } |
50 | 156 #endif |
51 static void set_toolbar(HWND hwnd, gboolean val) { | 157 static void set_toolbar(HWND hwnd, gboolean val) { |
52 LONG style=0; | 158 LONG style=0; |
53 | 159 |
54 style = GetWindowLong(hwnd, GWL_EXSTYLE); | 160 style = GetWindowLong(hwnd, GWL_EXSTYLE); |
55 if(val && !(style & WS_EX_TOOLWINDOW)) | 161 if(val && !(style & WS_EX_TOOLWINDOW)) |
57 else if(!val && style & WS_EX_TOOLWINDOW) | 163 else if(!val && style & WS_EX_TOOLWINDOW) |
58 style &= ~WS_EX_TOOLWINDOW; | 164 style &= ~WS_EX_TOOLWINDOW; |
59 else | 165 else |
60 return; | 166 return; |
61 SetWindowLong(hwnd, GWL_EXSTYLE, style); | 167 SetWindowLong(hwnd, GWL_EXSTYLE, style); |
62 SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); | 168 SetWindowPos(hwnd, 0, 0, 0, 0, 0, |
169 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); | |
170 | |
171 /* This really should be the following, but SWP_FRAMECHANGED strangely causes initermittent problems "Show Desktop" done more than once. | |
172 * Not having SWP_FRAMECHANGED *should* cause the Style not to be applied, but i haven't noticed any problems | |
173 * SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); | |
174 */ | |
63 } | 175 } |
64 | 176 |
65 static gboolean gtk_appbar_register(GtkAppBar *ab, HWND hwnd) { | 177 static gboolean gtk_appbar_register(GtkAppBar *ab, HWND hwnd) { |
66 APPBARDATA abd; | 178 APPBARDATA abd; |
67 | 179 |
90 ab->docking = FALSE; | 202 ab->docking = FALSE; |
91 } | 203 } |
92 return !ab->registered; | 204 return !ab->registered; |
93 } | 205 } |
94 | 206 |
95 static void gtk_appbar_querypos(GtkAppBar *ab, HWND hwnd, RECT *rc) { | 207 static void gtk_appbar_querypos(GtkAppBar *ab, HWND hwnd, RECT rcWorkspace) { |
96 APPBARDATA abd; | 208 APPBARDATA abd; |
97 int iWidth = 0; | 209 guint iWidth = 0; |
98 | 210 |
99 if(!ab->registered) | 211 if(!ab->registered) |
100 gtk_appbar_register(ab, hwnd); | 212 gtk_appbar_register(ab, hwnd); |
101 | 213 |
102 abd.hWnd = hwnd; | 214 abd.hWnd = hwnd; |
103 abd.cbSize = sizeof(APPBARDATA); | 215 abd.cbSize = sizeof(APPBARDATA); |
104 CopyRect(&abd.rc, rc); | |
105 abd.uEdge = ab->side; | 216 abd.uEdge = ab->side; |
106 | 217 |
107 iWidth = abd.rc.right - abd.rc.left; | 218 iWidth = ab->docked_rect.right - ab->docked_rect.left; |
108 | 219 |
109 abd.rc.top = 0; | 220 abd.rc.top = rcWorkspace.top; |
110 abd.rc.bottom = GetSystemMetrics(SM_CYSCREEN); | 221 abd.rc.bottom = rcWorkspace.bottom; |
111 switch (abd.uEdge) | 222 switch (abd.uEdge) |
112 { | 223 { |
113 case ABE_LEFT: | 224 case ABE_LEFT: |
114 abd.rc.left = 0; | 225 abd.rc.left = rcWorkspace.left; |
115 abd.rc.right = iWidth; | 226 abd.rc.right = rcWorkspace.left + iWidth; |
116 break; | 227 break; |
117 | 228 |
118 case ABE_RIGHT: | 229 case ABE_RIGHT: |
119 abd.rc.right = GetSystemMetrics(SM_CXSCREEN); | 230 abd.rc.right = rcWorkspace.right; |
120 abd.rc.left = abd.rc.right - iWidth; | 231 abd.rc.left = rcWorkspace.right - iWidth; |
121 break; | 232 break; |
122 } | 233 } |
123 | 234 |
124 /* Ask the system for the screen space */ | 235 /* Ask the system for the screen space */ |
125 SHAppBarMessage(ABM_QUERYPOS, &abd); | 236 SHAppBarMessage(ABM_QUERYPOS, &abd); |
133 case ABE_RIGHT: | 244 case ABE_RIGHT: |
134 abd.rc.left = abd.rc.right - iWidth; | 245 abd.rc.left = abd.rc.right - iWidth; |
135 break; | 246 break; |
136 } | 247 } |
137 | 248 |
138 CopyRect(rc, &abd.rc); | 249 CopyRect(&(ab->docked_rect), &abd.rc); |
139 } | 250 } |
140 | 251 |
141 static void gtk_appbar_setpos(GtkAppBar *ab, HWND hwnd) { | 252 static void gtk_appbar_setpos(GtkAppBar *ab, HWND hwnd) { |
142 APPBARDATA abd; | 253 APPBARDATA abd; |
143 | 254 |
163 } | 274 } |
164 | 275 |
165 static GdkFilterReturn wnd_moving(GtkAppBar *ab, GdkXEvent *xevent) { | 276 static GdkFilterReturn wnd_moving(GtkAppBar *ab, GdkXEvent *xevent) { |
166 MSG *msg = (MSG*)xevent; | 277 MSG *msg = (MSG*)xevent; |
167 POINT cp; | 278 POINT cp; |
168 LONG cxScreen; | |
169 RECT *rc = (RECT*)msg->lParam; | 279 RECT *rc = (RECT*)msg->lParam; |
280 RECT monRect; | |
170 int side = -1; | 281 int side = -1; |
282 long dockAreaWidth = 0; | |
171 | 283 |
172 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "wnd_moving\n"); | 284 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "wnd_moving\n"); |
173 | 285 |
174 cxScreen = GetSystemMetrics(SM_CXSCREEN); | |
175 GetCursorPos(&cp); | 286 GetCursorPos(&cp); |
176 | 287 monRect = get_rect_at_point(cp); |
288 | |
289 dockAreaWidth = (monRect.right - monRect.left) / 10; | |
177 /* Which part of the screen are we in ? */ | 290 /* Which part of the screen are we in ? */ |
178 if( cp.x > (cxScreen - (cxScreen / 10)) ) | 291 if (cp.x > (monRect.right - dockAreaWidth)) { |
179 side = ABE_RIGHT; | 292 side = ABE_RIGHT; |
180 else if( cp.x < (cxScreen / 10) ) | 293 } else if (cp.x < (monRect.left + dockAreaWidth)) { |
181 side = ABE_LEFT; | 294 side = ABE_LEFT; |
295 } | |
182 | 296 |
183 if(!ab->docked) { | 297 if(!ab->docked) { |
184 if( (side == ABE_RIGHT || side == ABE_LEFT) ) { | 298 if( (side == ABE_RIGHT || side == ABE_LEFT) ) { |
185 if( !ab->docking ) { | 299 if( !ab->docking ) { |
186 ab->side = side; | 300 ab->side = side; |
187 GetWindowRect(msg->hwnd, &(ab->docked_rect)); | 301 GetWindowRect(msg->hwnd, &(ab->docked_rect)); |
188 gtk_appbar_querypos(ab, msg->hwnd, &(ab->docked_rect)); | 302 gtk_appbar_querypos(ab, msg->hwnd, monRect); |
189 | 303 |
190 /* save pre-docking height */ | 304 /* save pre-docking height */ |
191 ab->undocked_height = rc->bottom - rc->top; | 305 ab->undocked_height = rc->bottom - rc->top; |
192 ab->docking = TRUE; | 306 ab->docking = TRUE; |
193 } | 307 } |
224 gtk_appbar_setpos(ab, msg->hwnd); | 338 gtk_appbar_setpos(ab, msg->hwnd); |
225 } | 339 } |
226 return GDK_FILTER_REMOVE; | 340 return GDK_FILTER_REMOVE; |
227 } | 341 } |
228 return GDK_FILTER_CONTINUE; | 342 return GDK_FILTER_CONTINUE; |
343 } | |
344 | |
345 static GdkFilterReturn wnd_activate(GdkXEvent *xevent) { | |
346 APPBARDATA abd; | |
347 MSG *msg = (MSG*)xevent; | |
348 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "wnd_activate\n"); | |
349 | |
350 abd.hWnd = msg->hwnd; | |
351 abd.cbSize = sizeof(APPBARDATA); | |
352 | |
353 SHAppBarMessage(ABM_ACTIVATE, &abd); | |
354 return GDK_FILTER_CONTINUE; | |
355 } | |
356 | |
357 static GdkFilterReturn wnd_poschanged(GdkXEvent *xevent) { | |
358 APPBARDATA abd; | |
359 MSG *msg = (MSG*)xevent; | |
360 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "wnd_poschanged\n"); | |
361 | |
362 abd.hWnd = msg->hwnd; | |
363 abd.cbSize = sizeof(APPBARDATA); | |
364 | |
365 SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd); | |
366 return GDK_FILTER_CONTINUE; | |
229 } | 367 } |
230 | 368 |
231 static GdkFilterReturn wnd_poschanging(GtkAppBar *ab, GdkXEvent *xevent) { | 369 static GdkFilterReturn wnd_poschanging(GtkAppBar *ab, GdkXEvent *xevent) { |
232 MSG *msg = (MSG*)xevent; | 370 MSG *msg = (MSG*)xevent; |
233 WINDOWPOS *wpos = (WINDOWPOS*)msg->lParam; | 371 WINDOWPOS *wpos = (WINDOWPOS*)msg->lParam; |
349 } | 487 } |
350 #endif | 488 #endif |
351 | 489 |
352 static GdkFilterReturn gtk_appbar_callback(GtkAppBar *ab, GdkXEvent *xevent) { | 490 static GdkFilterReturn gtk_appbar_callback(GtkAppBar *ab, GdkXEvent *xevent) { |
353 MSG *msg = (MSG*)xevent; | 491 MSG *msg = (MSG*)xevent; |
354 | 492 RECT orig; |
355 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback\n"); | 493 |
356 switch (msg->wParam) { | 494 switch (msg->wParam) { |
357 case ABN_STATECHANGE: | 495 case ABN_STATECHANGE: |
358 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_STATECHANGE\n"); | 496 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_STATECHANGE\n"); |
359 break; | 497 break; |
360 | 498 |
361 case ABN_FULLSCREENAPP: | 499 case ABN_FULLSCREENAPP: |
362 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_FULLSCREENAPP: %d\n", (BOOL)msg->lParam); | 500 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_FULLSCREENAPP: %d\n", (BOOL)msg->lParam); |
501 if ((BOOL)msg->lParam) { | |
502 SetWindowPos(msg->hwnd, HWND_BOTTOM, 0, 0, 0, 0, | |
503 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); | |
504 } else { | |
505 SetWindowPos(msg->hwnd, HWND_TOPMOST, 0, 0, 0, 0, | |
506 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); | |
507 } | |
508 | |
363 break; | 509 break; |
364 | 510 |
365 case ABN_POSCHANGED: | 511 case ABN_POSCHANGED: |
366 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_POSCHANGED\n"); | 512 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_POSCHANGED\n"); |
367 gtk_appbar_querypos(ab, msg->hwnd, &(ab->docked_rect)); | 513 CopyRect(&orig, &(ab->docked_rect)); |
368 MoveWindow(msg->hwnd, ab->docked_rect.left, ab->docked_rect.top, | 514 gtk_appbar_querypos(ab, msg->hwnd, get_rect_of_window(msg->hwnd)); |
369 ab->docked_rect.right - ab->docked_rect.left, | 515 if (EqualRect(&orig, &(ab->docked_rect)) == 0) { |
370 ab->docked_rect.bottom - ab->docked_rect.top, TRUE); | 516 MoveWindow(msg->hwnd, ab->docked_rect.left, ab->docked_rect.top, |
517 ab->docked_rect.right - ab->docked_rect.left, | |
518 ab->docked_rect.bottom - ab->docked_rect.top, TRUE); | |
519 } | |
371 gtk_appbar_setpos(ab, msg->hwnd); | 520 gtk_appbar_setpos(ab, msg->hwnd); |
372 break; | 521 break; |
522 #if 0 | |
523 default: | |
524 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: %d\n", msg->wParam); | |
525 #endif | |
373 } | 526 } |
374 return GDK_FILTER_CONTINUE; | 527 return GDK_FILTER_CONTINUE; |
375 } | 528 } |
376 | 529 |
377 static GdkFilterReturn gtk_appbar_event_filter(GdkXEvent *xevent, GdkEvent *event, gpointer data) { | 530 static GdkFilterReturn gtk_appbar_event_filter(GdkXEvent *xevent, GdkEvent *event, gpointer data) { |
381 switch(msg->message) { | 534 switch(msg->message) { |
382 case WM_EXITSIZEMOVE: | 535 case WM_EXITSIZEMOVE: |
383 return wnd_exitsizemove(data, xevent); | 536 return wnd_exitsizemove(data, xevent); |
384 case WM_WINDOWPOSCHANGING: | 537 case WM_WINDOWPOSCHANGING: |
385 return wnd_poschanging(data, xevent); | 538 return wnd_poschanging(data, xevent); |
539 case WM_WINDOWPOSCHANGED: | |
540 return wnd_poschanged(xevent); | |
541 case WM_ACTIVATE: | |
542 return wnd_activate(xevent); | |
386 case WM_SIZING: | 543 case WM_SIZING: |
387 return wnd_sizing(data, xevent); | 544 return wnd_sizing(data, xevent); |
388 case WM_MOVING: | 545 case WM_MOVING: |
389 return wnd_moving(data, xevent); | 546 return wnd_moving(data, xevent); |
390 case WM_SHOWWINDOW: | 547 case WM_SHOWWINDOW: |
397 #endif | 554 #endif |
398 case WM_SIZE: | 555 case WM_SIZE: |
399 return wnd_size(data, xevent); | 556 return wnd_size(data, xevent); |
400 case APPBAR_CALLBACK: | 557 case APPBAR_CALLBACK: |
401 return gtk_appbar_callback(data, xevent); | 558 return gtk_appbar_callback(data, xevent); |
559 #if 0 | |
560 default: | |
561 gaim_debug_info("gtkappbar", "gtk_appbar_event_filter %d\n", msg->message); | |
562 #endif | |
402 } | 563 } |
403 return GDK_FILTER_CONTINUE; | 564 return GDK_FILTER_CONTINUE; |
404 } | 565 } |
405 | 566 |
406 void gtk_appbar_dock(GtkAppBar *ab, UINT side) { | 567 void gtk_appbar_dock(GtkAppBar *ab, UINT side) { |
412 return; | 573 return; |
413 | 574 |
414 ab->side = side; | 575 ab->side = side; |
415 get_window_normal_rc(GDK_WINDOW_HWND(ab->win->window), &(ab->docked_rect)); | 576 get_window_normal_rc(GDK_WINDOW_HWND(ab->win->window), &(ab->docked_rect)); |
416 CopyRect(&orig, &(ab->docked_rect)); | 577 CopyRect(&orig, &(ab->docked_rect)); |
417 print_rect(&(ab->docked_rect)); | 578 gtk_appbar_querypos(ab, GDK_WINDOW_HWND(ab->win->window), |
418 gtk_appbar_querypos(ab, GDK_WINDOW_HWND(ab->win->window), &(ab->docked_rect)); | 579 get_rect_of_window(GDK_WINDOW_HWND(ab->win->window))); |
419 if(EqualRect(&orig, &(ab->docked_rect)) == 0) | 580 if(EqualRect(&orig, &(ab->docked_rect)) == 0) |
420 MoveWindow(GDK_WINDOW_HWND(ab->win->window), | 581 MoveWindow(GDK_WINDOW_HWND(ab->win->window), |
421 ab->docked_rect.left, | 582 ab->docked_rect.left, |
422 ab->docked_rect.top, | 583 ab->docked_rect.top, |
423 ab->docked_rect.right - ab->docked_rect.left, | 584 ab->docked_rect.right - ab->docked_rect.left, |