Fix move command parsing.
[fvwm.git] / modules / FvwmIconMan / fvwm.c
blob2d379dd34a8c54ddc3c69714e322d16d52af3de8
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 #include "config.h"
19 #include "FvwmIconMan.h"
20 #include "x.h"
21 #include "xmanager.h"
23 #include "libs/fvwmlib.h"
24 #include "libs/FScreen.h"
25 #include "libs/Module.h"
26 #include "libs/Parse.h"
27 #include "libs/Strings.h"
29 static WinData *fvwm_focus_win = NULL;
31 typedef struct {
32 Ulong paging_enabled;
33 } m_toggle_paging_data;
35 typedef struct {
36 Ulong desknum;
37 } m_new_desk_data;
39 typedef struct {
40 Ulong x, y, desknum;
41 } m_new_page_data;
43 typedef struct {
44 Ulong app_id, frame_id, dbase_entry;
45 } m_minimal_data;
47 typedef struct {
48 Ulong app_id, frame_id, dbase_entry;
49 Ulong xpos, ypos, icon_width, icon_height;
50 } m_icon_data;
52 typedef struct {
53 Ulong app_id, frame_id, dbase_entry;
54 union {
55 Ulong name_long[1];
56 Uchar name[4];
57 } name;
58 } m_name_data;
60 typedef struct {
61 Ulong arg, toggle, id;
62 Uchar str[4];
63 } m_property_data;
65 typedef struct {
66 Ulong app_id, frame_id, dbase_entry;
67 Ulong width, height, depth, picture, mask, alpha;
68 union {
69 Ulong name_long[1];
70 Uchar name[4];
71 } name;
72 } m_mini_icon_data;
74 typedef union {
75 m_toggle_paging_data toggle_paging_data;
76 m_new_desk_data new_desk_data;
77 ConfigWinPacket add_config_data;
78 m_new_page_data new_page_data;
79 m_minimal_data minimal_data;
80 m_icon_data icon_data;
81 m_name_data name_data;
82 m_mini_icon_data mini_icon_data;
83 m_property_data property_data;
84 } FvwmPacketBody;
86 /* only used by count_nonsticky_in_hashtab */
87 static WinManager *the_manager;
89 static int count_nonsticky_in_hashtab(void *arg)
91 WinData *win = (WinData *)arg;
92 WinManager *man = the_manager;
94 if (!(IS_STICKY_ACROSS_DESKS(win) || IS_STICKY_ACROSS_PAGES(win)) &&
95 !(WINDATA_ICONIFIED(win) && (IS_ICON_STICKY_ACROSS_PAGES(win) ||
96 IS_ICON_STICKY_ACROSS_DESKS(win))) &&
97 win->complete && win->manager == man)
99 return 1;
102 return 0;
105 static void set_draw_mode(WinManager *man, int flag)
107 int num;
109 if (!man)
111 return;
114 if (man->we_are_drawing == 0 && flag)
116 draw_manager(man);
118 else if (man->we_are_drawing && !flag)
120 the_manager = man;
121 num = accumulate_walk_hashtab(count_nonsticky_in_hashtab);
122 ConsoleDebug(
123 FVWM, "SetDrawMode on 0x%lx, num = %d\n",
124 (unsigned long)man, num);
126 if (num == 0)
128 return;
130 man->configures_expected = num;
132 man->we_are_drawing = flag;
135 static int drawing(WinManager *man)
137 if (!man)
139 return 1;
142 return man->we_are_drawing;
145 static void got_configure(WinManager *man)
147 if (man && !man->we_are_drawing)
149 man->configures_expected--;
150 ConsoleDebug(
151 FVWM, "got_configure on 0x%lx, num_expected now = %d\n",
152 (unsigned long) man, man->configures_expected);
153 if (man->configures_expected <= 0)
155 set_draw_mode(man, 1);
160 /* MMH <mikehan@best.com> 6/99
161 * Following a gruesome hack this function has been hijacked.
162 * The function is no longer about whether or not the window is in the
163 * viewport, but whether or not the manager wants to display the window,
164 * based on its current location.
166 int win_in_viewport(WinData *win)
168 return check_resolution(win->manager, win);
172 WinData *id_to_win(Ulong id)
174 WinData *win;
176 win = find_win_hashtab(id);
177 if (win == NULL)
179 win = new_windata();
180 win->app_id = id;
181 win->app_id_set = 1;
182 insert_win_hashtab(win);
185 return win;
188 static void set_win_configuration(WinData *win, FvwmPacketBody *body)
190 win->desknum = body->add_config_data.desk;
191 win->x = body->add_config_data.frame_x;
192 win->y = body->add_config_data.frame_y;
193 win->width = body->add_config_data.frame_width;
194 win->height = body->add_config_data.frame_height;
195 win->iconified = IS_ICONIFIED(&(body->add_config_data));
196 win->state = (win == fvwm_focus_win) ? FOCUS_CONTEXT : PLAIN_CONTEXT;
197 win->geometry_set = 1;
198 memcpy(&(win->flags), &(body->add_config_data.flags),
199 sizeof(win->flags));
201 int wb_x = body->add_config_data.border_width;
202 int wb_y = body->add_config_data.border_width;
203 int t_w = 2*wb_x;
204 int t_h = 2*wb_y;
206 if (HAS_TITLE_DIR(win, DIR_N))
208 wb_y += body->add_config_data.title_height;
209 t_h += body->add_config_data.title_height;
211 else if (HAS_TITLE_DIR(win, DIR_W))
213 wb_x += body->add_config_data.title_height;
214 t_w += body->add_config_data.title_height;
216 if (HAS_TITLE_DIR(win, DIR_S))
218 t_h += body->add_config_data.title_height;
220 if (HAS_TITLE_DIR(win, DIR_E))
222 t_w += body->add_config_data.title_height;
224 win->real_g.x = win->x + wb_x;
225 win->real_g.y = win->y + wb_y;
226 win->real_g.width = win->width - t_w;
227 win->real_g.height = win->height - t_h;
231 static void handle_config_info(unsigned long *body)
233 char *tline, *token, *rest;
234 int color;
235 extern void process_dynamic_config_line(char *line);
237 tline = (char*)&(body[3]);
238 token = PeekToken(tline, &rest);
239 if (StrEquals(token, "Colorset"))
241 color = LoadColorset(rest);
242 change_colorset(color);
244 else if (StrEquals(token, XINERAMA_CONFIG_STRING))
246 FScreenConfigureModule(rest);
248 else if (StrEquals(token, "IgnoreModifiers"))
250 sscanf(rest, "%d", &mods_unused);
252 else if (strncasecmp(tline, Module, ModuleLen) == 0)
254 process_dynamic_config_line(tline);
258 static void configure_window(FvwmPacketBody *body)
260 Ulong app_id = body->add_config_data.w;
261 WinData *win;
262 ConsoleDebug(FVWM, "configure_window: %ld\n", app_id);
264 win = id_to_win(app_id);
266 set_win_configuration(win, body);
268 check_win_complete(win);
269 check_in_window(win);
270 got_configure(win->manager);
273 static void focus_change(FvwmPacketBody *body)
275 Ulong app_id = body->minimal_data.app_id;
276 WinData *win = id_to_win(app_id);
278 ConsoleDebug(FVWM, "Focus Change\n");
279 ConsoleDebug(FVWM, "\tID: %ld\n", app_id);
281 if (fvwm_focus_win &&
282 fvwm_focus_win->button &&
283 fvwm_focus_win->manager->showonlyfocused)
284 delete_windows_button(fvwm_focus_win);
286 if (fvwm_focus_win && win != fvwm_focus_win)
288 del_win_state(fvwm_focus_win, FOCUS_CONTEXT);
289 if (fvwm_focus_win->manager &&
290 fvwm_focus_win->manager->focus_button)
292 fvwm_focus_win->manager->focus_button = NULL;
294 fvwm_focus_win = NULL;
297 if (win->complete &&
298 win->button &&
299 win->manager &&
300 win->manager->window_up &&
301 win->manager->followFocus)
303 win->manager->focus_button = win->button;
305 add_win_state(win, FOCUS_CONTEXT);
307 check_in_window(win);
309 globals.focus_win = win;
310 fvwm_focus_win = win;
311 ConsoleDebug(FVWM, "leaving focus_change\n");
314 static void res_name(FvwmPacketBody *body)
316 Ulong app_id = body->name_data.app_id;
317 Uchar *name = body->name_data.name.name;
318 WinData *win;
320 ConsoleDebug(FVWM, "In res_name\n");
322 win = id_to_win(app_id);
324 copy_string(&win->resname, (char *)name);
325 change_windows_manager(win);
327 ConsoleDebug(FVWM, "Exiting res_name\n");
330 static void class_name(FvwmPacketBody *body)
332 Ulong app_id = body->name_data.app_id;
333 Uchar *name = body->name_data.name.name;
334 WinData *win;
336 ConsoleDebug(FVWM, "In class_name\n");
338 win = id_to_win(app_id);
340 copy_string(&win->classname, (char *)name);
341 change_windows_manager(win);
343 ConsoleDebug(FVWM, "Exiting class_name\n");
346 static void icon_name(FvwmPacketBody *body)
348 WinData *win;
349 Ulong app_id;
350 Uchar *name = body->name_data.name.name;
352 ConsoleDebug(FVWM, "In icon_name\n");
354 app_id = body->name_data.app_id;
356 win = id_to_win(app_id);
358 if (win->iconname && !strcmp(win->iconname, (char *)name))
360 ConsoleDebug(
361 FVWM, "No icon change: %s %s\n", win->iconname, name);
362 return;
365 copy_string(&win->iconname, (char *)name);
366 ConsoleDebug(FVWM, "new icon name: %s\n", win->iconname);
368 ConsoleDebug(FVWM, "Exiting icon_name\n");
371 static void visible_icon_name(FvwmPacketBody *body)
373 WinData *win;
374 Ulong app_id;
375 Uchar *name = body->name_data.name.name;
377 ConsoleDebug(FVWM, "In visible_icon_name\n");
379 app_id = body->name_data.app_id;
381 win = id_to_win(app_id);
383 if (win->visible_icon_name &&
384 !strcmp(win->visible_icon_name, (char *)name))
386 ConsoleDebug(
387 FVWM, "No icon change: %s %s\n", win->iconname, name);
388 return;
391 copy_string(&win->visible_icon_name, (char *)name);
392 ConsoleDebug(
393 FVWM, "new visible icon name: %s\n", win->visible_icon_name);
394 if (change_windows_manager(win) == 0 && win->button &&
395 (win->manager->format_depend & ICON_NAME))
397 if (win->manager->sort)
399 resort_windows_button(win);
403 ConsoleDebug(FVWM, "Exiting icon_name\n");
406 static void window_name(FvwmPacketBody *body)
408 WinData *win;
409 Ulong app_id;
410 Uchar *name = body->name_data.name.name;
412 ConsoleDebug(FVWM, "In window_name\n");
414 app_id = body->name_data.app_id;
416 win = id_to_win(app_id);
418 /* This is necessary because bash seems to update the window title on
419 every keystroke regardless of whether anything changes */
420 if (win->titlename && !strcmp(win->titlename, (char *)name))
422 ConsoleDebug(
423 FVWM, "No name change: %s %s\n", win->titlename, name);
424 return;
427 copy_string(&win->titlename, (char *)name);
429 ConsoleDebug(FVWM, "Exiting window_name\n");
432 static void visible_name(FvwmPacketBody *body)
434 WinData *win;
435 Ulong app_id;
436 Uchar *name = body->name_data.name.name;
438 ConsoleDebug(FVWM, "In visible_name\n");
440 app_id = body->name_data.app_id;
442 win = id_to_win(app_id);
444 /* This is necessary because bash seems to update the window title on
445 every keystroke regardless of whether anything changes */
446 if (win->visible_name && !strcmp(win->visible_name, (char *)name))
448 ConsoleDebug(
449 FVWM, "No visible name change: %s %s\n",
450 win->visible_name, name);
451 return;
454 copy_string(&win->visible_name, (char *)name);
455 if (change_windows_manager(win) == 0 && win->button &&
456 (win->manager->format_depend & TITLE_NAME))
458 if (win->manager->sort)
460 resort_windows_button(win);
463 ConsoleDebug(FVWM, "Exiting visible_name\n");
467 static void new_window(FvwmPacketBody *body)
469 WinData *win;
471 win = id_to_win(body->add_config_data.w);
472 memcpy(&(win->flags), &(body->add_config_data.flags), sizeof(win->flags));
473 set_win_configuration(win, body);
474 got_configure(win->manager);
475 check_win_complete(win);
476 check_in_window(win);
477 /* FIXME: not perfect, the manager is not know yet */
478 tips_cancel(win->manager);
481 static void destroy_window(FvwmPacketBody *body)
483 WinData *win;
484 Ulong app_id;
486 app_id = body->minimal_data.app_id;
487 win = id_to_win(app_id);
488 if (win->manager)
490 tips_cancel(win->manager);
492 if (win == globals.focus_win)
494 globals.focus_win = NULL;
496 delete_win_hashtab(win);
497 if (win->button)
499 ConsoleDebug(FVWM, "destroy_window: deleting windows_button\n");
500 delete_windows_button(win);
502 if (win == fvwm_focus_win)
504 fvwm_focus_win = NULL;
506 free_windata(win);
509 static void mini_icon(FvwmPacketBody *body)
511 Ulong app_id = body->mini_icon_data.app_id;
512 WinData *win;
514 if (!FMiniIconsSupported)
516 return;
518 win = id_to_win(app_id);
519 set_win_picture(
520 win, body->mini_icon_data.picture, body->mini_icon_data.mask,
521 body->mini_icon_data.alpha, body->mini_icon_data.depth,
522 body->mini_icon_data.width, body->mini_icon_data.height);
525 ConsoleDebug(
526 FVWM, "mini_icon: 0x%lx 0x%lx %dx%dx%d\n",
527 (unsigned long) win->pic.picture, (unsigned long) win->pic.mask,
528 win->pic.width, win->pic.height, win->pic.depth);
531 static void icon_location(FvwmPacketBody *body)
533 Ulong app_id = body->minimal_data.app_id;
534 WinData *win;
536 win = id_to_win(app_id);
537 if (win == NULL)
539 return;
541 win->icon_g.x = body->icon_data.xpos;
542 win->icon_g.y = body->icon_data.ypos;
543 win->icon_g.width = body->icon_data.icon_width;
544 if (win->icon_g.width <= 0)
546 win->icon_g.width = 1;
548 win->icon_g.height = body->icon_data.icon_height;
549 if (win->icon_g.height <= 0)
551 win->icon_g.height = 1;
553 check_in_window(win);
556 static void iconify(FvwmPacketBody *body, int dir)
558 Ulong app_id = body->minimal_data.app_id;
559 WinData *win;
561 win = id_to_win(app_id);
562 set_win_iconified(win, dir);
563 icon_location(body);
564 check_win_complete(win);
565 check_in_window(win);
568 static void window_shade(FvwmPacketBody *body, int do_shade)
570 Window w;
571 WinManager *man;
573 w = (Window)(body->minimal_data.app_id);
574 man = find_windows_manager(w);
575 if (man == NULL)
577 return;
579 if (do_shade)
581 man->flags.needs_resize_after_unshade = 0;
582 man->flags.is_shaded = 1;
584 else
586 man->flags.is_shaded = 0;
587 if (man->flags.needs_resize_after_unshade)
589 draw_manager(man);
590 man->flags.needs_resize_after_unshade = 0;
594 return;
597 /* only used by remanage_winlist */
599 static void update_win_in_hashtab(void *arg)
601 WinData *p = (WinData *)arg;
602 check_in_window(p);
605 void remanage_winlist(void)
607 walk_hashtab(update_win_in_hashtab);
608 draw_managers();
611 static void new_desk(FvwmPacketBody *body)
613 globals.desknum = body->new_desk_data.desknum;
614 remanage_winlist();
617 static void sendtomodule(FvwmPacketBody *body)
619 extern void execute_function(char *);
620 Uchar *string = body->name_data.name.name;
622 ConsoleDebug(FVWM, "Got string: %s\n", string);
624 execute_function((char *)string);
627 static void property_change(FvwmPacketBody *body)
629 WinManager *man = NULL;
630 int j;
632 if (body->property_data.id != 0)
634 if (!(man = find_windows_manager(body->property_data.id)))
635 return;
638 if (body->property_data.arg == MX_PROPERTY_CHANGE_BACKGROUND)
640 if (man != NULL &&
641 CSET_IS_TRANSPARENT_PR(man->colorsets[DEFAULT]))
643 recreate_background(man, DEFAULT);
644 force_manager_redraw(man);
646 if (man != NULL)
648 return;
650 for (j = 0; j < globals.num_managers; j++)
652 man = &globals.managers[j];
653 if (CSET_IS_TRANSPARENT_PR(man->colorsets[DEFAULT]))
655 recreate_background(man, DEFAULT);
656 force_manager_redraw(man);
660 else if (body->property_data.arg == MX_PROPERTY_CHANGE_SWALLOW &&
661 man != NULL)
663 man->swallowed = body->property_data.toggle;
664 if (man->swallowed && body->property_data.str)
666 unsigned long u;
668 if (sscanf((char *)body->property_data.str, "%lu",
669 &u) == 1)
671 man->swallower_win = (Window)u;
673 else
675 man->swallower_win = 0;
681 static void ProcessMessage(Ulong type, FvwmPacketBody *body)
683 int i;
685 ConsoleDebug(FVWM, "fvwm message type: %ld\n", type);
687 switch(type)
689 case M_CONFIG_INFO:
690 ConsoleDebug(FVWM, "DEBUG::M_CONFIG_INFO\n");
691 handle_config_info((unsigned long*)body);
692 break;
694 case M_CONFIGURE_WINDOW:
695 ConsoleDebug(FVWM, "DEBUG::M_CONFIGURE_WINDOW\n");
696 configure_window(body);
697 break;
699 case M_FOCUS_CHANGE:
700 ConsoleDebug(FVWM, "DEBUG::M_FOCUS_CHANGE\n");
701 focus_change(body);
702 break;
704 case M_RES_NAME:
705 ConsoleDebug(FVWM, "DEBUG::M_RES_NAME\n");
706 res_name(body);
707 break;
709 case M_RES_CLASS:
710 ConsoleDebug(FVWM, "DEBUG::M_RES_CLASS\n");
711 class_name(body);
712 break;
714 case M_MAP:
715 ConsoleDebug(FVWM, "DEBUG::M_MAP\n");
716 break;
718 case M_ADD_WINDOW:
719 ConsoleDebug(FVWM, "DEBUG::M_ADD_WINDOW\n");
720 new_window(body);
721 break;
723 case M_DESTROY_WINDOW:
724 ConsoleDebug(FVWM, "DEBUG::M_DESTROY_WINDOW\n");
725 destroy_window(body);
726 break;
728 case M_MINI_ICON:
729 ConsoleDebug(FVWM, "DEBUG::M_MINI_ICON\n");
730 mini_icon(body);
731 break;
733 case M_WINDOW_NAME:
734 ConsoleDebug(FVWM, "DEBUG::M_WINDOW_NAME\n");
735 window_name(body);
736 break;
738 case M_VISIBLE_NAME:
739 ConsoleDebug(FVWM, "DEBUG::M_VISIBLE_NAME\n");
740 visible_name(body);
741 break;
743 case M_ICON_NAME:
744 ConsoleDebug(FVWM, "DEBUG::M_ICON_NAME\n");
745 icon_name(body);
746 break;
748 case MX_VISIBLE_ICON_NAME:
749 ConsoleDebug(FVWM, "DEBUG::MX_VISIBLE_ICON_NAME\n");
750 visible_icon_name(body);
751 break;
753 case M_DEICONIFY:
754 ConsoleDebug(FVWM, "DEBUG::M_DEICONIFY\n");
755 iconify(body, 0);
756 SendUnlockNotification(fvwm_fd);
757 break;
759 case M_ICONIFY:
760 ConsoleDebug(FVWM, "DEBUG::M_ICONIFY\n");
761 iconify(body, 1);
762 SendUnlockNotification(fvwm_fd);
763 break;
765 case M_ICON_LOCATION:
766 icon_location(body);
767 break;
769 case M_END_WINDOWLIST:
770 ConsoleDebug(FVWM, "DEBUG::M_END_WINDOWLIST\n");
771 ConsoleDebug(
772 FVWM, "+++++ End window list +++++\n");
773 if (globals.focus_win && globals.focus_win->button)
775 globals.focus_win->manager->focus_button =
776 globals.focus_win->button;
778 globals.got_window_list = 1;
779 for (i = 0; i < globals.num_managers; i++)
781 create_manager_window(i);
783 break;
785 case M_NEW_DESK:
786 ConsoleDebug(FVWM, "DEBUG::M_NEW_DESK\n");
787 new_desk(body);
788 break;
790 case M_NEW_PAGE:
791 ConsoleDebug(FVWM, "DEBUG::M_NEW_PAGE\n");
792 if (globals.x == body->new_page_data.x &&
793 globals.y == body->new_page_data.y &&
794 globals.desknum == body->new_page_data.desknum)
796 ConsoleDebug(FVWM, "Useless NEW_PAGE received\n");
797 break;
799 globals.x = body->new_page_data.x;
800 globals.y = body->new_page_data.y;
801 globals.desknum = body->new_page_data.desknum;
802 if (fvwm_focus_win && fvwm_focus_win->manager &&
803 fvwm_focus_win->manager->followFocus)
805 /* need to set the focus on a page change */
806 add_win_state(fvwm_focus_win, FOCUS_CONTEXT);
808 for (i = 0; i < globals.num_managers; i++)
810 set_draw_mode(&globals.managers[i], 0);
812 break;
814 case M_STRING:
815 ConsoleDebug(FVWM, "DEBUG::M_STRING\n");
816 sendtomodule(body);
817 break;
819 case MX_PROPERTY_CHANGE:
820 ConsoleDebug(FVWM, "DEBUG::MX_PROPERTY_CHANGE\n");
821 property_change(body);
822 break;
824 case M_WINDOWSHADE:
825 window_shade(body, 1);
826 break;
828 case M_DEWINDOWSHADE:
829 window_shade(body, 0);
830 break;
832 default:
833 break;
836 check_managers_consistency();
838 for (i = 0; i < globals.num_managers; i++)
840 if (drawing(&globals.managers[i]))
842 draw_manager(&globals.managers[i]);
846 check_managers_consistency();
849 void ReadFvwmPipe(void)
851 FvwmPacket* packet;
853 PrintMemuse();
854 ConsoleDebug(FVWM, "DEBUG: entering ReadFvwmPipe\n");
856 if ((packet = ReadFvwmPacket(fvwm_fd[1])) == NULL)
858 exit(0);
860 else
862 ProcessMessage(packet->type, (FvwmPacketBody *)packet->body);
865 ConsoleDebug(FVWM, "DEBUG: leaving ReadFvwmPipe\n");