static ObMenuEntryFrame* menu_entry_frame_new(ObMenuEntry *entry, ObMenuFrame *frame) { ObMenuEntryFrame *self; XSetWindowAttributes attr; self = g_slice_new0(ObMenuEntryFrame); self->entry = entry; self->frame = frame; menu_entry_ref(entry); attr.event_mask = ENTRY_EVENTMASK; self->window = createWindow(self->frame->window, CWEventMask, &attr); self->text = createWindow(self->window, 0, NULL); g_hash_table_insert(menu_frame_map, &self->window, self); g_hash_table_insert(menu_frame_map, &self->text, self); if ((entry->type == OB_MENU_ENTRY_TYPE_NORMAL) || (entry->type == OB_MENU_ENTRY_TYPE_SUBMENU)) { self->icon = createWindow(self->window, 0, NULL); g_hash_table_insert(menu_frame_map, &self->icon, self); } if (entry->type == OB_MENU_ENTRY_TYPE_SUBMENU) { self->bullet = createWindow(self->window, 0, NULL); g_hash_table_insert(menu_frame_map, &self->bullet, self); } XMapWindow(obt_display, self->window); XMapWindow(obt_display, self->text); window_add(&self->window, MENUFRAME_AS_WINDOW(self->frame)); return self; }
ObMenuFrame* menu_frame_new(ObMenu *menu, guint show_from, ObClient *client) { ObMenuFrame *self; XSetWindowAttributes attr; self = g_slice_new0(ObMenuFrame); self->obwin.type = OB_WINDOW_CLASS_MENUFRAME; self->menu = menu; self->selected = NULL; self->client = client; self->direction_right = TRUE; self->show_from = show_from; attr.event_mask = FRAME_EVENTMASK; self->window = createWindow(obt_root(ob_screen), CWEventMask, &attr); /* make it a popup menu type window */ OBT_PROP_SET32(self->window, NET_WM_WINDOW_TYPE, ATOM, OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_POPUP_MENU)); XSetWindowBorderWidth(obt_display, self->window, ob_rr_theme->mbwidth); XSetWindowBorder(obt_display, self->window, RrColorPixel(ob_rr_theme->menu_border_color)); self->a_items = RrAppearanceCopy(ob_rr_theme->a_menu); window_add(&self->window, MENUFRAME_AS_WINDOW(self)); stacking_add(MENUFRAME_AS_WINDOW(self)); return self; }
ObPopup *popup_new(void) { XSetWindowAttributes attrib; ObPopup *self = g_slice_new0(ObPopup); self->obwin.type = OB_WINDOW_CLASS_INTERNAL; self->gravity = NorthWestGravity; self->x = self->y = self->textw = self->h = 0; self->a_bg = RrAppearanceCopy(ob_rr_theme->osd_bg); self->a_text = RrAppearanceCopy(ob_rr_theme->osd_hilite_label); self->iconwm = self->iconhm = 1; attrib.override_redirect = True; self->bg = XCreateWindow(obt_display, obt_root(ob_screen), 0, 0, 1, 1, 0, RrDepth(ob_rr_inst), InputOutput, RrVisual(ob_rr_inst), CWOverrideRedirect, &attrib); self->text = XCreateWindow(obt_display, self->bg, 0, 0, 1, 1, 0, RrDepth(ob_rr_inst), InputOutput, RrVisual(ob_rr_inst), 0, NULL); XSetWindowBorderWidth(obt_display, self->bg, ob_rr_theme->obwidth); XSetWindowBorder(obt_display, self->bg, RrColorPixel(ob_rr_theme->osd_border_color)); XMapWindow(obt_display, self->text); stacking_add(INTERNAL_AS_WINDOW(self)); window_add(&self->bg, INTERNAL_AS_WINDOW(self)); return self; }
void frame_grab_client(struct wm_frame *self) { XReparentWindow(t_display, self->client->window, self->window, 0, 0); if(wm_state() == WM_STATE_STARTING) ++self->client->ignore_unmaps; XSelectInput(t_display, self->window, FRAME_EVENTMASK); window_add(&self->window, CLIENT_AS_WINDOW(self->client)); }
int main(int argc, char **argv) { int cnt, x, y, i = 0, verbose = 0; Window win = 0; Bool keysymMappingInitialized = False; int rc = 0; int inputEvents[100]; int inputEventsIndex = 0; int iEvent = 0; if (argc == 1) usage(argv[0]); const char* log_file = NULL; if (streq(argv[1],"-o") || streq(argv[1],"--logfile")) { i++; if (++i > argc) usage(argv[0]); log_file = argv[i]; } report_init(log_file); if (!xhandler_init(getenv("DISPLAY"))) exit(1); report_add_message(xhandler_get_server_time(), "Startup\n"); /* initialize subsystems */ xemu_init(xhandler.display); scheduler_init(xhandler.display); window_init(xhandler.display); application_init(); /* * Process the command line options. * Skip emulation options (--click, --drag, --key, --type), but remember they index * and process them later. */ while (++i < argc) { if (streq(argv[i],"-v") || streq(argv[i],"--verbose")) { verbose = 1; continue; } if (streq(argv[i], "-id") || streq(argv[i], "--id")) { char name[PATH_MAX]; if (++i >= argc) usage(argv[0]); cnt = sscanf(argv[i], "0x%lx", &win); if (cnt < 1) { cnt = sscanf(argv[i], "%lu", &win); } if (cnt < 1) { fprintf(stderr, "*** invalid window id '%s'\n", argv[i]); usage(argv[0]); } sprintf(name, "0x%lx", win); if (!window_add(win, application_monitor(name))) { fprintf(stderr, "Could not setup damage monitoring for window 0x%lx!\n", win); exit(1); } if (verbose) report_add_message(REPORT_LAST_TIMESTAMP, "Monitoring window 0x%lx\n", win); continue; } if (streq(argv[i], "-a") || streq(argv[i], "--application")) { if (++i >= argc) usage(argv[0]); response.application = application_monitor(argv[i]); if (response.application && verbose) { report_add_message(REPORT_LAST_TIMESTAMP, "Monitoring application '%s'\n", argv[i]); } if (!strcmp(argv[i], "*")) { application_set_monitor_all(true); } continue; } if (streq("-c", argv[i]) || streq("--click", argv[i])) { if (!xemu.pointer.dev) { fprintf(stderr, "Failed to open pointer device, unable to simulate pointer events.\n"); exit(-1); } if (inputEventsIndex == ASIZE(inputEvents)) { fprintf(stderr, "Too many input events specified\n"); exit(-1); } if (!argv[i + 1] || !match_regex(argv[i + 1], "^[0-9]+x[0-9]+(,[0-9]+)?$")) { fprintf(stderr, "Failed to parse --c options: %s\n", argv[i + 1]); exit(-1); } inputEvents[inputEventsIndex++] = i; if (++i >= argc) usage(argv[0]); continue; } if (streq("-l", argv[i]) || streq("--level", argv[i])) { if (++i >= argc) usage(argv[0]); if (!strcmp(argv[i], "raw")) { window_set_damage_level(XDamageReportRawRectangles); } else if (!strcmp(argv[i], "delta")) { window_set_damage_level(XDamageReportDeltaRectangles); } else if (!strcmp(argv[i], "box")) { window_set_damage_level(XDamageReportDeltaRectangles); } else if (!strcmp(argv[i], "nonempty")) { window_set_damage_level(XDamageReportNonEmpty); } else { fprintf(stderr, "Unrecongnized damage level: %s\n", argv[i]); usage(argv[0]); } if (verbose) report_add_message(REPORT_LAST_TIMESTAMP, "Setting damage report level to %s\n", argv[i]); continue; } if (streq("-x", argv[i]) || streq("--exclude", argv[i])) { char* exclude[] = { "none", "less", "greater" }; if (options.exclude_rules != EXCLUDE_NONE) { fprintf(stderr, "Duplicated --exclude parameter detected. Aborting\n"); exit(-1); } if (++i >= argc) usage(argv[0]); char rules[32] = ""; if ((cnt = sscanf(argv[i], "%ux%u,%s", &options.exclude_rect.width, &options.exclude_rect.height, rules)) >= 2) { options.exclude_size = 0; } else if ((cnt = sscanf(argv[i], "%u,%s", &options.exclude_size, rules)) >= 1) { options.exclude_rect.width = 0; options.exclude_rect.height = 0; } else { fprintf(stderr, "*** failed to parse '%s'\n", argv[i]); usage(argv[0]); } options.exclude_rules = *rules && !strcmp(rules, "greater") ? EXCLUDE_GREATER : EXCLUDE_LESS; if (verbose) { if (options.exclude_size) { report_add_message(REPORT_LAST_TIMESTAMP, "Excluding damage areas %s than %d pixels\n", exclude[options.exclude_rules], options.exclude_size); } else { report_add_message(REPORT_LAST_TIMESTAMP, "Excluding damage areas %s than (%dx%d)\n", exclude[options.exclude_rules], options.exclude_rect.width, options.exclude_rect.height); } } continue; } if (streq("-m", argv[i]) || streq("--monitor", argv[i])) { if (options.interested_damage_rect.width || options.interested_damage_rect.height || options.interested_damage_rect.x || options.interested_damage_rect.y) { fprintf(stderr, "Duplicated --monitor parameter detected. Aborting\n"); exit(-1); } if (++i >= argc) usage(argv[0]); if ((cnt = sscanf(argv[i], "%ux%u+%u+%u", &options.interested_damage_rect.width, &options.interested_damage_rect.height, &options.interested_damage_rect.x, &options.interested_damage_rect.y)) != 4) { fprintf(stderr, "*** failed to parse '%s'\n", argv[i]); usage(argv[0]); } if (verbose) { report_add_message(REPORT_LAST_TIMESTAMP, "Set monitor rect to %ix%i+%i+%i\n", options.interested_damage_rect.width, options.interested_damage_rect.height, options.interested_damage_rect.x, options.interested_damage_rect.y); } continue; } if (streq("-w", argv[i]) || streq("--wait", argv[i])) { if (++i >= argc) usage(argv[0]); if (options.damage_wait_secs >= 0) { fprintf(stderr, "Duplicate -w(--wait) option detected. Discarding the previous value\n"); } if ((options.damage_wait_secs = atoi(argv[i])) < 0) { fprintf(stderr, "*** failed to parse '%s'\n", argv[i]); usage(argv[0]); } if (verbose) report_add_message(REPORT_LAST_TIMESTAMP, "Set event timeout to %isecs\n", options.damage_wait_secs); continue; } if (streq("-b", argv[i]) || streq("--break", argv[i])) { if (options.break_timeout || options.break_on_damage) { fprintf(stderr, "Duplicate -b(--break)option detected. Discarding the previous value\n"); options.break_timeout = 0; options.break_on_damage = 0; } if (++i >= argc) usage(argv[0]); if (!strncmp(argv[i], "damage", 6)) { sscanf(argv[i] + 6, ",%d", &options.break_on_damage); if (!options.break_on_damage) options.break_on_damage = 1; if (verbose) report_add_message(REPORT_LAST_TIMESTAMP, "Break wait on the %d damage event\n", options.break_on_damage); } else { if ((options.break_timeout = atoi(argv[i])) < 0) { fprintf(stderr, "*** failed to parse '%s'\n", argv[i]); usage(argv[0]); } if (verbose) report_add_message(REPORT_LAST_TIMESTAMP, "Set break timout to %imsecs\n", options.break_timeout); } continue; } if (streq("-d", argv[i]) || streq("--drag", argv[i])) { if (!xemu.pointer.dev) { fprintf(stderr, "Failed to open pointer device, unable to simulate pointer events.\n"); exit(-1); } if (inputEventsIndex == ASIZE(inputEvents)) { fprintf(stderr, "Too many input events specified\n"); exit(-1); } if (!argv[i + 1] || (!match_regex(argv[i + 1], "^([0-9]+,)?(([0-9]+x[0-9]+,([0-9]+,)?)+[0-9]+x[0-9]+)$") && (!match_regex(argv[i + 1], "[0-9]+x[0-9]+-[0-9]+x[0-9]+") || !match_regex(argv[i + 1], "^(((([0-9]+,)?([0-9]+x[0-9]+)|([0-9]+x[0-9]+-[0-9]+x[0-9]+(\\*[0-9]+)?(\\+[1-9][0-9]*)?)),?)+)$") ) ) ) { fprintf(stderr, "Failed to parse --drag options: %s\n", argv[i + 1]); exit(-1); } inputEvents[inputEventsIndex++] = i; if (++i >= argc) usage(argv[0]); continue; } if (streq("-k", argv[i]) || streq("--key", argv[i])) { if (!xemu.keyboard.dev) { fprintf(stderr, "Failed to open keyboard device, unable to simulate keyboard events.\n"); exit(-1); } if (inputEventsIndex == ASIZE(inputEvents)) { fprintf(stderr, "Too many input events specified\n"); exit(-1); } inputEvents[inputEventsIndex++] = i; if (++i >= argc) usage(argv[0]); continue; } if (streq("-t", argv[i]) || streq("--type", argv[i])) { if (!xemu.keyboard.dev) { fprintf(stderr, "Failed to open keyboard device, unable to simulate keyboard events.\n"); exit(-1); } if (inputEventsIndex == ASIZE(inputEvents)) { fprintf(stderr, "Too many input events specified\n"); exit(-1); } inputEvents[inputEventsIndex++] = i; if (++i >= argc) usage(argv[0]); if (!keysymMappingInitialized) { xemu_load_keycodes(); keysymMappingInitialized = True; } continue; } /* since moving from command sequence approach the inspect parameter is deprecated */ if (streq("-i", argv[i]) || streq("--inspect", argv[i])) { if (verbose) report_add_message(REPORT_LAST_TIMESTAMP, "Just displaying damage events until timeout\n"); continue; } /* */ if (streq("-u", argv[i]) || streq("--user", argv[i]) || (xrecord.motion = (streq("-U", argv[i]) || streq("--user-all", argv[i])) ) ) { xinput_init(xhandler.display); if (verbose) report_add_message(REPORT_LAST_TIMESTAMP, "Reporting user input events\n"); continue; } if (streq(argv[i], "-r") || streq(argv[i], "--response")) { if (++i >= argc) usage(argv[0]); char option[500]; cnt = sscanf(argv[i], "%u,%s", &response.timeout, option); if (cnt < 1) { fprintf(stderr, "*** invalid response timeout value '%s'\n", argv[i]); usage(argv[0]); } if (cnt < 2) { report_set_silent(true); } else { if (strcmp(option, "verbose")) { fprintf(stderr, "*** invalid response option '%s'\n", argv[i]); usage(argv[0]); } } application_monitor_screen(); xinput_init(xhandler.display); if (verbose) report_add_message(REPORT_LAST_TIMESTAMP, "Monitoring application response time\n"); continue; } fprintf(stderr, "*** Dont understand %s\n", argv[i]); usage(argv[0]); } /* start monitoring the root window if no targets are specified */ if ((window_empty() && application_empty()) || response.timeout) { application_monitor(ROOT_WINDOW_RESOURCE); } window_monitor_all(); application_start_monitor(); /* eat first damage event when options.break_on_damage set */ if (options.break_on_damage) xhandler_eat_damage(); /* monitor the whole screen of no area is specified */ if (!options.interested_damage_rect.width && !options.interested_damage_rect.height && !options.interested_damage_rect.x && !options.interested_damage_rect.y) { options.interested_damage_rect.x = 0; options.interested_damage_rect.y = 0; options.interested_damage_rect.width = DisplayWidth(xhandler.display, DefaultScreen(xhandler.display)); options.interested_damage_rect.height = DisplayHeight(xhandler.display, DefaultScreen(xhandler.display)); } /* emulate user input */ for (iEvent = 0; iEvent < inputEventsIndex; iEvent++) { i = inputEvents[iEvent]; if (!strcmp("-c", argv[i]) || !strcmp("--click", argv[i])) { unsigned long delay = 0; Time start = 0; cnt = sscanf(argv[++i], "%ux%u,%lu", &x, &y, &delay); if (cnt == 2) { start = xhandler_get_server_time(); report_add_message(start, "Using no delay between press/release\n"); delay = 0; } else if (cnt != 3) { fprintf(stderr, "cnt: %d\n", cnt); fprintf(stderr, "*** failed to parse '%s'\n", argv[i]); usage(argv[0]); } /* Send the event */ start = xemu_button_event(x, y, delay); report_add_message(start, "Clicked %ix%i\n", x, y); continue; } if (!strcmp("-d", argv[i]) || !strcmp("--drag", argv[i])) { Time drag_time; char *s = NULL, *p = NULL; int button_state = XR_BUTTON_STATE_PRESS; s = p = argv[++i]; int delay = DEFAULT_DRAG_DELAY; int x1, y1, x2, y2; while (p) { p = strchr(s, ','); if (p) { *p++ = '\0'; } int count = DEFAULT_DRAG_COUNT; cnt = sscanf(s, "%ix%i-%ix%i*%i+%i", &x1, &y1, &x2, &y2, &delay, &count); if (cnt >= 4) { drag_time = xemu_drag_event(x1, y1, button_state, delay); button_state = XR_BUTTON_STATE_NONE; report_add_message(drag_time, "Dragged to %ix%i\n", x1, y1); int xdev = (x2 - x1) / (count + 1); int ydev = (y2 - y1) / (count + 1); for (i = 1; i <= count; i++) { x = x1 + xdev * i; y = y1 + ydev * i; drag_time = xemu_drag_event(x, y, button_state, delay); report_add_message(drag_time, "Dragged to %ix%i\n", x, y); } if (!p) button_state = XR_BUTTON_STATE_RELEASE; drag_time = xemu_drag_event(x2, y2, button_state, delay); report_add_message(drag_time, "Dragged to %ix%i\n", x2, y2); } else if (cnt == 2) { /* Send the event */ if (!p) { if (button_state == XR_BUTTON_STATE_PRESS) { fprintf(stderr, "*** Need at least 2 drag points!\n"); usage(argv[0]); } button_state = XR_BUTTON_STATE_RELEASE; } drag_time = xemu_drag_event(x1, y1, button_state, delay); report_add_message(drag_time, "Dragged to %ix%i\n", x1, y1); /* Make sure button state set to none after first point */ button_state = XR_BUTTON_STATE_NONE; /* reset the delay to default value */ delay = DEFAULT_DRAG_DELAY; } else if (cnt == 1) { delay = x1; } else { fprintf(stderr, "*** failed to parse '%s'\n", argv[i]); usage(argv[0]); } s = p; } continue; } if (!strcmp("-k", argv[i]) || !strcmp("--key", argv[i])) { char *key = NULL; char separator; unsigned long delay = 0; Time start = 0; cnt = sscanf(argv[++i], "%a[^,]%c%lu", &key, &separator, &delay); if (cnt == 1) { report_add_message(REPORT_LAST_TIMESTAMP, "Using default delay between press/release\n", delay); delay = DEFAULT_KEY_DELAY; } else if (cnt != 3 || separator != ',') { fprintf(stderr, "cnt: %d\n", cnt); fprintf(stderr, "*** failed to parse '%s'\n", argv[i]); if (key != NULL) free(key); usage(argv[0]); } start = xemu_send_key(key, delay); report_add_message(start, "Simulating keypress/-release pair (keycode '%s')\n", key); free(key); continue; } if (!strcmp("-t", argv[i]) || !strcmp("--type", argv[i])) { Time start = xemu_send_string(argv[++i]); report_add_message(start, "Simulated keys for '%s'\n", argv[i]); continue; } } /* setting the default wait period */ if (options.damage_wait_secs < 0) { options.damage_wait_secs = 5; } signal(SIGINT, abort_wait); /* wait for damage events */ rc = wait_response(); scheduler_fini(); report_flush_queue(); report_fini(); xinput_fini(); xemu_fini(); window_fini(); application_fini(); xhandler_fini(); return rc; }
ObPrompt* prompt_new(const gchar *msg, const gchar *title, const ObPromptAnswer *answers, gint n_answers, gint default_result, gint cancel_result, ObPromptCallback func, ObPromptCleanup cleanup, gpointer data) { ObPrompt *self; XSetWindowAttributes attrib; gint i; attrib.override_redirect = FALSE; self = g_slice_new0(ObPrompt); self->ref = 1; self->func = func; self->cleanup = cleanup; self->data = data; self->default_result = default_result; self->cancel_result = cancel_result; self->super.type = OB_WINDOW_CLASS_PROMPT; self->super.window = XCreateWindow(obt_display, obt_root(ob_screen), 0, 0, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, CWOverrideRedirect, &attrib); self->ic = obt_keyboard_context_new(self->super.window, self->super.window); /* make it a dialog type window */ OBT_PROP_SET32(self->super.window, NET_WM_WINDOW_TYPE, ATOM, OBT_PROP_ATOM(NET_WM_WINDOW_TYPE_DIALOG)); /* set the window's title */ if (title) OBT_PROP_SETS(self->super.window, NET_WM_NAME, utf8, title); /* listen for key presses on the window */ self->event_mask = KeyPressMask; /* set up the text message widow */ self->msg.text = g_strdup(msg); self->msg.window = XCreateWindow(obt_display, self->super.window, 0, 0, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, 0, NULL); XMapWindow(obt_display, self->msg.window); /* set up the buttons from the answers */ self->n_buttons = n_answers; if (!self->n_buttons) self->n_buttons = 1; self->button = g_new0(ObPromptElement, self->n_buttons); if (n_answers == 0) { g_assert(self->n_buttons == 1); /* should be set to this above.. */ self->button[0].text = g_strdup(_("OK")); } else { g_assert(self->n_buttons > 0); for (i = 0; i < self->n_buttons; ++i) { self->button[i].text = g_strdup(answers[i].text); self->button[i].result = answers[i].result; } } for (i = 0; i < self->n_buttons; ++i) { self->button[i].window = XCreateWindow(obt_display, self->super.window, 0, 0, 1, 1, 0, CopyFromParent, InputOutput, CopyFromParent, 0, NULL); XMapWindow(obt_display, self->button[i].window); window_add(&self->button[i].window, PROMPT_AS_WINDOW(self)); /* listen for button presses on the buttons */ XSelectInput(obt_display, self->button[i].window, ButtonPressMask | ButtonReleaseMask | ButtonMotionMask); } prompt_list = g_list_prepend(prompt_list, self); return self; }